SpringMVC - SpringBoot環境の利用と役割DelegatingFilterProxy(史郎[解決]フィルタを構成するときに、なぜプロキシを設定する必要がありますか?)

https://www.cnblogs.com/zhanhaitao/p/7857245.html

初心

DelegatingFilterProxy これは、サーブレットフィルタのためのプロキシです

  • このクラスを使用する利点は、サーブレットフィルタのライフサイクルを管理するために、Springコンテナを通じて主です
  • いくつかの例は、直接注射ばねにより、スプリングは、所望のフィルター容器内に存在する場合
  • また、いくつかの設定ファイルは、これらの操作が実装春によって構成することができやすく読み

DelegatingFilterProxy存在spring-web役割があるパッケージ、filter的代理

間接的Filterインタフェースを実装し、実際には、エージェントのフィルター実装クラスのデリゲートにSpringコンテナから取り出したのdoFilterに呼び出されます。

ここに画像を挿入説明

私たちはそこでは、チャート上で見ることができるDelegatingFilterProxyクラスの継承GenericFilterBean、間接的にこのインタフェースフィルタを実装するため、クラスフィルタに属します。

その後、彼らは、フィルタのinit、のdoFilterを実現しているだろう、3つのメソッドを破壊します。

演技の実現

# 初期化

まず、我々は見てinit私たちが知っている、方法フィルタは、初期化メソッドのinitを実行する場合

ソースから、我々は方法がGenericFilterBeanクラスに実装され、特定のコードを見つけることができ、具体的な機能は以下のとおりです。

  • 春ベースのフォームなどの特定のクラス、維持しやすい春
  • そして主な目的は、次のコードで具現見るために、春に維持ターゲットフィルタを見つけることで達成(DelegatingFilterProxy用)サブクラスでinitFilterBeanメソッドを呼び出します。
	/**
	 * 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");

		this.filterConfig = filterConfig;

		!将该类封装成spring特有的bean形式,方便spring维护
				↓
		// Set bean properties from init parameters.
		PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
		if (!pvs.isEmpty()) {
			try {
				BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
				ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
				Environment env = this.environment;
				if (env == null) {
					env = new StandardServletEnvironment();
				}
				bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, env));
				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);
			}
		}
		
		!该方法 initFilterBean 在子类 (DelegatingFilterProxy) 中实现
		我们可以到DelegatingFilterPoxy中去看看,具体完成了那些工作?
	  1、找到要代理bean的id ==> targetBeanName
	  2、在spring,bean容器中找到具体被代理的filter ==> delegate
			↓
		// Let subclasses do whatever initialization they like.
		initFilterBean();

		if (logger.isDebugEnabled()) {
			logger.debug("Filter '" + filterConfig.getFilterName() + "' configured for use");
		}
	}

initFilterBean() この方法の実行2つの主な機能:(以下のコード)

  1. プロキシクラスは、春に設定されている検索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(name)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スプリングに配置id(以下)

	/**
	 * Make the name of this filter available to subclasses.
	 * Analogous to GenericServlet's {@code getServletName()}.
	 * <p>Takes the FilterConfig's filter name by default.
	 * If initialized as bean in a Spring application context,
	 * it falls back to the bean name as defined in the bean factory.
	 * @return the filter name, or {@code null} if none available
	 * @see javax.servlet.GenericServlet#getServletName()
	 * @see javax.servlet.FilterConfig#getFilterName()
	 * @see #setBeanName
	 */
	@Nullable
	protected String getFilterName() {
	
		!找到被代理filter在spring中配置的id
			↓
		return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
	}

