内容目录
-
为什么要优雅的处理异常
-
实现案例@ControllerAdvice异常统一处理Controller接口运行测试
-
进一步理解@ControllerAdvice还可以怎么用?@ControllerAdvice是如何起作用的(原理)?
-
示例源码
-
更多内容
SpringBoot接口如何对异常进行统一封装,并统一返回呢?以上文的参数校验为例,如何优雅的将参数校验的错误信息统一处理并封装返回呢?@pdai
为什么要优雅的处理异常
如果我们不统一的处理异常,经常会在controller层有大量的异常处理的代码, 比如:
@Slf4j
@Api(value = "User Interfaces", tags = "User Interfaces")
@RestController
@RequestMapping("/user")
public class UserController {
/**
* http://localhost:8080/user/add .
*
* @param userParam user param
* @return user
*/
@ApiOperation("Add User")
@ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)
@PostMapping("add")
public ResponseEntity<String> add(@Valid @RequestBody UserParam userParam) {
// 每个接口充斥着大量的异常处理
try {
// do something
} catch(Exception e) {
return ResponseEntity.fail("error");
}
return ResponseEntity.ok("success");
}
}
那怎么实现统一的异常处理,特别是结合参数校验等封装?
实现案例
简单展示通过@ControllerAdvice进行统一异常处理。
@ControllerAdvice异常统一处理
对于400参数错误异常
/**
* Global exception handler.
*
* @author pdai
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* exception handler for bad request.
*
* @param e
* exception
* @return ResponseResult
*/
@ResponseBody
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = { BindException.class, ValidationException.class, MethodArgumentNotValidException.class })
public ResponseResult<ExceptionData> handleParameterVerificationException(@NonNull Exception e) {
ExceptionData.ExceptionDataBuilder exceptionDataBuilder = ExceptionData.builder();
log.warn("Exception: {}", e.getMessage());
if (e instanceof BindException) {
BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage)
.forEach(exceptionDataBuilder::error);
} else if (e instanceof ConstraintViolationException) {
if (e.getMessage() != null) {
exceptionDataBuilder.error(e.getMessage());
}
} else {
exceptionDataBuilder.error("invalid parameter");
}
return ResponseResultEntity.fail(exceptionDataBuilder.build(), "invalid parameter");
}
}
对于自定义异常
/**
* handle business exception.
*
* @param businessException
* business exception
* @return ResponseResult
*/
@ResponseBody
@ExceptionHandler(BusinessException.class)
public ResponseResult<BusinessException> processBusinessException(BusinessException b