一、關於AOP
無侵入的方式作用於方法當中,在controller層攔截並打印請求報文和響應報文
二、annotation類
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @class ApiLog
* @classdesc 用於打印請求和響應日志的注解
* @author chh
* @date 2020/8/26 14:43
* @version 1.0.0
* @see
* @since
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiLog {
}
三、切面實現類
package com.boss.xtrain.log.api.aop;
import com.boss.xtrain.core.context.BaseContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
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.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* @class MyApiLogAspect
* @classdesc 實現ApiLog的功能,即打印請求日志和響應日志
* @author chh
* @date 2020/8/26 15:07
* @version 1.0.0
* @see
* @since
*/
@Aspect
@Component
@Slf4j
public class MyApiLogAspect {
/**
* 記錄業務請求的時間
*/
private long req;
private String reqTime;
/**
* @param: void
* @return: void
* @desc: 定義空方法用於切點表達式
* @see
* @since
*/
@Pointcut("@annotation(com.boss.xtrain.log.api.annotation.ApiLog)")
public void pointcut(){
//do nothing just for filtering
}
/**
* @param: [joinPoint]
* @return: void
* @desc: 在進入controller之前攔截並打印請求報文日志
* @see
* @since
*/
@Before("pointcut()")
public void printRequestDatagram(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = getIpAddress(request);
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
SimpleDateFormat dateFormat = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
req = System.currentTimeMillis();
reqTime = dateFormat.format (new Date(req));
Object[] args = joinPoint.getArgs ();
log.info ("==> 攔截到請求\n"
+ "==> 請求者工號:" + BaseContextHolder.getUserCode() + "\n"
+ "==> 請求者IP:" + ip + "\n"
+ "==> 請求時間:" + reqTime + "\n"
+ "==> 請求接口:" + request.getMethod() + " " + request.getRequestURL() + "\n"
+ "==> 請求方法:" + method.getName() + "\n"
+ "==> 參數內容:"+ Arrays.toString(args));
}
/**
* @param: [joinPoint]
* @return: java.lang.Object
* @desc: 返回信息后,打印應答報文的日志
* @see
* @since
*/
@Around("pointcut()")
public Object printResponseDatagram(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
result = joinPoint.proceed ();
long respTime = System.currentTimeMillis() - req;
String d = String.valueOf(respTime);
log.info ( "<== 響應請求\n"
+ "<== 請求時間:" + reqTime + "\n"
+ "<== 請求耗時:" + Double.parseDouble(d)/1000 + "s\n"
+ "<== 應答內容:" + result );
return result;
}
/**
* @param: [request]
* @return: java.lang.String
* @desc: 獲取IP地址
* @see
* @since
*/
private String getIpAddress(HttpServletRequest request){
final 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();
}
return ip;
}
}