一、概述
java开发AOP(动态代理)是个比较常用的一种开发思想,今天以一个拦截请求记录操作日志的Demo分享下AOP的实现
二、分享开始
2.1 结构

2.2 日志信息记录类
@Data
public class UserOperation {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long operationLogId;
/**
* 用户昵称
*/
private String nickname;
/**
* 用户账号
*/
private String username;
/**
* 操作名称
*/
private String methodName;
/**
* 操作时间
*/
private Date operationTime;
/**
* 请求IP
*/
private String requestIp;
/**
* 请求URL
*/
private String requestUrl;
/**
* 请求参数
*/
private String requestParam;
/**
* 返回结果
*/
private String responseResult;
/**
* 操作结果
*/
private String resultStatus;
/**
* 错误信息
*/
private String errorInfo;
/**
* 模块
*/
private String model;
/**
* 请求开始时间
*/
private Date requestStartTime;
/**
* 请求结束时间
*/
private Date requestEndTime;
/**
* 响应时间
*/
private Long responseDate;
}
2.3 AOP实现类
@Aspect
@Slf4j
public class DbLogControllerAop {
// 服务模块名字
public String model;
// 成功状态
private static final String success = "success";
// 失败状态
private static final String error = "error";
// 是否只记录错误日志
public static final boolean IS_ONLY_RECORD_ERROR = true;
// 拦截@RestController下所有的方法
@Around("@within(org.springframework.web.bind.annotation.RestController)")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed = null;
UserOperation userOperation = new UserOperation();
long startTime = 0;
try {
// 获取Request对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 获取当前用户信息
setLoginUserInfo(userOperation);
// 设置请求参数
setServiceInfo(joinPoint, userOperation);
// 设置接口基础信息
startTime = getApiBaseInfo(joinPoint, userOperation, startTime, request);
} catch (Exception e) {
String errorMsg = ExceptionUtil.getErrorMsg(e);
log.error("设置日子基础信息异常:{}" + errorMsg);
}
try {
// 执行具体业务
proceed = joinPoint.proceed();
userOperation.setResultStatus(success);
// 设置返回参数
setReturnInfo(proceed, userOperation);
} catch (Exception e) {
String errorMsg = ExceptionUtil.getErrorMsg(e);
userOperation.setErrorInfo(errorMsg);
userOperation.setResultStatus(error);
throw e;
}
try {
// 保存日志
if (IS_ONLY_RECORD_ERROR) {
if (error.equals(userOperation.getResultStatus())) {
saveLog(userOperation, startTime);
}
}else {
saveLog(userOperation, startTime);
}
} catch (Exception e) {
String errorMsg = ExceptionUtil.getErrorMsg(e);
log.error("保存日志异常:{}" + errorMsg);
}
return proceed;
}
public void saveLog(UserOperation userOperation, long startTime) {
// 请求结束时间
Date endDate = new Date();
userOperation.setRequestEndTime(endDate);
userOperation.setResponseDate(endDate.getTime() - startTime);
BizDocumentInfoHolder.clear();
// 异步将操作日志保存
CompletableFuture.runAsync(() -> {
try {
// logClient.save(userOperation);
} catch (Exception e2) {
log.error("用户操作日记记录异常:{}" + ExceptionUtil.getErrorMsg(e2));
}
});
}
public long getApiBaseInfo(ProceedingJoinPoint joinPoint, UserOperation userOperation, long startTime, HttpServletRequest request) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 操作名称
userOperation.setMethodName(signature.getName());
// 操作时间
Date date = new Date();
startTime = date.getTime();
userOperation.setOperationTime(date);
// 请求开始时间
userOperation.setRequestStartTime(date);
// 请求IP
userOperation.setRequestIp(IPUtil.getRemoteIpAddr(request));
// URL
userOperation.setRequestUrl(request.getRequestURI());
// 模块
userOperation.setModel(model);
return startTime;
}
public void setLoginUserInfo(UserOperation userOperation) {
LoginAppUser loginAppUser = AppUserUtil.getLoginAppUser();
if (null != loginAppUser) {
// 操作人
userOperation.setUsername(StringUtil.getValue(loginAppUser.getUsername(), "内部feign调用"));
// 操作人账号
userOperation.setNickname(StringUtil.getValue(loginAppUser.getNickname(), "内部feign调用"));
// 用户类型
userOperation.setUserType(StringUtil.getValue(loginAppUser.getUserType(), "system"));
} else {
// 操作人
userOperation.setUsername("内部feign调用");
// 操作人账号
userOperation.setNickname("内部feign调用");
// 用户类型
userOperation.setUserType("system");
}
}
public void setServiceInfo(ProceedingJoinPoint pjp, UserOperation userOperation) {
try {
// 获取请求参数
Object[] args = pjp.getArgs();
if(!ObjectUtils.isEmpty(args)){
String paramJson = JSON.toJSONString(args);
userOperation.setRequestParam(paramJson);
}
} catch (Exception e) {
String errorMsg = ExceptionUtil.getErrorMsg(e);
userOperation.setRequestParam("请求参数解析报错{}" + errorMsg);
}
}
public void setReturnInfo(Object obj, UserOperation userOperation) {
if (!ObjectUtils.isEmpty(obj)) {
try {
String paramJson = JSON.toJSONString(obj);
userOperation.setResponseResult(paramJson);
} catch (Exception e) {
String errorMsg = ExceptionUtil.getErrorMsg(e);
userOperation.setResponseResult("返回参数解析报错{}" + errorMsg);
}
}
}
}
2.4 配置类注解
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(LogControllerAop.class)
public class LogAutoConfiguration {
}
2.5 注入类注解
import org.springframework.context.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(LogAutoConfiguration.class)
public @interface EnableOpLog {
}
说明:在启动类加上该注解就可以注入
网友评论