SpringCloud Alibaba combat from scratch (59) -- differences, relations and applications of filter, interceptor and AOP

preface

When implementing some common logic, many functions can be implemented through filters, interceptors and AOP, but different methods have different efficiency. See the description below for the specific difference.

filter

The filter intercepts URL s

The custom Filter in Spring generally has only one method, and the return value is void. When the request reaches the web container, it will detect whether the current request address is configured with a Filter, and if so, call the method of the Filter (there may be multiple filters), and then call the real business logic. So far, the Filter task is completed. The Filter does not define before and after the execution of the business logic, but only when the request arrives.

Special note: the input parameters of the filter method include request, response and FilterChain. FilterChain is a filter chain, which is relatively simple to use, while request and response are associated with the request process. Therefore, the request parameters can be filtered and modified. At the same time, after the FilterChain filter chain is executed and the business process is completed, it will return to the filter, At this time, you can also process the requested return data.

Interceptor

The interceptor intercepts the URL

The interceptor has three methods, which are more detailed than the filter, including before and after the execution of the intercepted logic. Interceptors in Spring have three methods: preHandle, postHandle, and afterCompletion. Respectively expressed as follows

Public Boolean prehandle (HttpServletRequest, HttpServletRequest, httpservletresponse, httpservletresponse, object o) indicates the custom processing before the method corresponding to the intercepted URL is executed

Public void posthandle (HttpServletRequest, HttpServletRequest, httpservletresponse, httpservletresponse, object o, modelAndView, modelAndView) indicates that modelAndView has not been rendered at this time, and the method corresponding to the intercepted URL is customized after execution,.

Public void aftercompletion (HttpServletRequest, HttpServletRequest, httpservletresponse, httpservletresponse, object o, exception E) indicates that the modelAndView has been rendered and the interceptor's custom processing is executed.

AOP (facing section)

The aspect oriented interception is the metadata of the class (package, class, method name, parameters, etc.)

Compared with interceptors, they are more detailed and flexible. Interceptors can only intercept URL s, while AOP can implement more complex business logic for specific code.

Three usage scenarios

Filter filter

1.Filter interception web visit url Address. Strictly speaking, filter Only applicable to web In, depending on Servlet Container, using Java The callback mechanism is implemented.
2.Filter Filter: independent of the framework, it can control the initial filter http Request, but finer classes and methods can't control it.
3.The filter can intercept the request and response of the method(ServletRequest request, ServletResponse response),And filter the request response like a response,
For example, set character coding, authentication operation, etc

Interceptor interceptor

Interceptor to intercept .action Ending url,intercept Action Access to. Interfactor Is based on Java Reflection mechanism of( APO Thought) to achieve without relying on Servlet Container.
Interceptors can be used before method execution(preHandle)And method execution(afterCompletion)Operation, callback operation(postHandle),You can get the name of the executed method and request(HttpServletRequest)
Interceptor: The controller and method of the request can be controlled, but the parameters in the request method cannot be controlled(Only the name of the parameter can be obtained, and the value of the parameter cannot be obtained)
(It is used to process and process the request response submitted by the page, such as internationalization, topic change, filtering, etc.).

Spring AOP interceptor

Can only intercept Spring Administration Bean Access (business layer) Service).  specific AOP Details refer to Spring AOP: Principle, notification, connection point, tangent point, tangent plane, expression
 In actual development, AOP Often combined with business: Spring Transaction management:Declarative transaction management(section)
AOP The operation can intercept the operation horizontally. The biggest advantage is that it can obtain the parameters of the execution method( ProceedingJoinPoint.getArgs() ),Unified treatment of methods.
Aspect : You can customize the entry point. There are method parameters, but you can't get them http Requests can be made in other ways, such as RequestContextHolder get(
ServletRequestAttributes servletRequestAttributes= (ServletRequestAttributes) 
Common use logs, transactions, request parameters, security verification, etc

Relationship and difference between Filter and Interceptor

Interceptors are java based reflection mechanisms that use proxy patterns, while filters are based on function callbacks.
The interceptor does not depend on the servlet container, and the filter depends on the servlet container.
Interceptors can only work on action s, while filters can work on almost all requests (protecting resources).
The interceptor can access the action context and the objects in the stack, but the filter cannot.

