java开发AOP(动态代理)是个比较常用的一种开发思想,今天以一个拦截请求记录操作日志的Demo分享下AOP的实现
image.png
@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;
}
@Aspect
@Slf4j
public class LogControllerAop {
@Value("${spring.application.name}")
private String model;
// 拦截所有@RestController
@Around("@within(org.springframework.web.bind.annotation.RestController)")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("开始捕获用户操作日志");
UserOperation userOperation = new UserOperation();
long startTime = 0;
try {
// 获取Request对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
LoginAppUser loginAppUser = AppUserUtil.getLoginAppUser();
if (null != loginAppUser) {
// 操作人
userOperation.setUsername(StringUtil.getValue(loginAppUser.getUsername(),"内部feign调用"));
// 操作人账号
userOperation.setNickname(StringUtil.getValue(loginAppUser.getNickname(),"内部feign调用"));
}else {
// 操作人
userOperation.setUsername("内部feign调用");
// 操作人账号
userOperation.setNickname("内部feign调用");
}
// 操作名称
userOperation.setMethodName(joinPoint.getSignature().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);
Object[] args = new Object[0];
try {
// 请求参数
args = joinPoint.getArgs();
String param = JSON.toJSONString(args);
userOperation.setRequestParam(param);
} catch (Exception e) {
log.error("截取参数异常"+e);
}
} catch (Exception e) {
e.printStackTrace();
}
Object proceed = null;
try {
proceed = joinPoint.proceed();
userOperation.setResultStatus("success");
return proceed;
} catch (Exception e) {
// 堆栈错误信息
String stackTrace = Arrays.toString(e.getStackTrace());
// 错误信息
String message = e.getMessage();
ConcurrentHashMap<String, String> errorMsg = new ConcurrentHashMap<>();
errorMsg.put("stackTrace",stackTrace);
errorMsg.put("message", e.getClass().getName() + ": " + message);
userOperation.setErrorInfo(JSON.toJSONString(errorMsg));
userOperation.setResultStatus("error");
throw e;
} finally {
try {
if (StringUtil.notEmpty(proceed)) {
// 返回结果
userOperation.setResponseResult(JSON.toJSONString(proceed));
}
// 请求结束时间
Date endDate = new Date();
userOperation.setRequestEndTime(endDate);
userOperation.setResponseDate(endDate.getTime() - startTime);
} catch (Exception e) {
log.error("获取返回结果异常{}"+e);
}
// 异步将操作日志保存
CompletableFuture.runAsync(() -> {
try {
// 保存日志,具体方法自定义
this.save(userOperation);
} catch (Exception e2) {
log.error("用户操作日记记录异常:{}"+e2);
}
});
}
}
}
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(LogControllerAop.class)
public class LogAutoConfiguration {
}
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 {
}
说明:在启动类加上该注解就可以注入
原网址: 访问
创建于: 2020-12-10 11:44:26
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论