代码之家  ›  专栏  ›  技术社区  ›  Almas Abdrazak

如何在春季开机时处理延迟结果中的异常?

  •  5
  • Almas Abdrazak  · 技术社区  · 7 年前

    我有一个休息方法:

    @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中的异常?

    3 回复  |  直到 6 年前
        1
  •  7
  •   jny harshit    7 年前

    DeferredResult has方法 setErrorResult documentation :

    处理时就像处理程序引发异常一样。

        2
  •  3
  •   Sri9911 Almas Abdrazak    6 年前

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

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

    和一个SeparateThreadsExceptionHandler类:

    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。在我的示例中,它是前端的错误代码。

        3
  •  0
  •   Kacper86    6 年前

    我用过 setErrorResult

    以下是我的控制器方法的主体:

    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