web.xml 配置
<!-- 配置shiro过滤器-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
spring bean 配置
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
...
</bean>
DelegatingFilterProxy本质是一个Filter类,是怎么和spring中的bean关联起来的
// init方法在父类 GenericFilterBean 中
public class DelegatingFilterProxy extends GenericFilterBean
1、Filter初始化
// org.springframework.web.filter.GenericFilterBean.init(FilterConfig)
// 去掉一些日志
public final void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
// Set bean properties from init parameters.
try {
PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
String msg = "Failed to set bean properties on filter '" +
filterConfig.getFilterName() + "': " + ex.getMessage();
logger.error(msg, ex);
throw new NestedServletException(msg, ex);
}
// Let subclasses do whatever initialization they like.
// 交给子类DelegatingFilterProxy实现
initFilterBean();
}
// org.springframework.web.filter.DelegatingFilterProxy.initFilterBean()
@Override
protected void initFilterBean() throws ServletException {
synchronized (this.delegateMonitor) {
if (this.delegate == null) {
// If no target bean name specified, use filter name.
if (this.targetBeanName == null) {
// targetBeanName属性可以通过在web.xml中的filter中的init-param中配置。一般我们不显式的配置
this.targetBeanName = getFilterName();
}
// Fetch Spring root application context and initialize the delegate early,
// if possible. If the root application context will be started after this
// filter proxy, we'll have to resort to lazy initialization.
// 获取WebApplicationContext上下文
WebApplicationContext wac = findWebApplicationContext();
if (wac != null) {
// 初始化被代理的Filter类(ShiroFilterFactoryBean)
this.delegate = initDelegate(wac);
}
}
}
}
protected final String getFilterName() {
// 获取web.xml中配置的filter-name值
// <filter-name>shiroFilter</filter-name>对应<bean id="shiroFilter">
return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
}
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
// 根据targetBeanName从WebApplicationContext上下文中获取bean,并初始化
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
2、Filter doFilter
// org.springframework.web.filter.DelegatingFilterProxy.doFilter(ServletRequest, ServletResponse, FilterChain)
// 代理类的doFilter方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Lazily initialize the delegate if necessary.
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized (this.delegateMonitor) {
if (this.delegate == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
}
this.delegate = initDelegate(wac);
}
delegateToUse = this.delegate;
}
}
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
// 执行被代理类的doFilter方法
protected void invokeDelegate(
Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
delegate.doFilter(request, response, filterChain);
}