4

前言

RFC3986定义URI的路径(Path)中可包含name-value片段,扩充了以往仅能通过查询字符串(Query String)设置可选参数的囧境。
假如现在需要设计一个用于“搜索某部门某些员工可选信息中的部分信息”的API,我们分别使用查询字符串和路径name-value方式来设计对比,看看具体效果:

  1. 查询字符串方式:/api/v1/users/optional-info?dept=321&name=joh*&fields=hometown,birth
    问题:其中的dept和name理应属于users路径,而fields则属于optional-info路径,但现在全部都要挤在查询字符串中。
  2. 路径name-value方式:/api/v1/users/depts=321;name=joh*/optional-fields/fields=hometown,birth

可以看出路径name-value的方式逻辑上更在理些。

@MatrixVariable注解属性说明

在正式开始前我们先死记硬背一下注解的属性吧。

  1. value 和属性pathVar的别名;
  2. pathVar 用于指定name-value参数所在的路径片段名称
  3. name 用于指定name-value参数的参数名
  4. required 是否为必填值,默认为false
  5. defaultValue 设置默认值

其中pathVarname到底是什么呢?请继续看后面的示例吧,准能秒懂!

启用@MatrixVariable

虽然从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) {}    

参数有多个值的玩法

若参数值不是单个,那么可以通过两种方式传递:

  1. 值之间通过逗号分隔,如dept=321,123
  2. 重名name-value对,如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个坑,请各位多加注意:

  1. 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){}   
  1. Map<String, Object[]>只能获取参数中的第一个值而已。
/*                                                                                                                                                                                                                                                                  
 请求为/Demo1/color=123,321                                                                                                                                                                                                                                         
 那么color值为123                                                                                                                                                                                                                                                   
*/                                                                                                                                                                                                                                                                  
@RequestMapping(path="/Demo1/{id}", method=RequestMethod.GET)                                                                                                                                                                                                       
public String test1(@MatrixVariable Map<String, Integer[]> color){}       
  1. 不同路径片段中出现名称相同的参数,那么必须通过pathVar标识所有相同参数所属路径,否则URI匹配失败。
// 以下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://www.cnblogs.com/fsjoh... —— 肥仔John


肥仔John
2.8k 声望1.8k 粉丝

《Petite-Vue源码剖析》作者