在项目中,难免会出现各种各样的异常,我们希望异常信息尽可能详细,包括响应状态码,响应的字符串异常信息,甚至操作时间等等,这样可以方便地快速定位到发生异常的位置.所以,一个项目中对于异常的处理就显得尤为重要.那么,小编就以SpringBoot框架,通过代码实例展示统一异常的处理方式.
1.首先我们简单搭建一个SpringBoot框架的项目,项目名称是exceptionhandler(异常处理)
2.导入相关依赖
导入lombok依赖,提供@getter注解
导入日期工具类JodaTime,提供DateTime.now()方法
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--日期工具类:JodaTime-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3.编写application.yml配置文件
注意这里添加了访问路径前缀
server:
port: 8082
servlet:
context-path: /exception
4.编写SpringBoot的启动类
package com.exception;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExceptionApplication {
public static void main(String[] args) {
SpringApplication.run(ExceptionApplication.class, args);
}
}
5.编写异常枚举类
异常枚举类中,应该列举出项目可能出现的所有异常类型,这里只拿数学计算异常举例
package com.exception.enums;
import lombok.Getter;
/**
* 异常枚举类
*/
@Getter
public enum ExceptionEnum {
ARTITHMETIC(500, "数学计算异常");
private Integer status;
private String message;
ExceptionEnum(Integer status, String message) {
this.status = status;
this.message = message;
}
}
6.编写自定义异常类
自定义异常类继承RuntimeException,同时RuntimeException继承Exception类,而Exception又继承Throwable类,super方法最终也是Throwable中的方法
package com.exception.exceptions;
import com.exception.enums.ExceptionEnum;
import lombok.Getter;
/**
* 自定义异常类
*/
@Getter
public class SelfDefinedException extends RuntimeException {
private Integer status;
public SelfDefinedException(ExceptionEnum exceptionEnum) {
super(exceptionEnum.getMessage());
this.status = exceptionEnum.getStatus();
}
public SelfDefinedException(ExceptionEnum exceptionEnum, Throwable cause) {
super(exceptionEnum.getMessage(), cause);
this.status = exceptionEnum.getStatus();
}
}
7.编写统一异常返回结果类
package com.exception.entity;
import com.exception.exceptions.SelfDefinedException;
import lombok.Getter;
import org.joda.time.DateTime;
/**
* 统一异常返回结果类
*/
@Getter
public class ExceptionResult {
private Integer status;
private String message;
private String timestamp;
public ExceptionResult(SelfDefinedException e) {
this.status = e.getStatus();
this.message = e.getMessage();
this.timestamp = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
}
}
8.编写统一异常拦截类
需注意两个spring注解的作用:
@ControllerAdvice:此注解默认情况下,会拦截所有加了@Controller注解的类
@ExceptionHandler():此注解用在方法上,括号内声明要处理的异常类型,可以指定多个,这里我们指定的是自定义异常
package com.exception.advice;
import com.exception.entity.ExceptionResult;
import com.exception.exceptions.SelfDefinedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* 统一异常拦截类
*/
@ControllerAdvice
@Slf4j
public class BasicExceptionAdvice {
@ExceptionHandler(SelfDefinedException.class)
public ResponseEntity<ExceptionResult> handlerException(SelfDefinedException e) {//参数类型与要处理的异常类型必须匹配
return ResponseEntity.status(e.getStatus()).body(new ExceptionResult(e));//body中的对象必须和ResponseEntity中的对象一致
}
}
9.编写测试类
package com.exception.controller;
import com.exception.enums.ExceptionEnum;
import com.exception.exceptions.SelfDefinedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class TestController {
@GetMapping("/test")
public ResponseEntity<String> login() {
try {
Integer tempValue = 10 / 0;
} catch (Exception e) {
throw new SelfDefinedException(ExceptionEnum.ARTITHMETIC);//catch捕获异常后,这里throw抛出异常并未处理,所以后面的代码不会执行
}
return ResponseEntity.ok("没发现异常,返回正确的字符串");
}
}
10.测试结果
通过IDEA自带的HTTP Client进行测试,观察响应结果如下.这样我们就得到了
总结:
因为项目中会出现各种各样的异常,所以我们通过一个异常枚举类将所有的异常进行列举.我们希望捕获自己定义的异常,所以编写了一个自定义异常类,同时我们希望响应的异常结果规则且详细,所以通过一个统一异常结果类来实现.最重要的是,我们还需要一个异常拦截类,这样在我们抛出自定义异常的时候,这个异常拦截类能够进行拦截,并将我们定义好的响应结果(也就是异常体所有信息)返回.