SpringSecurity - 基础概念之 RequestMatcher

时间:2025-04-11 13:49:32
public final class AntPathRequestMatcher implements RequestMatcher, RequestVariablesExtractor { private static final String MATCH_ALL = "/**"; private final Matcher matcher; private final String pattern; private final HttpMethod httpMethod; private final boolean caseSensitive; private final UrlPathHelper urlPathHelper; // 利用面向对象的多态特性定义了几个构造器 /** * Creates a matcher with the supplied pattern which will match the specified Http * method * @param pattern the ant pattern to use for matching * @param httpMethod the HTTP method. The {@code matches} method will return false if * the incoming request doesn't have the same method. * @param caseSensitive true if the matcher should consider case, else false * @param urlPathHelper if non-null, will be used for extracting the path from the * HttpServletRequest */ public AntPathRequestMatcher(String pattern, String httpMethod, boolean caseSensitive, UrlPathHelper urlPathHelper) { Assert.hasText(pattern, "Pattern cannot be null or empty"); this.caseSensitive = caseSensitive; if (pattern.equals(MATCH_ALL) || pattern.equals("**")) { pattern = MATCH_ALL; this.matcher = null; } else { // If the pattern ends with {@code /**} and has no other wildcards or path // variables, then optimize to a sub-path match if (pattern.endsWith(MATCH_ALL) && (pattern.indexOf('?') == -1 && pattern.indexOf('{') == -1 && pattern.indexOf('}') == -1) && pattern.indexOf("*") == pattern.length() - 2) { this.matcher = new SubpathMatcher(pattern.substring(0, pattern.length() - 3), caseSensitive); } else { this.matcher = new SpringAntMatcher(pattern, caseSensitive); } } this.pattern = pattern; this.httpMethod = StringUtils.hasText(httpMethod) ? HttpMethod.valueOf(httpMethod) : null; this.urlPathHelper = urlPathHelper; } /** * Returns true if the configured pattern (and HTTP-Method) match those of the * supplied request. * @param request the request to match against. The ant pattern will be matched * against the {@code servletPath} + {@code pathInfo} of the request. */ @Override public boolean matches(HttpServletRequest request) { if (this.httpMethod != null && StringUtils.hasText(request.getMethod()) && this.httpMethod != valueOf(request.getMethod())) { return false; } if (this.pattern.equals(MATCH_ALL)) { return true; } String url = getRequestPath(request); return this.matcher.matches(url); } ... @Override public MatchResult matcher(HttpServletRequest request) { if (this.matcher == null || !matches(request)) { return MatchResult.notMatch(); } String url = getRequestPath(request); return MatchResult.match(this.matcher.extractUriTemplateVariables(url)); } private String getRequestPath(HttpServletRequest request) { if (this.urlPathHelper != null) { return this.urlPathHelper.getPathWithinApplication(request); } String url = request.getServletPath(); String pathInfo = request.getPathInfo(); if (pathInfo != null) { url = StringUtils.hasLength(url) ? url + pathInfo : pathInfo; } return url; } public String getPattern() { return this.pattern; } // 重写了 hasCode、equals、toString 方法 // 定义了一个 Matcher 接口用于判断请求路径是否匹配,RequestMatcher 的入参是 HttpServletRequest private interface Matcher { boolean matches(String path); Map<String, String> extractUriTemplateVariables(String path); } // 下面是两个 Matcher 的实现类, private static final class SpringAntMatcher implements Matcher { ... } /** * Optimized matcher for trailing wildcards */ private static final class SubpathMatcher implements Matcher { ... } }