引入注解
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
创建日志注解
创建@AuditLog注解,作用与方法,生命周期存在于vm运行
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuditLog {
String method() default "";
String methodDescription() default "";
String httpMethod() default "";
String[] storageMode() default {"file"};
}
为@AuditLog注解声明切面
/*
声明切面
*/
@Aspect
@Component
@Slf4j
public class AuditLogAspect {
/*
定义切点,标记方法
*/
@Pointcut("@annotation(com.study.customannotation.aspect.annotation.AuditLog)")
public void operationLog() {
}
/**
*
*环绕增强,相当于MethodInterceptor
*
* @param joinPoint
* @param auditLog
* @return
*/
@Around("operationLog() && @annotation(auditLog)")
public Object arround(ProceedingJoinPoint joinPoint, AuditLog auditLog){
long beginTime = System.currentTimeMillis();
boolean result = true;
Object res = null;
try {
res = joinPoint.proceed();
} catch (Throwable throwable) {
result = false;
throwable.printStackTrace();
}finally {
}
long endTime = System.currentTimeMillis();
long requestTime = endTime - beginTime;
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String[] storageMode = auditLog.storageMode();
if (ArrayUtils.contains(storageMode, "file")) {
info_aop("", "", joinPoint.getSignature().getDeclaringTypeName(), auditLog.httpMethod(), joinPoint.getSignature().getName(), auditLog.method(), auditLog.methodDescription(), this.getIpAddr(request), ZonedDateTime.ofInstant(Instant.ofEpochMilli(beginTime), ZoneId.systemDefault()).format(DateTimeFormatter.ISO_INSTANT), ZonedDateTime.ofInstant(Instant.ofEpochMilli(endTime), ZoneId.systemDefault()).format(DateTimeFormatter.ISO_INSTANT), (double)requestTime, result);
}
return res;
}
public static void info_aop(final String userId, final String tenantCode, final String className, final String httpMethod, final String method, final String api, final String methodDescription, final String requestIp, final String startTime, final String endTime, final double duration, final boolean result) {
String logReturnMsg = "{\"startTime\":\"{}\",\"endTime\":\"{}\",\"userId\":\"{}\",\"tenantCode\":\"{}\",\"package\":\"{}\",\"method\":\"{}\",\"httpMethod\":\"{}\",\"api\":\"{}\",\"methodDescription\":\"{}\",\"requestIp\":\"{}\",\"duration\":\"{}\",\"result\":\"{}\"}";
log.info(logReturnMsg, new Object[]{startTime, endTime, userId, tenantCode, className, method, httpMethod, api, methodDescription, requestIp, duration, result});
}
private String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-DictClient-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-DictClient-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return StringUtils.substringBefore(ip, ",");
}
@Before("operationLog()")
public void doBeforeAdvice(JoinPoint joinPoint){
System.out.println("进入方法前执行.....");
}
/**
* 处理完请求,返回内容
* @param ret
*/
@AfterReturning(returning = "ret", pointcut = "operationLog()")
public void doAfterReturning(Object ret) {
System.out.println("方法的返回值 : " + ret);
}
/**
* 后置异常处理
* @param joinPoint
*/
@AfterThrowing("operationLog()")
public void throwss(JoinPoint joinPoint){
System.out.println("方法异常时执行.....");
}
/**
* 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
*
* @param jp
*/
@After("operationLog()")
public void after(JoinPoint jp){
System.out.println("方法最后执行.....");
}
}
在Controller的方法上添加@AuditLog注解
当执行到方法时,就会执行切面中的方法,通过java反射机制记录交易的日志,如:交易时间,交易ip,执行的类,指定的方法,参数,交易用时,交易结果等等
@GetMapping("/BloodDonation/page")
@AuditLog(method = "/api/BloodDonation/page", methodDescription = "献血列表(分页)", httpMethod = "GET")
@ApiOperation(value = "献血列表(分页)")
public ResponseEntity<ReturnResultDTO<?>> findBloodDonationPage(QueryUpbdBloodDonationRecordEntityDTO upbdBloodDonationRecordEntityDTO, Page page) {
return prepareReturnResult(ReturnCode.SUCCESS.getCode(), upbdBloodDonationService.findBloodDonation(page,upbdBloodDonationRecordEntityDTO));
}
git项目demo
https://gitee.com/ding-dawei/custom-annotation.git