一、类结构

  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,具体实现看下面代码:

  1. /**
  2. * Standard way of initializing this filter.
  3. * Map config parameters onto bean properties of this filter, and
  4. * invoke subclass initialization.
  5. * @param filterConfig the configuration for this filter
  6. * @throws ServletException if bean properties are invalid (or required
  7. * properties are missing), or if subclass initialization fails.
  8. * @see #initFilterBean
  9. */
  10. @Override
  11. public final void init(FilterConfig filterConfig) throws ServletException {
  12. Assert.notNull(filterConfig, "FilterConfig must not be null");
  13. if (logger.isDebugEnabled()) {
  14. logger.debug("Initializing filter '" + filterConfig.getFilterName() + "'");
  15. }
  16.   
  17. this.filterConfig = filterConfig;
  18.  
  19. // Set bean properties from init parameters.
  20. try {
        //将该类封装成spring特有的bean形式,方便spring维护
  21. PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
  22. BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
  23. ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
  24. bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
  25. initBeanWrapper(bw);
  26. bw.setPropertyValues(pvs, true);
  27. }
  28. catch (BeansException ex) {
  29. String msg = "Failed to set bean properties on filter '" +
  30. filterConfig.getFilterName() + "': " + ex.getMessage();
  31. logger.error(msg, ex);
  32. throw new NestedServletException(msg, ex);
  33. }
  34.  
  35. // 该方法在子类中实现,我们可以到DelegatingFilterPoxy中去看看,具体完成了那些工作?
      //1、找到要代理bean的id--》targetBeanName
      //2、在spring,bean容器中找到具体被代理的filter--》delegate
  36. initFilterBean();
  37.  
  38. if (logger.isDebugEnabled()) {
  39. logger.debug("Filter '" + filterConfig.getFilterName() + "' configured successfully");
  40. }
  41. }

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

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

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

  1. @Override
  2. protected void initFilterBean() throws ServletException {
  3. synchronized (this.delegateMonitor) {
  4. if (this.delegate == null) {
  5. // If no target bean name specified, use filter name.
  6. if (this.targetBeanName == null) {
           //找到要被代理的filter在spring中配置的id
  7. this.targetBeanName = getFilterName();
  8. }
  9. // Fetch Spring root application context and initialize the delegate early,
  10. // if possible. If the root application context will be started after this
  11. // filter proxy, we'll have to resort to lazy initialization.
  12. WebApplicationContext wac = findWebApplicationContext();
  13. if (wac != null) {
           //找到具体被代理的filter
  14. this.delegate = initDelegate(wac);
  15. }
  16. }
  17. }
  18. }

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

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

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

  1. //找到被代理的filter
    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. }
  1. 到这里我们可以看出来,我们要代理的filter其实就是我们配置filter中的filter-name标签中的filterName
  1. <filter-name>filterName</filter-name>
  2.  
  3. 我们在来看看doFilter方法具体实现,该方法主要是使用被代理的filter,并调用invokeDelegate方法,
    执行被代理filter的doFilter方法,具体实现,请看下面源码:
  1. @Override
  2. public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
  3. throws ServletException, IOException {
  4.  
  5. // 得到被代理的filter
  6. Filter delegateToUse = this.delegate;
  7. if (delegateToUse == null) {
  8. synchronized (this.delegateMonitor) {
  9. if (this.delegate == null) {
  10. WebApplicationContext wac = findWebApplicationContext();
  11. if (wac == null) {
  12. throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
  13. }
  14. this.delegate = initDelegate(wac);
  15. }
  16. delegateToUse = this.delegate;
  17. }
  18. }
  19.  
  20. // 执行被代理filter的doFilter方法
  21. invokeDelegate(delegateToUse, request, response, filterChain);
  22. }
  1. invokeDelegate方法的作用就是执行被代理filterdoFilter方法
  1. protected void invokeDelegate(
  2. Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
  3. throws ServletException, IOException {
  4.  
  5. delegate.doFilter(request, response, filterChain);
  6. }
  1. 看到这里我相信大家都明白DelegatingFilterPoxy是怎么回事了吧。下面我们看看spring+shiro是如何运用这个类的
  2.  
  3. 三、运用
      首先我们看web.xml具体配置,注意<filter-name>中配置的name,以nameidspringbean配置中找得到对应的bean
  1. <!-- Shiro Security filter-->
  2.   <filter>
  3.   <filter-name>shiroFilter</filter-name>
  4.   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  5.   <init-param>
  6.   <param-name>targetFilterLifecycle</param-name>
  7.   <param-value>true</param-value>
  8.   </init-param>
  9.   </filter>
  10.   <filter-mapping>
  11.   <filter-name>shiroFilter</filter-name>
  12.   <url-pattern>/*</url-pattern>
  13.   <dispatcher>REQUEST</dispatcher>
  14.   <dispatcher>ERROR</dispatcher>
  15.   </filter-mapping>
  1.  spring对于代理filter配置
  1. <bean id="shiroFilter" class="com.auth.SpringShiroFilter"/>
  1.  
  1.   第一次写博客,存在很多不足,希望大家见谅。
  1.  

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. keydown - > keypress - > keyup

    英文输入法:   事件触发顺序:keydown - > keypress - > keyup   中文输入法:   firfox:输入触发keydown,回车确认输入触发keyup chr ...

  2. 【转】NAS 黑群晖 配置完成(不含硬盘),NAS能做什么?

    在配黑群晖前,240元入手过一个艾美佳的NAS感受了下,功能倒还合适,就是配置太老,厂家固件也停止更新了,一直不太满意. 后来经常关注NAS1,发现现在X86的NAS也很好自己DIY了,就长草了,向女 ...

  3. XML读取信息并显示

    这个类命名叫Message.cs namespace Common { public class Message { /// <summary> /// 信息编号 /// </sum ...

  4. 移动端分享到微信和QQ

    关于在H5页面实现分享到微信和QQ,当初做的时候由于没有做过这方面的功能,也查了很多资料,找了很多插件,试了很多方法,大部分的都是点击后出现一个二维码,这不 符合我的需求,所以在网上找了一个 nati ...

  5. 使用HDFS客户端java api读取hadoop集群上的信息

    本文介绍使用hdfs java api的配置方法. 1.先解决依赖,pom <dependency> <groupId>org.apache.hadoop</groupI ...

  6. 史上最难的一道Java面试题 (分析篇)

    博客园 匠心零度 转载请注明原创出处,谢谢! 无意中了解到如下题目,觉得蛮好. 题目如下: public class TestSync2 implements Runnable { int b = 1 ...

  7. 模块:time,random,os,sys

    时间模块 import time # print(time.time()) #时间戳 # print(time.strftime('%Y-%m-%d %X')) #格式化字符 # print(time ...

  8. php环境搭建工具推荐

    楼楼最近由于一系列原因,使用了几款php环境搭建工具,安装配置方便,所以在这里推荐一下.第一款是XAMPP(网址http://www.xampps.com/),软件包原来的名字是 LAMPP,但是为了 ...

  9. 旅行(LCA)

    Description N-1座桥连接着N个岛屿,每座桥都连接着某两个不同的岛屿,从任意一个岛屿都可以到达所有的其他岛屿,过桥需要缴纳人民币1元的过桥费. 由于某些不可透露的原因,Jason和他的2个 ...

  10. Fedora 下 Google-Chrome 经常出现僵尸进程的权宜办法

    对于Chrome_ProcessL 和Chrome_FileThre这两僵尸进程,估计遇到过的人都对其各种无奈吧,放任不管吧,越来越多,然后卡死,只能另开个X环境或者在其他的TTY里干掉他俩再切回去, ...