一 点睛
主要涉及两个类和两个方法。
AbstractShiroFilter类的getExecutionChain方法。
PathMatchingFilterChainResolver类的getChain方法。
二 getExecutionChain方法
// 获取拦截器链流程
protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
FilterChain chain = origChain;
// 获取相应的FilterChainResolver,默认使用 PathMatchingFilterChainResolver 进行解析
FilterChainResolver resolver = getFilterChainResolver();
if (resolver == null) {
log.debug("No FilterChainResolver configured. Returning original FilterChain.");
return origChain;
}
// 通过FilterChainResolver根据当前请求解析到新的FilterChain拦截器链
FilterChain resolved = resolver.getChain(request, response, origChain);
if (resolved != null) {
log.trace("Resolved a configured FilterChain for the current request.");
chain = resolved;
} else {
log.trace("No FilterChain configured for the current request. Using the default.");
}
return chain;
}
三 getChain方法
// 它默认是根据当前请求的 URL 获取相应的拦截器链,使用 Ant 模式进行 URL 匹配
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
// 1、首先获取拦截器链管理器,默认使用 DefaultFilterChainManager 进行拦截器链的管理
FilterChainManager filterChainManager = getFilterChainManager();
if (!filterChainManager.hasChains()) {
return null;
}
// 2、接着获取当前请求的URL
String requestURI = getPathWithinApplication(request);
// 3、循环拦截器管理器中的拦截器定义(拦截器链的名字就是URL模式)
for (String pathPattern : filterChainManager.getChainNames()) {
// 4、如果当前URL匹配拦截器名字(URL模式)
if (pathMatches(pathPattern, requestURI)) {
if (log.isTraceEnabled()) {
log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "]. " +
"Utilizing corresponding filter chain...");
}
// 5、返回该URL模式定义的拦截器链
return filterChainManager.proxy(originalChain, pathPattern);
}
}
return null;
}
这个实现有点小问题:如果多个拦截器链都匹配了当前请求 URL,那么只返回第一个找到的拦截器链。