我准备开一个系列,就是写一些在简要的学习项目中可能会用到的奇奇怪怪的功能,比如线程池或者统一异常处理类
取名为【项目demo】系列
然后将会同步到GitHub中:https://github.com/Livorth/FunctionalLearning
统一异常处理类
在涉及到异常处理的时候,就会常常看到spring中两个常用的注解:
- @ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
- @ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开;其是对Controller层进行拦截
通过将将这两注解组合使用,能够写出一个统一的异常处理类
我自己将统一异常类的使用分为三档
- 直接对全部的异常做处理,不管是什么都返回相同的异常结果
- 对于已经被 java 所描述并封装对象的异常,将他们单独列出来进行特殊的异常处理
- 对于没有被 java 所描述并封装对象的异常,
-
对于拦截全部异常,@ExceptionHandler(Exception.class),也就是包含全部的异常
-
对于特殊异常处理,@ExceptionHandler(特殊异常泪目.class),其实对于自定义异常也是同理,特殊异常处理的优先级比全部异常更高
AllExceptionHandler.java
package cn.livorth.functionallearning.handler;
import cn.livorth.functionallearning.constant.ErrorCode;
import cn.livorth.functionallearning.entity.dto.ResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
@Slf4j
public class AllExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public ResultDTO doAllException(Exception e){
log.info("出现了异常:" + e.getMessage());
return ResultDTO.byErrorCode(ErrorCode.SYSTEM_ERROR);
}
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public ResultDTO doException(Exception e){
log.info("出现了异常:" + e.getMessage());
return ResultDTO.fail(505, "测试特殊异常处理");
}
}
UserController.java
@GetMapping("testExceptionHandler")
public List testExceptionHandler() throws Exception {
int a = 1 / 0;
throw new Exception();
}
然后进行测试:http://localhost:8888/user/testExceptionHandler
然后注掉int a = 1 / 0;
自定义异常类的自由度会更高,但是这里仅做简单测试
-
先要写一个自定义异常类,将自己想要分装的东西包含进去
CustomException.java
package cn.livorth.functionallearning.handler.exception; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class CustomException extends RuntimeException { private Integer code; private String msg; } -
然后对CustomException进行拦截
AllExceptionHandler.java
@ExceptionHandler(CustomException.class) @ResponseBody public ResultDTO doCustomException(CustomException e){ log.info("出现了异常:" + e.getMessage()); return ResultDTO.fail(e.getCode(), e.getMsg()); } -
编写controller,抛出CustomException准备进行测试
UserController.java
@GetMapping("testCustomException") public ListtestCustomException() throws Exception { throw new CustomException(505, "这里是自定义异常"); } -
进行测试:http://localhost:8888/user/testCustomException
然后代码中的ResultDTO是我自己分装的一个数据传递类,ErrorCode则是一个存储错误常量的枚举类
ResultDTO.java
package cn.livorth.functionallearning.entity.dto;
import cn.livorth.functionallearning.constant.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ResultDTO {
private Boolean success;
private Integer code;
private String msg;
private Object data;
public static ResultDTO success(Object data){
return new ResultDTO(true,200,"success", data);
}
public static ResultDTO fail(Integer code, String msg){
return new ResultDTO(false,code,msg,null);
}
public static ResultDTO byErrorCode(ErrorCode errorCode){
return new ResultDTO(false, errorCode.getCode(), errorCode.getMsg(),null);
}
}
ErrorCode.java
package cn.livorth.functionallearning.constant;
public enum ErrorCode {
PARAMS_ERROR(10001,"参数有误"),
ACCOUNT_PWD_NOT_EXIST(10002,"用户名或密码不存在"),
TOKEN_ERROR(10003,"token不合法"),
ACCOUNT_EXIST(10004,"账号已存在"),
NO_PERMISSION(70001,"无访问权限"),
SESSION_TIME_OUT(90001,"会话超时"),
NO_LOGIN(90002,"未登录"),
SYSTEM_ERROR(505, "系统出了点小问题,这不找管理员并ta一顿?");
private Integer code;
private String msg;
ErrorCode(Integer code, String msg){
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
不过也说不准以后会进行改动就是了
写在最后
很显然使用全部异常处理是最简单的,对于全部的异常都抛出同样的信息,基本上不用想事情
然后就是自定义异常,如果自定义异常类和处理方法相互之间的逻辑关系紧密的话,可以得到不错的效果
反正看个人喜好吧
我的项目demo系列都会同步到GitHub上,欢迎围观
https://github.com/Livorth/FunctionalLearning



