下面代码分别采用普通模式和断言的模式书写,断言其实是内部封装了判断,然后抛出异常,所以看起来就非常简洁。
@Test
public void test1() {
Order order = orderDao.selectById(orderId);
Assert.notNull(order, "订单不存在。");
}
@Test
public void test2() {
// 另一种写法
Order order = orderDao.selectById(orderId);
if (order == null) {
throw new IllegalArgumentException("订单不存在。");
}
}
用Assert(断言)封装异常,让代码更优雅(附项目源码):点击跳转
@NoArgsConstructor
@AllArgsConstructor
@Data
public class BaseException extends RuntimeException {
/**
* 异常信息
*/
private String message;
}
/**
* 这里模仿Assert的isNull的写法,
* Assert是抽象类,这里采用接口,所以需要default定义
* 唯一不同的地方是这里不定义具体的异常,该异常由各自的处理器自定义
*
* @author zhangfanjun
* @date 2022/5/17
* @see Assert#isNull(Object, String) 断言判断null
*/
public interface AssertHandler {
/**
* 没有入参的异常,这个处理主要是返回枚举的参数进行创建异常
*
* @return 异常
* @author zfj
* @date 2022/5/17
*/
BaseException newException();
/**
* 提供默认的异常返回,如果需要返回项目的自定义异常,就需要重写该方法
*
* @param message 异常的信息
* @return 自定义的基础异常
* @author zfj
*/
default BaseException newException(String message) {
return new BaseException(message);
}
/**
* 基础方法
* Supplier提供get方法
*
* @param messageSupplier Supplier表达式
* @return 字符串
* @author zfj
*/
default String nullSafeGet(Supplier messageSupplier) {
return messageSupplier != null ? messageSupplier.get() : null;
}
/**
* 判断null,这个时候采用自定义的异常来进行处理
*
* @param object 入参
* @author zfj
*/
default void isNull(Object object) {
if (object != null) {
throw newException();
}
}
/**
* 判断null
*
* @param object 入参
* @param message 异常信息
* @author zfj
*/
default void isNull(Object object, String message) {
if (object != null) {
throw newException(message);
}
}
/**
* 判断null
*
* @param object 入参
* @param messageSupplier 异常信息表达式
* @author zfj
*/
default void isNull(Object object, Supplier messageSupplier) {
if (object != null) {
throw newException(nullSafeGet(messageSupplier));
}
}
}
@Data
public class BusinessException extends BaseException {
/**
* 异常的
*/
private int code = 500;
/**
* 异常信息
*/
private String message;
public BusinessException() {
}
public BusinessException(String message) {
this.message = message;
}
public BusinessException(int code) {
this.code = code;
}
public BusinessException(int code, String message) {
this.code = code;
this.message = message;
}
}
public interface BusinessExceptionAssert extends AssertHandler {
/**
* 重写方法返回自定义的异常,用于项目自定义的异常捕捉
* BaseException也有默认的属性保存message,所以不重写就返回默认的异常
* @param message 异常信息
* @return 返回自定义的异常
* @author zfj
*/
@Override
default BaseException newException(String message) {
return new BusinessException(message);
}
}
@Getter
@AllArgsConstructor
public enum BusinessExceptionEnum implements BusinessExceptionAssert {
NOT_FOUND(500, "没有找到"),
NOT_EXIST(500,"不存在"),;
private int code;
private String message;
@Override
public BaseException newException() {
return new BusinessException(code,message);
}
}
想想这个无法满足需求,判断null,判断等于某个值,确实可以,但是业务处理中经常面临复杂的判断逻辑,这个场景下就不能满足了
@Test
void test1(){
String s = new String();
BusinessExceptionEnum.NOT_EXIST.isNull(s);
BusinessExceptionEnum.NOT_EXIST.isNull(s,()->{
return "222";
});
}
@FunctionalInterface
public interface AssertFunction {
/**
* 断言
*
* @return 断言结果
* @author zfj
* @date 2022/5/18
*/
boolean check();
}
自定义的断言接口中增加一个默认方法
/**
* 断言
*
* @param f 断言函数
* @author zfj
* @date 2022/5/18
*/
default void check(AssertFunction f) {
boolean check = f.check();
if (check){
throw newException();
}
}
测试
System.out.println("测试断言");
BusinessExceptionEnum.NOT_EXIST.check(()->{
return true;
});
不管是使用抽象方法或者抽象类,主要的目的是添加抽象方法,抽象方法必须被实现,所以就有了枚举类自定义了返回的异常。
可以,原本的断言的BaseException就能使用的,只是只有一个字段message,也可以将BaseException定义成项目业务的异常。