SpringBoot interceptors and Servlet3.0 Custom Filter, Listener

Official documents translation

Spring Boot includes an embedded Tomcat , Jetty and Undertow server support. Most developers using the appropriate "Starter" to obtain an instance of a fully configured. By default, the embedded server in the port 8080listens for HTTP requests.

If you choose CentOS use on Tomcat, please note that, by default, the temporary directory used to store compiled JSP, file upload and so on. When the application is running, tmpwatchyou can delete this directory, resulting in failure. To avoid this behavior, you may want to customize the tmpwatchconfiguration, so as not to delete tomcat.*a directory or configuration server.tomcat.basedirto use a different location embedded Tomcat.

1 Servlets,Filters 和 listeners

When using embedded servlet container, Spring beans may be used or the scanning assembly Servlet, register servlets, filters and all the Listeners (eg from Servlet specification HttpSessionListener).

The Servlets, Filters and Listeners registered as Spring Beans

As of any Spring bean Servlet, Filteror a servlet *Listenerare registered in the embedded container instance. If you want to during the configuration from the application.propertiesreference value, which may be particularly convenient.

By default, if the context contains only a Servlet, it will be mapped to /. In the case where a plurality of servlet beans, bean name as a prefix path. The map is filtered /*.

If the convention-based mapping is not flexible enough, you can use ServletRegistrationBean, FilterRegistrationBeanand ServletListenerRegistrationBeanclasses complete control.

Spring Boot comes with many possible definitions Filter beans of auto-configurations. The following are some examples of filters and their respective order (lower order value represents a higher priority):

Servlet Filters order
OrderedCharacterEncodingFilter Ordered.HIGHEST_PRECEDENCE
WebMvcMetricsFilter Ordered.HIGHEST_PRECEDENCE + 1
ErrorPageFilter Ordered.HIGHEST_PRECEDENCE + 1
HttpTraceFilter Ordered.LOWEST_PRECEDENCE - 10

The Filter beans disordered arrangement is generally safe.

If you need a specific order, you should avoid configuring the Ordered.HIGHEST_PRECEDENCEread request body Filter, the application because it may violate the character encoding configuration. If the requested packaging Servlet filters, use of less than or equal to the OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDERorder of configuration.

2 Servlet Context initialization

Embedded servlet container does not directly perform the Servlet 3.0 javax.servlet.ServletContainerInitializerinterface or Spring's org.springframework.web.WebApplicationInitializerinterface. This is a deliberate design decision, designed to reduce the risk of the war party libraries designed for internal war might break Spring Boot applications.

If you need to perform servlet context initialization in Spring Boot application, you should register achieve org.springframework.boot.web.servlet.ServletContextInitializerbean interface. Single onStartupmethod provides ServletContextaccess, if desired, can easily be used as a conventional WebApplicationInitializeradapter.

Scanning Servlet, filters and listeners

When using the embedded container, can be used @ServletComponentScanto enable use @WebServlet, @WebFilterand @WebListenerannotated classes are automatically registered.

@ServletComponentScanNo effect in separate containers, but the use of the built-in container discovery mechanism.

3 ServletWebServerApplicationContext

Under the hood, Spring Boot using different types of ApplicationContextembedding servlet container support. ServletWebServerApplicationContextIs a special type WebApplicationContext, it is a single search ServletWebServerFactoryto guide their bean. Normally TomcatServletWebServerFactory, JettyServletWebServerFactoryor UndertowServletWebServerFactoryhas been auto-configured.

You usually do not need to know these implementation classes. Most applications are auto-configured, and represent you create a proper ApplicationContextand ServletWebServerFactory.

4 Custom Embedded Servlet Container

You can use the Spring EnvironmentProperties Common servlet container configuration is provided. Usually, you will application.propertiesdefine the properties file.

Common server set comprising:

  • Network Settings: listening for incoming port HTTP requests ( server.port), bound to the server.addressinterface address, and so on.

  • Session Setup: session is persistent ( server.servlet.session.persistence), session timeout ( server.servlet.session.timeout), the position data of the session ( server.servlet.session.store-dir) Configuration and Cookie-session ( server.servlet.session.cookie.*).

  • Error management: position error pages ( server.error.path) and so on.

  • SSL

  • HTTP compression

Spring Boot try as much as possible exposure to common settings, but this is not always possible. For these cases, a dedicated namespace provides a custom server-specific (see server.tomcatand server.undertow). For example, a servlet container embedded features specific configuration access log .

For a complete list, see ServerProperties class.

Custom programming

If you need to programmatically configure an embedded servlet container that can achieve registration WebServerFactoryCustomizerinterface Spring bean. WebServerFactoryCustomizerProvide ConfigurableServletWebServerFactoryaccess to, including many custom setter methods. The following example displays port programmatically:

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
​
@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
​
    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);
    }
​
}

TomcatServletWebServerFactory, JettyServletWebServerFactoryAnd UndertowServletWebServerFactoryit is ConfigurableServletWebServerFactorya special variant, which respectively provide additional custom setter for Tomcat, Jetty and Undertow.

Direct custom ConfigurableServletWebServerFactory

If the previous custom technology is too limited, you can register yourself TomcatServletWebServerFactory, JettyServletWebServerFactoryor UndertowServletWebServerFactorybean.

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.setPort(9000);
    factory.setSessionTimeout(10, TimeUnit.MINUTES);
    factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
    return factory;
}

 

Provide a setter for many configuration options. If you need to do some more exotic things, but also to provide some protected methods "hooks." For more information, please refer to the source code documentation .

5 JSP restrictions

When running using an embedded servlet container Spring Boot application (packaged as an executable and archive), JSP support, there are some restrictions.

  • Using the Jetty and Tomcat, if a war package, it should work. War using executable java -jarstartup will work, and may also be deployed to any standard container. JSP does not support the use of executable jar.

  • Undertow does not support JSP.

  • Create a custom error.jsppage does not cover error handling default view. You should use a custom error page instead.

There is a JSP the Sample , so you can see how to set up.

Code

1 Filter

  • Startup class

    @SpringBootApplication
    @ServletComponentScan
    public class FilterApplication {
    ​
        public static void main(String[] args) {
            SpringApplication.run(FilterApplication.class, args);
        }
    ​
    }
  • filter

    ** 
     * @author the WGR
      * @Create 2019/11/14 - 21:25 
     * / 
    @WebFilter (urlPatterns = "/ API / *", filterName = "LoginFilter" )
     public  class LoginFilter the implements the Filter { 
        / ** 
         * when the container is loaded call 
         * / 
        @Override 
        public  void the init (the FilterConfig FilterConfig) throws ServletException { 
            System.out.println ( "LoginFilter the init" ); 
        } 
        / ** 
         * when the request is intercepted call 
         * / 
        @Override 
        public  void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("doFilter loginFilter");
    ​
            HttpServletRequest req = (HttpServletRequest) servletRequest;
            HttpServletResponse resp = (HttpServletResponse) servletResponse;
            String username = req.getParameter("username");
    ​
            if ("topcheer".equals(username)) {
                filterChain.doFilter(servletRequest,servletResponse);
            } else {
                resp.sendRedirect ("/index.html" );
                 return ; 
            } 
        } 
        / ** 
         * When the container is destroyed is called 
         * / 
        @Override 
        public  void the destroy () { 
            System.out.println ( "the destroy LoginFilter" ); 
        } 
    }
  • web layer

    /**
     * @author WGR
     * @create 2019/11/14 -- 21:32
     */
    ​
    @RestController
    public class LoginController {
    ​
        @GetMapping("/api/test_request")
        public Object testRequest(String username){
            return username;
        }
    }
  • html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    index static
    <h1>topcheer</h1>
    </body>
    </html>
  •  test

     

 

 

 

 

 

 

