SpringBoot魔法堂:@MatrixVariable引數註解使用詳解

^_^肥仔John發表於2021-01-16

前言

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/fsjohnhuang/p/14284988.html —— 肥仔John

相關文章