ATP application test platform -- Filter, Interceptor, Resolver and Aop in java application, can you understand it?

preface

Filter, Interceptor, Resolver and Aop are technologies often used in our application development. In this section, we will introduce their usage and application scenarios.

text

filter

  • Filter is a means of preprocessing web resources that depends on the existence of servlet. It does not depend on the start of spring container. It is an independent web resource preprocessor. It can uniformly intercept and filter dynamic and static resources. The unified interception function of the filter is useful in spring security to realize the control of access rights and resources. It is a coarse-grained resource access manager, which is mainly used to realize some functions such as unified coding setting, user access control and so on.
  • Use steps

① Create a filter and integrate the filter to implement its interface. The init() method will only be executed once when the project is started. The doFilter () method is the specific processing process of the interceptor for resources, and the destroy () method is executed once when the project is destroyed.

package com.yundi.atp.platform.filter;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: Bei Mingming
 * @Description: Filters: setting codes
 * Priority: Filter > interceptor > AOP section
 * Particle size: fi lt er < interceptor < AOP section
 * @Date: 2022/1/25 18:33
 * @Version: 1.0.0
 */
@Slf4j
public class ParamFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) {
        log.info("[Filter] init It is executed only once during initialization");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //Set code
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //Record the time spent on the request
        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("[Filter] spend total time:{}ms", System.currentTimeMillis() - startTime);
    }

    @Override
    public void destroy() {
        log.info("[Filter] destroy It will only be executed once when it is destroyed");
    }
}

② Register the filter in the FilterRegistrationBean instance

package com.yundi.atp.platform.config;

import com.yundi.atp.platform.filter.ParamFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: Bei Mingming
 * @Description: Filter registration: Servlet container level filter
 * @Date: 2022/1/25 18:38
 * @Version: 1.0.0
 */
@Configuration
public class FilterConfiguration {

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new ParamFilter());
        registration.addUrlPatterns("/*");
        registration.setName("paramFilter");
        // Sets the order in which filters are called
        registration.setOrder(1);
        return registration;
    }
}

Interceptor

  • Interceptor is one of the processing methods of web request resources in spring MVC. Interceptor can intercept dynamic resources. It is mainly used for login authentication, token verification, program execution time statistics and so on. It is a preprocessing method of application requests in dispatcher servlet. The spring container instance can be obtained to realize the business processing of interception results.
  • Use steps

① Create an auth annotation to realize the interception and release of the controller method, and release with auth annotation

package com.yundi.atp.platform.annotation;

import java.lang.annotation.*;

/**
 * @Author: Bei Mingming
 * @Description: Authorization note
 * @Date: 2022/1/25 16:30
 * @Version: 1.0.0
 */
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Auth {
}

② create interceptor AuthHandlerInterceptor

package com.yundi.atp.platform.interceptor;

import com.yundi.atp.platform.annotation.Auth;
import com.yundi.atp.platform.module.sys.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
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;

/**
 * @Author: Bei Mingming
 * @Description: Authentication through interceptor
 * @Date: 2022/1/25 16:53
 * @Version: 1.0.0
 */
@Slf4j
@Component
public class AuthHandlerInterceptor implements HandlerInterceptor {
    private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime");

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //Inject service
        UserService userService = this.getBean(UserService.class, request);
        log.info("injection service:" + userService);
        //Set current time
        startTimeThreadLocal.set(System.currentTimeMillis());
        log.info("[Interceptor method Controller Before method execution...");
        if ((handler instanceof HandlerMethod) && (((HandlerMethod) handler).getMethodAnnotation(Auth.class) != null)) {
            return true;
        }
        return verifyToken(request);
    }

    private boolean verifyToken(HttpServletRequest request) {
        String token = request.getHeader("token");
        if (StringUtils.isNotBlank(token)) {
            //token is parsed by todo, and false is not returned

        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        log.info("[Interceptor method Controller After the method is executed...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        log.info("[Interceptor view Execute after the view rendering is complete...");
        log.info("[Interceptor] spend total time:{}ms", System.currentTimeMillis() - startTimeThreadLocal.get());
    }

    /**
     * Get container object instance
     * @param clazz
     * @param request
     * @param <T>
     * @return
     */
    private <T> T getBean(Class<T> clazz, HttpServletRequest request) {
        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return applicationContext.getBean(clazz);
    }
}

③ registered interceptor

package com.yundi.atp.platform.config;

import com.yundi.atp.platform.interceptor.AuthHandlerInterceptor;
import com.yundi.atp.platform.resolver.AuthHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * @Author: Bei Mingming
 * @Description: Add a static resource file, and the external can directly access the address
 * @Date: 2021/5/18 10:54
 * @Version: 1.0.0
 */
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
        registry.addResourceHandler("/tinymce/**").addResourceLocations("classpath:/tinymce/");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthHandlerInterceptor()).addPathPatterns("/**").order(1);
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new AuthHandlerMethodArgumentResolver());
    }
}