Execution sequence: before filtering - before intercepting - Action processing - after intercepting - after filtering.
The functions of the three are similar, but each has its own advantages. From the perspective of filter – interceptor – interceptor, the interception rules are more and more detailed, and the execution order is filter, interceptor and aspect. In general, the earlier the data is filtered, the smaller the impact on the service performance. Therefore, when writing relatively common code, we give priority to filters, then interceptors, and finally 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; Log recording: generally, logs are only recorded 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.

From the above description of interceptors and filters, they are very similar and can process requests from clients. Their differences are as follows:

Different scopes
The filter depends on the servlet container and can only be used in the servlet web environment
Interceptors depend on spring containers and can be invoked in spring containers, regardless of what environment Spring is in.
Fine grained difference
The control of the filter is relatively rough. It can only be processed when the request comes in, and the request and response are packaged
The interceptor provides finer control, which can be called before or after the request processing of controller, or can be invoked after rendering the view to the user.
The execution of interrupt chain is difficult and easy
The interceptor can interrupt by returning false in the preHandle method
Filters are more complex, need to process request and response objects to cause interrupts, and need additional actions, such as redirecting users to the error page
Compared with the filter, the interceptor has more fine-grained control. It depends on the Spring container and can be started before or after the request. The filter mainly depends on the servlet. The interceptor can basically do whatever the filter can do.

Spring boot support for filter s, interceptors, interceptors, and AOP

springboot integration filter

There are two ways to implement the filter under springboot

1.Annotation method

When using this filter, you need to add @ WebFilter annotation and @ Component annotation to inject this class into the spring container as a component.

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
 

@Slf4j
@Component
@WebFilter(value = "/hello")
public class HelloFilter1 implements Filter {
 
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain filterChain) throws IOException, ServletException {
        log.info("Enter filter 1");
        filterChain.doFilter(servletRequest,servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
}

2.bean injection method
First customize the filter, and then configure a filtered bean under the springboot startup class. If it is not configured under the springboot startup class and is used on other classes, it is necessary to write @ Configuration on the class to mark that this class is a Configuration class. Springboot startup class annotation @ springbootApplication contains this annotation internally, so it does not need to be configured.

 
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 lombok.extern.slf4j.Slf4j;
 
 

@Slf4j
public class HelloFilter2 implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain filterChain) throws IOException, ServletException {
        log.info("Enter filter 2");
        //Release to next filter
        filterChain.doFilter(servletRequest,servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
}
 
import com.example.demo.filter.HelloFilter1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
 
@SpringBootApplication
public class DemoApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
 
    @Bean
    public FilterRegistrationBean registrationBean(){
        FilterRegistrationBean filter = new FilterRegistrationBean(new HelloFilter2());
        filter.addUrlPatterns("/hello");
        //Execution sequence when multiple filters
        //filter.setOrder(1);
        return filter;
    }
}

springboot integration interceptor

  1. Basic use of interceptors
    1.1 implementation class of interceptor
    Implement the HandlerInterceptor interface of Spring;
    Inherit the class that implements the HandlerInterceptor interface, for example: HandlerInterceptorAdapter;
    1.2 introduction to handlerinterceptor method
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    throws Exception;

    void postHandle(
    HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
    throws Exception;

    void afterCompletion(
    HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    throws Exception;
    preHandler: the business processor is called before processing the request to process the user's request. If the return value is true, it will continue to call the subsequent interceptor and target method; If the return value is false, the request is terminated; Login verification and permission interception can be added here.
    The method is invoked before the postHandler:Controller executes, but not before returning to the view. It can process the model data returned to the user before.
    After afterCompletion:Controller is executed and returned to the view, it can get abnormal information at Controller, where you can record operation logs, resource cleanup and so on.
    1.3 adding interceptors to MVC
    Above SpringBoot 2.0, WebMvcConfigurerAdapter is obsolete, but WebMvcConfigurerAdapter is actually an empty implementation class of the WebMvcConfigurer interface. Therefore, two methods can be implemented: implements WebMvcConfigurer is recommended

  2. @EnableWebMvc + implements WebMvcConfigurer
    Override the method of the parent class in the extension class, which will shield the automatic configuration of spring MVC by springboot.

  3. implements WebMvcConfigurer
    You can override the method of the parent class in the extension class. This method will use the automatic configuration of spring MVC by springboot.

  4. extends WebMvcConfigurationSupport
    Override the method of the parent class in the extension class, which will shield the automatic configuration of spring MVC by springboot.

According to the official documentation, try not to use the @ EnableWebMvc annotation because it will turn off automatic configuration.

@Component
public class LogInterceptor implements HandlerInterceptor {
private final static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
//The service processor is called before processing the request to process the user's request
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info("[interceptor] - [interceptor entered!!]);
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

}

}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private LogInterceptor logInterceptor;
//Configure interceptor
@Override
public void addInterceptors(InterceptorRegistry registry) {
//Specify interceptor and interception path
registry.addInterceptor(logInterceptor).addPathPatterns("/**");
}
}
2. User defined annotation of interceptor
Create an annotation class.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD}) acts on classes, interfaces and methods
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyLimit {
int intVal() default 5;
String stringVal() default "";
}
Create interceptor class - AnnotationInterceptor

