项目使用 GlobalExceptionHandler 与 @RestControllerAdvice自定义异常 二
未经博主允许不得转载:
自定义异常,不仅需要定义符合自己业务的异常状态码,也需要定义自己项目中的异常封装。记录下自己手敲代码中的异常封装:
1.定义一个枚举类,枚举类中定义状态码及状态码描述,再定义一个接口,使枚举类实现该接口,从而可以获取枚举类中当前的异常状态码,异常描述等。
package com.lf.mp.test; /** * 用来获取异常的状态码及描述 */ public interface ExceptionType { // 获取描述 public String getMessage(); // 获取状态码 public Integer getCode(); // 是否参数化 public Boolean isParam(); }
package com.lf.mp.test; /** * 自定义异常枚举 */ public enum ExceptionEnum implements ExceptionType { NOT_FOUNT(404, "页面或路径不存在"), METHOD_NOT_ALLOWED(405, "方法不允许", true), USEER_NOT_EXISTED(100001, "用户不存在"), PARAM_ERROR(100002, "参数错误", true), // 对于参数使用异常这种场景,会对参数进行不同的描述,这里可使用{}的方式代替,在解析的时候对{}进行替换 PARAMS_ERROR(100002, "{}"),; // 状态码 private Integer code; // 状态码描述 private String message; // 是否参数解析 private boolean isParam; // 重载 ExceptionEnum(Integer code, String message, boolean isParam) { this.code = code; this.message = message; this.isParam = isParam; } // 重载 ExceptionEnum(Integer code, String message) { this.code = code; this.message = message; } @Override public String getMessage() { this.message = message; return message; } @Override public Integer getCode() { return this.code; } @Override public Boolean isParam() { return this.isParam; } }
2.自定义异常类;
package com.lf.mp.test; import lombok.Data; import java.io.Serializable; /** * 自定义业务异常 */ @Data public class CustomException extends RuntimeException implements Serializable { private static final long serialVersion = 493083738120393040L; private ExceptionEnum exceptionEnum; private Integer code; private String message; // 对自定义异常进行构造封装 public CustomException(ExceptionEnum exceptionEnum) { this.exceptionEnum = exceptionEnum; this.message = exceptionEnum.getMessage(); this.code = exceptionEnum.getCode(); } public CustomException(String message, ExceptionEnum exceptionEnum) { super(message); this.exceptionEnum = exceptionEnum; this.message = message; } public CustomException(Throwable cause, ExceptionEnum exceptionEnum) { this.exceptionEnum = exceptionEnum; this.message = cause.getMessage(); } }
3.自定义异常捕捉后返回的数据接口
package com.lf.mp.test; import lombok.Data; /** * 定义response响应数据体 */ @Data public class Result { // 状态码 private Integer code; // 响应描述 private String msg; // 响应数据 private Object data; public Result(Integer code, String msg) { this.code = code; this.msg = msg; } }
4.通过@ControllerAdvice 或 @RestControllerAdvice 注解封装项目中的异常
通过@ControllerAdvice ,可以将对于控制器的全局配置放置在同一个位置,注解了@Controller 的类的方法可以使用@ExceptionHandler,@InitBinder,@ModelAttribute注解
到方法上,这对所有注解了@RequestMapping 的控制器内的方法有效。
@ExceptionHandler:用于全局处理控制器里的异常
@InitBinder: 用来设置WebDataBinder,WebDataBinder 用来自动绑定前台请求参数到Model中
@ModelAttribute:绑定键值对到Model里,此处是让全局的@RequestMapping 都能获得在此处设置的键值对。
@RestControllerAdvice 则是@ControllerAdvice 与 @ResponseBody 的合体
@ResponseBody 支持将返回值放在response 体内,而不是返回一个页面。我们在很多基于ajax 的程序的时候,可以一次注解返回数据而不是页面。
package com.lf.mp.test; import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 全局异常处理器 */ @RestControllerAdvice public class GlobalExceptionHandler { //处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常 @ExceptionHandler(BindException.class) public Result BindExceptionHandler(BindException e) { return new Result(ExceptionEnum.METHOD_NOT_ALLOWED.getCode(), e.getMessage()); } @ExceptionHandler(CustomException.class) public Result customExceptionHandler(HttpServletRequest request, final CustomException exception, HttpServletResponse response) { response.setStatus(HttpStatus.BAD_REQUEST.value()); return new Result(exception.getCode(), exception.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) public Result MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException exception) { return new Result(ExceptionEnum.METHOD_NOT_ALLOWED.getCode(), exception.getMessage()); } }
使用示例如下:
private void test() { try { int a = 1/0; } catch (CustomException e) { throw new CustomException(ExceptionEnum.OTHER_ERROR,"计算异常"); } }
-----
这种异常的封装很简洁,也很好使用,对项目的异常状态码,异常描述都有较好的封装。使用也很方便。
还有一种经常使用的异常封装。定义一个CustomException,并继承Exception类,在CustomException中定义异常状态码,以描述两个属性,
在使用过程中,状态码则使用HttpStatus中的异常码,描述则使用自定义描述,也很方便,主要符合自己业务,方便开发即可。