RFC3986定义URI的路径(Path)中可包含name-value片段,扩充了以往仅能通过查询字符串(Query String)设置可选参数的囧境。
假如现在需要设计一个用于“搜索某部门某些员工可选信息中的部分信息”的API,我们分别使用查询字符串和路径name-value方式来设计对比,看看具体效果:
/api/v1/users/optional-info?dept=321&name=joh*&fields=hometown,birth
问题:其中的dept和name理应属于users路径,而fields则属于optional-info路径,但现在全部都要挤在查询字符串中。/api/v1/users/depts=321;name=joh*/optional-fields/fields=hometown,birth
可以看出路径name-value的方式逻辑上更在理些。在正式开始前我们先死记硬背一下注解的属性吧。
value
和属性pathVar
的别名;pathVar
用于指定name-value参数所在的路径片段名称name
用于指定name-value参数的参数名required
是否为必填值,默认为falsedefaultValue
设置默认值其中pathVar
和name
到底是什么呢?请继续看后面的示例吧,准能秒懂!
虽然从Spring 3.2就已经支持@MatrixVariable
特性,但直至现在其依然为默认禁用的状态。我们需要手工配置开启才能使用。
@Configuration
public class SpringBootConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
注意:多个name-value间以分号分隔,如name=joh*;dept=321
。
/*
1. 获取单个路径片段中的参数
请求URI为 /Demo2/66;color=red;year=2020
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test1(@PathVariable String id, @MatrixVariable String color, @MatrixVariable String year){}
/*
2. 获取单个路径片段中的参数
请求URI为 /Demo2/color=red;year=2020
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test2(@MatrixVariable String color, @MatrixVariable String year){}
/*
3. 获取不同路径片段中的参数
请求URI为 /Demo2/66;color=red;year=2020/pets/77;color=blue;year=2019
*/
@RequestMapping(path="/Demo2/{id1}/pets/{id2}", method=RequestMethod.GET)
public String test3(@PathVariable String id1, @PathVariable String id2,
@MatrixVariable(name="color", pathVar="id1") String color1, @MatrixVariable(name="year", pathVar="id1") String year1,
@MatrixVariable(name="color", pathVar="id2") String color2, @MatrixVariable(name="year", pathVar="id2") String year2){}
/*
4. 获取不同路径片段中的参数
请求URI为 /Demo2/color=red;year=2020/pets/77;color=blue;year=2019
*/
@RequestMapping(path="/Demo2/{id1}/pets/{id2}", method=RequestMethod.GET)
public String test4(@PathVariable String id2,
@MatrixVariable(name="color", pathVar="id1") String color1, @MatrixVariable(name="year", pathVar="id1") String year1,
@MatrixVariable(name="color", pathVar="id2") String color2, @MatrixVariable(name="year", pathVar="id2") String year2){}
/*
5. 通过Map获取所有或指定路径下的所有参数
*/
@RequestMapping(path="/Demo3/{id1}/pets/{id2}", method=RequestMethod.GET)
public String test5(@MatrixVariable Map<String, Object> all, @MatrixVariable(pathVar="id1") Map<String, Object> mapId1) {}
若参数值不是单个,那么可以通过两种方式传递:
dept=321,123
dept=321;dept=123
/*
请求为/Demo1/color=123,321
那么color值为123,321
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test1(@MatrixVariable Integer[] color){}
/*
请求为/Demo1/color=123;color=321
那么color值为123,321
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test1(@MatrixVariable Integer[] color){}
在参数多值的情况下还有如下3个坑,请各位多加注意:
String
参数类型可以接受通过逗号和通过重名name-value传递的所有值,而其它类型只能获取第一个值。/*
请求为/Demo1/color=123,321
那么color值为123,321
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test1(@MatrixVariable String color){}
/*
请求为/Demo1/color=123;color=321
那么color值为123,321
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test1(@MatrixVariable String color){}
/*
请求为/Demo1/color=123;color=321
那么color值为123
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test1(@MatrixVariable Integer color){}
Map<String, Object[]>
只能获取参数中的第一个值而已。/*
请求为/Demo1/color=123,321
那么color值为123
*/
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)
public String test1(@MatrixVariable Map<String, Integer[]> color){}
// 以下handler仅标识第二个参数的pathVar,而没有标识第一个,那么也是会匹配失败的。
@RequestMapping(path="/Demo2/{id1}/pets/{id2}", method=RequestMethod.GET)
public String test2(@MatrixVariable String color, @MatrixVariable(name="color", pathVar="id2") String color2){}
今天就写到这里吧,后续会有更多Spring Boot的分享,请大家多关注我哦!
转载请注明来自: https://cloud.tencent.com/developer/article/1776808 —— 肥仔John