一、使用 @ControllerAdvice 和 @ExceptionHandler 处理全局异常

公司主营业务:成都做网站、网站建设、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出洋县免费做网站回馈大家。
这是目前很常用的一种方式,非常推荐。测试代码中用到了 Junit 5,如果你新建项目验证下面的代码的话,记得添加上相关依赖。
1. 新建异常信息实体类
非必要的类,主要用于包装异常信息。
src/main/java/com/twuc/webApp/exception/ErrorResponse.java
- /**
 - * @author shuang.kou
 - */
 - public class ErrorResponse {
 - private String message;
 - private String errorTypeName;
 - public ErrorResponse(Exception e) {
 - this(e.getClass().getName(), e.getMessage());
 - }
 - public ErrorResponse(String errorTypeName, String message) {
 - this.errorTypeName = errorTypeName;
 - this.message = message;
 - }
 - ......省略getter/setter方法
 - }
 
2. 自定义异常类型
src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java
一般我们处理的都是 RuntimeException ,所以如果你需要自定义异常类型的话直接集成这个类就可以了。
- /**
 - * @author shuang.kou
 - * 自定义异常类型
 - */
 - public class ResourceNotFoundException extends RuntimeException {
 - private String message;
 - public ResourceNotFoundException() {
 - super();
 - }
 - public ResourceNotFoundException(String message) {
 - super(message);
 - this.message = message;
 - }
 - @Override
 - public String getMessage() {
 - return message;
 - }
 - public void setMessage(String message) {
 - this.message = message;
 - }
 - }
 
3. 新建异常处理类
我们只需要在类上加上@ControllerAdvice注解这个类就成为了全局异常处理类,当然你也可以通过 assignableTypes指定特定的 Controller 类,让异常处理类只处理特定类抛出的异常。
src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java
- /**
 - * @author shuang.kou
 - */
 - @ControllerAdvice(assignableTypes = {ExceptionController.class})
 - @ResponseBody
 - public class GlobalExceptionHandler {
 - ErrorResponse illegalArgumentResponse = new ErrorResponse(new IllegalArgumentException("参数错误!"));
 - ErrorResponse resourseNotFoundResponse = new ErrorResponse(new ResourceNotFoundException("Sorry, the resourse not found!"));
 - @ExceptionHandler(value = Exception.class)// 拦截所有异常, 这里只是为了演示,一般情况下一个方法特定处理一种异常
 - public ResponseEntity
 exceptionHandler(Exception e) { - if (e instanceof IllegalArgumentException) {
 - return ResponseEntity.status(400).body(illegalArgumentResponse);
 - } else if (e instanceof ResourceNotFoundException) {
 - return ResponseEntity.status(404).body(resourseNotFoundResponse);
 - }
 - return null;
 - }
 - }
 
4. controller模拟抛出异常
src/main/java/com/twuc/webApp/web/ExceptionController.java
- /**
 - * @author shuang.kou
 - */
 - @RestController
 - @RequestMapping("/api")
 - public class ExceptionController {
 - @GetMapping("/illegalArgumentException")
 - public void throwException() {
 - throw new IllegalArgumentException();
 - }
 - @GetMapping("/resourceNotFoundException")
 - public void throwException2() {
 - throw new ResourceNotFoundException();
 - }
 - }
 
使用 Get 请求 localhost:8080/api/resourceNotFoundException[1] (curl -i -s -X GET url),服务端返回的 JSON 数据如下:
- {
 - "message": "Sorry, the resourse not found!",
 - "errorTypeName": "com.twuc.webApp.exception.ResourceNotFoundException"
 - }
 
