下面我们来看一个请求
/cars/{path;low=34;brand=byd,aodi,bc}
以 ; 结尾的请求就是矩阵变量
有这样一个面试题,页面开发,如果把cookie 禁用掉,session 里面的内容怎么找到
- cookie 和 session 的机制就是,session里面保存一个k-v的值,然后每个人都有一个jsessionid,这个jsessionid 会被保存在cookie里面,每次用户发送请求cookie 都会携带jsessionid ,如果把cookie 禁用掉,我们要获取session 的k获取v ,肯定要通过jsessionid来拿到这个session对象,但是jsession有保存在cookie 所以无法从session对象的v
- 这里我们可以使用 矩阵变量来获取 session 如 /user;jessionid=xxx 用过url 重写,把cookie的值使用矩阵变量的方式进行传递
如下有这样一个请求
前端
<a href="/cars/sales;low=23;brand=byd,ad,bc">矩阵变量</a>
后台处理控制器
@GetMapping(value = "/cars/sales")
public String cars(@MatrixVariable("low") Integer low,
@MatrixVariable("brand") List<String> brands) {
return "low = " + low + "--- brands=" + brands;
}
运行测试结果
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Mar 26 13:56:23 CST 2021
There was an unexpected error (type=Bad Request, status=400).
Missing matrix variable 'low' for method parameter of type Integer
org.springframework.web.bind.MissingMatrixVariableException: Missing matrix variable 'low' for method parameter of type Integer
- 错误的原因 springboot 默认是禁用了矩阵变量的功能,我们需要手动开启,这就需要我们定制化springboot的组件
源码解读
WebMvcAutoConfiguration 类的 configurePathMatch方法内部有这样一个处理
@Override
public 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 urlPathHelper = new UrlPathHelper(); 创建了一个UrlPathHelper 进行解析 其中在 UrlPathHelper类中有这样一个属性 removeSemicolonContent 默认为true 这个属性的意思就是 要不要移除分号内容
- 所以我们要自定义有以下2种写法 1是实现 WebMvcConfigurer 的 configurePathMatch 2是 @Bean 的方式给容器放入一个WebMvcConfigurer
这里我主要使用实现 WebMvcConfigurer 的方式
新增配置类 MyConfiguration 代码如下
@Configuration(proxyBeanMethods = false) //每次从容器中获取bean 是否为同一个 如果为false 则每次获取的实例都是不同的
public class MyConfiguration implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
//不移除举证变量后面的内容
urlPathHelper.setRemoveSemicolonContent(false);
urlPathHelper.setAlwaysUseFullPath(true);
configurer.setUrlPathHelper(urlPathHelper);
}
}
我们加入配置文件后再次访问这个请求运行如下
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Mar 26 14:15:18 CST 2021
There was an unexpected error (type=Not Found, status=404).
No message available
- 这次发现404 没有找到这个请求,这个主要是因为 矩阵变量主要绑定在 路径变量上的
- 修改 控制器里面的代码如下
@GetMapping(value = "/cars/{path}")
public String cars(@MatrixVariable("low") Integer low,
@MatrixVariable("brand") List<String> brands,
@PathVariable("path") String path) {
return "low = " + low + "--- brands=" + brands + "----path=" + path;
}
再次测试如下
low = 23--- brands=[byd, ad, bc]----path=sales
- 成功从控制器拿到响应的数据
扩展
如果请求为 user/1;age=20/2;age=40 这样的请求后台如何进行处理呢
前端请求
<a href="user/1;age=20/2;age=40">矩阵变量2</a>
后台处理器
@GetMapping("/user/{boosId}/{empid}")
public String getUser1(@MatrixVariable(value = "age", pathVar = "boosId") Integer boosId,
@MatrixVariable(value = "age", pathVar = "empid") Integer empid) {
return "get user boosId=" + boosId + "----empid=" + empid;
}
- 使用 MatrixVariable 的 pathVar 来确认这个请求到底是第一个参数的age 还是第二个参数的age 使用 pathVar 和 val 的名称来唯一确认一个值