定义注解
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
/**
* 方法描述,可使用占位符获取参数:{{tel}}
*/
String detail() default "";
/**
* 日志等级:自己定,此处分为1-9
*/
int level() default 0;
/**
* 操作类型(enum):主要是select,insert,update,delete
*/
OperationType operationType() default OperationType.UNKNOWN;
}
创建切面 (AOP)
@Aspect
@Component
public class OperationRecordAspect {
@Resource
private UserAuthorityService userAuthorityService;
@Pointcut("@annotation(com.onecent.avatar.annotation.OperationLog)")
public void operationLog() {
}
/**
* 环绕增强,相当于MethodInterceptor
*/
@Around("operationLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object res = null;
long time = System.currentTimeMillis();
try {
res = joinPoint.proceed();
time = System.currentTimeMillis() - time;
return res;
} finally {
try {
//方法执行完成后增加日志
addOperationLog(joinPoint, res, time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void addOperationLog(JoinPoint joinPoint, Object res, long time) {
String args = getParamter(joinPoint.getArgs());
//获得登录用户信息
UserAuthorityDTO account = (UserAuthorityDTO) SecurityUtils.getSubject().getPrincipal();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
OperationRecord record = new OperationRecord();
record.setUserId(account.getId());
record.setUserName(account.getUserName());
record.setPerms(account.getPerms());
record.setRole(account.getRole());
record.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
OperationLog annotation = signature.getMethod().getAnnotation(OperationLog.class);
if (annotation != null) {
record.setLogLevel(annotation.level());
record.setLogDescribe(annotation.detail());
record.setOperationType(annotation.operationType().getValue());
}
log.info(String.valueOf(account));
log.info("add operation record {}, params {}", record, args);
userAuthorityService.addOperationRecord(record);
}
/**
* 对当前登录用户和占位符处理
*
* @param args 方法参数数组
* @return 返回处理后的描述
*/
private String getParamter(Object[] args) {
Object[] arguments = new Object[args.length];
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
//ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
//ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
continue;
}
arguments[i] = args[i];
}
String paramter = "";
if (arguments != null) {
try {
paramter = JSONObject.toJSONString(arguments);
} catch (Exception e) {
paramter = arguments.toString();
}
}
return paramter;
}
@Before("operationLog()")
public void doBeforeAdvice(JoinPoint joinPoint) {
}
/**
* 处理完请求,返回内容
*
* @param ret
*/
@AfterReturning(returning = "ret", pointcut = "operationLog()")
public void doAfterReturning(Object ret) {
}
/**
* 后置异常通知
*/
@AfterThrowing("operationLog()")
public void throwss(JoinPoint jp) {
}
/**
* 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
*/
@After("operationLog()")
public void after(JoinPoint jp) {
}
}
应用场景
/**
* 删除用户
*/
@PostMapping("/user/del")
@OperationLog(detail = "删除用户", level = 1, operationType=“DELETE”)
public Response userDrl(@RequestParam String userName) throws Exception {
if (CheckUtils.checkEmpty(userName)) {
return new Response((ResponseCode.INVALID_PARAMETERS));
}
if (userAuthorityMapper.delUserByUserName(userName) == 1) {
return new Response(ResponseCode.SUCCESS);
}
return new Response(ResponseCode.FAILED);
}