处理已知异常
自定义http错误类,载入到全局异常管理类中
HttpException
定义HttpException父类,关于的Http这一块的异常处理类继承此父类
NotFoundException
ForibiddenException
他们都可以走进来,为什么要分别创建呢?如何去创建(12/2-5)?
关于HttpEception与Exception:
在我们现有代码GlobalExceptionAdvice中,handleException和HandleHttpException这两个方法中,一个是处理未知异常,另一个是处理http这一块的异常,所以里面的逻辑也是不一样的。
对于Exception的处理,我们可以写死返回结果
// 处理未知异常
@ExceptionHandler(value=Exception.class) // 监听异常是非常宽泛的,并不是一个具体的异常,这个其实算是未知异常
@ResponseBody
@ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
public UnifyResponse handleException(HttpServletRequest req,Exception e){
//这块异常的原因,对于前端开发者或者用户来说,都是无意义的,服务器端的开发者代码逻辑有问题。我们只需要服务器端的开发人员自己知道就行了
String url = req.getRequestURI();
String method = req.getMethod();
UnifyResponse message = new UnifyResponse(9999,"服务器异常",method + ":" + url);
// 开发时候,我们需要知道异常进行调试
System.out.println(e);
return message;
}
而HandleHttpException中,我们就要更加灵活的编码里面的逻辑,我们应该自己控制返回的response,而不是springboot它帮我们返回,还有我们需要http的状态码不是写死,而是从HttpException中读出来动态的设置
@ExceptionHandler(HttpException.class)
public ResponseEntity<UnifyResponse> handleHttpException(HttpServletRequest req, HttpException e) {
String url = req.getRequestURI();
String method = req.getMethod();
// 我们应该返回一个ResponseEntity // 设置很多属性,header body等,这种形式的控制,更加灵活一点
UnifyResponse message = new UnifyResponse(e.getCode(),codeConfiguration.getMessage(e.getCode()),method + " " + url);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
ResponseEntity<UnifyResponse> r = new ResponseEntity<UnifyResponse>(message,headers,httpStatus);
return r;
}
PS:code码和message未定义,需要在配置文件中定义
code代表一种类型的错误,给前端进行判断。
试一试关与这些异常的处理
MethodArgumentNoValidException (body参数验证错误)
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public UnifyResponse handleBeanValidation(HttpServletRequest req, MethodArgumentNotValidException e) {
String url = req.getRequestURI();
String method = req.getMethod();
List<ObjectError> errors = e.getBindingResult().getAllErrors();
String messages = this.formatAllErrorMessages(errors);
return new UnifyResponse(10001,messages,method + " " + url);
};
private String formatAllErrorMessages(List<ObjectError> errors) {
StringBuffer errorMsg = new StringBuffer();
errors.forEach(error ->
errorMsg.append(error.getDefaultMessage()).append(';')
);
return errorMsg.toString();
}
ConstrainViolationException(查询参数验证错误)
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public UnifyResponse handleConstraintViolationException(HttpServletRequest req,ConstraintViolationException e) {
String url = req.getRequestURI();
String method = req.getMethod();
return new UnifyResponse(10001,e.getMessage(),method + " " + url);
}
message为什么要写在配置文件中?
- code和message可以做映射
- 可以解决国际化的问题
- 硬编码message散落在各个角落,不利于管理
UnifyResponese 定义载入
定义数据类型:
{
"code": 10001,
"message": "test.id: 必须超过10",
"request": "GET /v1/banner/test/1"
}
UnifyResponese 数据结构的定义
UnifyResponese 正常返回的一些坑
get和set定义
@ReposeBody注解加入
处理未知异常
状态码修改@ResponseStatus
@ResponseStatus(code= HttpStatus的枚举)
加入展示错误代码
在开发环境中,虽然我们对前端屏蔽了错误信息,但是在服务器端方便我们调试,我们是需要打印这些错误信息用来修改我们的bug