@Component
public class AnnotationInterceptor implements HandlerInterceptor {
private final static Logger logger = LoggerFactory.getLogger(AnnotationInterceptor.class);

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //Judge whether the currently intercepted method contains annotations
    boolean assignableFromMethod = handler.getClass().isAssignableFrom(HandlerMethod.class);//[e-bag] designated
    logger.info("Is there a comment on the current method" + assignableFromMethod);
    if (assignableFromMethod) {
        //Gets the annotation of the custom annotation interceptor for the current method
        MyLimit methodAnnotation = ((HandlerMethod) handler).getMethodAnnotation(MyLimit.class);
        logger.info("Comments on the current method:" + methodAnnotation);
        if (methodAnnotation == null) {
            return true;
        }
        //Get parameters on annotation
        int intVal = methodAnnotation.intVal();
        String stringVal = methodAnnotation.stringVal();
        logger.info("Print parameters on annotation:[intVal={}][stringVal={}]", intVal, stringVal);
    }
    return true;
}

}
Configuring Interceptors

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private LogInterceptor logInterceptor;
@Resource
private AnnotationInterceptor annotationInterceptor;
//Configure interceptor
@Override
public void addInterceptors(InterceptorRegistry registry) {
//Specify interceptor and interception path
registry.addInterceptor(logInterceptor).addPathPatterns("/**");
registry.addInterceptor(annotationInterceptor);
}
}
Using annotations

@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
@MyLimit(stringVal = "Ha ha, ha ha")
public String getUesr(@RequestParam(value = "str", required = false) Integer integer) {
    try {
        if (integer == 2) {
            throw new RuntimeException("The requested address is illegal");
        }
    }catch (Exception e){
        logger.error("Illegal request parameter",e);
    }
    logger.info("Request parameters: str={}",integer);
    SysQuartzJobConfig sysQuartzJobConfig = sysQuartzJobConfigMapper.selectByPrimaryKey(integer);
    return JSON.toJSONString(sysQuartzJobConfig);
}

effect:

MyPrefix 16591 INFO com.Interceptor.impl.AnnotationInterceptor - whether there are annotations on the current method true
MyPrefix 16591 INFO com.Interceptor.impl.AnnotationInterceptor - annotation of the current method: @com.com Interceptor. annotation. Mylimit (intval = 5, stringval = ha ha ha ha)
MyPrefix 16592 INFO com.Interceptor.impl.AnnotationInterceptor - parameters on print annotation: [intVal=5][stringVal = ha ha ha ha]
3. Obtain request parameters and solve Java io. IOException: Stream closed
Pass request. In the interceptor getInputStream(); After obtaining the information in the body, an exception occurs when using the @ RequestBody annotation to obtain parameters in the Controller.

Cause analysis of abnormal flow closure

IO (1) Java bio system learning

The input stream contains an "implicit pointer" to record the reading position of the current stream. Therefore, once we read the InputStream in the interceptor, the @ RequestBody annotation cannot be used later.
You can use the filter before the interceptor to wrap the request and rewrite the getInputStream() method;
Save the data to the memory Byte [] and operate with ByteArrayInputStream.
Introduce dependency

In spring boot, there is no need to introduce.

