一、类结构

  DelegatingFilterProxy类存在与spring-web包中,其作用就是一个filter的代理,用这个类的好处是可以通过spring容器来管理filter的生命周期,还有就是,可以通过spring注入的形式,来代理一个filter执行,如shiro,下面会说到;有上图我们可以看到,DelegatingFilterProxy类继承GenericFilterBean,间接实现了Filter这个接口,故而该类属于一个过滤器。那么就会有实现Filter中init、doFilter、destroy三个方法。

二、代理具体实现

  首先我们看init方法,我们知道当filter初始化时会执行init方法,从源码中我们可以找到具体代码,该方法在GenericFilterBean类中实现,具体功能是,将该类封装成spring特有形式的类,方便spring维护,并且调用initFilterBean方法,该方法放在子类(DelegatingFilterProxy)实现,该方法主要目的是,找到在spring中维护的目标filter,具体实现看下面代码:

/**
* Standard way of initializing this filter.
* Map config parameters onto bean properties of this filter, and
* invoke subclass initialization.
* @param filterConfig the configuration for this filter
* @throws ServletException if bean properties are invalid (or required
* properties are missing), or if subclass initialization fails.
* @see #initFilterBean
*/
@Override
public final void init(FilterConfig filterConfig) throws ServletException {
Assert.notNull(filterConfig, "FilterConfig must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Initializing filter '" + filterConfig.getFilterName() + "'");
}
  
this.filterConfig = filterConfig; // Set bean properties from init parameters.
try {
    //将该类封装成spring特有的bean形式,方便spring维护
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);
} // 该方法在子类中实现,我们可以到DelegatingFilterPoxy中去看看,具体完成了那些工作?
  //1、找到要代理bean的id--》targetBeanName
  //2、在spring,bean容器中找到具体被代理的filter--》delegate
initFilterBean(); if (logger.isDebugEnabled()) {
logger.debug("Filter '" + filterConfig.getFilterName() + "' configured successfully");
}
}

initFilterBean()该方法主要完成两个功能:

1、找到被代理类在spring中配置的id并赋值给targetBeanName。

2、使用找到的id从spring容器中找到具体被代理的类,并赋值给delegate

@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) {
       //找到要被代理的filter在spring中配置的id
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 wac = findWebApplicationContext();
if (wac != null) {
       //找到具体被代理的filter
this.delegate = initDelegate(wac);
}
}
}
}

getFilterName()该方法的作用是,获取被代理的filter在spring中配置的id

protected final String getFilterName() {
  //找到被代理filter在spring中配置的id
return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
}

initDelegate()该方法的作用是,从spring容器中获取到具体被代理的filter 

//找到被代理的filter
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
到这里我们可以看出来,我们要代理的filter其实就是我们配置filter中的filter-name标签中的filterName了
<filter-name>filterName</filter-name>

