preface
Request interception is used to process user authentication and authorization, MDC, encoding and decoding, UA check, and multi-terminal mapping. The Servlet, Filter, Listener, and Interceptor components are needed. Converting a non-Spring Boot project to a Spring Boot project requires the same code as before, so it is important to understand its usage and lifecycle.
This series of articles
- Spring Boot 2.0 series 1 – Build Docker images using Gradle
- Spring Boot 2.0 Series ii – Global exception handling and testing
- Spring Boot 2.0 series (3) – Using @async to make asynchronous calls
- Spring Boot 2.0 series 4 – Use WebAsyncTask to handle asynchronous tasks
- Spring Boot 2.0 series 5 – Listener, Servlet, Filter, and Interceptor
- Spring Boot 2.0 series (vi) – Several implementations of single machine timing tasks
The body of the
1. Describes several components
1.1. Listener
The Listener listens for an event operation on the Web server and triggers the registered callback function. In popular language, it is a functional component that automatically executes code when application, Session and Request objects create/die or add/delete properties.
1.2. The Servlet
Servlet is a Java application running on the server side. It is platform – and protocol-independent and can dynamically generate Web pages. It works in the middle layer between client request and server response.
1.3. Filter
The Filter preprocesses the user request, then passes the request to the Servlet for processing and generating the response, and finally the Filter postprocesses the server response. Filters are reusable snippets of code commonly used to transform HTTP request, response, and header information. A Filter, unlike a Servlet, does not generate a response, but only modifies a request or response to a resource.
1.4. Interceptor
Similar to aspects and notifications in section-oriented programming, we enhanced the functionality by adding notifications to a service() method through dynamic proxies. Such as initialization before method execution and postprocessing after method execution. The idea of interceptors is similar to AOP, except that interceptors can only intercept HTTP requests from Controllers.
Filters vs. interceptors
2.1. Differences between the two
-
Filters are based on function callbacks, while Interceptor is based on Java reflection and dynamic proxies.
-
A Filter depends on a Servlet container, while an Interceptor does not.
-
A Filter works on almost all requests, while the Interceptor only works on Controller requests.
2.2. Order of execution
For the custom Servlet to request distribution process:
Filter
Filtering request processing;Servlet
Processing requests;Filter
Filter response processing.
Request distribution flow for custom Controller:
Filter
Filtering request processing;Interceptor
Interception request processing;- The corresponding
HandlerAdapter
Processing requests; Interceptor
Intercept response processing;Interceptor
Final treatment of;Filter
Filter response processing.
3. Environment preparation
Configure gradle dependencies
Use Spring Initializer to create a Gradle project spring-boot-listen-servlet-filter-interceptor. Add related dependencies when creating the gradle project. The resulting initial build.gradle looks like this:
buildscript {
ext {
springBootVersion = '. The 2.0.3 RELEASE '
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'io.ostenant.springboot.sample'
version = '0.0.1 - the SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')}Copy the code
Configure the startup entry class
Configure a Spring Boot Boot entry class with two annotations.
-
ServletComponentScan: allows Spring Boot to scan and load servlets configured under the current package path and subpath.
-
EnableWvc: Allows Spring Boot to configure Spring MVC related custom properties, such as interceptors, resource handlers, message converters, etc.
@EnableWebMvc
@ServletComponentScan
@SpringBootApplication
public class Application {
public static void main(String[] args) { SpringApplication.run(Application.class, args); }}Copy the code
4. Configure the Listener
Configure a ServletContext listener using the @webListener identifier. During Servlet container initialization, the contextInitialized() method is called and contextDestroyed() is called when the container is destroyed.
@WebListener
public class IndexServletContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexServletContextListener.class);
public static final String INITIAL_CONTENT = "Content created in servlet Context";
@Override
public void contextInitialized(ServletContextEvent sce) {
LOGGER.info("Start to initialize servlet context");
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("content", INITIAL_CONTENT);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
LOGGER.info("Destroy servlet context"); }}Copy the code
Here, when the container is initialized, the parameter INITIAL_CONTENT is set to the ServletContext, which is directly accessible globally.
5. To configure the Servlet
Configure IndexHttpServlet, override the doGet() method of HttpServlet, Direct output IndexHttpServlet defined initialization parameters and parameter in setting the ServletContext IndexServletContextListener context.
@WebServlet(name = "IndexHttpServlet",
displayName = "indexHttpServlet",
urlPatterns = {"/index/IndexHttpServlet"},
initParams = {
@WebInitParam(name = "createdBy", value = "Icarus"),
@WebInitParam(name = "createdOn", value = "2018-06-20")})public class IndexHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.getWriter().println(format("Created by %s", getInitParameter("createdBy")));
resp.getWriter().println(format("Created on %s", getInitParameter("createdOn")));
resp.getWriter().println(format("Servlet context param: %s",
req.getServletContext().getAttribute("content"))); }}Copy the code
Configure the @webServlet annotation to register this Servlet. The parameters of the @webServlet annotation correspond to the configuration in web.xml:
<servlet-mapping>
<servlet-name>IndexHttpServlet</servlet-name>
<url-pattern>/index/IndexHttpServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>IndexHttpServlet</servlet-name>
<servlet-class>io.ostenant.springboot.sample.servlet.IndexHttpServlet</servlet-class>
<init-param>
<param-name>createdBy</param-name>
<param-value>Icarus</param-value>
</init-param>
<init-param>
<param-name>createdOn</param-name>
<param-value>2018-06-20</param-value>
</init-param>
</servlet>
Copy the code
6. Configure the Filter
A Servlet request can be filtered through multiple filters, and ultimately processed by the Servlet and responded to the client. Here are two examples of configuring filters:
FirstIndexFilter.java
@WebFilter(filterName = "firstIndexFilter",
displayName = "firstIndexFilter",
urlPatterns = {"/index/*"},
initParams = @WebInitParam(
name = "firstIndexFilterInitParam",
value = "io.ostenant.springboot.sample.filter.FirstIndexFilter"))public class FirstIndexFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(FirstIndexFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("Register a new filter {}", filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("FirstIndexFilter pre filter the request");
String filter = request.getParameter("filter1");
if (isEmpty(filter)) {
response.getWriter().println("Filtered by firstIndexFilter, " +
"please set request parameter \"filter1\"");
return;
}
chain.doFilter(request, response);
LOGGER.info("FirstIndexFilter post filter the response");
}
@Override
public void destroy(a) {
LOGGER.info("Destroy filter {}", getClass().getName()); }}Copy the code
The above @webfilter configuration attributes correspond to the configuration of web. XML as follows:
<filter-mapping>
<filter-name>firstIndexFilter</filter-name>
<filter-class>io.ostenant.springboot.sample.filter.FirstIndexFilter</filter-class>
<url-pattern>/index/*</url-pattern>
<init-param>
<param-name>firstIndexFilterInitParam</param-name>
<param-value>io.ostenant.springboot.sample.filter.FirstIndexFilter</param-value>
</init-param>
</filter-mapping>
Copy the code
Configure FirstIndexFilter, annotated with the @webFilter annotation. When FirstIndexFilter is initialized, the init() method is executed. Each time the request path matches the path configured in urlPatterns, the doFilter() method is used for specific request and response filtering.
If an HTTP request carries the filter1 parameter, the request is allowed. Otherwise, the filter interrupts directly to end the request processing.
SecondIndexFilter.java
@WebFilter(filterName = "secondIndexFilter",
displayName = "secondIndexFilter",
urlPatterns = {"/index/*"},
initParams = @WebInitParam(
name = "secondIndexFilterInitParam",
value = "io.ostenant.springboot.sample.filter.SecondIndexFilter"))public class SecondIndexFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(SecondIndexFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("Register a new filter {}", filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("SecondIndexFilter pre filter the request");
String filter = request.getParameter("filter2");
if (isEmpty(filter)) {
response.getWriter().println("Filtered by firstIndexFilter, " +
"please set request parameter \"filter2\"");
return;
}
chain.doFilter(request, response);
LOGGER.info("SecondIndexFilter post filter the response");
}
@Override
public void destroy(a) {
LOGGER.info("Destroy filter {}", getClass().getName()); }}Copy the code
The above @webfilter configuration attributes correspond to the configuration of web. XML as follows:
<filter-mapping>
<filter-name>secondIndexFilter</filter-name>
<filter-class>io.ostenant.springboot.sample.filter.SecondIndexFilter</filter-class>
<url-pattern>/index/*</url-pattern>
<init-param>
<param-name>secondIndexFilterInitParam</param-name>
<param-value>io.ostenant.springboot.sample.filter.SecondIndexFilter</param-value>
</init-param>
</filter-mapping>
Copy the code
Configure SecondIndexFilter, marked with the @webFilter annotation. When SecondIndexFilter is initialized, the init() method is executed. Each time the request path matches the path configured in urlPatterns, the doFilter() method is used for specific request and response filtering.
If an HTTP request carries the filter2 parameter, the request is allowed. Otherwise, the filter interrupts directly to end the request processing.
Take a look at the three core parameters of doFilter() :
- ServletRequest: did not arrive
Servlet
的HTTP
Requests; - ServletResponse:
Servlet
Processed and generatedHTTP
Response; - FilterChain: FilterChain object that registers multiple filters in sequence.
FilterChain.doFilter(request, response);
Copy the code
Explanation: A filter chain object can register multiple filters in order. If the request meets the filtering conditions of the current filter, the request is processed by the next filter. Once all requests are filtered, the IndexHttpServlet processes and generates the response, which is then postfiltered in the opposite direction through the filter chain.
Configuring a Controller Controller
Configure IndexController to test whether the /index/IndexController path is filtered by a Filter or Interceptor, and verify the order of the two paths.
@RestController
@RequestMapping("index")
public class IndexController {
@GetMapping("IndexController")
public String index(a) throws Exception {
return "IndexController"; }}Copy the code
7. Configure the Interceptor
The Interceptor only applies to handlers. Spring MVC instantiates each request method in Controller as a Handler object, which routes requests to specific handlers from the HandlerMapping object. The HandlerAdapter then performs request processing and response via reflection, interspersed with intercept processing.
Writing interceptors
To distinguish logs, configure two interceptor classes for IndexController as well:
FirstIndexInterceptor.java
public class FirstIndexInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(FirstIndexInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOGGER.info("FirstIndexInterceptor pre intercepted the request");
String interceptor = request.getParameter("interceptor1");
if (isEmpty(interceptor)) {
response.getWriter().println("Filtered by FirstIndexFilter, " +
"please set request parameter \"interceptor1\"");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
LOGGER.info("FirstIndexInterceptor post intercepted the response");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOGGER.info("FirstIndexInterceptor do something after request completed"); }}Copy the code
SecondIndexInterceptor.java
public class SecondIndexInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SecondIndexInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOGGER.info("SecondIndexInterceptor pre intercepted the request");
String interceptor = request.getParameter("interceptor2");
if (isEmpty(interceptor)) {
response.getWriter().println("Filtered by SecondIndexInterceptor, " +
"please set request parameter \"interceptor2\"");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
LOGGER.info("SecondIndexInterceptor post intercepted the response");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOGGER.info("SecondIndexInterceptor do something after request completed"); }}Copy the code
Configuring interceptors
Configuring interceptors in Spring Boot is as simple as implementing the WebMvcConfigurer interface and adding interceptors and matching paths through the InterceptorRegistry in the addInterceptors() method.
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
private static final Logger LOGGER = LoggerFactory.getLogger(WebConfiguration.class);
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FirstIndexInterceptor()).addPathPatterns("/index/**");
registry.addInterceptor(new SecondIndexInterceptor()).addPathPatterns("/index/**");
LOGGER.info("Register FirstIndexInterceptor and SecondIndexInterceptor onto InterceptorRegistry"); }}Copy the code
The corresponding Spring XML configuration is as follows:
<bean id="firstIndexInterceptor"
class="io.ostenant.springboot.sample.interceptor.FirstIndexInterceptor"></bean>
<bean id="secondIndexInterceptor"
class="io.ostenant.springboot.sample.interceptor.SecondIndexInterceptor"></bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/index/**" />
<ref local="firstIndexInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/index/**" />
<ref local="secondIndexInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
Copy the code
The principle of analyzing
Let’s develop an interceptor by implementing the HandlerInterceptor interface. Let’s look at three important methods of the HandlerInterceptor interface:
-
PreHandle (): Executes before the controller receives the request and processes it, returning a Boolean. PostHandle () and afterCompletion() methods are executed if true; If false is returned, execution is interrupted.
-
PostHandle (): Executed after the controller handles the request and before the ModelAndView handles the response to modify the result.
-
AfterCompletion (): Execute after the DispatchServlet processes this request, that is, after the ModelAndView is generated.
Here’s a quick look at the principle of the doDispatch() method of the Spring MVC central DispatcherServlet, focusing on the order in which the interceptor’s three methods are executed.
- doDispatch():
DispatchServlet
The core method for handling request distribution.
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try{ processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest ! = request);// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return; }}// 1. Call each interceptor preHandle() method from front to back
if(! mappedHandler.applyPreHandle(processedRequest, response)) {return;
}
// 2. The HandlerAdapter starts the actual request processing and produces the response view object
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 3. Call each interceptor's postHandle() method back to front
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
// 4. The afterCompletion() method of the interceptor is eventually called
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
} catch (Throwable err) {
// 4. The afterCompletion() method of the interceptor is eventually called
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if(mappedHandler ! =null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); }}else {
if(multipartRequestParsed) { cleanupMultipart(processedRequest); }}}}Copy the code
The HandlerExecutionChain methods noted above: applyPreHandle(), applyPostHandle(), and triggerAfterCompletion().
- ApplyPreHandle () : pressOnce upon a time in the futureCall each interceptor in the order in which
preHandle()
Methods. Any oneHandlerInterceptor
Interception returnfalse
,preHandle()
returnfalse
To record the position of the interceptorinterceptorIndex
, then interrupts interception processing, and finally firesAfterCompletion()
Method and returnfalse
.
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if(! ObjectUtils.isEmpty(interceptors)) {for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if(! interceptor.preHandle(request, response,this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i; }}return true;
}
Copy the code
- ApplyPostHandle () : according to theFrom the back forwardTo call each interceptor in sequence
postHandle()
Methods. Only when allHandlerInterceptor
的preHandle()
Method returnstrue
“, will have the opportunity to executeapplyPostHandle()
Methods.
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if(! ObjectUtils.isEmpty(interceptors)) {for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv); }}}Copy the code
- triggerAfterCompletion:
triggerAfterCompletion()
Only in thepreHandle()
Method returnsfalse
和 Program throws an exceptionWhen the execution. inpreHandle()
Method, throughinterceptorIndex
Record the returnfalse
的 Interceptor index. Once theapplyPreHandle()
Method returnsfalse
, is returned from the currentfalse
The interceptorFrom the back forwardThe implementation of theafterCompletion()
Methods.
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if(! ObjectUtils.isEmpty(interceptors)) {for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); }}}}Copy the code
8. Start the test
Life cycle testing
Start the Spring Boot application and look at the program log at startup time, and I’ll break down what was done during the startup process in order.
- registered
Spring MVC
的dispatcherServlet
And customIndexHttpServlet
.
The 09:39:55 2018-06-23. 12301-400 the INFO [ost startStop - 1] O.S.B.W.S ervlet. ServletRegistrationBean: [/] 2018-06-23 09:39:55.404 INFO 12301 -- [ost-startstop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet IndexHttpServlet mapped to [/index/IndexHttpServlet]Copy the code
Note: The load-up-onstartup value of dispatcherServlet is 1, which takes precedence over other servlets.
- Put all filters in order
Filter
Object and path are mapped, wherecharacterEncodingFilter
是Spring MVC
Own to solve the garbled codeFilter
.
The 2018-06-23 09:39:55. 12301-408 the INFO [ost startStop - 1] O.S.B.W.S ervlet. FilterRegistrationBean: Mapping the filter:'characterEncodingFilter'To: [/ *] 2018-06-23 09:39:55. 12301-409 the INFO] [ost - startStop - 1 O.S.B.W.S ervlet. FilterRegistrationBean: Mapping filter:'firstIndexFilter'To urls: [/ index / *] 2018-06-23 09:39:55. 12301-409 the INFO] [ost - startStop - 1 O.S.B.W.S ervlet. FilterRegistrationBean: Mapping filter:'secondIndexFilter' to urls: [/index/*]
Copy the code
- Initialize the
IndexServletContextListener
And performcontextInitialized()
Method to initialize the context.
The 09:39:55 2018-06-23. 12301-429 the INFO [ost startStop - 1] I.O.S.S.L.I ndexServletContextListener: Start to initialize servlet contextCopy the code
- Executed in sequence
Filter
的init()
Method to initialize.
The 2018-06-23 09:39:55. 12301-432 the INFO [ost startStop - 1] I.O.S.S ample. Filter. SecondIndexFilter: Register a new filter secondIndexFilter 2018-06-23 09:39:55.434 INFO 12301 -- [ost-startstop-1] i.o.s.sample.filter.FirstIndexFilter : Register a new filter firstIndexFilterCopy the code
- Create, initialize, and uniformly register interceptors to
InterceptorRegistry
On.
The 2018-06-23 09:39:55. 13150-502 the INFO [main] I.O.S.S.I nterceptor. WebConfiguration: Register FirstIndexInterceptor and SecondIndexInterceptor onto InterceptorRegistryCopy the code
- right
IndexController
To process, putrequestURI
和 Processing methodMap toHandlerMapping
And cache it.
The 2018-06-23 09:39:55. 12301-541 the INFO [main] S.W.S.M.M.A.R equestMappingHandlerMapping: Mapped"{[/index/IndexController],methods=[GET]}" onto public java.lang.String io.ostenant.springboot.sample.controller.IndexController.index() throws java.lang.Exception
Copy the code
When the Spring Boot application is shut down, the following logs are displayed:
The 10:07:03 2018-06-23. 12301-294 the INFO [ost startStop - 2] I.O.S.S ample. Filter. FirstIndexFilter: Destroy the filter IO. Ostenant. Springboot. Sample. Filter. SecondIndexFilter 10:07:03 2018-06-23. 12301-294 the INFO [ost-startStop-2] i.o.s.sample.filter.FirstIndexFilter : Destroy the filter IO. Ostenant. Springboot. Sample. Filter. FirstIndexFilter 10:07:03 2018-06-23. 12301-294 the INFO [ost-startStop-2] i.o.s.s.l.IndexServletContextListener : Destroy servlet contextCopy the code
You can see the filter configuration above destroy () method and the IndexServletContextListener contextDestroyed () method is invoked.
Access control test
The Servlet test
Visit http://localhost:8080/index/IndexHttpServlet, the response page content is as follows:
Go to http://localhost:8080/index/IndexHttpServlet? Filter1 =filter1, the response page content is as follows:
Go to http://localhost:8080/index/IndexHttpServlet? Filter1 =filter1&filter2=filter2
Observe the console output logs to verify that the filter sequence is correct.
The 2018-06-23 10:19:47. 13150-944 the INFO [nio - 8080 - exec - 1] I.O.S.S ample. Filter. FirstIndexFilter: FirstIndexFilter pre filter the request 2018-06-23 10:19:47.944 INFO 13150 -- [NIO-8080-exec-1] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter Pre Filter the Request 2018-06-23 10:19:47.944 INFO 13150 -- [niO-8080-exec-1] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter Post filter the response 2018-06-23 10:19:47.944 INFO 13150 -- [niO-8080-exec-1] i.o.s.sample.filter.FirstIndexFilter : FirstIndexFilter post filter the responseCopy the code
Conclusion: Custom filters work for IndexHttpServlet, but custom interceptors work for IndexHttpServlet.
The controller test
Visit http://localhost:8080/index/IndexController, the response page content is as follows:
Go to http://localhost:8080/index/IndexController? Filter1 =filter1, the response page content is as follows:
Go to http://localhost:8080/index/IndexController? Filter1 =filter1&filter2=filter2
Go to http://localhost:8080/index/IndexController? Filter1 =filter1&filter2=filter2&interceptor1=interceptor1
Go to http://localhost:8080/index/IndexController? Filter1 =filter1&filter2=filter2&interceptor1=interceptor1&interceptor2=interceptor2
The 2018-06-23 10:21:42. 13150-533 the INFO [nio - 8080 - exec - 4] I.O.S.S ample. Filter. FirstIndexFilter: FirstIndexFilter pre filter the request 2018-06-23 10:21:42.533 INFO 13150 -- [NIO-8080-exec4] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter Pre Filter the Request 2018-06-23 10:21:42.534 INFO 13150 -- [niO-8080-exec-4] i.o.s.s.i.FirstIndexInterceptor : FirstIndexInterceptor pre intercepted the request 2018-06-23 10:21:42.534 INFO 13150 -- [NIO-8080-exec-4] i.o.s.s.i.SecondIndexInterceptor : SecondIndexInterceptor pre intercepted the Request 2018-06-23 10:21:42.535 INFO 13150 -- [NIO-8080-exec-4] i.o.s.s.i.SecondIndexInterceptor : SecondIndexInterceptor Post intercepted the response 2018-06-23 10:21:42.535 INFO 13150 -- [NIO-8080-exec-4] i.o.s.s.i.FirstIndexInterceptor : FirstIndexInterceptor post intercepted the response 2018-06-23 10:21:42.535 INFO 13150 -- [NIO-8080-exec-4] i.o.s.s.i.SecondIndexInterceptor : SecondIndexInterceptordoSomething After Request completed 2018-06-23 10:21:42.535 INFO 13150 -- [NIO-8080-exec-4] i.o.s.s.i.FirstIndexInterceptor : FirstIndexInterceptordoSomething After Request completed 2018-06-23 10:21:42.535 INFO 13150 -- [NIO-8080-exec-4] i.o.s.sample.filter.SecondIndexFilter : SecondIndexFilter Post filter the response 2018-06-23 10:21:42.535 INFO 13150 -- [NIO-8080-exec-4] i.o.s.sample.filter.FirstIndexFilter : FirstIndexFilter post filter the responseCopy the code
Conclusion: Custom filters and interceptors apply to Controller Controller. Filters take precedence over interceptors.
summary
This article introduces in detail the functions, methods, order, scope, and lifecycle of various Web components such as Listener, Servlet, Filter, Controller, and Interceptor. The detailed example code is given, the process is analyzed with the source code, and the conclusion is verified with the test. Hopefully, the Servlet component and the Spring MVC framework component will give you a clearer picture.
Welcome to pay attention to the technical public number: Zero one Technology Stack
This account will continue to share learning materials and articles on back-end technologies, including virtual machine basics, multithreaded programming, high-performance frameworks, asynchronous, caching and messaging middleware, distributed and microservices, architecture learning and progression.