## 后台异常处理 在开发过程中,不可避免的是需要处理各种异常,异常处理方法随处可见,所以代码中就会出现大量的`try {...} catch {...} finally {...}` 代码块,不仅会造成大量的冗余代码,而且还影响代码的可读性,所以对异常统一处理非常有必要。为此,我们定义了一个统一的异常类`YamiShopBindException` 与异常管理类 `DefaultExceptionHandlerConfig`。 我们先来看下 `YamiShopBindException`的代码 ```java public class YamiShopBindException extends RuntimeException { private static final long serialVersionUID = -4137688758944857209L; /** * http状态码 */ private Integer httpStatusCode; /** * @param httpStatus http状态码 */ public YamiShopBindException(YamiHttpStatus httpStatus) { super(httpStatus.getMsg()); this.httpStatusCode = httpStatus.value(); } /** * @param httpStatus http状态码 */ public YamiShopBindException(YamiHttpStatus httpStatus, String msg) { super(msg); this.httpStatusCode = httpStatus.value(); } public YamiShopBindException(String msg) { super(msg); this.httpStatusCode = HttpStatus.BAD_REQUEST.value(); } public Integer getHttpStatusCode() { return httpStatusCode; } } ``` `YamiHttpStatus`为我们自定义的返回状态码的枚举类,定义为一个枚举类,更直观处理异常返回的状态码及异常内容,以后每增加一种异常情况,只需增加一个枚举实例即可,不用每一种异常都定义一个异常类。 ```java public enum YamiHttpStatus { /** * 客户端看到401状态码时,应该重新登陆 */ UNAUTHORIZED(401, "未授权"), COUPONCANNOTUSETOGETHER(601, "优惠券不能共用"), ; private final int value; private final String msg; YamiHttpStatus(int value, String msg) { this.value = value; this.msg = msg; } public int value() { return this.value; } public String getMsg() { return msg; } public static YamiHttpStatus resolve(int statusCode) { for (YamiHttpStatus status : values()) { if (status.value == statusCode) { return status; } } return null; } } ``` 再来看看 `DefaultExceptionHandlerConfig`类 ```java @Controller @RestControllerAdvice public class DefaultExceptionHandlerConfig { @ExceptionHandler(YamiShopBindException.class) public ResponseEntity<String> unauthorizedExceptionHandler(YamiShopBindException e){ e.printStackTrace(); return ResponseEntity.status(e.getHttpStatusCode()).body(e.getMessage()); } } ``` ## 前台异常处理 前端请求与相应做了封装,请求响应的内容会被拦截器所拦截,当后台返回给前台特定的状态码,前台将显示不同报错信息。请求响应非常常见,我们查看在`src\utils\httpRequest.js`里面的其中一段代码 ```javascript http.interceptors.response.use(response => { return response }, error => { switch (error.response.status) { case 400: Message.error(error.response.data) break case 401: clearLoginInfo() router.push({ name: 'login' }) break case 405: Message.error('http请求方式有误') break case 500: Message.error('服务器出了点小差,请稍后再试') break case 501: Message.error('服务器不支持当前请求所需要的某个功能') break } return Promise.reject(error) }) ``` 这里将会统一拦截返回的状态码如`400`,进行错误提示。 ## RESTful 风格 我们的上述代码使用http状态码对请求进行统一响应,其中最大的 RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。 [RESTful概述](https://blog.igevin.info/posts/restful-architecture-in-general/)