Springboot_ Interceptor_ Filter_ monitor

Posted by Lynny on Sun, 06 Mar 2022 11:18:52 +0100

1.maven warehouse

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. Filter

The English name of Filter is Filter, which is the most practical technology in Servlet Technology.

Like its name, the filter is a filter between the client and server resource files, which helps us filter out some requests that do not meet the requirements. It is usually used as Session verification to judge user permissions. If it does not meet the set conditions, it will be intercepted to a special address or based on a special response.

@Log4j2
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("Initialize filter");
    }
  
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);
        String requestUri = request.getRequestURI();
        log.info("The request address is:"+requestUri);
        if (requestUri.contains("/addSession")
            || requestUri.contains("/removeSession")
            || requestUri.contains("/online")
            || requestUri.contains("/favicon.ico")) {
            filterChain.doFilter(servletRequest, response);
        } else {
            wrapper.sendRedirect("/online");
        }
    }
  
    @Override
    public void destroy() {
        //Destroy on service shutdown
        log.info("Destroy filter");
    }
}

3. Interceptor

The interceptor in Java is an object that dynamically intercepts the call of an action, and then provides some operations that can be added before and after the action is executed, or the operation can be stopped before the action is executed. The function is similar to that of a filter, but the standard and implementation method are different.

  • Login authentication: in some applications, the user's login status may be verified through the interceptor. If there is no login or login fails, it will give the user a friendly prompt or return to the login page. Of course, this method is not used in large projects. It is to invoke the single sign on system interface to verify the user.

  • Record system log: in common applications, we usually record the user's request information, such as request ip, method execution time, etc. through these records, we can monitor the status of the system, so as to facilitate information monitoring, information statistics, PV calculation, performance tuning, etc.

  • General processing: there may be information to be returned by all methods in the application, which can be realized by interceptors, eliminating the redundant and repeated code implementation of each method.

@Log4j2
@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("[MyInterceptor]Called:{}", request.getRequestURI());
        request.setAttribute("requestTime", System.currentTimeMillis());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {
        if (!request.getRequestURI().contains("/online")) {
            HttpSession session = request.getSession();
            String sessionName = (String) session.getAttribute("name");
            if ("haixiang".equals(sessionName)) {
                log.info("[MyInterceptor]The current browser does not exist session:{}",sessionName);
            }
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {
        long duration = (System.currentTimeMillis() - (Long)request.getAttribute("requestTime"));
        log.info("[MyInterceptor][{}]Call time:{}ms",request.getRequestURI(), duration);
    }
}

4. Listener

Listeners are usually used to monitor the sending of actions such as the creation and destruction of objects in Web applications, and deal with the listening situation accordingly. They are most commonly used to count the number of online people and visits of websites.

  • ServletContextListener: used to listen to the operation of ServletContext attribute, such as adding, modifying and deleting.

  • HttpSessionListener: a Session object used to listen to Web applications. It is usually used to count online situations.

  • ServletRequestListener: used to listen to the attribute operation of the Request object.

4.1 use of listener

We use HttpSessionListener to count the current number of online people, ip and other information. In order to avoid concurrency, we use atomic int to count.

ServletContext is a global space for storing information. Its life cycle is consistent with that of the Servlet container, that is, the server. It is destroyed only after the server is shut down.

request, one user can have multiple;

session, one for each user; ServletContext is shared by all users. Therefore, in order to save space and improve efficiency, some necessary and important thread information that all users need to share is safe in ServletContext.

Therefore, it is most appropriate for us to use ServletContext to store the online number sessionCount.

@Log4j2
public class MyHttpSessionListener implements HttpSessionListener {

    public static AtomicInteger userCount = new AtomicInteger(0);

    @Override
    public synchronized void sessionCreated(HttpSessionEvent se) {
        userCount.getAndIncrement();
        se.getSession().getServletContext().setAttribute("sessionCount", userCount.get());
        log.info("[Number of people online] increased to:{}",userCount.get());
      
        //Here, you can count the number of accesses in the ServletContext domain object, and then pass in the destruction method of the filter
        //The database is invoked in the destruction method, because the filter life cycle is consistent with the container.
    }

    @Override
    public synchronized void sessionDestroyed(HttpSessionEvent se) {
        userCount.getAndDecrement();
        se.getSession().getServletContext().setAttribute("sessionCount", userCount.get());
        log.info("[Number of people online] reduced to:{}",userCount.get());
    }
}

Listener listening for requests

public class MyHttpRequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("request The listener was destroyed");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
        String requestURI = req.getRequestURI();
        System.out.println(requestURI+"--"+"Called");
    }
}

5. Instantiation

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    MyInterceptor myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor);
    }

    /**
     * Register filter
     * @return
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new MyFilter());
        filterRegistration.addUrlPatterns("/*");
        return filterRegistration;
    }

    /**
     * Register listener
     * @return
     */
    @Bean
    public ServletListenerRegistrationBean registrationBean(){
        ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean();
        registrationBean.setListener(new MyHttpRequestListener());
        registrationBean.setListener(new MyHttpSessionListener());
        return registrationBean;
    }
}

6. Test

@RestController
public class TestController {

    @GetMapping("addSession")
    public String addSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.setAttribute("name", "haixiang");
        return "Number of people currently online" + session.getServletContext().getAttribute("sessionCount") + "people";
    }

    @GetMapping("removeSession")
    public String removeSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.invalidate();
        return "Number of people currently online" + session.getServletContext().getAttribute("sessionCount") + "people";
    }

    @GetMapping("online")
    public String online() {
        return "Number of people currently online" + MyHttpSessionListener.userCount.get() + "people";
    }

}

7. Difference between interceptor and filter

standard:

  1. Filter is the standard of Java EE, which depends on the Servlet container, and its life cycle is consistent with that of the container. This feature can be used to release resources or store data during destruction.

  2. Interceptor is the content in spring MVC and depends on the web framework. It is usually used to verify user permissions or log, but these functions can also be replaced by AOP.

Implementation method:

  1. The filter is implemented based on callback function and cannot be injected into bean s in ioc container.

  2. The interceptor is implemented based on reflection, so the interceptor can inject bean s in the ioc container, such as the business layer of Redis, to verify whether the user has logged in.

Topics: Java kafka Spring Spring Boot Interview