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
版权声明:本文为Xin_101原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。