The role and usage of DelegatingFilterProxy,
I. Class Structure
The DelegatingFilterProxy class exists in the spring-web package and serves as a filter proxy. The advantage of this class is that the lifecycle of the filter can be managed through the spring container, and that is, we can use spring injection to execute a filter as a proxy, for example, shiro. We can see that the DelegatingFilterProxy class inherits GenericFilterBean and indirectly implements the Filter interface, therefore, this class is a filter. The init, doFilter, and destroy methods in the Filter will be implemented.
II. Specific proxy implementation
First, let's look at the init method. We know that the init method will be executed when the filter is initialized. From the source code, we can find the specific code. This method is implemented in the GenericFilterBean class. The specific function is, this class is encapsulated into a spring-specific class to facilitate spring maintenance and call the initFilterBean method. This method is implemented in the DelegatingFilterProxy class. The main purpose of this method is, find the target filter maintained in spring. For the specific implementation, see the following code:
/*** 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 */@ Overridepublic 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 {
// Encapsulate this class into spring-specific bean form to facilitate spring's maintenance of 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); initBeanW Rapper (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);} // This method is implemented in the subclass. We can go to DelegatingFilterPoxy to see what work has been done?
// 1. Find the id of the bean to be proxy -- targetBeanName
// 2. Find the specific proxy filter in spring and bean containers -- "delegate
InitFilterBean (); if (logger. isDebugEnabled () {logger. debug ("Filter" + filterConfig. getFilterName () + "'configured successfully ");}}
InitFilterBean () This method mainly provides two functions:
1. Locate the id configured by the proxy class in spring and assign it to targetBeanName.
2. Use the found id to find the specific proxy class from the spring container and assign it to delegate
@ Overrideprotected void initFilterBean () throws ServletException {synchronized (this. delegateMonitor) {if (this. delegate = null) {// If no target bean name specified, use filter name. if (this.tar getBeanName = null ){
// Find the id this.tar getBeanName = 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 ){
// Find the specific filter this. delegate = initDelegate (wac );}}}}
GetFilterName () This method is used to obtain the id configured by the proxy filter in spring.
Protected final String getFilterName (){
// Find the id return (this. filterConfig! = Null? This. filterConfig. getFilterName (): this. beanName );}
InitDelegate () This method is used to obtain the specific proxy filter from the spring container.
// Find the proxy filter
Protected Filter initDelegate (WebApplicationContext wac) throws ServletException {Filter delegate = wac. getBean (getTargetBeanName (), Filter. class); if (isTargetFilterLifecycle () {delegate. init (getFilterConfig ();} return delegate ;}
Here we can see that the filter we want to proxy is actually configuring the filterName in the filter-name label in the filter.
<Filter-name> filterName </filter-name>
Let's take a look at the specific implementation of the doFilter method. This method mainly uses the filter to be proxy and calls the invokeDelegate method,
Execute the doFilter method of the proxy filter. For details, see the following source code:
@ Overridepublic void doFilter (ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {// get the proxy 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;} // execute the doFilter method invokeDelegate (delegateToUse, request, response, filterChain );}
The invokeDelegate method is used to execute the doFilter method filtered by the proxy.
protected void invokeDelegate( Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { delegate.doFilter(request, response, filterChain);}
I believe everyone understands what DelegatingFilterPoxy is. Let's take a look at how spring + shiro uses this class.
Iii. Application
First, let's take a look at the specific configuration of web. xml. Pay attention to the name configured in <filter-name> and use name as the id to find the corresponding bean in spring bean configuration.
<!-- 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>
Configure proxy filter in spring
<bean id="shiroFilter" class="com.auth.SpringShiroFilter"/>
I hope you will forgive me for writing a blog for the first time.