我准备开一个系列,就是写一些在简要的学习项目中可能会用到的奇奇怪怪的功能,比如线程池或者统一异常处理类
取名为【项目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;
/**
* @program: blog
* @description: 统一异常处理类
* @author: livorth
* @create: 2021-09-29 20:17
**/
@ControllerAdvice
@Slf4j
public class AllExceptionHandler {
/**
* 进行异常处理,处理Exception.class的异常
* 然后返回的是json类型的数据
*/
@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<User> 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; /** * @program: FunctionalLearning * @description: 自定义异常类 * @author: livorth * @create: 2021-10-03 11:49 **/ @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 List<User> testCustomException() 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;
/**
* @program: FunctionalLearning
* @description: 结果返回
* @author: livorth
* @create: 2021-10-03 11:17
**/
@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;
/**
* @program: ErrorCode
* @description: 错误码
* @author: livorth
* @create: 2021-09-28 17:24
**/
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