在工作过程中,我们常常需要在合适的地方抛出合适的异常,除了java自带的一些异常,我们可以在项目中定制自己的异常,并且全局捕获它,返回统一封装的信息,这样前端可以直接拿到我们的异常信息进行弹出!
那么,如何自定义异常呢?
1.首先需要一个自定义异常类,OrderException(需要继承RuntimeException)
public class OrderException extends RuntimeException {
private Integer code;
private String message;
public OrderException() {
}
public OrderException(String message){
super(message);
}
public OrderException(Integer code, String message) {
super(message);
this.code = code;
}
//定义枚举类,以错误码加信息的形式返回
public OrderException(ErrorCode errorCode) {
this.message = errorCode.getMsg();
this.code = errorCode.getCode();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2.错误信息枚举类:ErrorCode
/**
* @desc: 错误码枚举(code<1400为成功;code>=1400为失败)
* @author: WT
* @createTime:
* @version: 1.0
*/
public enum ErrorCode {
SUCCESS(1200, "操作成功"),
SUCCESS_LOGGED(1203,"已登录"),
ERROR(1500, "操作失败"),
ERROR_LOGIN(1600, "登录失败"),
ERROR_TOKEN(1602,"TOKEN失效或者错误"),
ERROR_ARG(1601, "参数错误"),
ERROR_AUTH(1606, "认证失败"),
ERROR_QUERY(1608, "数据丢失");
private final int code;
private final String msg;
/**
* @param code
* @param msg
*/
private ErrorCode(final int code, final String msg) {
this.code = code;
this.msg = msg;
}
/**
* @return the code
*/
public int getCode() {
return code;
}
/**
* @return the msg
*/
public String getMsg() {
return msg;
}
}
3.接下来我们需要在controller包下新建文件夹exceptionHandler,创建全局异常捕捉类:DefaultExceptionHandler
@RestControllerAdvice
public class DefaultExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionHandler.class);
@ExceptionHandler(OrderException.class)
public Message handlerSellerException(OrderException e) {
logger.error("订单模块异常:{}",e.getMessage());
return new Message(e.getCode(),e.getMessage());
}
@ExceptionHandler(RuntimeException.class)
public Message processRuntimeException(RuntimeException e) {
e.printStackTrace();
logger.error("运行时异常:{}",e.getMessage());
return new Message(1604,"操作失败");
}
@ExceptionHandler(Exception.class)
public Message processException(Exception e) {
e.printStackTrace();
logger.error("系统异常:{}",e.getMessage());
return new Message(1604,"操作失败");
}
}
4.这里的Message封装了controller返回信息的统一格式:Message
**
* @desc:信息返回对象
* @author:
* @createTime:
* @version: 1.0
*/
public class Message<T> {
// 状态码
private final int code;
// 提示语
private final String msg;
// 状态(true=成功)
private final boolean status;
// 对象
private T t;
// 对象
private Map map;
//跳转页面
private String path;
/**
* @param errorCode
*/
public Message(ErrorCode errorCode) {
super();
this.code = errorCode.getCode();
this.msg = errorCode.getMsg();
this.status = code < 1400 ? true : false;
}
public Message(int code, String msg) {
this.code = code;
this.msg = msg;
this.status = code < 1400 ? true : false;
}
/**
* @param errorCode
* @param t
*/
public Message(ErrorCode errorCode, T t) {
super();
this.code = errorCode.getCode();
this.msg = errorCode.getMsg();
this.status = code < 1400 ? true : false;
this.t = t;
}
public Message(ErrorCode errorCode, T t, String path) {
super();
this.code = errorCode.getCode();
this.msg = errorCode.getMsg();
this.status = code < 1400 ? true : false;
this.t = t;
this.path=path;
}
public Message(ErrorCode errorCode, T t, Map map) {
super();
this.code = errorCode.getCode();
this.msg = errorCode.getMsg();
this.status = code < 1400 ? true : false;
this.t = t;
this.map=map;
}
/**
* @return the code
*/
public int getCode() {
return code;
}
/**
* @return the msg
*/
public String getMsg() {
return msg;
}
/**
* @return the t
*/
public T getT() {
return t;
}
/**
* @param t
* the t to set
*/
public Message setT(T t) {
this.t = t;
return this;
}
/**
* @return the status
*/
public boolean isStatus() {
return status;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Message [code=");
stringBuilder.append(code);
stringBuilder.append(", msg=");
stringBuilder.append(msg);
stringBuilder.append(", status=");
stringBuilder.append(status);
stringBuilder.append(", t=");
stringBuilder.append(t);
stringBuilder.append("]");
return stringBuilder.toString();
}
/**
* @return the path
*/
public String getPath() {
return path;
}
/**
* @param path the path to set
*/
public void setPath(String path) {
this.path = path;
}
public Map getMap() {
return map;
}
public Message setMap(Map map) {
this.map = map;
return this;
}
}
5.新建测试类:TestExceptionHandler
@RestController
@RequestMapping("exception")
public class TestExceptionController {
@RequestMapping(value = "test",method = RequestMethod.GET)
public Message testException(String ex) {
Optional.ofNullable(ex).orElseThrow(() -> new OrderException(ErrorCode.ERROR_ARG));
return new Message(ErrorCode.SUCCESS);
}
}
6.测试
访问url: http://192.168.0.161:9002/exception/test(GET)
如果加入了security,需要在请求头中传入token或者在MyResourceServerConfig中进行过滤
测试结果:
{
"code": 1601,
"msg": "参数错误",
"status": false,
"t": null,
"map": null,
"path": null
}
控制台打印:ERROR 14652 --- [nio-9002-exec-3] c.h.h.c.e.DefaultExceptionHandler : 订单模块异常:参数错误
成功捕捉到我们抛出的异常并且将信息用我们统一的格式返回
访问url: http://192.168.0.161:9002/exception/test?ex=success(GET)
测试结果:
{
"code": 1200,
"msg": "操作成功",
"status": true,
"t": null,
"map": null,
"path": null
}
没有抛出异常的结果!
OK,自定义异常就是这么简单,棒棒哒!