SpringMVC的接口URL匹配
AntPathMatcher
spring-core模块中的org.springframework.util.AntPathMatcher提供URL匹配的方法,使用它可以将Http请求对象中的URI与系统暴露的接口URL做匹配。而系统中暴露了哪些接口,需要org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping提供映射数据。
RequestMappingHandlerMapping
此类中保存了当前系统中暴露的所有接口URL和Java方法的映射,通过它,可以获取到所有暴露的URL,也可以获取到对应的Java方法的相关信息,比如注解、签名、参数之类的信息,这对我们扩展自己的逻辑很有用。
UrlPathHelper
在进行匹配之前,需要使用org.springframework.web.util.UrlPathHelper获取请求对象中的URI,否则,你直接通过HttpServletRequest对象中的getRequestURI()方法获取到的URI会有些问题,比如请求对象中的URI获取到可能是"/app//test",这种多打了几个斜线的URI一样是可以匹配到SpringMVC暴露的接口的。所以需要UrlPathHelper提供的getRequestUri(),才是去掉了多余斜线的。这样才能在AntPathMatcher中成功匹配。
package com.penguin.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Set;
@Component
public class Test implements Filter {
private RequestMappingHandlerMapping rmhMapping;
@Autowired
public void setRmhMapping(RequestMappingHandlerMapping rmhMapping) {
this.rmhMapping = rmhMapping;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
/**
* 在过滤器中对请求路径进行一些判断
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String requestUri = rmhMapping.getUrlPathHelper().getRequestUri(request);
Map<RequestMappingInfo, HandlerMethod> handlerMethods = rmhMapping.getHandlerMethods();
boolean success = false;
for (RequestMappingInfo rmInfo : handlerMethods.keySet()) {
Set<String> patterns = rmInfo.getPatternsCondition().getPatterns();
for (String pattern : patterns) {
if (rmhMapping.getPathMatcher().match(pattern, requestUri)) {
System.out.println(String.format("匹配成功:pattern:[%s], requestUri:[%s]", pattern, requestUri));
success = true;
break;
}
}
}
System.out.println("过滤器执行结果:" + success);
}
@Override
public void destroy() {}
}
上述代码表明,RequestMappingHandlerMapping对象是通过Spring的自动注入赋值的,rmhMapping.getUrlPathHelper()返回UrlPathHelper对象,rmhMapping.getPathMatcher()返回AntPathMatcher。