Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在AOP for@Async方法中处理异常时丢失HttpServletRequest对象_Java_Spring_Spring Boot_Spring Aop - Fatal编程技术网

Java 在AOP for@Async方法中处理异常时丢失HttpServletRequest对象

Java 在AOP for@Async方法中处理异常时丢失HttpServletRequest对象,java,spring,spring-boot,spring-aop,Java,Spring,Spring Boot,Spring Aop,我遵循并创建了Executor、Callable和ExecutorConfig,正如答案中所描述的那样。现在我开始在AOP代码中获取HttpServletRequest对象,但该对象不包含任何内容。例如,request.getRequestURI()为NULL。 在我的AOP代码中,我只需要读取Throwable和HttpServletRequest对象,将错误信息和一些重要的请求头以及URI存储在表中 这是我的AOP代码- @Aspect @Component public class Err

我遵循并创建了Executor、Callable和ExecutorConfig,正如答案中所描述的那样。现在我开始在AOP代码中获取HttpServletRequest对象,但该对象不包含任何内容。例如,request.getRequestURI()为NULL。 在我的AOP代码中,我只需要读取Throwable和HttpServletRequest对象,将错误信息和一些重要的请求头以及URI存储在表中

这是我的AOP代码-

@Aspect
@Component
public class ErrorAspect {

    private static final String EXCEPTION_EXECUTION_PATH = "execution(* com.myproject.*.service.impl.*.*(..))";

    @Autowired
    private ErrorHelper         errorHelper;

    @Pointcut( EXCEPTION_EXECUTION_PATH)
    public void atExecutionExcpetion() {
    }

    @AfterThrowing( value = "atExecutionExcpetion()", throwing = "error")
    public void storeErrorAfterThrowing( Throwable error) {
        errorHelper.saveError(error);
    }
}
ErrorHelper中的saveError()方法是-

public void saveError( Throwable error) {
        HttpServletRequest request = null;
        if (RequestContextHolder.getRequestAttributes() != null) {
            request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        }
        Error error = prepareError(request, error);
        CompletableFuture.runAsync(() -> insertError(error));
    }  

private Error prepareError( HttpServletRequest request, Throwable error) {
    Error error = new Error();
    if (request == null) {
        String process = Constants.AUTO_JOB + LocalDateTime.now(ZoneId.of(PST_ZONE_ID)).toString().replaceAll("-", "");
        error.setProcessType(Constants.AUTO_JOB);
        error.setApplicationId(process);
        error.setSessionId(process);
        error.setUri(NA);
    } else {
        error.setProcessType(request.getHeader(Constants.PROCESS_ID));
        error.setApplicationId(request.getHeader(Constants.APPLICATION_ID));
        error.setSessionId(request.getHeader(Constants.SESSION_ID));
        error.setUri(request.getRequestURI());
    }
    error.setEventDateTime(Instant.now());
    error.setErrorType(getErrorType(error));
    error.setErrorMessage(getErrorMessage(error));
    return error;
}

这对于同步调用非常有效。但是对于@Async调用,请求对象中没有头/uri信息。

创建了一个装饰器,并将所需的请求属性复制到MDC。这是装饰代码-

public class ContextAwareExecutorDecorator implements Executor, TaskExecutor {

    private final Executor executor;

    public ContextAwareExecutorDecorator( Executor executor) {
        this.executor = executor;
    }

    @Override
    public void execute( Runnable command) {
        Runnable ctxAwareCommand = decorateContextAware(command);
        executor.execute(ctxAwareCommand);
    }

    private Runnable decorateContextAware( Runnable command) {
        RequestAttributes originalRequestContext = RequestContextHolder.currentRequestAttributes();

        if (originalRequestContext != null) {
            HttpServletRequest request = ((ServletRequestAttributes) originalRequestContext).getRequest();
            copyRequestToMDC(request);
        }

        final Map<String, String> originalContextCopy = MDC.getCopyOfContextMap();
        return () -> {
            try {
                if (originalRequestContext != null) {
                    RequestContextHolder.setRequestAttributes(originalRequestContext);
                }
                MDC.setContextMap(originalContextCopy);
                command.run();
            } finally {
                MDC.clear();
                RequestContextHolder.resetRequestAttributes();
            }
        };
    }

    private void copyRequestToMDC( HttpServletRequest request) {
        if (request != null) {
            MDC.put("requestURI", request.getRequestURI());
            // Set other required attributes
        }
    }
}
现在在AOP代码中,我能够从MDC检索属性

error.setUri(MDC.get("requestURI"));

我这里的问题和你在这里看到的一样,你能帮我解决这个问题吗?您的代码中的MDC是什么?
error.setUri(MDC.get("requestURI"));