Spring中的HandlerInterceptor和Servlet中的Filter

原创
2017/12/30 07:40
阅读数 108

Spring中的HandlerInterceptor和Servlet中的Filter有什么区别?

我们可以看看源代码,源代码中包含的信息绝对足够多。

javax.servlet.Filter
package javax.servlet;

import java.io.IOException;

/**
 * A filter is an object that performs filtering tasks on either the request to
 * a resource (a servlet or static content), or on the response from a resource,
 * or both. <br>
 * <br>
 * Filters perform filtering in the <code>doFilter</code> method. Every Filter
 * has access to a FilterConfig object from which it can obtain its
 * initialization parameters, a reference to the ServletContext which it can
 * use, for example, to load resources needed for filtering tasks.
 * <p>
 * Filters are configured in the deployment descriptor of a web application
 * <p>
 * Examples that have been identified for this design are<br>
 * 1) Authentication Filters <br>
 * 2) Logging and Auditing Filters <br>
 * 3) Image conversion Filters <br>
 * 4) Data compression Filters <br>
 * 5) Encryption Filters <br>
 * 6) Tokenizing Filters <br>
 * 7) Filters that trigger resource access events <br>
 * 8) XSL/T filters <br>
 * 9) Mime-type chain Filter <br>
 *
 * @since Servlet 2.3
 */
public interface Filter {

    /**
     * Called by the web container to indicate to a filter that it is being
     * placed into service. The servlet container calls the init method exactly
     * once after instantiating the filter. The init method must complete
     * successfully before the filter is asked to do any filtering work.
     * <p>
     * The web container cannot place the filter into service if the init method
     * either:
     * <ul>
     * <li>Throws a ServletException</li>
     * <li>Does not return within a time period defined by the web
     *     container</li>
     * </ul>
     *
     * @param filterConfig The configuration information associated with the
     *                     filter instance being initialised
     *
     * @throws ServletException if the initialisation fails
     */
    public void init(FilterConfig filterConfig) throws ServletException;

    /**
     * The <code>doFilter</code> method of the Filter is called by the container
     * each time a request/response pair is passed through the chain due to a
     * client request for a resource at the end of the chain. The FilterChain
     * passed in to this method allows the Filter to pass on the request and
     * response to the next entity in the chain.
     * <p>
     * A typical implementation of this method would follow the following
     * pattern:- <br>
     * 1. Examine the request<br>
     * 2. Optionally wrap the request object with a custom implementation to
     * filter content or headers for input filtering <br>
     * 3. Optionally wrap the response object with a custom implementation to
     * filter content or headers for output filtering <br>
     * 4. a) <strong>Either</strong> invoke the next entity in the chain using
     * the FilterChain object (<code>chain.doFilter()</code>), <br>
     * 4. b) <strong>or</strong> not pass on the request/response pair to the
     * next entity in the filter chain to block the request processing<br>
     * 5. Directly set headers on the response after invocation of the next
     * entity in the filter chain.
     *
     * @param request  The request to process
     * @param response The response associated with the request
     * @param chain    Provides access to the next filter in the chain for this
     *                 filter to pass the request and response to for further
     *                 processing
     *
     * @throws IOException if an I/O error occurs during this filter's
     *                     processing of the request
     * @throws ServletException if the processing fails for any other reason
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;

    /**
     * Called by the web container to indicate to a filter that it is being
     * taken out of service. This method is only called once all threads within
     * the filter's doFilter method have exited or after a timeout period has
     * passed. After the web container calls this method, it will not call the
     * doFilter method again on this instance of the filter. <br>
     * <br>
     *
     * This method gives the filter an opportunity to clean up any resources
     * that are being held (for example, memory, file handles, threads) and make
     * sure that any persistent state is synchronized with the filter's current
     * state in memory.
     */
    public void destroy();

}
org.springframework.web.servlet.HandlerInterceptor
package org.springframework.web.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.method.HandlerMethod;

