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
.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
;
@RestControllerAdvice
public class GlobalExceptionHandler {
static Logger logger
= LoggerFactory
.getLogger(GlobalExceptionHandler
.class);
@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
);
}
@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
);
}
@ExceptionHandler(NullPointerException
.class)
public ResponseVO
exceptionHandler(NullPointerException e
) {
String errorMsg
= e
.getMessage();
logger
.info("Null pointer Exception Validataion: {}", errorMsg
);
return ResponseVO
.exception(4004);
}
@ExceptionHandler(ArithmeticException
.class)
public ResponseVO
exceptionHandler(ArithmeticException e
) {
String errorMsg
= e
.getMessage();
logger
.info("Arithmetic Exception Validataion: {}", errorMsg
);
return ResponseVO
.exception(4003);
}
@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
.*
;
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
;
@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();
}
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
;
@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