当前位置: 首页 > 知识库问答 >
问题:

使用处理程序spring boot进行异常处理

红智鑫
2023-03-14

我是一个有Spring和Spring靴的新手。在创建了一个简单的REST API来对用户执行CRUD操作之后,我还创建了自定义的异常处理程序来捕获应用程序中发生的任何异常。这是我写的代码

controller类

public class UserController {

    @Autowired
    private IUserService userService;

    @ApiOperation(value = "View list of all users", response = Iterable.class)
    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public @ResponseBody List<User> getAll() throws EntityNotFoundException {
        return userService.query();
    }

    @ApiOperation(value = "View a specific user", response = User.class)
    @RequestMapping(value = "/users/{id}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
    public @ResponseBody List<User> getUser(@PathVariable(value = "id") String userid) throws EntityNotFoundException {
        return userService.query(userid);
    }

    @ApiOperation(value = "create a user")
    @RequestMapping(value = "/users", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
    public ResponseEntity<HttpStatus> createUser(@Valid @RequestBody User user) throws Exception {
        userService.add(user);
        return ResponseEntity.ok(HttpStatus.OK);
    }

    @ApiOperation(value = "update a user")
    @RequestMapping(value = "/users", method = RequestMethod.PUT, produces = { MediaType.APPLICATION_JSON_VALUE })
    public ResponseEntity<User> updateUser(@Valid @RequestBody User entity) throws Exception {
        User user = userService.update(entity);
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(user);
    }

    @ApiOperation(value = "delete a user")
    @RequestMapping(value = "/userid/{id}", method = RequestMethod.DELETE, produces = {
            MediaType.APPLICATION_JSON_VALUE })
    public ResponseEntity<HttpStatus> deleteUser(@PathVariable(value = "id") String userid) throws Exception {
        String result = userService.remove(userid);
        if (result.equals(null)) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(HttpStatus.OK);
    }

}

使用@ControllerAdvice注释的异常处理程序类

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

    /**
     * Handles javax.validation.ConstraintViolationException. Thrown
     * when @Validated fails.
     *
     * @param ex
     *            the ConstraintViolationException
     * @return the ApiError object
     */
    @ExceptionHandler(javax.validation.ConstraintViolationException.class)
    protected ResponseEntity<Object> handleConstraintViolation(javax.validation.ConstraintViolationException ex) {
        ApiError apiError = new ApiError(BAD_REQUEST);
        apiError.setMessage("Validation error");
        return buildResponseEntity(apiError);
    }

    /**
     * Handles EntityNotFoundException. Created to encapsulate errors with more
     * detail than javax.persistence.EntityNotFoundException.
     *
     * @param ex
     *            the EntityNotFoundException
     * @return the ApiError object
     */
    @ExceptionHandler(EntityNotFoundException.class)
    protected ResponseEntity<Object> handleEntityNotFound(EntityNotFoundException ex) {
        ApiError apiError = new ApiError(NOT_FOUND);
        apiError.setMessage(ex.getMessage());
        return buildResponseEntity(apiError);
    }


    /**
     * Handle Exception, handle generic Exception.class
     *
     * @param ex
     *            the Exception
     * @return the ApiError object
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    protected ResponseEntity<Object> handleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException ex,
            WebRequest request) {
        ApiError apiError = new ApiError(BAD_REQUEST);
        apiError.setMessage(String.format("The parameter '%s' of value '%s' could not be converted to type '%s'",
                ex.getName(), ex.getValue(), ex.getRequiredType().getSimpleName()));
        apiError.setDebugMessage(ex.getMessage());
        return buildResponseEntity(apiError);
    }

    private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
        return new ResponseEntity<>(apiError, apiError.getStatus());
    }

}

但是,当发生任何异常时,应用程序将被重定向到/error page,而不是由异常处理程序类处理。谁能给出正确的方法来做这件事。

共有1个答案

空翼
2023-03-14

哪些异常未被处理程序捕获?ConstraintViolationExceptions吗?

当您这样做时:

@Valid @RequestBody User entity

您正在方法中触发验证,因此如果用于修饰用户类的约束没有实现,将抛出MethodArgumentNotValidException,而不是ConstraintViolationException。

在扩展ResponseEntityExceptionHandler时,应该检查此类类的代码,该类定义了以下方法:

@ExceptionHandler({
        HttpRequestMethodNotSupportedException.class,
        HttpMediaTypeNotSupportedException.class,
        HttpMediaTypeNotAcceptableException.class,
        MissingPathVariableException.class,
        MissingServletRequestParameterException.class,
        ServletRequestBindingException.class,
        ConversionNotSupportedException.class,
        TypeMismatchException.class,
        HttpMessageNotReadableException.class,
        HttpMessageNotWritableException.class,
        MethodArgumentNotValidException.class,
        MissingServletRequestPartException.class,
        BindException.class,
        NoHandlerFoundException.class,
        AsyncRequestTimeoutException.class
    })
@Nullable
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {
    HttpHeaders headers = new HttpHeaders();

    if (ex instanceof HttpRequestMethodNotSupportedException) {
        HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED;
        return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request);
    }
    else if (ex instanceof HttpMediaTypeNotSupportedException) {
        HttpStatus status = HttpStatus.UNSUPPORTED_MEDIA_TYPE;
        return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, headers, status, request);
    }
    else if (ex instanceof HttpMediaTypeNotAcceptableException) {
        HttpStatus status = HttpStatus.NOT_ACCEPTABLE;
        return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, headers, status, request);
    }
    else if (ex instanceof MissingPathVariableException) {
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return handleMissingPathVariable((MissingPathVariableException) ex, headers, status, request);
    }
    else if (ex instanceof MissingServletRequestParameterException) {
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, headers, status, request);
    }
    else if (ex instanceof ServletRequestBindingException) {
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleServletRequestBindingException((ServletRequestBindingException) ex, headers, status, request);
    }
    else if (ex instanceof ConversionNotSupportedException) {
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return handleConversionNotSupported((ConversionNotSupportedException) ex, headers, status, request);
    }
    else if (ex instanceof TypeMismatchException) {
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleTypeMismatch((TypeMismatchException) ex, headers, status, request);
    }
    else if (ex instanceof HttpMessageNotReadableException) {
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, headers, status, request);
    }
    else if (ex instanceof HttpMessageNotWritableException) {
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, headers, status, request);
    }
    else if (ex instanceof MethodArgumentNotValidException) {
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleMethodArgumentNotValid((MethodArgumentNotValidException) ex, headers, status, request);
    }
    else if (ex instanceof MissingServletRequestPartException) {
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleMissingServletRequestPart((MissingServletRequestPartException) ex, headers, status, request);
    }
    else if (ex instanceof BindException) {
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleBindException((BindException) ex, headers, status, request);
    }
    else if (ex instanceof NoHandlerFoundException) {
        HttpStatus status = HttpStatus.NOT_FOUND;
        return handleNoHandlerFoundException((NoHandlerFoundException) ex, headers, status, request);
    }
    else if (ex instanceof AsyncRequestTimeoutException) {
        HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE;
        return handleAsyncRequestTimeoutException((AsyncRequestTimeoutException) ex, headers, status, request);
    }
    else {
        // Unknown exception, typically a wrapper with a common MVC exception as cause
        // (since @ExceptionHandler type declarations also match first-level causes):
        // We only deal with top-level MVC exceptions here, so let's rethrow the given
        // exception for further processing through the HandlerExceptionResolver chain.
        throw ex;
    }
}

因此这里捕获了MethodArgumentNotValidException,并将此类异常的处理传递给handleMethodArgumentNotValid方法。

默认的handleMethodArgumentNotValid只调用:

return handleExceptionInternal(ex, null, headers, status, request);
 类似资料:
  • 我有一个带post请求的控制器。我试图用一个简单的NotNull注释验证POJO。我正在使用ControllerAdvice来处理异常。 所以我尝试使用它,但当我启动应用程序时,我得到了以下信息: 因此,我想为BindException创建自己的处理程序,但当我为BindException类创建ExceptionHandler时,spring应用程序不会启动。如果我注释掉handleBindExc

  • 问题内容: 假设我有一个抛出某种Exception的方法。引发异常的代码位于访问外部服务的第三方库中。我有一些课程可以很好地处理外部服务,并且有很多异常处理程序可以处理潜在的问题。我遇到的问题是我可能有很多异常,但是如果有一个动作,并且可能有大量尝试/捕获块,我可能只需要执行几个动作之一。异常的类型甚至可能不相关,或者不同的方法可能会抛出相同类型的异常,但是根据抛出该异常的方法,需要采取不同的操作

  • 1.1 异常处理的基本使用 try: <语句块1> except: <语句块2> try 捕获异常 except 发生异常时执行 try: <语句块1> except <异常类型名字>: <语句块2> except <异常类型名字> 发生对应异常时才会执行 1.2 异常处理的高级使用 try: <语句块1> except

  • 我正在尝试进行大量的外部服务调用,每个调用都遵循异常处理和有条件的进一步处理。我认为使用内部的. on完成来扩展这个不错的(Scala中带有期货的异步IO)示例会很容易,但似乎我对范围和/或期货有些不理解。有人能给我指出正确的方向吗? 在我的电脑上(Scala 2.10.4 ),这打印出来: 我要(顺序不重要):

  • 本文向大家介绍SpringBoot使用统一异常处理详解,包括了SpringBoot使用统一异常处理详解的使用技巧和注意事项,需要的朋友参考一下 场景:针对异常处理,我们原来的做法是一般在最外层捕获异常即可,例如在Controller中 这样的话也能解决部分问题,但是无法获取到自己指定的异常,引入全局统一异常处理的话将会极大的改善代码,减少冗余代码的产生。 自定义异常类:注意要继承自RuntimeE

  • 我应该知道这一点,但不知为何我现在还想不出来。 是否有方法重写此代码以避免?