如何处理春季启动延迟结果中的异常?



我有一个休息方法:

@RequestMapping(value = "wash/washHistory", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
@ResponseBody
public DeferredResult<String> getWashHistory(@RequestParam(value = "sid", required = true, defaultValue = "") String sid,
HttpServletResponse response, HttpServletRequest request,
@RequestParam(value = "sort", defaultValue = "") String sortType,
@RequestParam(value = "order", defaultValue = "") String order,
@RequestParam(value = "limit", defaultValue = "") String limit,
@RequestParam(value = "offset", defaultValue = "") String offset) {
System.out.println("Thread: "+Thread.currentThread());
final Integer managerId = checkSession(sid);      
DeferredResult<String> defResult = new DeferredResult<>();
new Thread(() -> {
final String result = washController.getWashHistory( managerId, order, sortType, limit, offset);
defResult.setResult(result);            
}).start();
return defResult;
}

在"getWashHistory"中,我抛出以下自定义异常:

throw new InvalidUserInputException("Wrong offset", this.getClass().getSimpleName(), "getWashHist", params);

为了处理此异常,我使用以下类:

@ControllerAdvice
@EnableWebMvc
public class GlobalExceptionHandler {
@ExceptionHandler(value = InvalidUserInputException.class)
public ResponseEntity<String> invalidUserInputExc(InvalidUserInputException e) {
logger.log("GMoika", e.error().getClassName(), e.error().getMethodName(), e.error().getParams(), e.error().getCause());
return ResponseEntity.
status(HttpStatus.BAD_REQUEST).
body(e.error().getErrorCode());  
}
}

只要我不使用延迟结果,它就可以正常工作,但是当我想使用非阻塞方式时,会发生超时异常。 我找到了一种方法来解决它:

defResult.onTimeout(new Runnable() {
@Override
public void run() {
defResult.setErrorResult("Explanation goes here.");
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); //or SC_NO_CONTENT
}
});

但这不是我要找的,因为我用特定的构造函数抛出我自己的异常,以便在抛出此异常的类中编写原因。 是否有任何其他可能的方法可以在我的 GlobalExceptionHandler 类中处理 DeferredResult 中的异常?

DeferredResult有方法setErrorResult可以接受异常,并根据文档:

该值可以是异常或可抛出的,在这种情况下,它将是 处理,就好像处理程序引发异常一样。

在大多数情况下,@jny决定是正确的,但对我来说,我找到了另一种方法 在我的休息控制器中,我添加了以下代码:

new Thread(() -> {          
Thread.currentThread().setUncaughtExceptionHandler(new SeparateThreadsExceptionHandler(defResult));
final String result = washController.getWashHistory(managerId, order, sortType, limit, offset);
defResult.setResult(result);
}).start();

和一个单独的线程异常处理程序类:

public class SeparateThreadsExceptionHandler implements Thread.UncaughtExceptionHandler{
private DeferredResult<String> dr;
public SeparateThreadsExceptionHandler(DeferredResult<String> dr){
this.dr = dr;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if(e instanceof InvalidUserInputException){
InvalidUserInputException throwableException =  (InvalidUserInputException)e;
dr.setResult(throwableException.error().getErrorCode());
} else {
dr.setResult(UnknownException.UNKNOWN_ERROR_CODE);
}
}
}

当我的自定义异常被抛出时,我可以将一些字符串错误消息设置为 DeferredResult。在我的示例中,它是前端的错误代码。

是否有任何其他可能的方法可以在我的全局异常处理程序类中处理延迟结果中的异常

我使用了setErrorResult指出的方法@jny

这是我的控制器方法的主体:

DeferredResult<Wrapper<Object>> deferredResult = new DeferredResult<>();
ForkJoinPool.commonPool().submit(() -> {
try {
Wrapper<Object> response = ...
deferredResult.setResult(response);
} catch (Exception e) {
deferredResult.setErrorResult(e);
}
});
return deferredResult;

在这种情况下,在新线程中引发的异常被传递给全局@ExceptionHandler

最新更新