首先说明这篇文章没有解决办法
背景
用spring boot aop添加操作日,为了给前端更快的返回结果,日志操作用了异步方式
问题
为了获取请求地址,调用异步方法会把request传过去,有时候这里
String url = request.getRequestURL().toString();
会报空指针异常
aop方法代码:
@AfterReturning(returning = "result", pointcut = "log()")
public void doAfterReturning(Result result) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
System.out.println("+++++++++++++++++++++++");
System.out.println(request.getRequestURL().toString());
System.out.println("+++++++++++++++++++++++");
operationUtil.operationRedis(request, result);
}
System.out.println("执行时间: " + (System.currentTimeMillis() - startTime.get()) + "ms");
startTime.remove();
}
异步方法代码:
@Async
public void operationRedis(HttpServletRequest request, Result result) {
System.out.println("========================");
System.out.println(request.getRequestURL().toString());
System.out.println("========================");
String ip = GetIp.getIpAddress(request);
String url = request.getRequestURL().toString();
url = url.substring(url.lastIndexOf("/") + 1);
if (DELETE.equals(url) || UPDATE.equals(url) || CREATE.equals(url)) {
JSONObject user = JSON.parseObject(request.getParameter("tokenUser"));
Operation operation = new Operation(null, result.getLogs(), null, LocalDateTime.now(), ip, (Integer) user.get("id"), (Integer) user.get("companyId"), (String) user.get("name"));
switch (url) {
case DELETE:
operation.setType(OperationEnum.DELETE.value());
break;
case UPDATE:
operation.setType(OperationEnum.UPDATE.value());
break;
case CREATE:
operation.setType(OperationEnum.CREATE.value());
break;
default:
break;
}
redisTemplate.opsForList().rightPush(operationRedisKey, operation);
}
//如果redis中的操作记录数量大于2000就立刻写入数据库
if (redisTemplate.opsForList().size(operationRedisKey) > MAX_LIST) {
operationPersistence();
}
}
报错:
原因
个人猜测是aop方法执行完后 jvm 就把 request 回收了,导致异步方法里的 request
值为空
验证
在异步方法里面先睡眠2秒,在调用方法,发现每次都会抛出空指针异常
解决
还没想到。。。emmm