处理已知异常

自定义http错误类,载入到全局异常管理类中

HttpException

定义HttpException父类,关于的Http这一块的异常处理类继承此父类

NotFoundException

ForibiddenException

他们都可以走进来,为什么要分别创建呢?如何去创建(12/2-5)?

关于HttpEception与Exception:

在我们现有代码GlobalExceptionAdvice中,handleException和HandleHttpException这两个方法中,一个是处理未知异常,另一个是处理http这一块的异常,所以里面的逻辑也是不一样的。
对于Exception的处理,我们可以写死返回结果

  1. // 处理未知异常
  2. @ExceptionHandler(value=Exception.class) // 监听异常是非常宽泛的,并不是一个具体的异常,这个其实算是未知异常
  3. @ResponseBody
  4. @ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
  5. public UnifyResponse handleException(HttpServletRequest req,Exception e){
  6. //这块异常的原因,对于前端开发者或者用户来说,都是无意义的,服务器端的开发者代码逻辑有问题。我们只需要服务器端的开发人员自己知道就行了
  7. String url = req.getRequestURI();
  8. String method = req.getMethod();
  9. UnifyResponse message = new UnifyResponse(9999,"服务器异常",method + ":" + url);
  10. // 开发时候,我们需要知道异常进行调试
  11. System.out.println(e);
  12. return message;
  13. }

而HandleHttpException中,我们就要更加灵活的编码里面的逻辑,我们应该自己控制返回的response,而不是springboot它帮我们返回,还有我们需要http的状态码不是写死,而是从HttpException中读出来动态的设置

  1. @ExceptionHandler(HttpException.class)
  2. public ResponseEntity<UnifyResponse> handleHttpException(HttpServletRequest req, HttpException e) {
  3. String url = req.getRequestURI();
  4. String method = req.getMethod();
  5. // 我们应该返回一个ResponseEntity // 设置很多属性,header body等,这种形式的控制,更加灵活一点
  6. UnifyResponse message = new UnifyResponse(e.getCode(),codeConfiguration.getMessage(e.getCode()),method + " " + url);
  7. HttpHeaders headers = new HttpHeaders();
  8. headers.setContentType(MediaType.APPLICATION_JSON);
  9. HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
  10. ResponseEntity<UnifyResponse> r = new ResponseEntity<UnifyResponse>(message,headers,httpStatus);
  11. return r;
  12. }

PS:code码和message未定义,需要在配置文件中定义

code代表一种类型的错误,给前端进行判断。

试一试关与这些异常的处理

MethodArgumentNoValidException (body参数验证错误)

  1. @ExceptionHandler(MethodArgumentNotValidException.class)
  2. @ResponseBody
  3. @ResponseStatus(code = HttpStatus.BAD_REQUEST)
  4. public UnifyResponse handleBeanValidation(HttpServletRequest req, MethodArgumentNotValidException e) {
  5. String url = req.getRequestURI();
  6. String method = req.getMethod();
  7. List<ObjectError> errors = e.getBindingResult().getAllErrors();
  8. String messages = this.formatAllErrorMessages(errors);
  9. return new UnifyResponse(10001,messages,method + " " + url);
  10. };
  11. private String formatAllErrorMessages(List<ObjectError> errors) {
  12. StringBuffer errorMsg = new StringBuffer();
  13. errors.forEach(error ->
  14. errorMsg.append(error.getDefaultMessage()).append(';')
  15. );
  16. return errorMsg.toString();
  17. }

ConstrainViolationException(查询参数验证错误)

  1. @ExceptionHandler(ConstraintViolationException.class)
  2. @ResponseBody
  3. @ResponseStatus(code = HttpStatus.BAD_REQUEST)
  4. public UnifyResponse handleConstraintViolationException(HttpServletRequest req,ConstraintViolationException e) {
  5. String url = req.getRequestURI();
  6. String method = req.getMethod();
  7. return new UnifyResponse(10001,e.getMessage(),method + " " + url);
  8. }

message为什么要写在配置文件中?

  1. code和message可以做映射
  2. 可以解决国际化的问题
  3. 硬编码message散落在各个角落,不利于管理

image.png

UnifyResponese 定义载入

定义数据类型:

  1. {
  2. "code": 10001,
  3. "message": "test.id: 必须超过10",
  4. "request": "GET /v1/banner/test/1"
  5. }


UnifyResponese 数据结构的定义

url = method+url

UnifyResponese 正常返回的一些坑

get和set定义

@ReposeBody注解加入

处理未知异常

状态码修改@ResponseStatus

@ResponseStatus(code= HttpStatus的枚举)

加入展示错误代码

在开发环境中,虽然我们对前端屏蔽了错误信息,但是在服务器端方便我们调试,我们是需要打印这些错误信息用来修改我们的bug