一、类结构

  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. 常见SQL分页方式效率比较

    结一下. 1.创建测试环境,(插入100万条数据大概耗时5分钟). ,) ) )) ),end 2.几种典型的分页sql,下面例子是每页50条,198*50=9900,取第199页数据. id id ...

  2. Python自学笔记-面向对象编程(Mr seven)

    类的成员可以分为三大类:字段.方法和属性. 一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 二.方法 方法 ...

  3. YYModel学习总结YYClassInfo(1)

    OC的run-time 机制,简直像是网络上的猫! 我在开发中很少用到,但是作为iOS开发 人家肯定会问这个东西,所以深入的学习了下. 对于 run-time的入手,YYModel的学习,简直让人美滋 ...

  4. web容器启动后自动执行程序的几种方式比较

    1.       背景 1.1.       背景介绍 在web项目中我们有时会遇到这种需求,在web项目启动后需要开启线程去完成一些重要的工作,例如:往数据库中初始化一些数据,开启线程,初始化消息队 ...

  5. Awesome Projects (汇聚全球所有🐮项目,你值得拥有)

    Awesome Projects SkySeraph Oct 2017 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www.skyseraph.c ...

  6. C++点滴20130724

    warning c4627:"#include stdafx.h":在查找预编译头使用时跳过 原因: 1.没有添加 #include "stdafx.h" 2. ...

  7. C++基础知识2

    2 变量和基本类型 2.1 基本内置类型 C++定义了一系列包括算术类型(arithmetic type)和空类型(void)在内的基本数据类型.其中算术类型包含字符,整型数,布尔值和浮点数.空类型不 ...

  8. php代码常见错误详解整理

    错误类型: 一.未使用二进制上传   代码:    Fatal error: This encoded file is corrupted. Please refer to http://www.ze ...

  9. 利用Python对文件批量重命名

    由于要用到对无序的文件进行重命名,以下写了一个脚本,进行批量进行重命名. 基本格式是  i.后缀名 ( i  循环条件下的数 ) 1 #coding:utf8 2 import os; 3 4 def ...

  10. 变量值a交换b,b交换a....

    package day01; public class Test1 { public static void main(String[] args) { //不利用其它变量时期A和B的值交换 Inte ...