Spring MVC 在底层处理 Web 请求接收的传参类型,大概分为了4类。
注解
@PathVariable、@RequestParam、@MatrixVariable、@RequestBody、@RequestHeader、@CookieValue、@ModelAttribute
@PathVariable
样例1
URL:
http://127.0.0.1/PathVariable/id/59/age/18/name/张三
控制器:
@RequestMapping(path = "PathVariable/id/{id}/age/{age}/name/{name}")public Map PathVariable(@PathVariable("id") Integer id,@PathVariable("age") Integer age,@PathVariable("name") String name) {Map<String, Object> map = new HashMap<>();map.put("id", id);map.put("age", age);map.put("name", name);return map;}
Postman:
@RequestParam
样例1
URL:
http://127.0.0.1/RequestParam1?name=张三&age=18
http://127.0.0.1/RequestParam2?name=张三&age=18
控制器
@RequestMapping(path = "RequestParam1")public String PathVariableTest1(@RequestParam(name = "name") String name,@RequestParam(name = "age") Integer age) {return "name -> " + name + "; age -> " + age;}
@RequestMapping(path = "RequestParam2")public Map PathVariableTest2(@RequestParam(name = "name") String name,@RequestParam(name = "age") Integer age) {Map<String, Object> map = new HashMap<>();map.put("name", name);map.put("age", age);return map;}
@MatrixVariable
注意
Spring Boot 默认禁用了 @MatrixVariable 矩阵变量功能,如果需要开启:
@Beanpublic WebMvcConfigurer webMvcConfigurer() {return new WebMvcConfigurer() {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();// 不移除 ; 后面的内容,使得矩阵变量功能可以生效。urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}};}
样例1
请求URL:
http://127.0.0.1/car/1;price=34;brand=byd;brand=捷豹
http://127.0.0.1/car/1;price=34;brand=byd,捷豹
控制器:
@GetMapping("/car/{path}")public Map car(@PathVariable("path") String path,@MatrixVariable("price") Integer low,@MatrixVariable("brand") List<String> brand,@MatrixVariable Map<String, String> paramsA,@MatrixVariable MultiValueMap<String, String> paramsB) {Map<String, Object> map = new HashMap<>();map.put("price", low);map.put("brand", brand);map.put("path", path);map.put("paramsA", paramsA);map.put("paramsB", paramsB);return map;}
Postman:
样例2
请求URL:
http://127.0.0.1/boss/1;age=20/employee/2;age=10
http://127.0.0.1/boss/1;age=35;name=老板A/employee/2;age=20;name=打工人A
控制器:
@GetMapping("/boss/{bossId}/employee/{employeeId}")public Map boss(@MatrixVariable(value = "age", pathVar = "bossId") Integer bossAge,@MatrixVariable(value = "age", pathVar = "employeeId") Integer empAge,@MatrixVariable Map<String, String> paramsA,@MatrixVariable MultiValueMap<String, String> paramsB) {Map<String, Object> map = new HashMap<>();map.put("bossAge", bossAge);map.put("employeeAge", empAge);map.put("paramsA", paramsA);map.put("paramsB", paramsB);return map;}
Postman:

开启矩阵变量功能(含原理解析)
开启矩阵变量功能,这就涉及到了定制化 Spring Boot 的东西。
我们来到 Spring MVC 的配置类 WebMvcAutoConfiguration ,所有的自动配置都在这儿。
开启矩阵变量的核心在这儿:
默认的行为:配置了映射
@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {if (this.mvcProperties.getPathmatch().getMatchingStrategy() == WebMvcProperties.MatchingStrategy.PATH_PATTERN_PARSER) {configurer.setPatternParser(new PathPatternParser());}configurer.setUseSuffixPatternMatch(this.mvcProperties.getPathmatch().isUseSuffixPattern());configurer.setUseRegisteredSuffixPatternMatch(this.mvcProperties.getPathmatch().isUseRegisteredSuffixPattern());this.dispatcherServletPath.ifAvailable((dispatcherPath) -> {String servletUrlMapping = dispatcherPath.getServletUrlMapping();if (servletUrlMapping.equals("/") && singleDispatcherServlet()) {UrlPathHelper urlPathHelper = new UrlPathHelper();urlPathHelper.setAlwaysUseFullPath(true);configurer.setUrlPathHelper(urlPathHelper);}});}
因此,我们需要修改默认的路径匹配规则,这里有一个重要的类 UrlPathHelper 路径帮助器,它里面有一个属性是:
private boolean removeSemicolonContent = true;
默认是 true 。
看一下这个属性的 set 方法:
/*** Set if ";" (semicolon) content should be stripped from the request URI.* <p>Default is "true".*/public void setRemoveSemicolonContent(boolean removeSemicolonContent) {checkReadOnly();this.removeSemicolonContent = removeSemicolonContent;}
可以看到,文档上已经标注了这个属性的功能。如果需要 ;后的内容需要被移除,就把它设置为 true 。
因此,我们需要自定义 Spring MVC 的功能,回顾过去学习的知识:
https://www.yuque.com/jaded/nql9hd/eo2dbg?inner=rQSqY
我们知道,可以使用 @Configuration + webMvcConfigurer 自定义 Spring MVC 的规则。
@Configuration 代表这个东西是容器中的一个组件,只要容器中有一个 webMvcConfigurer 的组件,然我们来定制化它就可以了。
我们来看一下 webMvcConfigurer 是什么:
显然,它是一个接口,这个里面定义了一个方法叫 configurePathMatch ,而 WebMvcAutoConfiguration 自动配置的时候,它给容器里配置了一个组件 WebMvcAutoConfigurationAdapter ,它也实现了 WebMvcConfigurer 这个接口。
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {if (this.mvcProperties.getPathmatch().getMatchingStrategy() == WebMvcProperties.MatchingStrategy.PATH_PATTERN_PARSER) {configurer.setPatternParser(new PathPatternParser());}configurer.setUseSuffixPatternMatch(this.mvcProperties.getPathmatch().isUseSuffixPattern());configurer.setUseRegisteredSuffixPatternMatch(this.mvcProperties.getPathmatch().isUseRegisteredSuffixPattern());this.dispatcherServletPath.ifAvailable((dispatcherPath) -> {String servletUrlMapping = dispatcherPath.getServletUrlMapping();if (servletUrlMapping.equals("/") && singleDispatcherServlet()) {UrlPathHelper urlPathHelper = new UrlPathHelper();urlPathHelper.setAlwaysUseFullPath(true);configurer.setUrlPathHelper(urlPathHelper);}});}
它在定义路径映射规则的时候,是默认移除内容的。
所以我们只需要在这儿放一个我们自己定义的 WebMvcConfigurer 。
我们想要自定义它,就是给容器中放一个组件,就有两种写法:
1、使用 @Bean 的方式,给容器中注册一个我们自己写的 WebMvcConfigurer 类型的组件。
2、让配置类实现 WebMvcConfigurer 这个接口,由于 JDK8 有我们接口的默认实现,所以我们无需把接口的每一个方法都实现了,我们只需要实现我们想修改的方法就可以了。
我们只需要修改 configurePathMatch 方法即可。
@Configuration(proxyBeanMethods = false)public class WebConfig /* implements WebMvcConfigurer */ {// 方法1@Beanpublic WebMvcConfigurer webMvcConfigurer() {return new WebMvcConfigurer() {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();// 不移除 ; 后面的内容,使得矩阵变量功能可以生效。urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}};}// 方法2// @Override// public void configurePathMatch(PathMatchConfigurer configurer) {// UrlPathHelper urlPathHelper = new UrlPathHelper();// urlPathHelper.setRemoveSemicolonContent(false);// configurer.setUrlPathHelper(urlPathHelper);// }}
@RequestBody
json传参、xml传参等。
样例1
URL:
http://127.0.0.1/RequestBody1
http://127.0.0.1/RequestBody2
Body:
{"name": "张三","id": 59,"age": 18}
Postman:

@RequestHeader
@CookieValue
@ModelAttribute
Servlet API
HttpServletRequest、WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId
HttpServletRequest
URL:
127.0.0.1/httpServletRequest?age=18&name=张三
控制器:
@RequestMapping(path = "httpServletRequest")public Map httpServletRequest(HttpServletRequest request) {Map<String, Object> map = new HashMap<>();map.put("age",request.getParameter("age"));map.put("name",request.getParameter("name"));map.put("allParams", request.getParameterMap());return map;}
Postman:
复杂参数
Map、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)、ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder
自定义对象参数
可以自动类型转换与格式化,可以级联封装。
