使用过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. 在TFS中使用Git Tags(标签或标记),实现代码的版本管理

    一.概述: 与TFVC中标记(Label)一样,Git的标签(Tag)也是TFS系统的代码管理中非常重要的一个版本管理工具.使用标签,我们可以每个时间点的代码注上一个通俗.并且容易记忆的名称(例如标签 ...

  2. C#内存释放(垃圾回收)

    今天写了个很小的程序,程序的功能仅仅是截图,但是如果长时间开启并截图的时候,程序会变的很大,从刚开始的运行在任务管理器中只有十几K大小,运行一段时间后在任务管理器中看到程序可以达到1G或2G甚至更大: ...

  3. Asp .Net Core网页数据爬取笔记

    突然要用到地区数据,想到以前用python的Scrapy框架写过一个爬虫,于是打算直接去国家统计局把最新的地区数据抓取回来.本想只需要copy一下以前的代码,就可以得到新鲜出炉的数据,谁知打开以前的项 ...

  4. .Net 百度经纬度转高德

    1.需求 由于我们项目里面的经纬坐标是百度的,而对接的第三方需要的是高德的经纬坐标,两者之间是有位差区别的,不能直接使用,我们需要通过一个算法将百度经纬度转化为高德经纬度,在百度官网上,有java算法 ...

  5. JavaScript模块化与esl.js

    2016-2-2 晚上 松合时代公寓中 1.前端为什么需要模块化? http://requirejs.org/docs/why.html 2.https://github.com/ecomfe/esl ...

  6. 【文文殿下】【BZOJ4804】欧拉心算

    题解 显然有 \(ans=\sum _{i=1} ^{n} \lfloor \frac{n}{i} \rfloor \sum _{d|i} \mu(d) \phi (\frac{i}{d})\) 前半 ...

  7. elasticsearch索引目录设置

    path.data and path.logs If you are using the .zip or .tar.gz archives, the data and logs directories ...

  8. CSS3盒子模型(中)

    在CSS盒子模型(上)讲到了盒子模型的边框,内外边距,外边距合并等知识,接下来要总结的是盒子模型的布局常用到的一些CSS属性,比如:float.position等知识. 盒子模型布局稳定性 开始学习盒 ...

  9. servlet中request和response

    一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象 ...

  10. day 43 mysql 学习 以及pymysql 学习

    前情提要: 本次主要学习sql 的难点, 多表查询以及连接python  一:多表关联 >多表查询的缺点 二:单表的连表查询[自关联查询] 三:子查询 >主查询 >主查询 >主 ...