/**
 * Workflow interface that allows for customized handler execution chains.
 * Applications can register any number of existing or custom interceptors
 * for certain groups of handlers, to add common preprocessing behavior
 * without needing to modify each handler implementation.
 *
 * <p>A HandlerInterceptor gets called before the appropriate HandlerAdapter
 * triggers the execution of the handler itself. This mechanism can be used
 * for a large field of preprocessing aspects, e.g. for authorization checks,
 * or common handler behavior like locale or theme changes. Its main purpose
 * is to allow for factoring out repetitive handler code.
 *
 * <p>In an asynchronous processing scenario, the handler may be executed in a
 * separate thread while the main thread exits without rendering or invoking the
 * {@code postHandle} and {@code afterCompletion} callbacks. When concurrent
 * handler execution completes, the request is dispatched back in order to
 * proceed with rendering the model and all methods of this contract are invoked
 * again. For further options and details see
 * {@code org.springframework.web.servlet.AsyncHandlerInterceptor}
 *
 * <p>Typically an interceptor chain is defined per HandlerMapping bean,
 * sharing its granularity. To be able to apply a certain interceptor chain
 * to a group of handlers, one needs to map the desired handlers via one
 * HandlerMapping bean. The interceptors themselves are defined as beans
 * in the application context, referenced by the mapping bean definition
 * via its "interceptors" property (in XML: a &lt;list&gt; of &lt;ref&gt;).
 *
 * <p>HandlerInterceptor is basically similar to a Servlet Filter, but in
 * contrast to the latter it just allows custom pre-processing with the option
 * of prohibiting the execution of the handler itself, and custom post-processing.
 * Filters are more powerful, for example they allow for exchanging the request
 * and response objects that are handed down the chain. Note that a filter
 * gets configured in web.xml, a HandlerInterceptor in the application context.
 *
 * <p>As a basic guideline, fine-grained handler-related preprocessing tasks are
 * candidates for HandlerInterceptor implementations, especially factored-out
 * common handler code and authorization checks. On the other hand, a Filter
 * is well-suited for request content and view content handling, like multipart
 * forms and GZIP compression. This typically shows when one needs to map the
 * filter to certain content types (e.g. images), or to all requests.
 *
 * @author Juergen Hoeller
 * @since 20.06.2003
 * @see HandlerExecutionChain#getInterceptors
 * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter
 * @see org.springframework.web.servlet.handler.AbstractHandlerMapping#setInterceptors
 * @see org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor
 * @see org.springframework.web.servlet.i18n.LocaleChangeInterceptor
 * @see org.springframework.web.servlet.theme.ThemeChangeInterceptor
 * @see javax.servlet.Filter
 */
public interface HandlerInterceptor {

   /**
    * Intercept the execution of a handler. Called after HandlerMapping determined
    * an appropriate handler object, but before HandlerAdapter invokes the handler.
    * <p>DispatcherServlet processes a handler in an execution chain, consisting
    * of any number of interceptors, with the handler itself at the end.
    * With this method, each interceptor can decide to abort the execution chain,
    * typically sending a HTTP error or writing a custom response.
    * <p><strong>Note:</strong> special considerations apply for asynchronous
    * request processing. For more details see
    * {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
    * @param request current HTTP request
    * @param response current HTTP response
    * @param handler chosen handler to execute, for type and/or instance evaluation
    * @return {@code true} if the execution chain should proceed with the
    * next interceptor or the handler itself. Else, DispatcherServlet assumes
    * that this interceptor has already dealt with the response itself.
    * @throws Exception in case of errors
    */
   boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
         throws Exception;

   /**
    * Intercept the execution of a handler. Called after HandlerAdapter actually
    * invoked the handler, but before the DispatcherServlet renders the view.
    * Can expose additional model objects to the view via the given ModelAndView.
    * <p>DispatcherServlet processes a handler in an execution chain, consisting
    * of any number of interceptors, with the handler itself at the end.
    * With this method, each interceptor can post-process an execution,
    * getting applied in inverse order of the execution chain.
    * <p><strong>Note:</strong> special considerations apply for asynchronous
    * request processing. For more details see
    * {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
    * @param request current HTTP request
    * @param response current HTTP response
    * @param handler handler (or {@link HandlerMethod}) that started asynchronous
    * execution, for type and/or instance examination
    * @param modelAndView the {@code ModelAndView} that the handler returned
    * (can also be {@code null})
    * @throws Exception in case of errors
    */
   void postHandle(
         HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
         throws Exception;

   /**
    * Callback after completion of request processing, that is, after rendering
    * the view. Will be called on any outcome of handler execution, thus allows
    * for proper resource cleanup.
    * <p>Note: Will only be called if this interceptor's {@code preHandle}
    * method has successfully completed and returned {@code true}!
    * <p>As with the {@code postHandle} method, the method will be invoked on each
    * interceptor in the chain in reverse order, so the first interceptor will be
    * the last to be invoked.
    * <p><strong>Note:</strong> special considerations apply for asynchronous
    * request processing. For more details see
    * {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.
    * @param request current HTTP request
    * @param response current HTTP response
    * @param handler handler (or {@link HandlerMethod}) that started asynchronous
    * execution, for type and/or instance examination
    * @param ex exception thrown on handler execution, if any
    * @throws Exception in case of errors
    */
   void afterCompletion(
         HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
         throws Exception;

}

spring 中拦截器 与servlet 的filter 有相似之处.比如二者都是aop 编程思想的体现都能实现权限检查,日志记录等.不同之处

  1. 使用范围不同 Filter 是Servlet 规定的.只能用于web 程序.而拦截器既可以用于Web 程序,也可以用于Apllicatioon,Swing程序中。
  2. 规范不同:Filter是在SerVlet 规范定义的,是Servlet容器支持的。而拦截器是在Spring 容器内的,Spring 框架所支持的。
  3. 使用资源不同:同其他代码块一样,拦截器也是一个Spring的组件,归Spring 管理。配置在Spring 中,因此能使用Spring 中的任何资源,对象,例如Service对象,数据源,事务管理等。通过Ioc注入到拦截器即可。而filter 则不能。
  4. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  5. 深度不同:Filter 只在Servlet前后起作用,而拦截器能深入到方法前后,异常抛出前后因而拦截器的使用具有更大的弹性,所以在spring 中优先使用拦截器。

配上网上的一张图

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部