SpringBoot filter, interceptor, Aop section
1, Filter
Add the following annotation to the startup class: @ ServletComponentScan.
Filter is a Servlet container level filter. It can filter almost all requests based on function callback. The complete process of filter: filter preprocesses the user request, then sends the request to the Servlet for preprocessing and generates a response, and finally filter post processes the server response. The filter implementation example is as follows:
package com.example.demo01.filter; import org.springframework.util.StringUtils; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; @WebFilter(filterName = "SessionFilter", displayName = "SessionFilter", urlPatterns = {"/*"}, initParams = @WebInitParam( name = "SessionFilterInitParam", value = "SessionFilter") ) public class SessionFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper((HttpServletRequest) servletRequest) { @Override public String getHeader(String name) { String superHeader = super.getHeader(name); if ("test".equals(name) && StringUtils.isEmpty(superHeader)) { String session = servletRequest.getParameter("session"); if (!StringUtils.isEmpty(session)) { return session; } } return superHeader; } }; filterChain.doFilter(requestWrapper, servletResponse); } }
2, Interceptor
Interceptor interceptor is essentially different from filter. Filter depends on Servlet container, while interceptor depends on Spring framework. It is a manifestation of AOP and implemented by Java based dynamic agent. Interceptors are used in AOP to intercept a method or field before it is accessed, and then add some operations before or after it. Interception is an implementation strategy of AOP.
Interceptor function:
Log record: record the log of request information;
Permission check: for example, login detection, enter the processor to detect whether to log in;
Performance monitoring: the interceptor records the start time before entering the processor and the end time after processing, so as to obtain the processing time of the request.
Interceptor implementation
Implement the HandlerInterceptor interface and rewrite the method of the interface to realize user-defined interception. How to implement interceptors in SpringBoot:
Class declaring Interceptor:
By implementing the HandlerInterceptor interface, preHandle, postHandle and afterCompletion methods are implemented.
Configuration Interceptor:
The addInterceptors method is implemented by implementing the WebMvcConfigurer interface. The following example code:
@Slf4j public class SignAuthInterceptor implements HandlerInterceptor { /** * 5 Minute validity */ private final static long MAX_EXPIRE = 5 * 60; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("request URI = " + request.getRequestURI()); HttpServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request); //Get all parameters (including URL and on the body) SortedMap<String, String> allParams = HttpUtils.getAllParams(requestWrapper); //Signature verification of parameters String headerSign = request.getHeader(CommonConstant.X_SIGN); String timesTamp = request.getHeader(CommonConstant.X_TIMESTAMP); //1. There is a message about the verification time try { DateUtils.parseDate(timesTamp, "yyyyMMddHHmmss"); } catch (Exception e) { throw new IllegalArgumentException("Signature verification failed:X-TIMESTAMP Format must be:yyyyMMddHHmmss"); } Long clientTimestamp = Long.parseLong(timesTamp); //Judgment timestamp = 2018091113 if ((DateUtils.getCurrentTimestamp() - clientTimestamp) > MAX_EXPIRE) { throw new IllegalArgumentException("Signature verification failed:X-TIMESTAMP Expired "); } //2. Verification signature boolean isSigned = SignUtil.verifySign(allParams,headerSign); if (isSigned) { log.debug("Sign Signature passed! Header Sign : {}",headerSign); return true; } else { log.error("request URI = " + request.getRequestURI()); log.error("Sign Signature verification failed! Header Sign : {}",headerSign); //If the verification fails, return to the front end response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); PrintWriter out = response.getWriter(); Result<?> result = Result.error("Sign Signature verification failed!"); out.print(JSON.toJSON(result)); return false; } }
/** * Signature interceptor configuration */ @Configuration public class SignAuthConfiguration implements WebMvcConfigurer { public static String[] urlList = new String[] {"/sys/dict/getDictItems/*", "/sys/dict/loadDict/*","/sys/api/translateDictFromTable", "/sys/api/translateDictFromTableByKeys"}; @Bean public SignAuthInterceptor signAuthInterceptor() { return new SignAuthInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(signAuthInterceptor()).addPathPatterns(urlList); } }
3, Spring aop aspect
Compared with interceptors, Spring's aop is more powerful and encapsulated in more detail.
The notes involved in Aop are as follows:
@Aspect: define a java class as an aspect class.
@Pointcut: defines a pointcut, which can be a regular expression, such as all functions under a package in the following example, or an annotation.
@Before: cut into the content at the beginning of the entry point.
@After: cut in content at the end of the pointcut.
@After returning: processing logic after the pointcut return content.
@Around: cut in the content before and after the pointcut, and control when to execute the content of the pointcut itself. In principle, it can be replaced
@Before and @ After.
@After throwing: used to handle the processing logic after an exception is thrown in the cut in content part.
@Order(100): the execution order of AOP section. The smaller the @ Before value, the earlier the execution, @ After and @ AfterReturning
The larger the value, the earlier the execution.
Introduce dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
The example code is as follows:
import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; @Aspect @Slf4j @Component public class MethodMonitorAspect { private long startTime; //Declare the aspect class path. The type must be final String. The variables to be used in the annotation can only be static constant types //public static final String POINT = "execution(* com.product.service.*.*(..))"; //You can also use annotations to declare pointcuts, as follows @Pointcut("execution(* com.liuc.server.api.sechdule.invoice.*.*(..))") public void point() { } @Before("point()") public void doBefore(JoinPoint pj) { this.startTime = System.currentTimeMillis(); Object target = pj.getTarget(); String className = target.getClass().getName(); //The class and package to which the currently executed method belongs MethodSignature signature = (MethodSignature) pj.getSignature(); String methodName = signature.getName(); //Name of the currently executed method SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); log.info("class{}.{}Method starts execution" + (dateformat.format(this.startTime)),className,methodName); } @After("point()") public void doAfter(JoinPoint pj) { long endTime = System.currentTimeMillis(); Object target = pj.getTarget(); String className = target.getClass().getName(); //The class and package to which the currently executed method belongs MethodSignature signature = (MethodSignature) pj.getSignature(); String methodName = signature.getName(); //Name of the currently executed method log.info("class{}.{}Method executed" + (endTime - this.startTime) + "ms",className,methodName); } @Around("point()") public Object around(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); //Execution method Object result = point.proceed(); //Execution time (MS) long time = System.currentTimeMillis() - beginTime; //Save log saveSysLog(......); return result; } }
summary
Call order of filters, interceptors, and slices
Call sequence filter - > interceptor - > aspect - > controller.
The earlier the request is filtered in the system, the smaller the impact on the performance of the service. Therefore, when writing relatively common code, give priority to the filter, then the interceptor, and finally the AOP. For example, permission verification. Generally, all requests require login verification. At this time, the filter should be used to verify at the top level; For example, log recording, generally, logs are only used for some logic, and involve the log records before and after the completion of business logic. Therefore, the use of filters cannot divide modules in detail. At this time, interceptors should be considered. However, interceptors also match rules according to URL s, so they are not detailed enough. Therefore, we will consider using AOP, AOP can intercept the method level of the code, which is very suitable for the logging function.
1. Filter
The Filter can get the original http request, but can't get the information of the requested controller and the method in the request controller. The Filter can intercept the request and response of the method (ServletRequest request, ServletResponse response), and make response like filtering operations on the request response, such as setting character coding, authentication, etc. The Filter depends on the Servlet container and is part of the Servlet specification. The implementation of Filter is completed by the Servlet container callback. The lifecycle of the Filter is managed by the Servlet container.
2. Interceptor
The interceptor can get the controller and method you requested, but can't get the parameters of the requested method. Interceptors exist independently and can be used in any case. Interceptors are usually executed by dynamic proxy (reflection) and managed by IOC container. Therefore, it is more convenient to obtain instances of other beans by injection.
3.Aop slice
AOP can get the parameters of the method, but it can't get the objects of http request and response. AOP operation can intercept the operation horizontally. The biggest advantage is that it can obtain the parameters of the execution method and deal with the method uniformly Common use logs, transactions, request parameters, security verification, etc.