为了满足Shiro的分布式登录需求, 系统学习了Shiro的组件及流程, 但对于shiroFilter式如何注入到容器的存在疑问, 于是重新梳理了SpingWeb Filter的加载及调用。
一 基础组件认知
1 ApplicationFilterChain 是过滤器的起始对象,生命周期与一次请求的生命周期相同,保存着对应urlMaping的过滤器和全局过滤器, 主要成员变量如下:
private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;
public static final int INCREMENT = 10;
//保存所有的filter
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
//当前执行的Filter
private int pos = 0;
//filter数量
private int n = 0;
private Servlet servlet = null;
private boolean servletSupportsAsync = false;
private static final StringManager sm;
private static final Class<?>[] classType;
private static final Class<?>[] classTypeUsedInService;
2 ApplicationFilterFactory
ApplicationFilterChain 工厂类, 根据request生成ApplicationFilterChain
读取请求配置的Filter,生成对应的ApplicationFilterChain
ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
public static ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) {
if (servlet == null) {
return null;
} else {
ApplicationFilterChain filterChain = null;
if (request instanceof Request) {
Request req = (Request)request;
if (Globals.IS_SECURITY_ENABLED) {
filterChain = new ApplicationFilterChain();
} else {
filterChain = (ApplicationFilterChain)req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
req.setFilterChain(filterChain);
}
}
} else {
filterChain = new ApplicationFilterChain();
}
filterChain.setServlet(servlet);
filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
StandardContext context = (StandardContext)wrapper.getParent();
FilterMap[] filterMaps = context.findFilterMaps();
if (filterMaps != null && filterMaps.length != 0) {
DispatcherType dispatcher = (DispatcherType)request.getAttribute("org.apache.catalina.core.DISPATCHER_TYPE");
String requestPath = null;
Object attribute = request.getAttribute("org.apache.catalina.core.DISPATCHER_REQUEST_PATH");
if (attribute != null) {
requestPath = attribute.toString();
}
String servletName = wrapper.getName();
FilterMap[] var10 = filterMaps;
int var11 = filterMaps.length;
int var12;
FilterMap filterMap;
ApplicationFilterConfig filterConfig;
for(var12 = 0; var12 < var11; ++var12) {
filterMap = var10[var12];
if (matchDispatcher(filterMap, dispatcher) && matchFiltersURL(filterMap, requestPath)) {
filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());
if (filterConfig != null) {
filterChain.addFilter(filterConfig);
}
}
}
var10 = filterMaps;
var11 = filterMaps.length;
for(var12 = 0; var12 < var11; ++var12) {
filterMap = var10[var12];
if (matchDispatcher(filterMap, dispatcher) && matchFiltersServlet(filterMap, servletName)) {
filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());
if (filterConfig != null) {
filterChain.addFilter(filterConfig);
}
}
}
return filterChain;
} else {
return filterChain;
}
}
}
二 执行流程
org.apache.catalina.core.StandardWrapperValve#invoke
-> ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
-> filterChain.doFilter(request.getRequest(), response.getResponse());
->org.apache.catalina.core.ApplicationFilterChain#internalDoFilter
->filter.doFilter(request, response, this);
->chain.doFilter(request, response); //在调用第3步,成链式调用