Springboot基础系列:统一处理(返回异常)

it2025-01-08  9

1 统一异常

统一异常配置,使用@RestControllerAdvice增强@RestController,同时直接返回JSON数据,若使用@ControllerAdvice,需要在异常方法上添加@ResponseBody.异常返回方法上添加@ExceptionHandler,捕获指定的异常类.方法参数异常使用org.springframework.web.bind.MethodArgumentNotValidException. package com.company.web.exception; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.MethodArgumentNotValidException; // import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import com.company.web.vo.common.*; import java.util.List; import java.util.stream.Collectors; import javax.validation.ConstraintViolationException; /** * Uniform exception handle. * @author xindaqi * @since 2020-10-21 */ @RestControllerAdvice public class GlobalExceptionHandler { static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 参数绑定异常 * @param e * @return */ @ExceptionHandler(BindException.class) public ResponseVO validationExceptionHandler(BindException e) { BindingResult bindingResult = e.getBindingResult(); List<FieldError> fieldErrors = bindingResult.getFieldErrors(); String errorMsg = "bindException"; logger.info("Bind Validataion: {}", errorMsg); return ResponseVO.invalid(errorMsg); } /** * 方法参数校验异常 * @param e * @return */ @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseVO methodValidationExceptionHandler(MethodArgumentNotValidException e) { BindingResult bindingResult = e.getBindingResult(); List<FieldError> fieldErrors = bindingResult.getFieldErrors(); fieldErrors.forEach(fieldError -> { logger.info("Invalid message: {}", fieldError.getDefaultMessage()); }); fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.toList()); logger.info("field error: {}", fieldErrors); String errorMsg = fieldErrors.toString(); logger.info("Method Validataion: {}", errorMsg); return ResponseVO.invalid(errorMsg); } /** * 空指针异常 * @param e * @return */ @ExceptionHandler(NullPointerException.class) public ResponseVO exceptionHandler(NullPointerException e) { String errorMsg = e.getMessage(); logger.info("Null pointer Exception Validataion: {}", errorMsg); return ResponseVO.exception(4004); } /** * 数据计算异常 * @param e * @return */ @ExceptionHandler(ArithmeticException.class) public ResponseVO exceptionHandler(ArithmeticException e) { String errorMsg = e.getMessage(); logger.info("Arithmetic Exception Validataion: {}", errorMsg); return ResponseVO.exception(4003); } /** * 未知异常 * @param e * @return */ @ExceptionHandler(Exception.class) public ResponseVO exceptionHandler(Exception e) { String errorMsg = e.getMessage(); logger.info("Exception Validataion: {}", errorMsg); return ResponseVO.invalid(errorMsg); } }

2 统一返回

统一异常码和异常信息返回,可依据情况自定义添加.

package com.company.web.vo.common; import com.company.web.enums.common.*; /** * Uniform response. * @author xindaqi * @since 2020-10-20 * @param <T> */ public class ResponseVO<T> { private Integer code; private String msg; private T data; public void setCode(Integer code) { this.code = code; } public Integer getCode() { return code; } public void setMsg(String msg) { this.msg = msg; } public String getMsg() { return msg; } public void setData(T data) { this.data = data; } public T getData() { return data; } public ResponseVO(){} public ResponseVO(Integer code, String msg) { this.code = code; this.msg = msg; } public ResponseVO(Integer code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public static ResponseVO ok() { return new ResponseVO(EnumsCode.SUCCESS.getCode(), EnumsCode.SUCCESS.getMsg()); } public static ResponseVO ok(Object data) { return new ResponseVO(EnumsCode.SUCCESS.getCode(), EnumsCode.SUCCESS.getMsg(), data); } public static ResponseVO fail() { return new ResponseVO(EnumsCode.FAIL.getCode(), EnumsCode.FAIL.getMsg()); } public static ResponseVO invalid() { return new ResponseVO(EnumsCode.INVALID.getCode(), EnumsCode.FAIL.getMsg()); } public static ResponseVO invalid(String msg) { return new ResponseVO(EnumsCode.INVALID.getCode(), msg); } public static ResponseVO exception(Integer code) { switch (code) { case 4003: return new ResponseVO(EnumsCode.ARITHMETICEXCEPTION.getCode(), EnumsCode.ARITHMETICEXCEPTION.getMsg()); case 4004: return new ResponseVO(EnumsCode.NULLPOINTEREXCEPTION.getCode(), EnumsCode.NULLPOINTEREXCEPTION.getMsg()); } return new ResponseVO(EnumsCode.INVALID.getCode(), EnumsCode.INVALID.getMsg()); } }

3 接口测试

3.1 异常捕捉:空指针

package com.company.web.controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.annotation.Validated; import org.springframework.validation.BindException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.company.web.dto.*; import com.company.web.service.*; import com.company.web.vo.common.*; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import java.util.List; /** * Transactional test. * @author xindaqi * @since 2020-10-20 */ @CrossOrigin(origins = "*", maxAge = 3600) @RestController @RequestMapping("/api/function/test") @Validated public class TransactionalTestController { static Logger logger = LoggerFactory.getLogger(TransactionalTestController.class); @Autowired private IDataSaveService dataSaveService; @RequestMapping(value = "/transactional/rollback/raw", method = RequestMethod.POST) public ResponseVO saveDataWithRollback(@RequestBody QuestionAnswerInputDTO params) { String result = null; if(result.equals("SUCCESS")) { return ResponseVO.ok(); } // Integer a = 1 / 0; return ResponseVO.ok(); } } 结果 { "code": 4005, "msg": "空指针异常", "data": null }

3.2 异常捕捉:计算异常

package com.company.web.controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.annotation.Validated; import org.springframework.validation.BindException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.company.web.dto.*; import com.company.web.service.*; import com.company.web.vo.common.*; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import java.util.List; /** * Transactional test. * @author xindaqi * @since 2020-10-20 */ @CrossOrigin(origins = "*", maxAge = 3600) @RestController @RequestMapping("/api/function/test") @Validated public class TransactionalTestController { static Logger logger = LoggerFactory.getLogger(TransactionalTestController.class); @Autowired private IDataSaveService dataSaveService; @RequestMapping(value = "/transactional/rollback/raw", method = RequestMethod.POST) public ResponseVO saveDataWithRollback(@RequestBody QuestionAnswerInputDTO params) { Integer a = 1 / 0; return ResponseVO.ok(); } } 结果 { "code": 4004, "msg": "计算异常", "data": null }

4 小结

统一异常处理通过注解@RestControllerAdvice实现在方法上添加注解@ExceptionHandler(Exception.class),参数为特定的异常类所有的异常可以通过统一异常类进行捕获接口中省略了try…catch,使代码更简洁

[参考文献] [1]https://blog.csdn.net/Three_Two/article/details/87699211 [2]https://blog.csdn.net/starexplode/article/details/81198703 [3]https://blog.csdn.net/songguopeng/article/details/98961787 [4]https://www.cnblogs.com/gaomanito/p/10863765.html [5]https://blog.csdn.net/RudeCrab/article/details/105834218 [6]https://zhuanlan.zhihu.com/p/109227851

最新回复(0)