Parameter parser

  • The parameter parser HandlerMethodArgumentResolver parses the parameters in the web request into standard data and binds it to the controller to receive it, which is similar to the @ RequestBody annotation to realize the unified processing of data.
  • Use steps

① Create a parameter parser annotation

package com.yundi.atp.platform.annotation;

import java.lang.annotation.*;

/**
 * @Author: Bei Mingming
 * @Description: Authorization note
 * @Date: 2022/1/25 16:30
 * @Version: 1.0.0
 */
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Param {
}

② create a parameter parser ParamHandlerMethodArgumentResolver

package com.yundi.atp.platform.resolver;

import com.yundi.atp.platform.annotation.Param;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author: Bei Mingming
 * @Description: Parameter parser authentication: its function is to parse request parameters and bind data to Controller input parameters
 * @Date: 2022/1/25 17:47
 * @Version: 1.0.0
 */
@Slf4j
@Component
public class ParamHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        log.info("[[method parser] parameter parser authentication 2!");
        return methodParameter.hasParameterAnnotation(Param.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
        if (methodParameter.getParameterType().equals(String.class)) {
            HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
            String token = request.getHeader("token");
            return token;
        }
        return null;
    }
}

③ Register parameter parser

/*
 * ******************************************************************************************************************************************
 * Copyright (c) 2021 .
 * All rights reserved.
 * Project Name: ATP platform
 * Project Description: application test platform management end
 * Copyright note: this software is owned by Yundi Technology Co., Ltd. without the formal authorization of Yundi Technology Co., Ltd., no enterprise or individual can obtain, read, install and disseminate any content protected by intellectual property rights involved in this software.
 * *******************************************************************************************************************************************
 */
package com.yundi.atp.platform.config;

import com.yundi.atp.platform.interceptor.AuthHandlerInterceptor;
import com.yundi.atp.platform.resolver.ParamHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * @Author: Bei Mingming
 * @Description: Add a static resource file, and the external can directly access the address
 * @Date: 2021/5/18 10:54
 * @Version: 1.0.0
 */
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
        registry.addResourceHandler("/tinymce/**").addResourceLocations("classpath:/tinymce/");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthHandlerInterceptor()).addPathPatterns("/**").order(1);
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new ParamHandlerMethodArgumentResolver());
    }
}

④ Bind parameter parser to controller

 @ApiOperation(value = "Query all user information details test")
 @GetMapping(value = "/findAllUserInfoTest")
 public Result findAllUserInfoTest(@Param String id) {
     return Result.success(id);
 }

aop section

  • aop aspect is one of the important components of spring framework. In the project application, it is mainly used to record the operation log. It can obtain the method level input and output parameters, and can be used as a low granularity web resource processor.
  • Use steps

① Create section annotation

package com.yundi.atp.platform.annotation;

import java.lang.annotation.*;

/**
 * @Author: Bei Mingming
 * @Description: Log annotation
 * @Date: 2022/1/25 16:30
 * @Version: 1.0.0
 */
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OperationLog {
}

② Create log facet OperationLogAspect

package com.yundi.atp.platform.aspect;

import com.yundi.atp.platform.annotation.OperationLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: Bei Mingming
 * @Description: Through aspect authentication
 * @Date: 2022/1/25 16:34
 * @Version: 1.0.0
 */
@Aspect
@Slf4j
@Configuration
public class OperationLogAspect {
    /**
     * Tangent point
     */
    @Pointcut("@annotation(com.yundi.atp.platform.annotation.OperationLog)")
    public void logPointCut() {

    }

    @Around(value = "logPointCut() && @annotation(operationLog)")
    public void operationLogStore(JoinPoint joinPoint, OperationLog operationLog) {
        //todo log processing
        log.info("[Section] this is the use of a section!");
    }

}

③ Apply

@Auth
@OperationLog
@ApiOperation(value = "Query all user information details")
@GetMapping(value = "/findAllUserInfo")
public Result findAllUserInfo() {
	List<User> userList = userService.findAllUserInfo();
	return Result.success(userList);
}    

epilogue

OK, that's the end of this issue. I'll see you in the next issue...

Keywords: Java Back-end

Added by CoolAsCarlito on Mon, 21 Feb 2022 13:15:08 +0200