Code Nong Xiao Wang-spring MVC processor Interceptor Detailed

Source: Internet
Author: User

Introduction to Processor interceptors

The processor interceptor for Spring WEB MVC (if no special instructions, the interceptor as described below as the processor interceptor) is similar to the filter filters in the servlet development for preprocessing and post-processing of the processor

Common Application Scenarios
    1. Logging: Log The request information for information monitoring, information statistics, calculation of PV (Page View) and so on.
    2. Permission check: such as login detection, enter the processor detection check whether to log in, if not directly back to the login page;
    3. Sometimes the system at some time is inexplicably slow, can through the interceptor before entering the processor before recording the start time, after processing the PostScript
      The processing time of the request (if there is a reverse proxy, such as Apache can be automatically recorded);
    4. Common behavior: Read the cookie to get user information and put the user object into the request, so as to facilitate the subsequent use of the process, as well as the extraction locale, Theme
      Information and so on, as long as multiple processors are required to use the interceptor implementation.
    5. Opensessioninview: such as Hibernate, when entering the processor open session, after completion of the session closed.
      ............ Nature is also AOP (aspect-oriented programming), meaning that all features that conform to crosscutting concerns can be put into the interceptor implementation.
Interceptor interface
package  Org.springframework.web.servlet; public  interface   Handlerinterceptor  { boolean  prehandle (HttpServletRequest R Equest, httpservletresponse response, Object handler) throws  Exc    Eption;             void  posthandle (httpservletrequest request, httpservletresponse response,    Object handler, Modelandview modelandview) throws  Exception; void  aftercompletion (httpservletrequest request, HttpServletResponse respons E, Object handler, Exception ex) throws  Exception;}  

We may notice that there are 3 callback methods in the interceptor, and the filter filter in general is only two, what is going on? Analyze now

    • Prehandle: Preprocessing callback method, implement processor preprocessing (such as login check), the third parameter is the processor of the response (such as the controller implementation of our previous chapter); return value: True indicates continuation process (e.g. call next Interceptor or processor) False indicates a process interruption (such as a login check failure) and does not continue to invoke other interceptors or processors, where we need to generate a response via response
    • Posthandle: A post-processing callback method that implements post-processing of the processor (but before rendering the view), at which point we can process the model data through Modelandview (model and view objects), or the views are processed, Modelandview may also be null.
    • Aftercompletion: The entire request is processed by the callback method, which is the callback when the view is rendered, such as in performance monitoring where we can record the end time
      And output consumption time, you can also do some resource cleanup, similar to try-catch-finally in the Finally, but only call the processor execution chain Prehandle return True Interceptor aftercompletion.
Interceptor Adapter

Sometimes we may only need to implement one of the three callback methods, if the implementation of the Handlerinterceptor interface, three methods must be implemented, whether you need not, Spring provides a handlerinterceptoradapter adapter (an implementation of an adapter design pattern) that allows us to implement only the callback methods that are needed.

