Directory
- Objective
- Important interface and class introduction
- SOURCE Analysis
- Interceptor Configuration
- Writing a custom Interceptor
- Summarize
Objective
SPRINGMVC is currently one of the mainstream web MVC frameworks.
If a classmate is unfamiliar with it, then please refer to it's Getting started blog:http://www.cnblogs.com/fangjian0423/p/springmvc-introduction.html
Interceptors are a must-have feature for each web framework and are a commonplace theme.
This article will analyze how the interceptor function of SPRINGMVC is designed, and let the reader understand the principle of the function design.
Important interface and class introduction
1. Handlerexecutionchain class
Classes made up of Handlermethod and interceptor collections are obtained by the GetHandler method of the Handlermapping interface.
2. Handlerinterceptor interface
SPRINGMVC Interceptor Base interface.
3. abstracthandlermapping
Handlermapping the underlying abstract class.
4. Asynchandlerinterceptor
Inherits the Handlerinterceptor interface and provides an additional afterconcurrenthandlingstarted method, which is used to handle asynchronous requests. This method is triggered when there is an asynchronous request method in the controller. The landlord has done the test, the asynchronous request first supports Prehandle, then executes the afterconcurrenthandlingstarted. Executes Prehandle, Posthandle, aftercompletion after the asynchronous thread finishes. Interested readers can do their own research.
5. Handlerinterceptoradapter
An abstract class that implements the Asynchandlerinterceptor interface, which is typically inherited by the use of interceptors. The corresponding method is then replicated.
6. Webrequestinterceptor
Similar to the Handlerinterceptor interface, the difference is that the Webrequestinterceptor Prehandle has no return value. There is also webrequestinterceptor for the request, there is no response in the interface method parameter.
The interceptors inside Abstracthandlermapping is a collection of object types. When processing, it is determined that mappedinterceptor[joins to the Mappedinterceptors collection];handlerinterceptor, Webrequestinterceptor ( Fit into Webrequesthandlerinterceptoradapter) [Add to Adaptedinterceptors]
7. Mappedinterceptor
A class that includes the IncludePatterns and excludepatterns string sets combined with Handlerinterceptor. It is obvious that there are interceptors that are specifically included and excluded for some addresses.
8. Conversionserviceexposinginterceptor
The default <annotation-driven/> tag initialization is initialized with the Conversionserviceexposinginterceptor interceptor, and is constructed as a parameter to the constructor method. Mappedinterceptor. It is then added to the Abstracthandlermapping mappedinterceptors collection. The interceptor will drop the conversionservice in each request. Mainly used for the use of spring:eval tags.
SOURCE Analysis
First we look at how the interceptor is called.
After the Web request is Dispatcherservlet intercepted, the Dispatcherservlet Dodispatcher method is called.
It is clear that the Handlerexecutionchain method is called after the Handleradapter is processed and after processing is complete.
Handlerexecutionchain's Applyprehandle, Applyposthandle, and Triggeraftercompletion methods are as follows:
It is obvious that the internal implementation is called to handlerinterceptor the corresponding methods of the interface collection.
Let's look at the tectonic process of the handlerexecutionchain.
The Handlerexecutionchain is obtained from the GetHandler method of the Handlermapping interface.
Handlermapping in the underlying abstract class Abstracthandlermapping:
As we can see, the Handlerexecutionchain interceptor is obtained from the adaptedinterceptors and Mappedinterceptors attributes in the abstracthandlermapping.
Interceptor Configuration
Once you know how the Handlerexecutionchain interceptor property is constructed, here's how SPRINGMVC configures the interceptor.
1. Add <mvc:interceptors> Configure in *-dispatcher.xml configuration file
<Mvc:interceptors><mvc:interceptor> <mvc:mapping path="/** "/> <mvc:exclude-mapping path= "/login"/> <mvc:exclude-mapping path= "/index"/> < bean class= " Package.interceptor.XXInterceptor "/> </mvc:interceptor ></MVC:INTERCEPTORS>
Each <mvc:interceptor> configured here will be parsed into mappedinterceptor.
where child tags <mvc:mapping path= "/**"/> will be parsed into Mappedinterceptor includepatterns properties; <mvc:exclude-mapping path= "/**"/ > will be parsed into Mappedinterceptor's Excludepatterns attribute;<bean/> will be parsed into the Interceptor attribute of Mappedinterceptor.
<mvc:interceptors> This tag is parsed by the Interceptorsbeandefinitionparser class.
2. Configure requestmappinghandlermapping and configure the Interceptors collection properties for that bean. The Interceptors collection here is an object-type generic collection.
The abstracthandlermapping abstract class exposes only 1 interceptor set methods, interceptors.
Both Adaptedinterceptors and mappedinterceptors do not expose the Set method, so we can only configure interceptors properties for requestmappinghandlermapping.
In fact abstracthandlermapping internal initinterceptors method, will traverse interceptors collection, and then determine whether each item is Mappedinterceptor, Handlerinterceptor, Webrequestinterceptor.
Where the Mappedinterceptor type of interceptor is added to the Mappedinterceptors collection, the Handlerinterceptor type is added to the Adaptedinterceptors collection, The Webrequestinterceptor type will be Webrequesthandlerinterceptoradapter added to the Adaptedinterceptors collection.
The configuration is as follows:
<bean class= "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" > <property name=" interceptors "> <bean class= "Package.interceptor.XXInterceptor"/> </property> < Property name= "order" value=< Span class= "Hljs-value" "-1"/></BEAN>
Here is a property order, which is a 1. Why is it?
Actually, it's a little bit of knowledge to share with the readers.
Spring provides an order interface, mainly for sorting purposes.
The abstracthandlermapping abstract class we are using here also implements this interface.
Dispatcherservlet initializes the code of the Handlermapping collection:
Therefore, if the reader is also configured with:
<mvc:annotation-driven/>
Then there will be 2 handlermapping, so when we configure requestmappinghandlermapping, we set the order to 1, which is to give this handlermapping a higher priority than <MVC: The requestmappinghandlermapping level of the annotation-driven/> configuration.
If the reader has only configured requestmappinghandlermapping, the <mvc:annotation-driven/> is not configured. Then you can ignore this little knowledge ~~~~~~~~
It is generally recommended to use the first method.
Writing a custom Interceptor
PublicClassLogininterceptorExtends Handlerinterceptoradapter {@OverridePublicBooleanPrehandle (HttpServletRequest request, httpservletresponse response, Object handler)Throws Exception {Gets the URI of the request path String URI = Request.getrequesturi ();Determine if the path is logout or login authentication, is one of the two, the method defined in the controller is executed if (Uri.endswith ("/login/auth") | | uri.endswith ("/login/out") {return true;} //Enter the login page, determine if there is a key in the session, some words redirect to the homepage, otherwise enter the login interface if (Uri.endswith ("/login/") | | uri.endswith ("/login") {if ( Request.getsession ()! = null && request.getsession (). getattribute ("Loginuser")! = null) { Response.sendredirect (Request.getcontextpath () + "/index"); } else { return true;}} //Other circumstances determine if there is a key in the session, and some continue the operation of the user if (request.getsession () = null && request.getsession (). getattribute ( "Loginuser") = null) { return true;} //The last situation is to enter the login page response.sendredirect (request.getcontextpath () + "/login"); return false;}}
Login Controller:
@Controller@RequestMapping(value = "/login")public class LoginController { @RequestMapping(value = {"/", ""}) public String index() { return "login"; } @RequestMapping("/auth") public String auth(@RequestParam String username, HttpServletRequest req) { req.getSession().setAttribute("loginUser", username); return "redirect:/index"; } @RequestMapping("/out") public String out(HttpServletRequest req) { req.getSession().removeAttribute("loginUser"); return "redirect:/login"; } }
*-diapatcher.xml configuration:
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="org.format.demo.interceptor.LoginInterceptor"/> </mvc:interceptor></mvc:interceptors>
PS: We see that the Prehandle method in Logininterceptor is not processed for the address "/login/auth" and "/login/out".
Therefore, you can write a point configuration and write less Java code. Add 2 exclude-mapping to the Interceptor configuration and remove the Logininterceptor
if(uri.endsWith("/login/auth") || uri.endsWith("/login/out")) { return true;}
Configuration additions:
<mvc:exclude-mapping path="/login/out"/><mvc:exclude-mapping path="/login/auth"/>
Summarize
summed up the principle of the SPRINGMVC interceptor and various configurations, like many people on the Internet will ask why the Interceptor execution Prehandle method returned false or will execute Aftercompletion method, in fact, we see the source code will know.
About interceptors for asynchronous requests and the second configuration method (Interceptors collection properties can be added to classes that inherit from Handlerinterceptoradapter abstract classes and classes that implement Webrequestinterceptor interfaces). Readers can do their own research.
There is inevitably a mistake in the text, hoping that the reader can point it out.
Go SPRINGMVC Interceptor detailed [with source analysis]