java实现自定义异常并全局捕获

在工作过程中,我们常常需要在合适的地方抛出合适的异常,除了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,自定义异常就是这么简单,棒棒哒!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值