# exception-handler
**Repository Path**: geekerdream/exception-handler
## Basic Information
- **Project Name**: exception-handler
- **Description**: 统一异常处理,配置简单,可扩展。支持Spring项目、SpringBoot项目。
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 34
- **Forks**: 13
- **Created**: 2018-03-04
- **Last Updated**: 2024-08-29
## Categories & Tags
**Categories**: utils
**Tags**: None
## README
[TOC]
## 作者:编程界的小学生
## 时间:2018-02-03
## 项目名称:exception-handler
## 是什么?
**统一异常处理。支持返回统一的Json格式和跳转到错误页面。**
## 有什么用?
**我们项目中难免会遇到一些异常,比如自定义异常、参数传递异常等等其他异常。遇到异常我们一般是捕获并解决,或者直接将错误信息抛给客户端,问题来了,一堆乱七八糟的错误日志直接抛给用户,用户看得懂吗?会有人说,那可以直接判断状态码不是200的话就弹出系统异常等字样提示。是可以的,但是我们想更精确的知道是什么异常,比如参数异常,我们的业务异常等,所以这个`exception-handler`就是一个统一异常处理的工具类。他能帮我们处理你任何自定义的异常以及其他异常,处理方式为统一返回如下格式的JSON给客户端**
```
{
"code": 1,
"msg": "系统异常",
"result": "xxxxx"
}
```
*注意:不同类型的异常code是不同的,内置分为参数异常和系统异常,前端可以根据不同的code来进行不同的处理,比如跳转不同的页面等。*
## 怎么用?
**我上面说了有什么用,现在来说说具体怎么用。分为两种使用,一种是maven项目的使用,一种是非maven项目的使用。**
**maven项目的使用**
*首先下载此项目,在项目根目录(包含pom.xml的目录)运行如下命令*
`mvn clean install`
*然后将如下配置放到你项目的pom.xml中*
```xml
com.chentongwei
exception-handler
1.0.0
```
**非maven项目的使用**
*首先下载项目,然后导出成jar包放到项目的lib目录。*
**接下来说下spring项目和springboot项目如何使用**
**`spring`使用**
*直接复制下面配置到你的配置文件即可。*
``
**`springboot`使用**
*将如下配置类复制到你项目中受spring所管理的包中即可生效。*
```java
import com.chentongwei.interceptor.ExceptionResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author TongWei.Chen 2018-03-01 16:13
*/
@Configuration
public class WebConfig {
@Bean
public ExceptionResolver getBean() {
return new ExceptionResolver();
}
}
```
**配置完成后即可使用,如果你项目中报任何错误,都会被系统拦截到并将错误级别(这里所谓的错误级别是指msg)和错误具体信息抛给客户端。如果我们想要抛出我们自定义的异常的怎么办?**
**可以直接自己建立自定义异常类并继承`com.chentongwei.exception.ExceptionStrategy`(内置了一个`BussinessException`)**
*自定义异常Demo*
```java
import com.chentongwei.enums.IBaseEnum;
import com.chentongwei.strategy.ExceptionStrategy;
/**
* @author TongWei.Chen 2018-03-01 15:55
*/
public class UserNotExistException extends ExceptionStrategy {
private IBaseEnum baseEnum;
public IBaseEnum getBaseEnum() {
return baseEnum;
}
public void setBaseEnum(IBaseEnum baseEnum) {
this.baseEnum = baseEnum;
}
public UserNotExistException(IBaseEnum baseEnum) {
this.baseEnum = baseEnum;
}
@Override
public IBaseEnum resolverException() {
return this.baseEnum;
}
}
```
*注意:`com.chentongwei.enums.IBaseEnum`是我自定义的一个错误信息枚举接口,所以必须包含比此属性并且带有此属性的构造器。*
**如果我们想自定义异常错误码和错误信息怎么办?可以自定义枚举类然后实现`com.chentongwei.enums.IBaseEnum`**
*自定义枚举Demo*
```java
import com.chentongwei.enums.IBaseEnum;
/**
* @author TongWei.Chen 2018-03-02 14:20:38
*/
public enum ResponseEnum implements IBaseEnum{
NULL(2, "未查到此数据")
;
private int code;
private String msg;
ResponseEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
}
```
**完整Demo**
```java
import com.chentongwei.enums.IBaseEnum;
import com.chentongwei.strategy.ExceptionStrategy;
/**
* @author TongWei.Chen 2018-03-01 15:55
*/
public class UserNotExistException extends ExceptionStrategy {
private IBaseEnum baseEnum;
public IBaseEnum getBaseEnum() {
return baseEnum;
}
public void setBaseEnum(IBaseEnum baseEnum) {
this.baseEnum = baseEnum;
}
public UserNotExistException(IBaseEnum baseEnum) {
this.baseEnum = baseEnum;
}
@Override
public IBaseEnum resolverException() {
return this.baseEnum;
}
}
import com.chentongwei.enums.IBaseEnum;
/**
* @author TongWei.Chen 2018-03-02 14:20:38
*/
public enum ResponseEnum implements IBaseEnum{
NULL(2, "未查到此数据")
;
private int code;
private String msg;
ResponseEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
}
@RestController
public class UserController {
@GetMapping("/user/{id}")
public void detail(@PathVariable Integer id) {
throw new UserNotExistException(ResponseEnum.NULL);
}
}
```
**调用URL**
```url
http://ip:port/projectname/user/1
```
**返回结果**
```json
{
"code": 2,
"msg": "未查到此数据",
"result": "未查到此数据"
}
```
**结果简单说明**
上面的JSON数据很明显是我们自定义枚举类里的内容,所以这样就达到了可扩展,根据不同的业务可以抛出不同的异常。而我们的`exception-handler`全都会为我们捕获并抛给客户端。
**跳转页面配置**
上面说的是返回统一的JSON,接下来简单说下如果不是静态分离的项目,应该如何配置才能跳转到自定义的异常页面上。
在`resources`目录下新建`system.properties`,里面支持两个参数,如下
```properties
com.chentongwei.exception.handler.type=HTML
com.chentongwei.exception.view=/error.html
```
*第一个参数若不配置则默认是返回JSON,这里配置为HTML,则就会触发跳转到页面的逻辑,而不是统一返回JSON的逻辑;第二个参数是需要跳转到哪个页面上。*
## 项目其他描述
*如果你有用到Hibernate Valid(比如@NotNull,@NotEmpty等等注解验证),则我们的`exception-handler`也为我们捕获了此异常,称之为参数传递异常。如下做个Demo进行演示查看效果*
```java
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
/**
* @author TongWei.Chen 2018-02-28 15:49
*/
public class UserIO {
@NotNull(message = "用户名不能为空")
private String username;
@Range(min = 0, max = 100, message = "年龄必须在0~100之间")
private int age;
private int ageTo;
private String xxx;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getAgeTo() {
return ageTo;
}
public void setAgeTo(int ageTo) {
this.ageTo = ageTo;
}
public String getXxx() {
return xxx;
}
public void setXxx(String xxx) {
this.xxx = xxx;
}
}
@GetMapping("/user")
public List query(@Valid UserIO userIO) {
return null;
}
```
**调用URL**
`http://ip:port/projectname/user?username=&age=101`
**返回结果**
```json
{
"code": 3,
"msg": "参数传递异常",
"result": "年龄必须在0~100之间并且用户名不能为空"
}
```
**结果简单说明**
code为3,msg称为参数传递异常,result是具体因为什么而发生异常的一个详细说明。很完美的JSON。完全无需我们在额外管理其他东西。
*PS:对Valid验证不了解的,希望自行学习下,学习成本很低,很了不起的一个校验框架,能省下很多时间,也支持自定义的注解校验,不是此处重点,所以不进行过多讲解。*
*日志问题*
我们都想在抛出异常时记录下日志到文件,默认采取的是log4j,若你是logback或其他,请自行将`com.chentongwei.interceptor.ExceptionResolver`里面这句话换掉。
`private static final Logger LOG = LogManager.getLogger("exceptionLog");`
若您采取的是log4j,则只需要声明个name为exceptionLog的logger即可。
*值得注意的地方*
若此项目与您的项目jar重复导致问题的话,请用maven依赖的时候将我这里的jar排除掉即可。
## 写在最后的话
我是一个对编程充满无限兴趣的小学生。写的东西不是很完美,希望大家多多提ISSUE,共同交流一起进步!
*个人名言:*
**什么都要会一点,这样装起逼来不会尴尬。**
**彪悍的人生不需要解释。**