SpringBoot request interception--filter, interceptor, ao

created at 07-27-2021 views: 2

1 Scene

In web programs, user requests are often intercepted and processed. Commonly used processing methods are as follows:

  • Filter
  • Interceptor
  • AOP

Based on the SpringBoot web program, the three interception methods are explained here.

2 Request order

Based on the SpringBoot web program, the request sequence of Filter, Interceptor, and Aop is as follows: Filter -> Interceptor ->AOP -> Controller

request process

3 Version

3.1 maven dependency

Filter and Interceptor have spring-boot-starter-web dependency:

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

The aspectJ that AOP depends on requires additional maven dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.2.9.RELEASE</version>
</dependency>

3.2 Test Controller

package com.wangcp.intercept.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
* test class
* @author wangcp
* @date 2021/05/12 15:45
**/
@RestController
@RequestMapping(value = "/my")
public class MyController {

    @GetMapping(value = "/test")
    public Map<String,Object> test(String userName , String age){
        String message = "[Controller Action]:userName=" + userName + ";age=" + age;
        System.out.println(message);
        Map<String,Object> map = new HashMap<>();
        map.put("success",true);
        map.put("message",message);
        return map;
    }

}

4 Filter code implementation

4.1 Description

1. Implement the interface

Implementation interface: javax.servlet.Filter

2. The core method

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}

4.2 Definition

1. Define Filter

package com.wangcp.intercept.filter;


import javax.servlet.*;
import java.io.IOException;
import java.util.Date;

/**
* Calculate execution time Filter
* @author wangcp
* @date 2021/05/12 15:50
**/
public class TimerFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        long begin = new Date().getTime();
        System.out.println("[Filter-Time]:进入Filter");
        // Execute the servlet method (such as intercepting the request, not executing the servlet, this method may not be executed)
        filterChain.doFilter(servletRequest , servletResponse);
        long end = new Date().getTime();
        System.out.println("[Filter-Time]:结束Filter,共" + (end - begin) + "毫秒");
    }
}

2. Configuration

package com.wangcp.intercept.filter.config;

import com.wangcp.intercept.filter.TimerFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

/**
* filter Configuration class
* @author wangcp
* @date 2021/05/12 15:54
**/
@Configuration
public class WebFilterConfig {

    @Bean
    public FilterRegistrationBean timerFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        // Settings: Implementation class
        registrationBean.setFilter(new TimerFilter());
        // Setting: UrlPatterns (url to be intercepted)
        registrationBean.setUrlPatterns(Arrays.asList("/*"));
        // Setting: Priority
        registrationBean.setOrder(1);
        return registrationBean;
    }

}

4.3 Testing

1. Test request

http://localhost:8080/my/test?userName=wangcp&age=18

2. Output result

[Filter-Time]:进入Filter
[Controller Action]:userName=wangcp;age=18
[Filter-Time]:结束Filter,共40毫秒

4.4 Configuration sequence

// Setting: Priority
registrationBean.setOrder(1);

5 HandlerInterceptor code implementation

5.1 Description

1. Implement the interface

Implementation interface: org.springframework.web.servlet.HandlerInterceptor

2. The core method

// Before calling the Controller method
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

// It will be executed when the current Interceptor's preHandle method returns true
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable ModelAndView modelAndView) throws Exception;

// It also needs to be executed when the return value of the current corresponding Interceptor's preHandle method is true.
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception;

5.2 Definition

1. Define Interceptor

package com.wangcp.intercept.interceptor;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
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;

/**
* Authentication interceptor
* @author wangcp
* @date 2021/05/12 16:05
 * https://blog.csdn.net/weixin_41767154/article/details/84648873
**/
@Component
public class AuthInterceptor implements HandlerInterceptor {

    /**
    * Before calling the Controller method
    * @author wangcp
    * @date 2021/05/12 16:06
     * @param request
     * @param response
     * @param handler
    * @return boolean
    */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("[Interceptor-auth]:进入preHandle");
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            System.out.println("[Interceptor-auth]:访问信息=" + handlerMethod.getShortLogMessage());
            // Get head authentication information
            String sign = request.getHeader("sign");
            if (!"123456".equals(sign)) {
                // Authentication failed
                response.setCharacterEncoding("utf-8");
                response.setContentType("application/json; charset=utf-8");
                PrintWriter writer = response.getWriter();
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("success", false);
                jsonObject.put("message", "鉴权失败");
                writer.write(jsonObject.toJSONString());
                writer.flush();
                writer.close();
                System.out.println("[Interceptor-auth]:----------鉴权不通过----------");
                System.out.println("[Interceptor-auth]:结束preHandle");
                return false;
            } else {
                // Authentication passed
                System.out.println("[Interceptor-auth]:----------鉴权通过----------");
                System.out.println("[Interceptor-auth]:结束preHandle");
                return true;
            }
        }
        System.out.println("[Interceptor-auth]:结束preHandle");
        // Return true to pass the verification, return false to fail the verification
        return true;
    }

    /**
    * It will be executed when the current Interceptor's preHandle method returns true
     *Execution timing: execute before DispatcherServlet renders the view, that is to say you can operate ModelAndView in this method
    * @author wangcp
    * @date 2021/05/12 16:07
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
    * @return void
    */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("[Interceptor-auth]:postHandle ModelAndView=" + JSONObject.toJSONString(modelAndView));
    }

    /**
     * It also needs to be executed when the return value of the current corresponding Interceptor's preHandle method is true.
     * Execution timing: This method will be executed after the entire request is completed, that is, the DispatcherServlet renders the view
     * (The main function of this method is to clean up resources)
    * @author wangcp
    * @date 2021/05/12 16:07
     * @param request
     * @param response
     * @param handler
     * @param ex
    * @return void
    */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("[Interceptor-auth]:afterCompletion Exception=" + JSONObject.toJSONString(ex));
    }
}

