springboot通过aop环形切的方式来实现日志记录
添加依赖
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
implementation 'com.alibaba:fastjson:1.2.78'
自定义注解
package com.shop.annos;
import com.shop.codes.EnumOperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//注解在哪个阶段执行
@Retention(RetentionPolicy.RUNTIME)
//注解放置的目标位置,METHOD是可注解在方法级别上
@Target({ElementType.METHOD})
public @interface OperLog {
String message(); // 介绍
EnumOperationType operation(); // 日志类型
}
日志实体类
package com.shop.entity;
import java.util.Date;
/*
*日志实体类 SysLog
*/
public class SysLog {
private Long id; //
private String userId; // 操作用户 ID
private String message; // 消息
private String operation; // 日志类型
private String method; // 请求方法
private String params; // 请求参数
private String ip; // 请求IP
private Date createDate;// 请求时间
private Long totalTime; //总耗时长(毫秒)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Long getTotalTime() {
return totalTime;
}
public void setTotalTime(Long totalTime) {
this.totalTime = totalTime;
}
}
操作类型类
package com.shop.codes;
/**
* 操作类型类 OperationType
*/
public enum EnumOperationType {
LOGIN("LOGIN"),
LOGOUT("LOGOUT"),
INSERT("INSERT"),
QUERY ("QUERY"),
UPDATE ("UPDATE "),
DELETE ("DELETE ");
private String desc;
EnumOperationType(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "EnumStatusCode{" +
" desc='" + desc + '\'' +
'}';
}
}
切面处理
package com.shop.config.LogAsceptConfig;
import com.alibaba.fastjson.JSON;
import com.shop.annos.OperLog;
import com.shop.entity.SysLog;
import java.lang.reflect.Method;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 系统日志:切面处理类
*/
@Aspect
@Component
public class SysLogAspect {
private static Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
//定义切点 @Pointcut
//在注解的位置切入代码
@Pointcut("@annotation( com.shop.annos.OperLog)")
public void logPoinCut() {
}
//@Around:环绕通知
@Around("logPoinCut()")
public Object saveSysLog(ProceedingJoinPoint proceedingJoinPoint) {
logger.info("环绕通知开始。。。。。");
//保存日志
SysLog sysLog = new SysLog();
//从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取操作
OperLog myLog = method.getAnnotation(OperLog.class);
if (myLog != null) {
String value = myLog.message();
sysLog.setMessage(value);//保存获取的操作
}
//获取请求的类名
String className = proceedingJoinPoint.getTarget().getClass().getName();
//获取请求的方法名
String methodName = method.getName();
sysLog.setMethod(className + "." + methodName);
//请求的参数
Object[] args = proceedingJoinPoint.getArgs();
//将参数所在的数组转换成json
String params = JSON.toJSONString(args);
sysLog.setParams(params);
sysLog.setCreateDate(new Date());
//获取用户名
//获取用户ip地址
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("URL : " + request.getRequestURL().toString());
logger.info("HTTP_METHOD : " + request.getMethod());
logger.info("IP : " + request.getRemoteAddr());
sysLog.setIp(request.getRemoteAddr());
//开始调用时间
// 计时并调用目标函数
long start = System.currentTimeMillis();
Long time = System.currentTimeMillis() - start;
sysLog.setTotalTime(time);
//调用service保存SysLog实体类到数据库
//sysLogService.save(sysLog);
try {
Object result = proceedingJoinPoint.proceed();
logger.info(" "+result.toString());
logger.info("环绕通知结束。。。。。");
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
logger.info(""+throwable);
}
return "系统异常";
}
}
将注解加到需要记录用户操作的方法体上
在Controller层上添加我们的自定义注解就可以了:
@OperLog(message = “日志描述”,operation = 日志类型)
@PostMapping(value = "/loginIn")
@OperLog(message = "用户登录",operation = EnumOperationType.LOGIN)
@ApiOperation(value = "登录接口",notes = "登录接口",produces = "application/json")
public String login(String name,String password){
User user = tidDSUserService.loginIn(name,password);
// String s = weatherController.QueryWeather();
if(user !=null){
return "success";
}else {
return "error";
}
}
爱意随风起,风停意难平
爱意随风起,却不随风散