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

  1. Spring Boot 2.0 series 1 – Build Docker images using Gradle
  2. Spring Boot 2.0 Series ii – Global exception handling and testing
  3. Spring Boot 2.0 series (3) – Using @async to make asynchronous calls
  4. Spring Boot 2.0 series 4 – Use WebAsyncTask to handle asynchronous tasks
  5. Spring Boot 2.0 series 5 – Listener, Servlet, Filter, and Interceptor
  6. 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

  1. Filters are based on function callbacks, while Interceptor is based on Java reflection and dynamic proxies.

  2. A Filter depends on a Servlet container, while an Interceptor does not.

  3. 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:

  1. FilterFiltering request processing;
  2. ServletProcessing requests;
  3. FilterFilter response processing.

Request distribution flow for custom Controller:

  1. FilterFiltering request processing;
  2. InterceptorInterception request processing;
  3. The correspondingHandlerAdapterProcessing requests;
  4. InterceptorIntercept response processing;
  5. InterceptorFinal treatment of;
  6. FilterFilter 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 arriveServletHTTPRequests;
  • ServletResponse:ServletProcessed and generatedHTTPResponse;
  • 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(): DispatchServletThe 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 whichpreHandle()Methods. Any oneHandlerInterceptorInterception returnfalse,preHandle()returnfalseTo 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 sequencepostHandle()Methods. Only when allHandlerInterceptorpreHandle()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 returnsfalseProgram throws an exceptionWhen the execution. inpreHandle()Method, throughinterceptorIndexRecord the returnfalseInterceptor index. Once theapplyPreHandle()Method returnsfalse, is returned from the currentfalseThe 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.

  • registeredSpring MVCdispatcherServletAnd 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 orderFilterObject and path are mapped, wherecharacterEncodingFilterSpring MVCOwn 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 theIndexServletContextListenerAnd 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 sequenceFilterinit()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 toInterceptorRegistryOn.
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
  • rightIndexControllerTo process, putrequest URIProcessing methodMap toHandlerMappingAnd 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.