initDelegate() この方法の効果は、特定のバネを容器から取得し、プロキシ filter

	/**
	 * Initialize the Filter delegate, defined as bean the given Spring
	 * application context.
	 * <p>The default implementation fetches the bean from the application context
	 * and calls the standard {@code Filter.init} method on it, passing
	 * in the FilterConfig of this Filter proxy.
	 * @param wac the root application context
	 * @return the initialized delegate Filter
	 * @throws ServletException if thrown by the Filter
	 * @see #getTargetBeanName()
	 * @see #isTargetFilterLifecycle()
	 * @see #getFilterConfig()
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	protected Filter initDelegate(WebApplicationContext wac) throws ServletException {

		! 取出上面找到的 id
			↓
		String targetBeanName = getTargetBeanName();
		Assert.state(targetBeanName != null, "No target bean name set");
		
		! 找到被代理的filter
			↓
		Filter delegate = wac.getBean(targetBeanName, Filter.class);
		if (isTargetFilterLifecycle()) {
			delegate.init(getFilterConfig());
		}
		return delegate;
	}

ここでは見ることができ、我々は、エージェントが欲しいfilter実際に我々が設定されたタグのをfilterfilter-namefilterName

<filter-name>filterName</filter-name>

#のdoFilter

我々は見てとるdoFilter主に使用して、特定の実装方法を、被代理的filterと呼んinvokeDelegate方法、
実装被代理filterdoFilter方法、具体的な実装を、下のソースコードを参照してください。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
		throws ServletException, IOException {

	! 得到被代理的filter
		↓
	// Lazily initialize the delegate if necessary.
	Filter delegateToUse = this.delegate;
	if (delegateToUse == null) {
		synchronized (this.delegateMonitor) {
			delegateToUse = this.delegate;
			if (delegateToUse == null) {
				WebApplicationContext wac = findWebApplicationContext();
				if (wac == null) {
					throw new IllegalStateException("No WebApplicationContext found: " +
							"no ContextLoaderListener or DispatcherServlet registered?");
				}
				delegateToUse = initDelegate(wac);
			}
			this.delegate = delegateToUse;
		}
	}

	! 执行被代理filter的doFilter方法
		↓
	// Let the delegate perform the actual doFilter operation.
	invokeDelegate(delegateToUse, request, response, filterChain);
}

invokeDelegate この方法は、のdoFilterのプロキシ・フィルタ方式であるの役割を実行することです

/**
 * Actually invoke the delegate Filter with the given request and response.
 * @param delegate the delegate Filter
 * @param request the current HTTP request
 * @param response the current HTTP response
 * @param filterChain the current FilterChain
 * @throws ServletException if thrown by the Filter
 * @throws IOException if thrown by the Filter
 */
protected void invokeDelegate(
		Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
		throws ServletException, IOException {

	delegate.doFilter(request, response, filterChain);
}

ここを参照してください、私はそれが今どのように我々はすべてのDelegatingFilterPoxyを理解すると信じています。

ここでは、春の+の士郎を見て、このクラスを使用する方法です

使用(SpringBoot環境)

需要

フィルタにspringbootで、注入さビジネスツール(APIUtil)が、注入がヌルであります

疑問が生じたので:springbootの注入Beanが使用されるフィルタは、ヌルソリューションです

分析:春は実際には、Webアプリケーションの順序が起動されます。

リスナー⇒フィルタ⇒サーブレット

それだけで私たちのdispathServletの初期化に続いた後、フィルタの初期化に戻ってくるし、その後、第1の初期化のリスナーであり、

理由

しかし サーブレットフィルタは、バネコンテナ管理を返さない、本明細書で定義され、直接スプリングビーンに注入することができない(与えられます)

溶液#1

public class TokenAuthFilter implements Filter {
 
    private final static Logger log = LoggerFactory.getLogger(TokenAuthFilter.class);
 
    @Autowired
    private APIUtil apiUtil;
}

例えば、手で豆用のフィルタを作成し、Configクラスを追加します。

@Configuration
public class WebConfig {
 
  @Bean
    public Filter tokenAuthFilter() {
 
        return new TokenAuthFilter();
    }
    /**
     * 注册filter,统一处理api开头的请求
     * @return FilterRegistrationBean
     */
    @Bean
    public FilterRegistrationBean tokenAuthFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        // DelegatingFilterProxy把servlet 容器中的filter同spring容器中的bean关联起来
        registration.setFilter(new DelegatingFilterProxy("tokenAuthFilter"));
        registration.addUrlPatterns("/api/*");
        registration.setName("tokenAuthFilter");
        registration.setOrder(1);
        return registration;
    }
 
}

溶液#2(高結合)

Beanのスプリング・コンテキストの初期化、初期化によって取得されました。

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
    RedisTemplate demoBean = (RedisTemplate)context.getBean("redisTemplate");
    System.out.println(demoBean);
 }
公開された501元の記事 ウォンの賞賛112 ・は 20000 +を見て

おすすめ

転載: blog.csdn.net/LawssssCat/article/details/105027791
おすすめ