SpringMVC + @PathVariable 注意事项
技术 Spring 4

问题出现的条件

  1. 使用@PathVariable 注解
  2. 该注解绑定的参数位于uri 的最后
  3. 请求传参时,参数中含有.(点)

出现的问题

示例代码:

// TestController.java

    @RequestMapping("/test/{param}")
    public Result test(@PathVariable("param") String param) {
        return new Result();
    }

如果需要调用上面的接口,一般可能是GET /test/abc,此时param 的值应该为abc
但是当传入的参数包含点时,spring 会将最后一个点后面的内容截断。比如/test/abc.def.ghi,则,此时后端拿到的param 的值会被截断为abc.def

处理方法

  • 可以在该参数后面增加一段,如:@RequestMapping("/test/{param}/end")
  • 可以修改匹配的方式,使用正则匹配,如:@RequestMapping("/test/{param:.+}")

出现的问题2

上面一个方法可以解决后端取路径中参数不正确的问题,但是经过上面的方法解决之后,当调用接口(如输入一个邮箱12345@qq.com)后,依旧会报错,并最终返回406,报错如下:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:239)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:180)
	at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:119)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:981)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:873)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:858)
...

这是因为在请求时候,spring 将最后一个点及后面的内容识别成了扩展名。认为请求的是一个文件,但是请求返回的可能是json 串,这时候就出现HttpMediaTypeNotAcceptableException 了。

经初步测试发现,只有当spring 认为这是个文件扩展名时,才会产生错误,如果传入的参数是中文(abc.你好)或非扩展名结尾(abc.aaa)等,就不会抛出类型不正确的异常。
但是由于邮箱有很多是以com 结尾,同时又正好又com 扩展名的文件,所以这一点需要注意。

解决方法2

修改spring boot 的配置
详见ContentNegotiationConfigurer

Error 406 while using an email address as a path variable in Spring Boot

SpringMVC + @PathVariable 注意事项
https://halo.persipa.site/2023/0331
作者
Persipa
发布于
更新于
许可