1. 使用 @ControllerAdvice和@ExceptionHandler处理全局异常
1. 新建异常信息实体类
非必要的类,主要用于包装异常信息。
1 package com.test.exception.myexception; 2 3 public class ErrorResponse { 4 private String message; 5 private String errorTypeName; 6 7 public ErrorResponse(Exception e) { 8 this(e.getClass().getName(), e.getMessage()); 9 } 10 11 public ErrorResponse(String errorTypeName, String message) { 12 this.errorTypeName = errorTypeName; 13 this.message = message; 14 } 15 16 public String getMessage() { 17 return message; 18 } 19 20 public void setMessage(String message) { 21 this.message = message; 22 } 23 24 public String getErrorTypeName() { 25 return errorTypeName; 26 } 27 28 public void setErrorTypeName(String errorTypeName) { 29 this.errorTypeName = errorTypeName; 30 } 31 }
2. 自定义异常类型
package com.test.exception.myexception; public class ReourceNotFoundException extends RuntimeException { private String message; public ReourceNotFoundException() { super(); } public ReourceNotFoundException(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
类,让异常处理类只处理特定类抛出的异常。
1 package com.test.exception.handler; 2 3 4 import com.test.exception.myexception.ErrorResponse; 5 import com.test.exception.myexception.ReourceNotFoundException; 6 import org.springframework.http.ResponseEntity; 7 import org.springframework.web.bind.annotation.ControllerAdvice; 8 import org.springframework.web.bind.annotation.ExceptionHandler; 9 import org.springframework.web.bind.annotation.ResponseBody; 10 import org.springframework.web.server.ResponseStatusException; 11 12 @ControllerAdvice(assignableTypes = {com.test.exception.controller.ExceptionController.class}) 13 @ResponseBody 14 public class GlobalExceptionHandler { 15 ErrorResponse illegalArgumentResponse = new ErrorResponse(new IllegalArgumentException("参数错误!")); 16 ErrorResponse resourseNotFoundResponse = new ErrorResponse(new com.test.exception.myexception.ReourceNotFoundException("Sorry, the resourse not found!")); 17 18 19 @ExceptionHandler(value = Exception.class)// 拦截所有异常, 这里只是为了演示,一般情况下一个方法特定处理一种异常 20 public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) { 21 22 if (e instanceof IllegalArgumentException) { 23 return ResponseEntity.status(400).body(illegalArgumentResponse); 24 } else if (e instanceof ReourceNotFoundException) { 25 return ResponseEntity.status(404).body(resourseNotFoundResponse); 26 }else if(e instanceof ResponseStatusException){ 27 return ResponseEntity.status(502).body(resourseNotFoundResponse); 28 } 29 return null; 30 } 31 }
4. controller模拟抛出异常
1 package com.test.exception.controller; 2 3 import com.test.exception.myexception.ReourceNotFoundException; 4 import org.springframework.http.HttpStatus; 5 import org.springframework.web.bind.annotation.GetMapping; 6 import org.springframework.web.bind.annotation.RestController; 7 import org.springframework.web.server.ResponseStatusException; 8 9 @RestController 10 public class ExceptionController { 11 12 @GetMapping("/illegalArgumentException") 13 public void throwException() { 14 throw new IllegalArgumentException(); 15 } 16 17 @GetMapping("/resourceNotFoundException") 18 public void throwException2() { 19 throw new ReourceNotFoundException(); 20 21 } 22 23 @GetMapping("/resourceNotFoundException2") 24 public void throwException3() { 25 throw new ResponseStatusException(HttpStatus.BAD_GATEWAY,"The resource not found",new ReourceNotFoundException()); 26 } 27 }
使用 Get 请求: http://localhost:8080/resourceNotFoundException
{"message":"Sorry, the resourse not found!","errorTypeName":"com.test.exception.myexception.ReourceNotFoundException"}
3. ResponseStatusException
研究 ResponseStatusException 我们先来看看,通过 ResponseStatus
注解简单处理异常的方法(将异常映射为状态码)。
package com.test.exception.myexception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.BAD_GATEWAY) public class ReourceNotFoundException2 extends RuntimeException { public ReourceNotFoundException2() { } public ReourceNotFoundException2(String message) { super(message); } }
这种通过 ResponseStatus
注解简单处理异常的方法是的好处是比较简单,但是一般我们不会这样做,通过ResponseStatusException
会更加方便,可以避免我们额外的异常类。
@GetMapping("/resourceNotFoundException2") public void throwException3() { throw new ResponseStatusException(HttpStatus.BAD_GATEWAY,"The resource not found",new ReourceNotFoundException()); }
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 : 抛出的异常