org.apache.tomcat.embed tomcat-embed-core 8.5.15 new interceptor

@Component
public class LogInterceptor implements HandlerInterceptor {

private final static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

//The service processor is called before processing the request to process the user's request
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    logger.info("[Interceptor]-[Interceptor entered!!]");
    logger.info("[Interceptor]-request Type of{}", request.getClass());
    String bodyString = HttpHelper.getBodyString(request);
    logger.info("bodyString Value of:" + bodyString);
    return true;
}

}
New filter

public class HttpServletRequestReplacedFilter implements Filter {

private final static Logger logger = LoggerFactory.getLogger(HttpServletRequestReplacedFilter.class);

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    logger.info("[Filter]-[Entered filter!]");
    ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
    chain.doFilter(requestWrapper, response);
}

@Override
public void destroy() {

}

}
Packaging request

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final static Logger logger = LoggerFactory.getLogger(BodyReaderHttpServletRequestWrapper.class);

private final byte[] body;

public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) {
    super(request);
    //Get request body
    logger.info("[Filter]-[Get requested body [information]");
    body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
}

//override method 
@Override
public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(getInputStream()));
}

@Override
public ServletInputStream getInputStream() throws IOException {
    //Node flow
    final ByteArrayInputStream bais = new ByteArrayInputStream(body);
    return new ServletInputStream() {
        @Override
        public boolean isFinished() {
            return false;
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setReadListener(ReadListener listener) {
            //monitor
            logger.info("[Interceptor]-[BodyReaderHttpServletRequestWrapper ReadListener:{}]", this);
        }

        @Override
        public int read() throws IOException {
            return bais.read();
        }
    };
}

}
Read the tool class of the Body

public class HttpHelper {
private final static Logger logger = LoggerFactory.getLogger(HttpHelper.class);
public static String getBodyString(HttpServletRequest request) {

    StringBuffer sb = new StringBuffer();
    InputStream inputStream;
    BufferedReader bufferedReader;
    try {
        //Save the data to the array and read it every time
        inputStream = request.getInputStream();
        //Use the byte array as the destination of the output
        //Convert byte stream to character stream (processing stream)
        bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
            sb.append(line);
        }
    } catch (Exception e) {
        logger.error("Data reading exception", e);
    }
    return sb.toString();
}

}
The interceptor filter is added to the container

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private LogInterceptor logInterceptor;
// @Resource
// private AnnotationInterceptor annotationInterceptor;
//Configure interceptor
@Override
public void addInterceptors(InterceptorRegistry registry) {
//Specify interceptor and interception path
registry.addInterceptor(logInterceptor).addPathPatterns("/**");
// registry.addInterceptor(annotationInterceptor);
}

@Bean
public FilterRegistrationBean httpServletRequestReplacedRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new HttpServletRequestReplacedFilter());
    registration.addUrlPatterns("/*");
    registration.addInitParameter("paramName", "paramValue");
    registration.setName("httpServletRequestReplacedFilter");
    registration.setOrder(1);
    return registration;
}

}

springboot integrates AOP

aop log implementation
AOP (Aspect Oriented Programming) is a big topic. It is not introduced here, but used directly.
Implementation effect: when the user operates the web page in the browser, the corresponding operation will be recorded in the database.
Implementation idea: customize an annotation, add the annotation to a method, use aop surround to notify the agent of the annotated method, prepare the log before surround, and store the log after executing the method.

2.1 log table
CREATE TABLE log (
id int(11) NOT NULL AUTO_INCREMENT,
operateor varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
operateType varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
operateDate datetime(0) NULL DEFAULT NULL,
operateResult varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
ip varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
2.2 pojo
The entity class corresponding to the log table uses the @ Data annotation of lombok, or can be replaced by get and set. mybatisplus is used, so @ TableName and other annotations are configured. If mybatis or other orm are used, the annotation can be removed.

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

@Data
@TableName("log")
public class Log {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;

@TableField("operateor")
private String operateor;

@TableField("operateType")
private String operatetype;

@TableField("operateDate")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date operatedate;

@TableField("operatereSult")
private String operateresult;

@TableField("ip")
private String ip;

}
2.3 controller
The Controller is used to receive user requests and record user operations.

import cn.lastwhisper.springbootaop.core.annotation.LogAnno;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
/**
*@ desc here, in order to facilitate aop logging directly on the controller, it can also be placed on the service.

 * @Param 
 * @return
 */
@LogAnno(operateType = "Add user")
@RequestMapping(value = "/user/add")
public void add() {
    System.out.println("Add user to database!!");
}

}
2.4 mapper
This mapper is used to operate on the log table

