若依远程调用异步方法AOP日志无法写入
问题场景描述:
修改菜单是远程异步方法可以正常写入日志,但无法写入业务操作日志.异常如下:
/**
* 保存系统日志记录
*/
@Async //取消异步请求可以正常写入日志,但为了用户体验效果和运行速度后来想来想去还是异步快。
public void saveSysLog(SysOperLog sysOperLog){
remoteOperLogService.saveLog(sysOperLog);
}
目前系统写入日志流程如下
1、safe-business 模块->调用者
2、ruoyi-common-log 模块->异步方法
3、ruoyi-common-log 模块->操作日志远程服务接口 feign api
4、ruoyi-api-system 模块->system模块controller
5、ruoyi-system 模块->service-impl-mapper
@PostMapping
@ResponseBody
@Log(title = "测试", businessType = BusinessType.UPDATE)
public AjaxResult add(@RequestBody Demo demo) {
System.out.println(demo.getName());
return AjaxResult.success(null);
}
/**
* 自定义操作日志记录注解
*
* @author 黑猫
*
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/**
* 模块
*/
public String title() default "";
/**
* 功能
*/
public BusinessType businessType() default BusinessType.OTHER;
/**
* 操作人类别
*/
public OperatorType operatorType() default OperatorType.PC;
/**
* 是否保存请求的参数
*/
public boolean isSaveRequestData() default true;
}
/**
* 操作日志记录处理
*
* @author 黑猫
*/
@Aspect
@Component
public class LogAspect{
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {
try
{
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
return;
}
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
operLog.setOperIp(ip);
// 返回参数
operLog.setJsonResult(JSON.toJSONString(jsonResult));
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
String username = SecurityUtils.getUsername();
if (StringUtils.isNotBlank(username))
{
operLog.setOperName(username);
}
if (e != null)
{
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 设置请求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog);
// 保存数据库
asyncLogService.saveSysLog(operLog);//主要看这行代码
}
catch (Exception exp)
{
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
}
/**
* 异步调用日志服务
*
* @author 黑猫
*/
@Service
public class AsyncLogService
{
@Autowired
private RemoteLogService remoteLogService;
@Autowired
private RemoteOperLogService remoteOperLogService;
/**
* 保存系统日志记录
*/
@Async
public void saveSysLog(SysOperLog sysOperLog)
{
remoteOperLogService.saveLog(sysOperLog);
}
}
/** 操作日志远程服务接口
* @Author: 黑猫
* @Date: 2022/6/28 15:41
*/
@FeignClient(contextId = "remoteOperLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteOperLogFallbackFactory.class)
public interface RemoteOperLogService
{
/**
* 保存系统日志
* @param sysOperLog 日志实体
* @return 结果
*/
@PostMapping("/operlog")
R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog);
/**
* 保存业务操作日志记录
* @param operLog 业务日志实体
* @return
*/
@PostMapping("/businessoperlog")
R<Boolean> saveBusinessOperLog(@RequestBody JsjdBusinessOperLog operLog);
}
/**
* 操作日志记录
* @Author: 黑猫
* @Date: 2022/6/28 15:41
*/
@RestController
@RequestMapping("/operlog")
public class SysOperlogController extends BaseController
{
@PostMapping
public AjaxResult add(@RequestBody SysOperLog operLog)
{
return toAjax(operLogService.insertOperlog(operLog));
}
}
其它的代码就忽略了。
最后发现本人的问题处在FeignSecureRequestInterceptor拦截器上. 注释掉就可以正常了。
/** feign拦截器:请求header传递
* @Author: 黑猫
* @Date: 2022/6/28 15:41
*/
@Component
public class FeignSecureRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
requestTemplate.header(name, values);
}
}
}
}
总结:
1:启动类添加@EnableAsync注解
2:异步方法添加@async注解
注意:异步方法跟调用异步的方法不能在同一个类,如果同一个类里放就等于同步不生效。
本文来自博客园,作者:星星之草%,转载请注明原文链接:https://www.cnblogs.com/zhaodefu/p/16418724.html