5. 编写测试类
MockMvc 由org.springframework.boot.test包提供,实现了对Http请求的模拟,一般用于我们测试 controller 层。
- /**
 - * @author shuang.kou
 - */
 - @AutoConfigureMockMvc
 - @SpringBootTest
 - public class ExceptionTest {
 - @Autowired
 - MockMvc mockMvc;
 - @Test
 - void should_return_400_if_param_not_valid() throws Exception {
 - mockMvc.perform(get("/api/illegalArgumentException"))
 - .andExpect(status().is(400))
 - .andExpect(jsonPath("$.message").value("参数错误!"));
 - }
 - @Test
 - void should_return_404_if_resourse_not_found() throws Exception {
 - mockMvc.perform(get("/api/resourceNotFoundException"))
 - .andExpect(status().is(404))
 - .andExpect(jsonPath("$.message").value("Sorry, the resourse not found!"));
 - }
 - }
 
二、 @ExceptionHandler 处理 Controller 级别的异常
我们刚刚也说了使用@ControllerAdvice注解 可以通过 assignableTypes指定特定的类,让异常处理类只处理特定类抛出的异常。所以这种处理异常的方式,实际上现在使用的比较少了。
我们把下面这段代码移到 src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java 中就可以了。
- @ExceptionHandler(value = Exception.class)// 拦截所有异常
 - public ResponseEntity
 exceptionHandler(Exception e) { - if (e instanceof IllegalArgumentException) {
 - return ResponseEntity.status(400).body(illegalArgumentResponse);
 - } else if (e instanceof ResourceNotFoundException) {
 - return ResponseEntity.status(404).body(resourseNotFoundResponse);
 - }
 - return null;
 - }
 
三、 ResponseStatusException
研究 ResponseStatusException 我们先来看看,通过 ResponseStatus注解简单处理异常的方法(将异常映射为状态码)。
src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java
- @ResponseStatus(code = HttpStatus.NOT_FOUND)
 - public class ResourseNotFoundException2 extends RuntimeException {
 - public ResourseNotFoundException2() {
 - }
 - public ResourseNotFoundException2(String message) {
 - super(message);
 - }
 - }
 
src/main/java/com/twuc/webApp/web/ResponseStatusExceptionController.java
- @RestController
 - @RequestMapping("/api")
 - public class ResponseStatusExceptionController {
 - @GetMapping("/resourceNotFoundException2")
 - public void throwException3() {
 - throw new ResourseNotFoundException2("Sorry, the resourse not found!");
 - }
 - }
 
使用 Get 请求 localhost:8080/api/resourceNotFoundException2[2] ,服务端返回的 JSON 数据如下:
- {
 - "timestamp": "2019-08-21T07:11:43.744+0000",
 - "status": 404,
 - "error": "Not Found",
 - "message": "Sorry, the resourse not found!",
 - "path": "/api/resourceNotFoundException2"
 - }
 
这种通过 ResponseStatus注解简单处理异常的方法是的好处是比较简单,但是一般我们不会这样做,通过ResponseStatusException会更加方便,可以避免我们额外的异常类。
- @GetMapping("/resourceNotFoundException2")
 - public void throwException3() {
 - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Sorry, the resourse not found!", new ResourceNotFoundException());
 - }
 
使用 Get 请求 localhost:8080/api/resourceNotFoundException2[3] ,服务端返回的 JSON 数据如下,和使用 ResponseStatus 实现的效果一样:
- {
 - "timestamp": "2019-08-21T07:28:12.017+0000",
 - "status": 404,
 - "error": "Not Found",
 - "message": "Sorry, the resourse not found!",
 - "path": "/api/resourceNotFoundException3"
 - }
 
ResponseStatusException 提供了三个构造方法:
- public ResponseStatusException(HttpStatus status) {
 - this(status, null, null);
 - }
 - public ResponseStatusException(HttpStatus status, @Nullable String reason) {
 - this(status, reason, null);
 - }
 - public ResponseStatusException(HttpStatus status, @Nullable String reason, @Nullable Throwable cause) {
 - super(null, cause);
 - Assert.notNull(status, "HttpStatus is required");
 - this.status = status;
 - this.reason = reason;
 - }
 
构造函数中的参数解释如下:
•status :http status
•reason :response 的消息内容
•cause :抛出的异常
                网页题目:SpringBoot处理异常的几种常见姿势
                
                网站URL:http://www.csdahua.cn/qtweb/news11/174611.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网