publicabstractclass HandlerInterceptorAdapter implements HandlerInterceptor {     //省略代码 此处所以三个回调方法都是空实现,preHandle返回true。}
    1. How's it going to run?
      Normal time to deal with a bit similar to the order of the stack!

      At the time of the interruption

      In the interrupt process, such as the HandlerInterceptor2 interrupt process (Prehandle returns false), only the Aftercompletion method that called it before the prehandle of the Interceptor returns TRUE.
How exactly does the Dispatcherservlet work inside the bar:
//dodispatch Method//1, Processor interceptor preprocessing (positive sequence execution)Handlerinterceptor[] interceptors = mappedhandler.getinterceptors ();if(Interceptors! =NULL) { for(inti =0; i < interceptors.length; i++) {Handlerinterceptor interceptor = interceptors[i];if(!interceptor.prehandle (processedrequest, Response, Mappedhandler.gethandler ())) {//1.1, the call to trigger aftercompletion on FailureTriggeraftercompletion (Mappedhandler, Interceptorindex, processedrequest, response,NULL);return; } interceptorindex = i;//1.2, logging the index of the current preprocessing success}}//2, the processor adapter calls our processorMV = Ha.handle (processedrequest, Response, Mappedhandler.gethandler ());//When we return null or do not return the logical view name when the default view name is translatedif(MV! =NULL&&!mv.hasview ()) {Mv.setviewname (Request) (getdefaultviewname);}//3, Processor interceptor post-processing (reverse)if(Interceptors! =NULL) { for(inti = interceptors.length-1; I >=0;      i--) {Handlerinterceptor interceptor = interceptors[i]; Interceptor.posthandle (processedrequest, Response, Mappedhandler.gethandler (), MV);}}//4, rendering of viewsif(MV! =NULL&&!mv.wascleared ()) {render (MV, processedrequest, response);if(Errorview) {webutils.clearerrorrequestattributes (request);}///5, trigger the entire request processing completed callback method AftercompletionTriggeraftercompletion (Mappedhandler, Interceptorindex, processedrequest, response,NULL);
//Triggeraftercompletion methodPrivate void triggeraftercompletion(Handlerexecutionchain Mappedhandler,intInterceptorindex, HttpServletRequest request, httpservletresponse response, Exception ex)throwsException {///5, trigger the entire request processing complete callback method Aftercompletion (reverse order from 1.2 in the preprocessing at the successful index of the Interceptor execution)        if(Mappedhandler! =NULL) {handlerinterceptor[] interceptors = mappedhandler.getinterceptors ();if(Interceptors! =NULL) { for(inti = Interceptorindex; I >=0; i--) {Handlerinterceptor interceptor = interceptors[i];Try{interceptor.aftercompletion (Request, Response, Mappedhandler.gethandler (), ex); }Catch(Throwable ex2) {Logger.error ("Handlerinterceptor.aftercompletion threw exception", EX2); }                }            }        }    }
Getting Started example
    1. Normal process
 PackageCn.javass.chapter5.web.interceptor;//Omit import Public  class HandlerInterceptor1 extends handlerinterceptoradapter {///Here generally inherit the Handlerinterceptoradapter adapter to    @Override     Public Boolean Prehandle(HttpServletRequest request, httpservletresponse response, Object handler)throwsException {System.out.println ("===========handlerinterceptor1 prehandle");return true; }@Override     Public void Posthandle(HttpServletRequest request, httpservletresponse response, Object handler, Modelandview Modelandview)throwsException {System.out.println ("===========handlerinterceptor1 posthandle"); }@Override     Public void aftercompletion(HttpServletRequest request, httpservletresponse response, Object handler, Exception ex)throwsException {System.out.println ("===========handlerinterceptor1 aftercompletion"); }}

Controller:

package cn.javass.chapter5.web.controller;//省略importpublicclass TestController implements Controller {    @Override    publichandleRequestthrows Exception {        System.out.println("===========TestController");        returnnew ModelAndView("test");    }}

Spring configuration file Chapter5-servlet.xml

name="/test"class="cn.javass.chapter5.web.controller.TestController"id="handlerInterceptor1"class="cn.javass.chapter5.web.interceptor.HandlerInterceptor1"id="handlerInterceptor2"class="cn.javass.chapter5.web.interceptor.HandlerInterceptor2"/>
<Bean class="Org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" >    < property name="Interceptors">        <list>           <ref Bean="HandlerInterceptor1"/>          <ref Bean="HandlerInterceptor2"/>        </list>    </Property ></Bean>Interceptors: Specifies the Interceptor chain, and the order in which the interceptors are executed is the order in which the interceptors are added;

View

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%System.out.println("==========test.jsp");%>test page

Output

===========HandlerInterceptor1 preHandle===========HandlerInterceptor2 preHandle===========TestController===========HandlerInterceptor2 postHandle===========HandlerInterceptor1 postHandle==========test.jsp===========HandlerInterceptor2 afterCompletion===========HandlerInterceptor1 afterCompletion

Interrupted processing flow
return false to be good!

    @Override    publicbooleanpreHandlethrows Exception {        System.out.println("===========HandlerInterceptor1 preHandle");response.getWriter().print("break");//流程中断的话需要我们进行响应的处理        returnfalse;//返回false表示流程中断    }
Application

Performance monitoring
If you record the processing time of the request, get some slow requests (such as processing time more than 500 milliseconds) for performance improvement, the general reverse proxy server such as Apache has this feature, but here we demonstrate how to implement using interceptors.
Implementation analysis:
1, before entering the processor to record the start time, that is, the Prehandle record start time in the interceptor;
2, the end time after the end of the request processing, that is, the aftercompletion record end of the interceptor implementation, and the end time-start time to get the processing time of this request.

Problem:
Our interceptors are singleton, so how do we keep track of time, no matter how many times a user requests that there is only one interceptor implementation, that is, thread insecurity?
The solution is to use threadlocal, which is a thread-bound variable that provides thread-local variables (a thread of a threadlocal,a thread threadlocal can only see the threadlocal of a thread, You cannot see the threadlocal of the B thread).

 PackageCn.javass.chapter5.web.interceptor; Public  class stopwatchhandlerinterceptor extends handlerinterceptoradapter {    PrivateNamedthreadlocal<long> starttimethreadlocal =NewNamedthreadlocal<long> ("Stopwatch-starttime");@Override     Public Boolean Prehandle(HttpServletRequest request, httpservletresponse response, Object handler)throwsException {LongBeginTime = System.currenttimemillis ();//1, start timeStarttimethreadlocal.set (BeginTime);//thread-bound variable (the data is only visible to the currently requested thread)        return true;//Continuation process}@Override     Public void aftercompletion(HttpServletRequest request, httpservletresponse response, Object handler, Exception ex)throwsException {LongEndTime = System.currenttimemillis ();//2, End time        LongBeginTime = Starttimethreadlocal.get ();//Get thread-bound local variable (start time)        LongConsumetime = Endtime-begintime;//3, Time consumed        if(Consumetime > -) {//The request is considered to be slow request for processing time exceeding 500 milliseconds            //todo logging to a log fileSystem.out.println (String.Format ("%s consume%d Millis", Request.getrequesturi (), consumetime)); }            }}

Namedthreadlocal:spring provides a named threadlocal implementation.

Login detection
When you access certain resources (such as the Order page), users need to log in to view them, so login detection is required.
Process:
1. When accessing the resource to be logged in, the interceptor redirects to the login page;
2, if the access is the login page, the interceptor should not intercept;
3, the user login success, to cookie/session add login successful identification (such as user number);
4. On the next request, the interceptor decides whether to continue the process or to the login page by judging if there is an identity in the cookie/session;
5. This interceptor should also allow visitors to access the resources.

@Override Public Boolean Prehandle(HttpServletRequest request, httpservletresponse response, Object handler)throwsException {//1, request to login page release    if(Request.getservletpath (). StartsWith (loginurl)) {return true; }//2, TODO such as exit, home page and other pages do not need to login, that is, to release the request to allow visitors    //3, if the user has logged in and released    if(Request.getsession (). getattribute ("username") !=NULL) {//better use cookies for the way they are implemented        return true; }//4, illegal requests that these requests need to be logged in to access    //Redirect to login pageResponse.sendredirect (Request.getcontextpath () + loginurl);return false;}

Tip: It is recommended that the functionality implemented using filter filters in the SERVLET specification be implemented with the filter, because Handlerinteceptor is only available in spring WEB MVC environments, so filter is the most common and should be used first. It is best to use filter to log on to this interceptor.

Code Nong Xiao Wang-spring MVC processor Interceptor Detailed

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.