目标:
统一处理异常信息,尽量少的 try catch
代码块,只关注业务逻辑,而不用花费大量精力写冗余的 try catch
代码块。
Spring
家族的org.springframework.util.Assert
,在我们写测试用例的时候经常会用到,比如
@Test
public void test1() {
...
User user = userDao.selectById(userId);
Assert.notNull(user, "用户不存在.");
...
}
@Test
public void test2() {
// 另一种写法
User user = userDao.selectById(userId);
if (user == null) {
throw new IllegalArgumentException("用户不存在.");
}
}
我们查看源码 可以看到,Assert
其实就是帮我们把 if {...}
封装了一下,但是编码体验至少提升了一个档。
/**
* Assert that an object is {@code null}.
* Assert.isNull(value, "The value must be null");
* @param object the object to check
* @param message the exception message to use if the assertion fails
* @throws IllegalArgumentException if the object is not {@code null}
*/
public static void isNull(@Nullable Object object, String message) {
if (object != null) {
throw new IllegalArgumentException(message);
}
}
模仿org.springframework.util.Assert
,写一个断言类,断言失败后抛出的异常自己定义的异常。
首先自定义异常:
import lombok.Data;
@Data
public abstract class BaseException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
private String code;
private String message;
// private Object[] objects;
private IExceptionEnum enum1;
// private Throwable throwable;
public BaseException(Exception e){
super(e);
}
public BaseException(IExceptionEnum enum1,Object[] objects,String message){
this.enum1=enum1;
this.message =message;
//this.objects=objects;
this.code=enum1.getCode()+"";
}
public BaseException(IExceptionEnum enum1,Object[] objects,String message,Throwable throwable){
this.enum1=enum1;
this.code=enum1.getCode()+"";
this.message =message;
// this.objects=objects;
// this.throwable=throwable;
}
}
/***
* 自定义异常处理类
* @author WJP
*
*/
public class SumuException extends BaseException {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* @param exceptionEnum
* @param objects
* @param message
*/
public SumuException(IExceptionEnum exceptionEnum,Object[] objects ,String message) {
super(exceptionEnum,objects,message);
}
public SumuException(IExceptionEnum responseEnum, Object[] args, String message, Throwable cause) {
super(responseEnum, args, message, cause);
}
}
异常信息枚举接口
public interface IExceptionEnum{
int getCode();
String getMessage();
}
定义断言接口Assert
public interface Assert {
/**
* 创建异常
* @param args
* @return
*/
BaseException newException(Object... args);
/**
* 创建异常
* @param t
* @param args
* @return
*/
BaseException newException(Throwable t, Object... args);
/**
* 断言对象obj
非空。如果对象obj
为空,则抛出异常
*
* @param obj 待判断对象
*/
default void assertNotNull(Object obj) {
if (obj == null) {
throw newException(obj);
}
}
/**
* 判断两个值是否相等
* @param obj
*/
default void notEquals(String a1,String a2){
assertNotNull(a1);
if (a1!=a2||a1.compareTo(a2)!=0) {
throw newException(a1);
}
}
}
异常接口继承Assert
import java.text.MessageFormat;
public interface BaseExceptionAssert extends IExceptionEnum, Assert {
@Override
default BaseException newException(Object... args) {
String msg = MessageFormat.format(this.getMessage(), args);
return new SumuException(this, args, msg);
}
@Override
default BaseException newException(Throwable t, Object... args) {
String msg = MessageFormat.format(this.getMessage(), args);
return new SumuException(this, args, msg, t);
}
}
使用枚举类结合Assert
,只需根据特定的异常情况定义不同的枚举实例
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 异常枚举
* @author WJP
*
*/
@Getter
@AllArgsConstructor
public enum ExceptionEnum implements BaseExceptionAssert {
USER_NOT_FOUND(1001, "用户信息不存在"),
/**
* 用户或密码信息错误
*/
PASSWD_ERR(1002, "用户或密码信息错误") ,
STATE_ERR(1003, "密码已锁定,请稍微重试") ;
/**
* 返回码
*/
private int code;
/**
* 返回消息
*/
private String message;
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}
简单验证:
使用 断言 和 枚举类 相结合的方式,再配合统一异常处理,基本大部分的异常都能够被捕获。