2. Configuration

package com.wangcp.intercept.interceptor.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* WEB unified configuration
* @author wangcp
* @date 2021/05/12 16:20
**/
@Component
public class GlobalWebMvcConfigurer implements WebMvcConfigurer {

    @Autowired
    private HandlerInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/**");

        // 支持定义多个PathPattern和excludePathPatterns
//        registry.addInterceptor(authInterceptor).addPathPatterns("/xxx","/**").excludePathPatterns("/yyy","/zzz");
    }
}

5.3 Testing

1. Forward test

request:

http://localhost:8080/my/test?userName=wangcp&age=18
request head:sign=123456

output:

[Interceptor-auth]:进入preHandle
[Interceptor-auth]:访问信息=com.wangcp.intercept.controller.MyController#test[2 args]
[Interceptor-auth]:----------鉴权通过----------
[Interceptor-auth]:结束preHandle
[Controller Action]:userName=wangcp;age=18
[Interceptor-auth]:postHandle ModelAndView=null
[Interceptor-auth]:afterCompletion Exception=null

output result:

{
    "success": true,
    "message": "[Controller Action]:userName=wangcp;age=18"
}

2. Reverse test

request:

http://localhost:8080/my/test?userName=wangcp&age=18
request head:sign=8888

output:

[Interceptor-auth]:进入preHandle
[Interceptor-auth]:访问信息=com.wangcp.intercept.controller.MyController#test[2 args]
[Interceptor-auth]:----------鉴权不通过----------
[Interceptor-auth]:结束preHandle

output result

{
    "success": false,
    "message": "Authentication failed"
}

6 AOP code implementation

6.1 Description

Related notes

org.aspectj.lang.annotation.Aspect
org.aspectj.lang.annotation.Pointcut
org.aspectj.lang.annotation.Before
org.aspectj.lang.annotation.After
org.aspectj.lang.annotation.Around

6.2 Definition

package com.wangcp.intercept.aop;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
* AOP implements interception request
* @author wangcp
* @date 2021/05/12 16:34
 * https://blog.csdn.net/qq_45515432/article/details/104187326
**/
@Component
@Order(1)
@Aspect
public class LogApp {

    @Pointcut("execution(public * com.wangcp..controller..*(..))")
    public void log() {

    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println("[AOP-log]:Before");
    }

    @After("log()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println("[AOP-log]:After");
    }

    @Around("log()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("[AOP-log]:Around-进入");
        // Request parameter
        System.out.println("[AOP-log]:Around-请求参数="+ JSONObject.toJSONString(joinPoint.getArgs()));

        // Execution aspect method
        Object object = joinPoint.proceed();

        // Results of the
        System.out.println("[AOP-log]:Around-执行结果="+ JSONObject.toJSONString(object));
        System.out.println("[AOP-log]:Around-结束");
        return object;
    }
}

6.3 Test

1. Test request

http://localhost:8080/my/test?userName=wangcp&age=18

2. Output result

[AOP-log]:Around-进入
[AOP-log]:Around-请求参数=["wangcp","18"]
[AOP-log]:Before
[Controller Action]:userName=wangcp;age=18
[AOP-log]:After
[AOP-log]:Around-执行结果={"success":true,"message":"[Controller Action]:userName=wangcp;age=18"}
[AOP-log]:Around-结束

3. Request results

{"success":true,"message":"[Controller Action]:userName=wangcp;age=18"}

7 Summary test

At the same time, open the above-mentioned Filter, Interceptor, and AOP to intercept the request together.

1. Test request

http://localhost:8080/my/test?userName=wangcp&age=18
request head:sign=123456

2. Output result

[Filter-Time]:进入Filter
[Interceptor-auth]:进入preHandle
[Interceptor-auth]:访问信息=com.wangcp.intercept.controller.MyController#test[2 args]
[Interceptor-auth]:----------鉴权通过----------
[Interceptor-auth]:结束preHandle
[AOP-log]:Around-进入
[AOP-log]:Around-请求参数=["wangcp","18"]
[AOP-log]:Before
[Controller Action]:userName=wangcp;age=18
[AOP-log]:After
[AOP-log]:Around-执行结果={"success":true,"message":"[Controller Action]:userName=wangcp;age=18"}
[AOP-log]:Around-结束
[Interceptor-auth]:postHandle ModelAndView=null
[Interceptor-auth]:afterCompletion Exception=null
[Filter-Time]:结束Filter,共1毫秒

The output order is the same as the order explained at the beginning of the article.

3. Request results

{
    "success": true,
    "message": "[Controller Action]:userName=wangcp;age=18"
}
Please log in to leave a comment.