一、类结构

  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. Python实战之用类的静态方法实现登录验证

    #!usr/bin/env Python3 # -*-coding:utf-8-*- __author__="William" #define a class,just to le ...

  2. winwebmail设置能用foxmail收发邮件

    域名解析注意 1.首先做A记录解析: 主机名处:输入 mail IP地址处:输入IP地址 2.做MX记录: 主机名处: 大都保持空输入,什么也不用输入   TTL:默认就可以了,不需要改动 优先级:一 ...

  3. VS2010 c/c++ 本地化 emscripten 配置

    配置环境 1.下载emsdk-1.35.0-full-64bit.exe,有VS2010的话直接安装. 2.安装好之后,打开cmd,# emsdk update # emsdk install lat ...

  4. Hadoop(五)搭建Hadoop与Java访问HDFS集群

    前言 上一篇详细介绍了HDFS集群,还有操作HDFS集群的一些命令,常用的命令: hdfs dfs -ls xxx hdfs dfs -mkdir -p /xxx/xxx hdfs dfs -cat ...

  5. Swift搭建服务端

    原文:Hello Server Side Swift 作者:Logan Wright 译者:CocoaChina--kmyhy(博客) 自从苹果官方发布了一个 Swift 的 Linux 开源版本之后 ...

  6. 框架应用 : Spring MVC - 开发详述

    软件开发中的MVC设计模式 软件开发的目标是减小耦合,让模块之前关系清晰. MVC模式在软件开发中经常和ORM模式一起应用,主要作用是将(数据抽象,数据实体传输和前台数据展示)分层,这样前台,后台,数 ...

  7. visual studio 2015 warning MSB3246

    在我们很高兴的按下 本地计算机运行 按钮,希望看到我们程序运行的时候,垃圾vs就告诉我们,你的程序出现了问题,问题就是: warning MSB3246: 解析的文件包含错误图像.无元数据或不可访问. ...

  8. redis基本教程

    http://www.runoob.com/redis/redis-tutorial.html

  9. EF异常探究(An entity object cannot be referenced by multiple instances of IEntityChangeTracker.)

    今天在改造以前旧项目时出现了一项BUG,是由于以前不规范的EF写法所导致.异常信息如下: "An entity object cannot be referenced by multiple ...

  10. Java基础总结--Java编程环境变量配置

    1.jdk--bin--都是命令行程序(图形化是对命令行的封装)eg javac&java执行javac必须切换到其所在目录--太麻烦---想在任意目录下使用要执行一个命令--先在当前目录下找 ...