1. Introduce Aop dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Copy the code
2. Define sectionsAspect
package com.example.boot.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
/**
* com.example.boot.aspect
* Description:
*
* @author jack
* @date2021/6/24 11:18am */
@Aspect
@Component
@Slf4j
public class LogAspect {
/** * Configure pointcut */
@Pointcut("@annotation(com.example.boot.aspect.Log)")
public void logPointcut(a) {}/** * Configure surround notifications, using pointcuts ** registered with the method logPointcut()@param joinPoint join point for advice
*/
@Around("logPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
printLog(joinPoint, startTime);
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
log.debug("Cost : {}ms", endTime - startTime);
System.out.println();
return result;
}
private void printLog(ProceedingJoinPoint joinPoint, long startTime) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (Objects.isNull(servletRequestAttributes)) {
return;
}
HttpServletRequest request = servletRequestAttributes.getRequest();
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
String requestType = request.getMethod();
String uri = request.getRequestURI();
String requestTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date(startTime));
log.debug("====================Request time:{}====================", requestTime);
log.debug("Controller : {}#{}", className, methodName);
log.debug("RequestType : {}", requestType);
log.debug("Uri : {}", uri);
log.debug("Parameters : {}", geParametersString(request));
log.debug("RequestJson : {}", getSubscribeJson(request));
log.debug("Ip : {}", getIpAddress(request));
}
/** * Get the form submission parameters **@param request requestp
* @return parameterString
*/
private String geParametersString(HttpServletRequest request) {
Map<String, String[]> parameterMap = request.getParameterMap();
StringBuilder stringBuilder = new StringBuilder();
parameterMap.forEach((k, v) -> stringBuilder.append(k).append("=").append(Arrays.toString(v)).append(""));
return stringBuilder.toString();
}
/** * Get json ** from request@param request request
* @return parameterJson
*/
public String getSubscribeJson(HttpServletRequest request) {
String contentType = request.getContentType();
if (!"application/json".equals(contentType)) {
return null;
}
BufferedReader reader = null;
StringBuilder stringBuilder = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
String line;
while((line = reader.readLine()) ! =null) { stringBuilder.append(line); }}catch (IOException e) {
log.error("Failed to get JSON data from request");
} finally {
try {
if (null != reader) {
reader.close();
}
} catch (IOException e) {
log.error("GetSubscribeJson () failed to close the data stream"); }}return stringBuilder.toString();
}
/** * Obtain client IP **@param request request
* @return ip
*/
private String getIpAddress(HttpServletRequest request) {
String unknown = "unknown";
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();
}
returnip; }}Copy the code
3. Customize annotations to intercept sections
/**
* com.example.boot.aspect
* Description:
*
* @author jack
* @date 2021/6/24 11:20 上午
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
}
Copy the code
4. Use annotations
@RestController
@RequestMapping(value = "/message")
@Slf4j
public class MessageController {
@Log
@GetMapping(value = "/getOne")
public void getOne(Long id) {
log.info("getOne:{}", id); }}Copy the code
Effect of 5.
6.advice
Order of execution
6.1 Order of normal cases of a single section
@Around
@Before
joinPoint.proceed();
Execution method@AfterReturning
@After
@Around
6.2 Sequence of single section exceptions
@Around
@Before
joinPoint.proceed();
Execution method@AfterThrowing
6.3 Sequence of normal cases of multiple sections
The smaller the @order value, the more the Order is executed first, and the more the Order is executed last
Aspect1 @Around
Aspect1 @Before
Aspect2 @Around
Aspect2 @Before
Aspect2 joinPoint.proceed();
Execution methodAspect2 @AfterReturning
Aspect2 @After
Aspect2 @Around
Aspect1 @AfterReturning
Aspect1 @After
Aspect1 @Around
6.4 Test Code
LogAspect1
package com.example.boot.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* com.example.boot.aspect
* Description:
*
* @author jack
* @date2021/6/24 11:18am */
@Aspect
@Component
@Slf4j
@Order(1)
public class LogAspect1 {
/** * Configure pointcut */
@Pointcut("@annotation(com.example.boot.aspect.Log)")
public void logPointcut(a) {}/** * Notice before declaration **@param point point
*/
@Before("logPointcut()")
public void doBefore(JoinPoint point) {
log.info("LogAspect1:doBefore");
}
/** * Notice after declaration **@param point point
* @param returnValue returnValue
*/
@AfterReturning(pointcut = "logPointcut()", returning = "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
log.info("LogAspect1:doAfterReturning,returnValue:{}", returnValue);
}
/** * Declare exception notification **@param e e
*/
@AfterThrowing(pointcut = "logPointcut()", throwing = "e")
public void doAfterThrowing(Exception e) {
log.error("LogAspect1:doAfterThrowing", e);
}
/** * Declaration final Notice */
@After("logPointcut()")
public void doAfter(a) {
log.info("LogAspect1:doAfter");
}
/** * Configure surround notifications, using pointcuts ** registered with the method logPointcut()@param joinPoint join point for advice
*/
@Around("logPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("LogAspect1:doAround-1");
Object result = joinPoint.proceed();
log.info("LogAspect1:doAround-2");
returnresult; }}Copy the code
LogAspect2
package com.example.boot.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* com.example.boot.aspect
* Description:
*
* @author jack
* @date2021/6/24 11:18am */
@Aspect
@Component
@Slf4j
@Order(2)
public class LogAspect2 {
/** * Configure pointcut */
@Pointcut("@annotation(com.example.boot.aspect.Log)")
public void logPointcut(a) {}/** * Notice before declaration **@param point point
*/
@Before("logPointcut()")
public void doBefore(JoinPoint point) {
log.info("LogAspect2:doBefore");
}
/** * Notice after declaration **@param point point
* @param returnValue returnValue
*/
@AfterReturning(pointcut = "logPointcut()", returning = "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
log.info("LogAspect2:doAfterReturning,returnValue:{}", returnValue);
}
/** * Declare exception notification **@param e e
*/
@AfterThrowing(pointcut = "logPointcut()", throwing = "e")
public void doAfterThrowing(Exception e) {
log.error("LogAspect2:doAfterThrowing", e);
}
/** * Declaration final Notice */
@After("logPointcut()")
public void doAfter(a) {
log.info("LogAspect2:doAfter");
}
/** * Configure surround notifications, using pointcuts ** registered with the method logPointcut()@param joinPoint join point for advice
*/
@Around("logPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("LogAspect2:doAround-1");
Object result = joinPoint.proceed();
log.info("LogAspect2:doAround-2");
returnresult; }}Copy the code