添加AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
自定义操作日志记录注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
public String title(); // 操作业务的功能名称
public String operatorType(); // 操作人类别
public int businessType(); // 业务类型(0其它;1新增;2修改;3删除)
public boolean isSaveRequestData() default true; // 是否保存请求的参数
public boolean isSaveResponseData() default true; // 是否保存响应的参数
}
定义一个切面类,并且在该切面类中提供一个环绕通知方法
@Aspect
@Component
public class LogAspect {
@Resource
private AsyncOperLogService asyncOperLogService;
@Around("@annotation(sysLog)")
public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog) {
// 构建前置参数
SysOperLog sysOperLog = new SysOperLog();
LogUtil.beforeHandlerLog(sysLog, joinPoint, sysOperLog);
Object proceed = null;
try {
proceed = joinPoint.proceed();
// 执行业务方法
LogUtil.afterHandlerLog(sysLog, proceed, sysOperLog, 0, null);
// 构建响应结果参数
} catch (Throwable e) { // 代码执行进入到catch中,业务方法执行产生异常
e.printStackTrace(); // 打印异常信息
LogUtil.afterHandlerLog(sysLog, proceed, sysOperLog, 1, e.getMessage());
throw new RuntimeException();
}
// 保存日志数据
asyncOperLogService.saveSysOperLog(sysOperLog);
return proceed; // 返回执行结果
}
}
通过Import注解导入日志切面类到Spring容器中
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(LogAspect.class)
public @interface EnableLogAspect {
}
在服务的启动类上添加@EnableLogAspect注解
@EnableLogAspect
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class , args) ;
}
}
定义一个日志实体类
@Data
public class SysOperLog {
private String title; // 模块标题
private String method; // 方法名称
private String requestMethod; // 请求方式
private String operatorType; // 操作类别(0其它 1后台用户 2手机端用户)
private Integer businessType ; // 业务类型(0其它 1新增 2修改 3删除)
private String operName; // 操作人员
private String operUrl; // 请求URL
private String operIp; // 主机地址
private String operParam; // 请求参数
private String jsonResult; // 返回参数
private Integer status; // 操作状态(0正常 1异常)
private String errorMsg; // 错误消息
}
定义一个Log工具类
public class LogUtil {
// 操作执行之前调用
public static void beforeHandlerLog(Log sysLog, ProceedingJoinPoint joinPoint, SysOperLog sysOperLog) {
// 设置操作模块名称
sysOperLog.setTitle(sysLog.title());
sysOperLog.setOperatorType(sysLog.operatorType().name());
// 获取目标方法信息
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
sysOperLog.setMethod(method.getDeclaringClass().getName());
// 获取请求相关参数
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
sysOperLog.setRequestMethod(request.getMethod());
sysOperLog.setOperUrl(request.getRequestURI());
sysOperLog.setOperIp(request.getRemoteAddr());
// 设置请求参数
if (sysLog.isSaveRequestData()) {
String requestMethod = sysOperLog.getRequestMethod();
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
String params = Arrays.toString(joinPoint.getArgs());
sysOperLog.setOperParam(params);
}
}
sysOperLog.setOperName(AuthContextUtil.get().getUserName());
}
// 操作执行之后调用
public static void afterHandlerLog(Log sysLog, Object proceed, SysOperLog sysOperLog, int status, String errorMsg) {
// 是否保存响应的参数
if (sysLog.isSaveResponseData()) {
sysOperLog.setJsonResult(JSON.toJSONString(proceed));
}
sysOperLog.setStatus(status);
sysOperLog.setErrorMsg(errorMsg);
}
}
@Async // 异步执行保存日志操作
@Override
public void saveSysOperLog(SysOperLog sysOperLog) {
sysOperLogMapper.insertSysOperLog(sysOperLog);
}
<insert id="insertSysOperLog">
insert into sys_oper_log (id, title, method, request_method, operator_type, oper_name,
oper_url, oper_ip, oper_param, json_result, status, error_msg)
values (#{id}, #{title}, #{method}, #{requestMethod}, #{operatorType}, #{operName},
#{operUrl}, #{operIp}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg})
</insert>
使用
@Log(title = "logTest", operatorType = "管理平台", businessType = 0)
@PostMapping("/logTest")
public Result logTest() {
// ...
}