写在前面:

根据RFC3986的规范,矩阵变量应当绑定在路径变量中;

若有多个矩阵变量,应当使用英文分号;分隔("/search/stu;name=sumu;age=22");

若一个矩阵变量有多个值,应当使用英文逗号,分隔,或者命名多个重复的key中间使用英文分号;分隔(如"/search/cars;brand=Audi,Benz,BMW" 或者 "/search/cars;brand=Audi;brand=Benz;brand=BMW")。

一、矩阵变量功能默认不生效原因

1、编写Controller的业务代码

@RestController
public class ParamTestController {
    /**
     * 语法:/search/cars;low=30;brand=Audi,Benz,BMW
     */
    @GetMapping("/search/{path}")
    public Map searchCars(@MatrixVariable("low") Integer low,
                          @MatrixVariable("brand") List<String> brand,
                          @PathVariable("path") String path) {
        Map<String, Object> map = new HashMap<>();
        map.put("low", low);
        map.put("brand", brand);
        map.put("path",path);
        return map;
    }
}

2、浏览器发送 http://localhost:8080/search/cars;low=30;brand=Audi,Benz,BMW 请求,会发现报一个400错误

image-20210208172248128

3、错误原因分析:

  • 由源码可以看到WebMvc自动配置类WebMvcAutoConfiguration中的WebMvc自动配置适配器WebMvcAutoConfigurationAdapter是实现了WebMvcConfigurer接口并重写了configurePathMatch()方法
  • 由于配置路径匹配方法configurePathMatch() 需要 Url路径帮助程序UrlPathHelper 来对路径进行解析
  • UrlPathHelper类中的removeSemicolonContent变量默认值为true(即:默认删除分号内容)
  • 因为WebMvc默认删除分号内容,而矩阵变量要绑定在路径变量中并且使用英文分号;分隔,所以SpringBoot默认是禁用了矩阵变量的功能

二、如何使矩阵变量功能生效

1、由源码可知WebMvcConfigurer是一个接口,并且接口里的方法都有默认实现,所以只需重写要修改的方法即可。

2、所以有以下两者方法可以使矩阵变量功能生效:

  • 第一种:通过配置类实现WebMvcConfigurer接口并且重写configurePathMatch()方法
@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        // 将removeSemicolonContent属性设置为false(不删除分号后内容),使矩阵变量生效
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}
  • 第二种:在配置类中通过@Bean注解向容器中添加WebMvcConfigurer类型的组件
@Configuration(proxyBeanMethods = false)
public class WebConfig {

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                // 将removeSemicolonContent属性设置为false(不删除分号内容),使矩阵变量生效
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
    }
}

3、浏览器发送 http://localhost:8080/search/cars;low=30;brand=Audi,Benz,BMW 请求,即可看到矩阵变量已经生效

image-20210208185408268

三、若有多个路径变量,并且多个路径变量中具有相同的矩阵变量名时

1、编写Controller业务代码

@RestController
public class ParamTestController {
    /**
     * 语法:/search/1;age=18/5;age=20
     */
    @GetMapping("/search/{tecId}/{stuId}")
    public Map searchAge(@MatrixVariable(value = "age", pathVar = "tecId") Integer tecAge,
                          @MatrixVariable(value = "age", pathVar = "stuId") Integer stuAge) {
        Map<String, Object> map = new HashMap<>();
        map.put("tecAge", tecAge);
        map.put("stuAge", stuAge);
        return map;
    }

}

2、浏览器发送http://localhost:8080/search/1;age=18/5;age=20请求

image-20210208202702937

以上为@MatrixVariable注解的使用!

Q.E.D.


Keep going, believe in yourself, and never give up.