package cn.lastwhisper.springbootaop.mapper;

import cn.lastwhisper.springbootaop.pojo.Log;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface LogMapper extends BaseMapper {
}

2.5 core
2.5. 1 log comments
This annotation is used to identify the method that needs to be surrounded by notifications for log operations

import org.springframework.core.annotation.Order;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**

  • Log annotation

*/
@Target(ElementType.METHOD) / / method annotation
@Retention(RetentionPolicy.RUNTIME) / / visible at runtime
public @interface LogAnno {
String operateType();// Operation type of logging
}
2.5.2 aop surround notification class
Log the method with the LogAnno annotation around the notification.

@The Order(3) annotation must be marked to support AspectJ aspect sorting.

import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.Date;

import cn.lastwhisper.springbootaop.core.annotation.LogAnno;
import cn.lastwhisper.springbootaop.core.common.HttpContextUtil;
import cn.lastwhisper.springbootaop.mapper.LogMapper;
import cn.lastwhisper.springbootaop.pojo.Log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**

  • AOP implementation log

*/
@Order(3)
@Component
@Aspect
public class LogAopAspect {
//Log mapper, it is easy to write less service here
@Autowired
private LogMapper logMapper;

/**
 * Record the log around the notification, and match the annotation to the method that needs to add the log function
 * 
 * @param pjp
 * @return
 * @throws Throwable
 */
@Around("@annotation(cn.lastwhisper.springbootaop.core.annotation.LogAnno)")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
    // 1. Processing before method execution is equivalent to pre notification
    // Get method signature
    MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
    // Acquisition method
    Method method = methodSignature.getMethod();
    // Get the annotation above the method
    LogAnno logAnno = method.getAnnotation(LogAnno.class);
    // Gets the property value of the operation description
    String operateType = logAnno.operateType();
    // Create a log object (prepare to log)
    Log log = new Log();
    log.setOperatetype(operateType);// Operating instructions

    // Set the operator and get it from the session. It's simplified here. It's dead.
    log.setOperateor("lastwhisper");
    String ip = HttpContextUtil.getIpAddress();
    log.setIp(ip);
    Object result = null;
    try {
        // Let proxy method execute
        result = pjp.proceed();
        // 2. It is equivalent to post notification (go here after the method is successfully executed)
        log.setOperateresult("normal");// Set operation results
    } catch (SQLException e) {
        // 3. Equivalent to exception notification
        log.setOperateresult("fail");// Set operation results
    } finally {
        // 4. Equivalent to final notice
        log.setOperatedate(new Date());// Set operation date
        logMapper.insert(log);// Add logging
    }
    return result;
}

}
2.5.3 common
Used to obtain the user's ip address

package cn.lastwhisper.springbootaop.core.common;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

public class HttpContextUtil {
public static HttpServletRequest getRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
}

/**
 * Method of obtaining IP address
 *
 * @param request Pass a request object down
 * @return
 */
public static String getIpAddress() {
    HttpServletRequest request = getRequest();
    String ip = request.getHeader("x-forwarded-for");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("HTTP_CLIENT_IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getRemoteAddr();
    }
    return ip;
}

}
2.6 final configuration
Configure application Properties file

spring.application.name = lastwhisper-aoplog
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/wxlogin?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root

Configure springboot boot boot class SpringbootaopApplication

package cn.lastwhisper.springbootaop;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("CN. Lastwisper. Springbootaop. Mapper") / / set the scanning package of the mapper interface
@SpringBootApplication
public class SpringbootaopApplication {

public static void main(String[] args) {
    SpringApplication.run(SpringbootaopApplication.class, args);
}

}

So far, a complete SpringBoot AOP logging system has basically taken shape.

  1. test
    Start the main method of SpringbootaopApplication. visit http://localhost:8080/user/add

Keywords: Java Spring Struts

Added by tipjones on Sat, 18 Dec 2021 14:05:55 +0200