主要涉及兩個類和兩個方法。
AbstractShiroFilter類的getExecutionChain方法。
PathMatchingFilterChainResolver類的getChain方法。
// 獲取攔截器鏈流程
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,那麼只返回第一個找到的攔截器鏈。