我们在来看看doFilter方法具体实现,该方法主要是使用被代理的filter,并调用invokeDelegate方法,
执行被代理filter的doFilter方法,具体实现,请看下面源码:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException { // 得到被代理的filter
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;
}
} // 执行被代理filter的doFilter方法
invokeDelegate(delegateToUse, request, response, filterChain);
}
invokeDelegate方法的作用就是执行被代理filter的doFilter方法
protected void invokeDelegate(
Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException { delegate.doFilter(request, response, filterChain);
}
看到这里我相信大家都明白DelegatingFilterPoxy是怎么回事了吧。下面我们看看spring+shiro是如何运用这个类的

三、运用
  首先我们看web.xml具体配置,注意<filter-name>中配置的name,以name为id在spring的bean配置中找得到对应的bean
<!-- Shiro Security filter-->
  <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>ERROR</dispatcher>
  </filter-mapping>
 spring对于代理filter配置
<bean id="shiroFilter" class="com.auth.SpringShiroFilter"/>

  第一次写博客,存在很多不足,希望大家见谅。
 

org.springframework.web.filter.DelegatingFilterProxy的作用的更多相关文章

  1. org.springframework.web.filter.DelegatingFilterProxy的理解

    org.springframework.web.filter.DelegatingFilterProxy可以将filter交给spring管理. 我们web.xml中配置filter时一般采用下面这种 ...

  2. Spring管理过滤器:org.springframework.web.filter.DelegatingFilterProxy

    配置web.xml <filter>        <filter-name>springSecurityFilterChain</filter-name>     ...

  3. org.springframework.web.filter.CharacterEncodingFilter

    感谢:http://blog.csdn.net/heidan2006/article/details/3075730 很简单很实用的一个过滤器,当前台JSP页面和JAVA代码中使用了不同的字符集进行编 ...

  4. java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter

    今天在用git merge 新代码后报了如下错误:java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterE ...

  5. 通过org.springframework.web.filter.CharacterEncodingFilter定义Spring web请求的编码

    通过类org.springframework.web.filter.CharacterEncodingFilter,定义request和response的编码.具体做法是,在web.xml中定义一个F ...

  6. java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast to javax.servlet.Filter

    java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast ...

  7. SpringMVC(四):@RequestMapping结合org.springframework.web.filter.HiddenHttpMethodFilter实现REST请求

    1)REST具体表现: --- /account/1  HTTP GET       获取id=1的account --- /account/1  HTTP DELETE 删除id=1的account ...

  8. Caused by: java.lang.ClassNotFoundException: org.springframework.web.filter.FormContentFilter

    又是一个报错,我写代码真的是可以,所有的bug都会被我遇到,所有的问题我都能踩一遍,以前上学的时候同学就喜欢问我问题,因为他们遇到的问题,我早就遇到了......... 看看报错内容: 2019-04 ...

  9. SpringMVC------报错:java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter

    详细信息: java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter 严重: E ...

随机推荐

  1. ImageSharp一个专注于NetCore平台图像处理的开源项目

    今天大家分享的是一个专注于NetCore平台图像处理的开源项目,老实说为这篇文章取名字想了5分钟,可能是词穷亦或是想更好的表达出这款开源项目的作用:这个项目在图像处理方面有很多功能,如:缩放,裁剪,绘 ...

  2. 【MVC】会员注册/登录,普通验证,会员名是否注册Ajax验证以及会员邮件验证实现原理

    using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentM ...

  3. JavaWeb之response响应中文乱码问题

    response向页面响应中文乱码问题  字节流 * 有可能乱码,与中文转换成字节数组.浏览器打开的默认字符编码有关 * 解决方式:将中文转成字节数组的时候和浏览器默认打开的时候采用的字符集一致 re ...

  4. javascript中关于this指向问题详解

      前  言 LiuDaP 在前端的学习中,我们必然要用到js,js可以说是前端必不可少的的东西.在学习js的过程中,我们会经常用到this这个东西,而this的指向问题就变得尤为重要.今天正好有空闲 ...

  5. PHP二维关联数组的遍历方式

    采用foreach循环对二维索引数组进行遍历,相对来讲速度更快,效率更高,foreach循环是PHP中专门用来循环数组的.实例也相对简单,多加练习,想清楚程序运行逻辑即可. <?php $arr ...

  6. java基础--static关键字的使用

    一.static关键字的作用 使类成员完全独立于该类的任何对象.通常情况下,类成员必须通过它的类的对象访问,但是被static修饰的成员,能够被自己访问,而不必引用特定的实例. 一旦一个成员被声明为s ...

  7. Windows 10 16251 添加的 api

    本文主要讲微软最新的sdk添加的功能,暂时还不能下载,到 7月29 ,现在可以下载是 16232 ,支持Neon效果 实际上设置软件最低版本为 16232 就自动支持 Neon 效果. 主要添加了 A ...

  8. MySQL中字段类型为timestamp的小坑

    之前遇到过一个MySQL的字段为timestamp类型的小坑. MySQL中一个字段存储时间类型数据的时候,该字段的类型如果为timestamp类型的话,最多只能存储到2038-01-19 11:14 ...

  9. (转)spring事务管理几种方式

    转自:http://blog.csdn.net/jeamking/article/details/43982435 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置 ...

  10. OSW 快速安装部署

    关于在运行Oracle的环境下部署OSW具体好处不再多说,只需要知晓,在日常Oracle定位各类故障,osw的数据可以协助诊断问题.MOS很多文档也多处提到需要osw的监控数据. 一.前期资料准备 1 ...