SpringMVC中统一处理异常

今天和大家谈谈SpringMVC中如何统一处理异常。本篇文章我们还是以简单明了的风格和大家介绍。

我们使用SpringBoot来进行讲解,其版本为2.2.1.RELEASE。首先来谈一下SpringMVC和Http状态码的关系。

把异常映射为HTTP状态码

需要提到的是在SpringMVC中出现以下异常时,SpringMVC就会把这些异常自动转换成特定的Http状态码。异常和状态码的映射关系如下:

  1. BindException->400:BadRequest
  2. ConversionNotSupportedException->500:Internal Server Error
  3. HttpMediaTypeNotAcceptableException->406:Not Acceptable
  4. HttpMediaTypeNotSupportedException->415:Unsupported Media Type
  5. HttpMessageNotReadableException->400:BadRequest
  6. HttpMessageNotWritableException->500:Internal Server Error
  7. HttpRequestMethodNotSupportedException->405:Method Not Allowed
  8. MethodArgumentNotValidException->500:Internal Server Error
  9. MissingServletRequestParameterException->400:BadRequest
  10. MissingServletRequestPartException->400:BadRequest
  11. TypeMismatchException->400:BadRequest

除此之外,我们还可以把我们自定义的异常也映射为HTTP状态码。达到这种目的的方式是用一个注解来标记这个我们自定义的异常,这个注解就是@ResponseStatus,用法如下:

49ae8a9b680bf58d5925168e8cabbfcc.png

@ResponseStatus标记异常类

@ResponseStatus注解的value属性表示返回的HTTP状态码,reason表示消息。当Controller抛出ParamException异常时,SpringMVC会返回一个400的HTTP状态码,因为HttpStatus.BAD_REQUEST的值是400。

5d4a0e7e4293aa4430f6867ae79cbd05.png

抛出ParamException

请求index3路径之后浏览器会收到400的响应,如图:

5c630bf9a47f04573f87ac2b4ae88a4c.png

type=Bad Request, status=400

那么如果我们把ParamException异常类的注解@ResponseStatus去掉,浏览器又会收到什么状态码呢?去掉后如图:

e8f4adf7bc89d594b8af36df73b48d87.png

注释掉@ResponseStatus

浏览器得到的状态如下,我们可以从图中看到HTTP状态是500:

3460c1a9c05bef8dce7a56a734c17a9c.png

type=Internal Server Error, status=500

这就说明了我们是可以通过@ResponseStatus注解把ParamException异常映射为400状态码的。

在SpringMVC的开发过程中仅仅把特定的异常映射为HTTP状态码是远远不够的,我们还需要统一处理Controller中抛出的异常。那么如何实现呢?我们在这里提供2种方式,下面我们一一来看。

第一种:在Controller的基类中统一处理

        首先要说明的是@ExceptionHandler注解,这个注解是用来标记一个方法是异常处理器。这个注解标记的方法能够处理当前Controller中所有抛出的异常,如果把这个注解用在一个Controller的基类中,让所有的Controller都继承这个基类,那么这个被@ExceptionHandler注解标记的方法就能处理所有Controller抛出的异常了。

        先看一下基类如何设置:

基类

package com.fri.audioengine.utils;

import org.springframework.web.bind.annotation.ExceptionHandler;

public class BaseExceptionController {
    @ExceptionHandler(Exception.class)
    void myExcptionHandler(Exception ex){
        if(ex instanceof IllegalStateException){
            System.out.println("io is");
        }else if(ex instanceof NullPointerException){
            System.out.println("null ex");
        }
    }
}

        从图中可以看到这个基类非常简单,仅仅一个方法,而且这个方法被@ExceptionHandler注解标记,括号中的参数表示这个方法用于处理什么类型的异常。这个方法有一个参数,这个参数可以接收到抛出的异常。

继承基类

        再让其他的具体的Controller继承这个基类就可以了,如图:

6aaa5143fcc06849398d539677a8a2a3.png

        这样就完成了,在基类的myExceptionHandler方法中就可以统一处理所有Controller中抛出的异常了。

第二种:在Controller的切面中统一处理

        这种方式就是为Controller设置一个切面,在切面中处理异常。

定义切面

        首先定义一个切面,定义切面的方式是在切面类上添加@ControllerAdvice注解就可以了,标记完切面之后再通过@ExceptionHandler注解定义异常处理方法,如图:

5c167fdcf9e0f495e921157a93a90734.png

        然后我们就可以定义控制器了,而且我们的控制器也不用继承基类控制器了,如图:

c6c20892f0bae79401c7bb3bf47e7b86.png

        这样所有Controller抛出的异常都能被Controller的切面中的异常处理器捕获到了,是不是很简单呢?

结束语

        今天简单和大家分享了如果统一处理Controller的异常,在这里简单总结一下,第一点就是定义处理异常的handler,这是必须的,而且无论你是通过基类处理还是通过切面处理这都是不能缺少的。在这两种方式中定义异常handler的方式都是通过@ExceptionHandler注解完成的。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 Spring MVC ,我们可以通过实现一个异常处理器来统一处理控制器抛出的异常。具体步骤如下: 1. 实现一个异常处理器类,并添加 @ControllerAdvice 注解。 2. 在异常处理器类定义处理不同类型异常的方法,并使用 @ExceptionHandler 注解标记。 3. 在方法编写异常处理逻辑,例如将异常信息记录到日志、返回错误信息等。 4. 如果需要返回 JSON 格式的错误信息,可以使用 @ResponseBody 注解。 以下是一个简单的示例: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) @ResponseBody public Map<String, Object> handleException(Exception e) { Map<String, Object> errorMap = new HashMap<>(); errorMap.put("code", "500"); errorMap.put("message", e.getMessage()); return errorMap; } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody public Map<String, Object> handleValidationException(MethodArgumentNotValidException e) { Map<String, Object> errorMap = new HashMap<>(); errorMap.put("code", "400"); errorMap.put("message", "参数校验失败"); List<String> errors = e.getBindingResult() .getFieldErrors() .stream() .map(FieldError::getDefaultMessage) .collect(Collectors.toList()); errorMap.put("errors", errors); return errorMap; } } ``` 在上述示例,我们定义了两个处理异常的方法:handleException 和 handleValidationException。handleException 方法处理所有未被其他方法处理异常,返回一个包含错误码和错误信息的 Map 对象;handleValidationException 方法处理参数校验失败的异常,并将校验失败的所有错误信息返回。 最后,需要注意的是,如果同时存在多个异常处理方法,Spring MVC 会按照异常类型匹配最合适的处理方法。如果没有找到合适的处理方法,则会将异常抛给 Servlet 容器进行处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fang·up·ad

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值