使用过springSecurity的朋友都知道,首先需要在web.xml进行以下配置

  1. <filter>
  2. <filter-name>springSecurityFilterChain</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. <init-param>
  5. <param-name>targetFilterLifecycle</param-name>
  6. <param-value>true</param-value>  <!-- 默认是false -->
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>springSecurityFilterChain</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. </filter-mapping>

非springSecurity用法如下:

  1. <filter>
  2. <filter-name>DelegatingFilterProxy</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. <init-param>
  5. <param-name>targetBeanName</param-name>
  6. <!-- 自定义filter -->
  7. <param-value>exportExamineFilter</param-value>
  8. </init-param>
  9. <init-param>
  10. <!-- 判断targetFilterLifecycle属性是false还是true,决定是否调用自定义类的init()、destry()方法 -->
  11. <param-name>targetFilterLifecycle</param-name>
  12. <param-value>false</param-value>
  13. </init-param>
  14. </filter>
  15. <filter-mapping>
  16. <filter-name>DelegatingFilterProxy</filter-name>
  17. <url-pattern>/*</url-pattern>
  18. </filter-mapping>

从这个配置中,可能会给我们造成一个错觉,以为DelegatingFilterProxy类就是springSecurity的入口,但其实这个类位于spring-web-3.0.5.RELEASE.jar这个jar下面,说明这个类本身是和springSecurity无关。DelegatingFilterProxy类继承于抽象类GenericFilterBean,间接地implement 了javax.servlet.Filter接口,Servlet容器在启动时,首先会调用Filter的init方法,GenericFilterBean的作用主要是可以把Filter的初始化参数自动地set到继承于GenericFilterBean类的Filter中去。在其init方法的如下代码就是做了这个事:

  1. PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
  2. BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
  3. ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
  4. bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader));
  5. initBeanWrapper(bw);
  6. bw.setPropertyValues(pvs, true);

另外在init方法中调用了initFilterBean()方法,该方法是GenericFilterBean类是特地留给子类扩展用的

  1. protected void initFilterBean() throws ServletException {
  2. // If no target bean name specified, use filter name.
  3. if (this.targetBeanName == null) {
  4. this.targetBeanName = getFilterName();
  5. }
  6. // Fetch Spring root application context and initialize the delegate early,
  7. // if possible. If the root application context will be started after this
  8. // filter proxy, we'll have to resort to lazy initialization.
  9. synchronized (this.delegateMonitor) {
  10. WebApplicationContext wac = findWebApplicationContext();
  11. if (wac != null) {
  12. this.delegate = initDelegate(wac);
  13. }
  14. }
  15. }

可以看出上述代码首先看Filter是否提供了targetBeanName初始化参数,如果没有提供则直接使用filter的name做为beanName,产生了beanName后,由于我们在web.xml的filter的name是springSecurityFilterChain,从spring的IOC容器中取出bean的代码是initDelegate方法,下面是该方法代码:

  1. protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
  2. Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
  3. if (isTargetFilterLifecycle()) {
  4. delegate.init(getFilterConfig());
  5. }
  6. return delegate;
  7. }

通过跟踪代码,发现取出的bean是org.springframework.security.FilterChainProxy,该类也是继承于GenericFilterBean,取出bean后,判断targetFilterLifecycle属性是false还是true,决定是否调用该类的init方法。这个FilterChainProxy bean实例最终被保存在DelegatingFilterProxy类的delegate属性里,

下面看一下DelegatingFilterProxy类的doFilter方法

  1. public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
  2. throws ServletException, IOException {
  3. // Lazily initialize the delegate if necessary.
  4. Filter delegateToUse = null;
  5. synchronized (this.delegateMonitor) {
  6. if (this.delegate == null) {
  7. WebApplicationContext wac = findWebApplicationContext();
  8. if (wac == null) {
  9. throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
  10. }
  11. this.delegate = initDelegate(wac);
  12. }
  13. delegateToUse = this.delegate;
  14. }
  15. // Let the delegate perform the actual doFilter operation.
  16. invokeDelegate(delegateToUse, request, response, filterChain);
  17. }

真正要关注invokeDelegate(delegateToUse, request, response, filterChain);这句代码,在下面可以看出DelegatingFilterProxy类实际是用其delegate属性即org.springframework.security.FilterChainProxy实例的doFilter方法来响应请求。

  1. protected void invokeDelegate(
  2. Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
  3. throws ServletException, IOException {
  4. delegate.doFilter(request, response, filterChain);
  5. }

以上就是DelegatingFilterProxy类的一些内部运行机制,其实主要作用就是一个代理模式的应用,可以把servlet 容器中的filter同spring容器中的bean关联起来。

此外还要注意一个DelegatingFilterProxy的一个初始化参数:targetFilterLifecycle ,其默认值为false 。 但如果被其代理的filter的init()方法和destry()方法需要被调用时,需要设置targetFilterLifecycle为true。具体可见DelegatingFilterProxy中的如下代码:

  1. protected void initFilterBean() throws ServletException {
  2. synchronized (this.delegateMonitor) {
  3. if (this.delegate == null) {
  4. // If no target bean name specified, use filter name.
  5. if (this.targetBeanName == null) {
  6. this.targetBeanName = getFilterName();
  7. }
  8. // Fetch Spring root application context and initialize the delegate early,
  9. // if possible. If the root application context will be started after this
  10. // filter proxy, we'll have to resort to lazy initialization.
  11. WebApplicationContext wac = findWebApplicationContext();
  12. if (wac != null) {
  13. this.delegate = initDelegate(wac);
  14. }
  15. }
  16. }
  17. }
  18. protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
  19. Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
  20. if (isTargetFilterLifecycle()) {    //注意这行
  21. delegate.init(getFilterConfig());
  22. }
  23. return delegate;
  24. }

DelegatingFilterProxy类的作用的更多相关文章

  1. [转]springSecurity源码分析—DelegatingFilterProxy类的作用

    使用过springSecurity的朋友都知道,首先需要在web.xml进行以下配置, <filter>  <filter-name>springSecurityFilterC ...

  2. C++虚基类的作用

    虚基类的作用     当一个基类被声明为虚基类后,即使它成为了多继承链路上的公共基类,最后的派生类中也只有它的一个备份.例如:class CBase { }:class CDerive1:virtua ...

  3. dubbo源码分析4——SPI机制_ExtensionFactory类的作用

    ExtensionFactory的源码: @SPI public interface ExtensionFactory { /** * Get extension. * * @param type o ...

  4. 关于struts2中ActionContext类的作用

    关于struts2中ActionContext类的作用有三个: 1.获取三大作用域对象及页面参数 2.是struts标签的上下文对象 3.ThreadLocal内装的就是ActionContext 怎 ...

  5. JAVA基础加强(张孝祥)_类加载器、分析代理类的作用与原理及AOP概念、分析JVM动态生成的类、实现类似Spring的可配置的AOP框架

    1.类加载器 ·简要介绍什么是类加载器,和类加载器的作用 ·Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader ...

  6. Java中Class和单例类的作用与类成员的理解

    Java中Class类的作用与深入理解 在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识.这个信息跟踪着每个对象所属的类.JVM利用运行时信息选择相应的方法执行.而保存 ...

  7. 【转载】C#中SqlCommand类的作用以及常用方法

    在C#的数据库操作过程中,SqlCommand类一般用于Sqlserver数据库的SQL语句的执行,包括Select语句.Update语句.Delete语句以及SQL存储过程等,SqlCommand的 ...

  8. 【转载】C#中SqlConnection类的作用以及常用方法

    在C#的数据库编程中,SqlConnection类主要用于连接Sqlserver数据库,使用SqlConnection类的实例方法我们可以打开Sqlserver数据库连接以及获取数据完毕后关闭数据库连 ...

  9. servlet过滤器Filter使用之DelegatingFilterProxy类

    正常情况下,我们需要添加一个过滤器,需要实现javax.servlet.Filter接口,再在web.xml中配置filter,如下: package cc.eabour.webapp.securit ...

随机推荐

  1. 二叉树(Binary Tree)相关算法的实现

    写在前面: 二叉树是比较简单的一种数据结构,理解并熟练掌握其相关算法对于复杂数据结构的学习大有裨益 一.二叉树的创建 [不喜欢理论的点我跳过>>] 所谓的创建二叉树,其实就是让计算机去存储 ...

  2. mui关闭侧滑

    一个页面有多个webview时,其中一个可以侧滑,其它禁止侧滑 document.getElementsByClassName('mui-inner-wrap')[0].addEventListene ...

  3. pageadmin CMS网站建设教程:如何修改用户密码?

    pageadmin CMS网站建设教程: 当我们想修改密码,该如何修改呢? 1. 首先,登录会员中心,会员中心的地址是在网址后面加上/member/login: 2. 例:我的网站地址是localho ...

  4. Django templates html中进行模板渲染时使用python语法的基本方式

    导包(可以在模板中导入python包进行使用): <%!import urllib%> <%! from ** import **%> 使用if for等python语句: % ...

  5. python 中 使用sys模块 获取运行脚本时在命令行输入的参数

    在python项目的开发的过程中, 经常需要运行各种python脚本, 有时候还需要根据不同的使用情况输入不同的参数, 如果每次都去编辑一下脚本那就太麻烦,太耗费时间了, 这时就可以使用Python自 ...

  6. MySQL(增删改查补充)

    SQL语句数据行操作补充             create table tb12(                 id int auto_increment primary key,       ...

  7. express form/ajax 后端获取前端数据

    -------------------2017/12/02补充:缺了一个重要条件... var bodyParser = require('body-parser');var app = expres ...

  8. Android访问网络,使用HttpURLConnection还是HttpClient?

    本文转自:http://blog.csdn.net/guolin_blog/article/details/12452307,感谢这位网友的分享,谢谢. 最近在研究Volley框架的源码,发现它在HT ...

  9. window本地运行mapreduce程序

    mapreduce的运行方式一般有两种,一是从本地导出一个jar包,在传到虚拟机上运行,这样调试起来非常的不方便,如果出现错误就需要重新导出jar包. 第二种方式是在本地直接运行,但是在运行前需要进行 ...

  10. java命令行编译和运行引用jar包的文件

    经常遇到需要添加第三方jar文件的情况.在命令行状态下要加载外部的jar文件非常麻烦,很不好搞,在网上折腾了很久终于搞定了,在这里做个笔记: 2.运行:java -Djava.ext.dirs=./l ...