标题: [讨论]当自定义的注解用在异步方法上时,如何在Spring AOP切面恰当的位置获取到请求头里token等信息
时间: 04-02 11:22发布,04-02 12:44修改
SpringBoot项目,项目中早已整合了一套Spring AOP切面相关技术实现,该有的流程都有,常规操作就是给方法加上自定义注解就可以在被调用时,根据当前请求头获取到用户信息(token)、请求IP地址等信息,然后分两种情况写入数据库日志表:
但是现在有个新的需求,如题,当我尝试将该现有的日志注解写在主线程中的“某个异步方法”时,切面日志类在写入数据库之前有个“获取请求头”信息的的操作理所当然的报错了。
这两天我没少查阅资料,为了存请求头信息,考虑过redis、MQTT、MySQL在记录一条请求头的记录等等,都被我推翻了。目前我采用写死的方案:
然后我将当前的日志切面类(LogAspect)抽离成父类(BaseLogAspect),再定义一个异常日志切面类(LogAsyncAspect),分别继承自父类(BaseLogAspect),其中LogAspect留空不写,完整继承父类;LogAsyncAspect则是部分继承,部分重写父类方法,这里我重写了获取用户请求头信息的那个方法,我不再通过String userStr = request.getHeader(AuthConstant.USER_TOKEN_HEADER);
获取,而是改成用我上面预设的用户信息,请求ip用localhost;(以上还在撸代码,执行结果暂时未知是否符合当前预期)
/**
* @apiNote 日志异步切面<br>
* 部分继承 BaseLogAspect 抽象类,部分重写。
* @since 2024年3月29日
* @author TabKey9
* @version 0.0.1.240329
*/
@Slf4j
@Aspect
@Component
public class LogAsyncAspect extends BaseLogAspect {
@Override
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
try {
// 虚拟一个异步线程专用账号信息
UserDto userDto = new UserDto();
userDto.setId(-1L);
userDto.setUsername("异步操作专员");
// MySQL 日志记录表实体对象
SysOperLogEntity operLog = new SysOperLogEntity();
// 操作状态
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址 【获取不到】
operLog.setOperIp("localhost");
// 请求url 【获取不到】
operLog.setOperUrl("/**");
// 操作人员
operLog.setOperName(userDto.getUsername());
if (e != null) {
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(e.getMessage());
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 设置请求方式
operLog.setRequestMethod("Async");
// 处理设置注解上的参数 【调用父类方法】
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 设置消耗时间 【TIME_THREADLOCAL在父类用protected修饰符定义】
operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
operLog.setOperTime(new Date());
// 保存数据库 【sysOperLogService在父类用protected修饰符定义】
sysOperLogService.save(operLog);
} catch (Exception exp) {
// 记录本地异常日志
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
} finally {
//【TIME_THREADLOCAL在父类用protected修饰符定义】
TIME_THREADLOCAL.remove();
}
}
}
请问:我的做法合理吗?或者有哪里考虑不周吗?以及还有其它解决方案嘛?
『回复列表(4|隐藏机器人聊天)』