[original] use of Spring Boot filter, listener and interceptor

Focus on "full stack of Java backend technology"**

Reply to "interview" to obtain a full set of interview materials from large factories

There are many scenarios in which filters, listeners and interceptors are used in development. Today, let's talk about how these three are used in daily development.

Concepts and usage scenarios

monitor

listener is a special class defined in servlet specification. It is used to listen for creation and destruction events of domain objects such as servletContext, HttpSession and servletRequest.

Implementation method: implement the interface javax servlet. http. HttpSessionListener

It can be mainly used in the following aspects:

  • Statistics of online population and online users
  • Load initialization information at system startup
  • Statistics of website visits
  • Record user access path
filter

Filter is the most practical technology in Servlet Technology. Web developers use filter technology to manage all web resources managed by web server. The filter preprocesses the request after it enters the tomcat container but before it enters the servlet. The end of the request is also returned, which is after the servlet is processed and before it is returned to the front end.

  • For example, Jsp, Servlet, static picture file or static html file are intercepted to realize some special functions
  • For example, it realizes some advanced functions such as URL level access control, filtering sensitive words, compressing response information and so on

It is mainly used to preprocess user requests or post process HttpServletResponse. The complete process of using Filter: Filter preprocesses the user request, then sends the request to the servlet for processing and generates a response, and finally Filter post processes the server response. The Filter only works before and after the servlet, so it can't catch exceptions, get bean objects, etc

Implementation method: implement the interface javax servlet. Filter

Interceptor

Interceptor is used to intercept a method or field before it is accessed, and then add some operations before or after it. Such as log, security, etc. General interceptor methods are implemented by dynamic agent. It can be used to verify the authority, or judge whether the user logs in, or judge whether the current time is the ticket purchase time like 12306. Generally, in project development, there is basically a place for unified exception interception and processing. In fact, by comparison, we can find that the interceptor can do what the filter can do, and the second interceptor does not necessarily do what the filter can do.

Implementation method: org springframework. web. servlet. HandlerInterceptor

Comparison of the three

Interceptors and filters: before filtering - > before interception - > action / controller execution - > after interception - > after filtering

For better understanding, here are some pictures on the Internet:

actual combat

The project continues to use the project used in the previous article.

Add filter
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class UserFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println(servletRequest.getParameter("name"));
        HttpServletRequest hrequest = (HttpServletRequest) servletRequest;
        HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) servletResponse);
        //There are some keywords in the filter URI
        if (hrequest.getRequestURI().indexOf("/index") != -1 ||
                hrequest.getRequestURI().indexOf("/online") != -1 ||
                hrequest.getRequestURI().indexOf("/login") != -1
                ) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            wrapper.sendRedirect("/login");
        }
    }
    @Override
    public void destroy() {
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

A custom Filter can also use servlet3 The @ WebFilter in the third step is the annotation of 3.0

1) Add @ ServletComponentScan to the startup class for scanning

2) Create a new Filter class, implements Filter, and implement the corresponding interface

3) @WebFilter marks a class as filter and is scanned by spring

urlPatterns: interception rules, support regular

4) Control chain Call the method of dofilter to realize whether to pass or not. web application resp sendRedirect("/index.html"); Scenarios: permission control, user login (non front-end and back-end separation scenarios), etc

Add listener

The listener will be associated with the listener design pattern. It is equivalent to the examiner staring at you all the time during the exam. Once someone makes a move, the examiner will always supervise you. Once someone cheats, the examiner will take it down immediately.

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class UserHttpSessionListener implements HttpSessionListener {
    //Monitor the number of people online
    public static int online = 0;
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("establish session");
        online++;
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("Destroy session");
    }
}
Add interceptor
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
public class UserInterceptor implements HandlerInterceptor {
    //Before entering the controller method
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle Called");
        System.out.println(httpServletRequest.getParameter("username"));
        if(httpServletRequest.getParameter("username").equals("zhangsan")) {
            return true;   
        }else {
            //If false, the process is stopped and the api is intercepted
            //Generally, the authentication is to log in. If there is no login, the login operation will be carried out
            PrintWriter printWriter = httpServletResponse.getWriter();
            printWriter.write("please login again!");
            return false;
        }
    }
    //After calling the controller, before rendering the view
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle Called");
    }
   //After the whole process is completed, it is usually used for resource cleanup
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion Called");
    }
}

The preHandle method is called before our controller method executes.

Add configuration class
package com.example.demo.config;
import com.example.demo.filter.UserFilter;
import com.example.demo.listener.UserHttpSessionListener;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//The main interceptor jumps to different user-defined interceptors according to different interception paths 
@Configuration
public class UserWebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/index").setViewName("login");
    }
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public FilterRegistrationBean filterRegist() {
        FilterRegistrationBean frBean = new FilterRegistrationBean();
        frBean.setFilter(new UserFilter());
        frBean.addUrlPatterns("/*");
        System.out.println("filter");
        return frBean;
    }
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public ServletListenerRegistrationBean listenerRegistry() {
        ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
        srb.setListener(new UserHttpSessionListener());
        System.out.println("listener");
        return srb;
    }
}

Test class, write a controller to test

package com.example.demo;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.example.demo.listener.UserHttpSessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
    private final Logger logger = LoggerFactory.getLogger(UserController.class);
    @GetMapping("/welcome")
    public String welcome(Map<String, Object> model) {
        model.put("time", new Date());
        model.put("message", "hello world");
        return "welcome";
    }
    @RequestMapping("/login")
    @ResponseBody
    public Object login() {
        logger.info("-----login---");
        return "login";
    }
    @RequestMapping("/index/{name}")
    @ResponseBody
    public Object index(@PathVariable String name, HttpServletRequest request) {
        HttpSession session = request.getSession(true);
        session.setAttribute(UUID.randomUUID().toString(), name);
        return "index";
    }
    @RequestMapping("/online")
    @ResponseBody
    public Object online() {
        return "Number of people currently online:" + UserHttpSessionListener.online + "people";
    }
}

The above is the relevant knowledge of listeners, filters and interceptors shared today. I suggest you try it manually~

I feel shallow when I get it on paper. I absolutely know that I have to practice it.

Recommended reading

You must know the difference between Exception and Error

How does an SQL statement execute in MySQL?

Interview was asked: 500 million integer large documents, in order?

Tags: Java Spring Boot

Posted by ashrust on Sun, 08 May 2022 23:18:38 +0300