2 Servlet

  • servlet
@WebServlet(name = "userServlet",urlPatterns = "/v1/api/test/customs")
public class UserServlet extends HttpServlet{

     @Override
     public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
         resp.getWriter().print("custom sevlet");
         resp.getWriter().flush();
         resp.getWriter().close();
     }

     
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doGet(req, resp);
    }

     
    
}
  • testing method
 @GetMapping("/v1/api/test/customs")
    public Object testServlet(){
        return "success";
    }
  • Test Results

 

3 Listener

  • listener
@WebListener
public class RequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        // TODO Auto-generated method stub
        System.out.println("======requestDestroyed========");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("======requestInitialized========");

    }


}
  • test

 

 

 

 4 interceptor

@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer  {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/*/**");
        registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/api/*/**");
        
        //.excludePathPatterns("/api2/xxx/**"); //拦截全部 /*/*/**
        
        WebMvcConfigurer.super.addInterceptors(registry);
    }

    
    
    


}
public class LoginIntercepter implements HandlerInterceptor{

    /**
     * 进入controller方法之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        System.out.println("LoginIntercepter------->preHandle");

//        String token = request.getParameter("access_token");
//        
//        response.getWriter().print("fail");
        
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    / ** 
     * after the calling controller, before view rendering 
     * / 
    @Override 
    public  void postHandle (Request the HttpServletRequest, 
            HttpServletResponse the Response, Object Handler, 
            ModelAndView ModelAndView) throws Exception { 
        
        System.out.println ( "LoginIntercepter ------- > The postHandle " ); 
        
        HandlerInterceptor from. Super .postHandle (Request, Response, Handler, ModelAndView); 
    } 

    / ** 
     * after the completion of the whole, is typically used to clean up the resources 
     * / 
    @Override 
    public  void  afterCompletion (the HttpServletRequest Request,
            the HttpServletResponse Response, Object Handler, Exception EX) 
            throws Exception {
        System.out.println("LoginIntercepter------->afterCompletion");
        
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    
    
}
public  class TwoIntercepter the implements HandlerInterceptor from { 

    / ** 
     * before entering the corresponding controller methods 
     * / 
    @Override 
    public  Boolean The preHandle (the HttpServletRequest Request, 
            the HttpServletResponse Response, Object Handler) throws Exception { 

        System.out.println ( "TwoIntercepter ------ > the preHandle " );
         return HandlerInterceptor from. Super .preHandle (Request, Response, Handler); 
    } 

    / ** 
     * after the controller processing returns before the corresponding view 
     * / 
    @Override 
    public  voidThe postHandle (the HttpServletRequest Request, 
            the HttpServletResponse Response, Object Handler, 
            ModelAndView ModelAndView) throws Exception { 
        System.out.println ( "TwoIntercepter ------> The postHandle" ); 
        . HandlerInterceptor from Super .postHandle (Request, Response, Handler, ModelAndView) ; 
    } 

    / ** 
     * after the entire request call back view rendering, is mainly used to clean up resources 
     * / 
    @Override 
    public  void afterCompletion (the HttpServletRequest request, 
            the HttpServletResponse Response, Object Handler, Exception EX) 
            throws Exception { 
        System.out.println ("TwoIntercepter------>afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    
}

 

test:

 

 to sum up:

1, @ Configuration
inherit WebMvcConfigurationAdapter (the old version before SpringBoot2.X)

SpringBoot2.X new version configured interceptor implements WebMvcConfigurer

2, custom interceptor HandlerInterceptor
preHandle: Controller before calling a method
postHandle: call, before rendering a view, if the Controller after Controller appeared abnormal, this method is not performed
afterCompletion: Whether or not an exception, this will be afterCompletion calls for resources to clean up

3, to intercept registered in accordance with the order to register, first to be intercepted

Interceptor does not take effect frequently asked questions:
1) Is there a plus @Configuration
2) whether there is a path to intercept and question ** *
3) interceptor last path must be "/ *", if it is, then the directory is / * /

Filter
is based on callback doFilter (), which is based AOP Interceptor ideas
Filter the only work around Servlet, and before and after the Interceptor reach deep into the method, an exception is thrown around, etc.

It relies on web application Servlet Container i.e., not dependent on the Interceptor and Servlet containers can be run in a variety of environments.

Interface called life cycle, Interceptor can be called multiple times, and Filter can only be called once when the container is initialized.

Filter Interceptor and the order of execution

before filtration -> front knockdown -> Action Execution -> intercepting -> filtration

 

Guess you like

Origin www.cnblogs.com/dalianpai/p/11863283.html