Spring源碼解析 - AntPathMatcher


最近在看SpringMVC的源碼,發現request分發時,路徑匹配最后是委托給AntPathMatcher實現的.索性看看吧.

文章摘要:

  1. ant匹配規則

  2. PathMatcher接口

  3. 通過測試用例看AntPathMatcher的使用

 

ant匹配規則

AntPathMatcher如名使用的ant 的匹配規則,我們先看看吧.

  字符wildcard    描述

   ?         匹配一個字符

   *         匹配0個及以上字符

   **         匹配0個及以上目錄directories

看幾個官方的例子吧:

  com/t?st.jsp -             匹配: com/test.jsp  ,  com/tast.jsp  ,  com/txst.jsp
  com/*.jsp -             匹配: com文件夾下的全部.jsp文件
  com/**/test.jsp -          匹配: com文件夾和子文件夾下的全部.jsp文件,
  org/springframework/**/*.jsp -    匹配: org/springframework文件夾和子文件夾下的全部.jsp文件
  org/**/servlet/bla.jsp -       匹配: org/springframework/servlet/bla.jsp  ,  org/springframework/testing/servlet/bla.jsp  ,  org/servlet/bla.jsp

 

PathMatcher接口

主要是判斷是否匹配pattern,並解析出path中的參數

 1 package org.springframework.util;
 2 
 3 public interface PathMatcher {
 4 
 5     /**
 6      * 判斷傳入的path是否可以作為pattern使用
 7      */
 8     boolean isPattern(String path);
 9 
10     /**
11      * 使用pattern匹配path
12      */
13     boolean match(String pattern, String path);
14 
15     /**
16      * 如名,是否開始部分匹配
17      */
18     boolean matchStart(String pattern, String path);
19 
20     /**
21      * 提取path中匹配到的部分,如pattern(myroot/*.html),path(myroot/myfile.html),返回myfile.html
22      */
23     String extractPathWithinPattern(String pattern, String path);
24 
25     /**
26      * 提取path中匹配到的部分,只是這邊還需跟占位符配對為map,
27      * 如pattern(/hotels/{hotel}),path(/hotels/1),解析出"hotel"->"1"
28      */
29     Map<String, String> extractUriTemplateVariables(String pattern, String path);
30 
31     /**
32      * 提供比較器
33      */
34     Comparator<String> getPatternComparator(String path);
35 
36     /**
37      * 合並pattern,pattern1然后pattern2
38      */
39     String combine(String pattern1, String pattern2);
40 
41 }

 

 

通過測試用例看AntPathMatcher的使用

一看測試用例,瞬間服了,人家開發真是規范.

人家整這么規范,還是有空直接看源碼好了.這邊挑幾個簡單的例子看看就好

1. match 跟 matchStart 的差異,這個我們在測試用例看下面的情況會比較明確

  這邊的代碼,我截取了一小部分

 1 package org.springframework.util;
 2 public class AntPathMatcherTests {
 3     @Test
 4     public void match() {
 5         // ...
 6         assertFalse(pathMatcher.match("/x/x/**/bla", "/x/x/x/"));
 7         // ...
 8     }
 9     @Test
10     public void withMatchStart() {
11         // ...
12         assertTrue(pathMatcher.matchStart("/x/x/**/bla", "/x/x/x/"));
13         // ...
14     }
15 }

 

2. extractPathWithinPattern,代碼很清楚,不廢話

 1 package org.springframework.util;
 2 public class AntPathMatcherTests {
 3     @Test
 4     public void extractPathWithinPattern() throws Exception {
 5         // ...
 6         assertEquals("", pathMatcher.extractPathWithinPattern("/docs/commit.html", "/docs/commit.html"));
 7         assertEquals("cvs/commit", pathMatcher.extractPathWithinPattern("/docs/*", "/docs/cvs/commit"));
 8         assertEquals("docs/cvs/commit", pathMatcher.extractPathWithinPattern("/d?cs/*", "/docs/cvs/commit"));
 9         // ...
10     }
11 }

3. extractUriTemplateVariables

 1 package org.springframework.util;
 2 public class AntPathMatcherTests {
 3     @Test
 4     public void extractUriTemplateVariables() throws Exception {
 5         Map<String, String> result = pathMatcher.extractUriTemplateVariables("/hotels/{hotel}", "/hotels/1");
 6         assertEquals(Collections.singletonMap("hotel", "1"), result);
 7         // ...
 8         result = pathMatcher.extractUriTemplateVariables("/{page}.*", "/42.html");
 9         assertEquals(Collections.singletonMap("page", "42"), result);
10         // ...
11     }
12     /**
13      * SPR-7787
14      */
15     @Test
16     public void extractUriTemplateVarsRegexQualifiers() {
17         Map<String, String> result = pathMatcher.extractUriTemplateVariables(
18                 "{symbolicName:[\\p{L}\\.]+}-sources-{version:[\\p{N}\\.]+}.jar",
19                 "com.example-sources-1.0.0.jar");
20         assertEquals("com.example", result.get("symbolicName"));
21         assertEquals("1.0.0", result.get("version"));
22         // ...
23     }
24 }

4. combine

 1 package org.springframework.util;
 2 public class AntPathMatcherTests {
 3     @Test
 4     public void combine() {
 5         // ...
 6         assertEquals("/hotels", pathMatcher.combine("/hotels", null));
 7         assertEquals("/hotels/booking", pathMatcher.combine("/hotels/*", "/booking"));
 8         assertEquals("/hotels/**/booking", pathMatcher.combine("/hotels/**", "booking"));
 9         assertEquals("/hotels/**/booking", pathMatcher.combine("/hotels/**", "/booking"));
10         assertEquals("/hotels/booking", pathMatcher.combine("/hotels", "/booking"));
11         assertEquals("/hotels/{hotel}", pathMatcher.combine("/hotels/*", "{hotel}"));
12         assertEquals("/hotels/**/{hotel}", pathMatcher.combine("/hotels/**", "{hotel}"));
13         assertEquals("/hotels/*/booking/{booking}", pathMatcher.combine("/hotels/*/booking", "{booking}"));
14     }
15 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM