导学 ==> 项目异常统一处理:
-
异常处理器
-
自定义异常
-
自定义异常编码
一、异常处理器
平时开发可能出现的异常及其原因
- 框架内抛出异常:因使用规范不一致导致
- 数据层(Repository)抛出异常:因外部服务器故障导致
- 业务层(Service)排除异常:因业务逻辑书写错误导致
- 表现层(Controller)抛出异常:因数据手机,效验规则导致
- 工具类(Utils)抛出异常:因工具类书写不严谨、不健壮导致
各个层级均有可能抛出异常,如果我们每层都处理异常,代码过于冗余
我们可以将各层的异常统统抛出,到表现层(Controller)对这些异常进行统一的处理
那我们如何在表现层处理这些异常呢?每个方法都去单独书写异常处理方案?这样不仅书写量巨大且耗时,又不利于维护。我们可以采用AOP思想 ,SpringMvc已经为我们造好了轮子
1,在Controller层下新建ProjectException类
@RestControllerAdvice
public class ProjectException {
@ExceptionHandler(Exception.class)
public void executeException(Exception e){
System.out.println("异常被我处理啦");
}
}
2,在SpringMvc配置类下扫描当前类
package com.brrbaii.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@ComponentScan("com.brrbaii.controller")
//Json数据转对象
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
//过滤静态资源,防止被SpringMvc拦截
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}
3,测试
我们在Service层手动制造一个异常
访问这个方法,观察控制台输出结果
4,设置异常处理统一格式
新建Result类
package com.brrbaii.controller;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class Result<T> {
//数据
T data;
//消息
String msg;
//状态码
Integer code;
public Result(Integer code,T data, String msg) {
this.data = data;
this.msg = msg;
this.code = code;
}
public Result(Integer code,T data) {
this.data = data;
this.code = code;
}
}
修改ProjectException类,使其方法返回Result
前端收到的结果:
二、自定义异常
项目遇到的异常分类:
- 业务异常(BusinessException)
- 规范的用户行为产生的异常
- 不规范的用户行为操作产生的异常
- 系统异常(SystemException)
- 项目运行过程中可预计但无法避免的异常
- 其他异常(Exception)
- 编程人员未预期到的异常
上述异常处理方案:
- 业务异常(BusinessException)
- 发送对应的消息传递给客户,题型规范操作
- 系统异常(SystemException)
- 发送固定消息传递给用户,安抚用户
- 发送特定的消息给运维人员,提醒维护
- 记录日志
- 其他异常(Exception)
- 发送固定消息传递给用户,安抚用户
- 发送特定的消息给编程人员,提醒维护(纳入后续预期范围)
- 记录日志
我们对可能出现的种种异常集中为上面三类异常,分别创建对应的类
1,BusinessException
package com.brrbaii.controller.exception;
import lombok.Data;
@Data
public class BusinessException extends RuntimeException{
//自定义异常编码
private Integer code;
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
public BusinessException(Integer code, String message, Throwable cause ) {
super(message, cause);
this.code = code;
}
}
2,SystemException
package com.brrbaii.controller.exception;
import lombok.Data;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Data
public class SystemException extends RuntimeException{
private Integer code;
public SystemException(Integer code, String message) {
super(message);
this.code = code;
}
public SystemException(Integer code, String message, Throwable cause ) {
super(message, cause);
this.code = code;
}
}
3,修改我们的异常处理器(ProjectException),然它处理上述两异常异常
package com.brrbaii.controller.exception;
import com.brrbaii.controller.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class ProjectException {
//处理系统异常
@ExceptionHandler(SystemException.class)
public Result executeSystemException(SystemException e){
// 1,发送固定消息传递给用户,安抚用户
// 2,发送特定的消息给运维人员,提醒维护
// 3,记录日志
// 4,返回异常消息
return new Result(e.getCode(),null,e.getMessage());
}
//处理业务异常
@ExceptionHandler(BusinessException.class)
public Result executeBusinessException(BusinessException e){
// 1,发送固定消息传递给用户,安抚用户
// 2,发送特定的消息给开发人员,提醒维护(后续纳入可预期异常范畴)
// 3,记录日志
// 4,返回异常消息
return new Result(e.getCode(),null,e.getMessage());
}
}
接下来我们对可能出现异常的代码进行包装,将异常转换为我们上述自定义的异常
三、自定义异常编码
对于返回的异常编码,我们不想固定写死
可以创建一个Code类,对异常编码进行统一
package com.brrbaii.controller;
public class Code {
//系统异常
public static final Integer SYSTEM_ERR = 50001;
//业务异常
public static final Integer BUSINESS_ERR = 50006;
//请求成功
public static final Integer SAVE_OK = 20011;
public static final Integer DELETE_OK = 20021;
public static final Integer UPDATE_OK = 20031;
public static final Integer SELECT_OK = 20041;
//请求失败
public static final Integer SAVE_ERR = 20010;
public static final Integer DELETE_ERR = 20020;
public static final Integer UPDATE_ERR = 20030;
public static final Integer SELECT_ERR = 20040;
}
修改方法返回的异常编码