文章目录
assert机制
其实就是相当于判断工具,如果不符合期待,就抛出异常,异常信息为自定义的message。
代码:
原生assert(java关键字assert)例子:
assert !StringUtils.isEmpty(request.getName());
assert工具类列子(如spring的Assert类):
Assert.hasText(null,"参数错误");
Assert.notNull(null,"asdf");
Assert.isTrue(false,"判断错误");
为什么要用assert
最直接的原因就是为了简化代码。
可以看下下面代码的区别。
不用断言:
String username="";
String password="";
if(StringUtils.isNotEmpty(username)){
return "用户名不能为空";
}
if(StringUtils.isNotEmpty(username)){
return "用户名不能为空";
}
使用断言:
try {
String username="";
String password="";
Assert.hasLength(username,"用户名不能为空");
Assert.hasLength(username,"密码不能为空");
}catch (IllegalArgumentException e) {
logger.error("errorMessage:{}", e.getMessage(), e);
}
断言配合全局异常处理来用很不错:
@ControllerAdvice("com.test")
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public String illegalArgumentExceptionHandler( IllegalArgumentException ex) {
return ex.getMessage();
}
}
完整版代码(包括异常处理)
代码:
JsonResult result = new JsonResult<>();
String methodName="定制断言功能_断言工具isEmpty";
try {
log.info(methodName+"请求开始,request={}",JSON.toJSONString(request));
Assert.hasLength(request.getName(),"名称不能为空");
Assert.hasLength(request.getPassword(),"密码不能为空");
Assert.hasLength(request.getAge(),"年龄不能为空");
log.info(methodName+"请求完成,result={}", JSON.toJSONString(result));
return result;
}catch(IllegalArgumentException e){ // 注:这里虽然是异常,但是打失败的日志,和不期待的异常区分开
log.info(methodName+"请求失败,{}",e.getMessage()); // 这里的写法注意下,去掉error=,直接用{}
return JsonResult.error("-1",methodName+"请求失败,"+e.getMessage());
}catch(Exception e){
log.error(methodName+"请求异常,error=",e);
return JsonResult.error("-1",methodName+"请求异常,error="+e.getMessage());
}
效果一目了然,不用每个判断都单独写log和返回了,集中捕获IllegalArgumentException
进行处理即可,当然,如果全局异常处理那更加方便。
判断是否是空字符串
Assert.hasLength("","用户名不能为空");
相当于
StringUtils.isNotEmpty("");
生产环境为什么不推荐用断言
因为断言默认是关闭的,如果没有手动开启,那么相当于无效,容易造成不同环境逻辑不一致,留坑。
编译和运行的时候要加参数,否则编译不通过,或者运行无效。
javac -source 1.4 AssertTest.java # 编译的时候要加 -source 1.4
java -ea AssertTest # 运行的时候要加 -ea
在vm中加-ea
(enable assert)表示启用断言。
在vm中加-da
(disable assert)表示禁用断言(实际默认就是禁用)。
assert和AssertUtils的区别
注:这里的assert指的是java关键字assert。
AssertUtils指的是封装后Assert工具,如spring的Assert类。
对比下就比较清楚了:
— | assert | AssertUtils |
---|---|---|
是否受环境限制 | 受环境限制,默认是关闭 | 不受环境限制 |
报错 | 异常类型为java.lang.AssertionError ,Exception捕获不到(这也挺坑的,因为一般try catch都是用Exception) | 异常类型为java.lang.IllegalArgumentException ,Exception可以捕获到 |
这就一目了然了,assert不好用,推荐用Assert工具。
Assert工具为什么不受断言开关的影响呢?
看下实现代码就明白了,Assert工具是用代码模拟出了assert的效果,并没有用到assert关键字,所以不受assert开关的影响。
spring Assert的使用
AssertUtils有很多组织都实现了,如:spring、apache、hutools等。
简单看了下,spring的用着就可以,又不用引入额外包,所以就以spring的Assert类为例。
判断字符串是否为空
用hasLength() 注:不是notEmpty(),因为notEmpty方法是给数组用的。
spring只有Assert这一个实现类吗?
自定义断言工具
有时第三方提供的断言工具功能不满足我们的要求怎么办?
其实可以大胆一点,跳出第三方的限制,直接自定义工具。
因为实现原理很清晰,就是校验不通过,抛出IllegalArgumentException即可。
想通这一点,思路一下子宽了很多。
另外:如果不想把异常分的太细,直接捕获Exception也是可以的。
自定义断言工具代码
也是网上通用的代码:
/*
* 定制断言工具
*/
public class CustomAssertUtils {
public static void isNotEmpty(String string,String message){
if(!StringUtils.isNotEmpty(string)){
throw new IllegalArgumentException(message);
}
}
public static void isSuccess(boolean b,String message){
if(!b){
throw new IllegalArgumentException(message);
}
}
public static void collectionIsNotEmpty(Collection collection, String message){
if(CollectionUtils.isEmpty(collection)){
throw new IllegalArgumentException(message);
}
}
public static void collectionIsEmpty(Collection collection, String message){
if(!CollectionUtils.isEmpty(collection)){
throw new IllegalArgumentException(message);
}
}
public static void objectIsNotNull(Object object, String message){
if(ObjectUtils.isEmpty(object)){
throw new IllegalArgumentException(message);
}
}
public static void objectIsNull(Object object, String message){
if(!ObjectUtils.isEmpty(object)){
throw new IllegalArgumentException(message);
}
}
}