参数校验,汲取优秀开源框架最佳实践
阅读引导:
1、程序员的美德是“偷懒”,它山之石可以攻玉。
2、代码体现了个人的思维逻辑,是程序员的门面,是你的领导、同事、下属对你的最重要印象。
3、为自己工作,为自己的系统工作,做自己的老板,形成正循环:打磨当前工作的核心关键能力——>高效能工作——>更多时间打磨自己的系统——>更高效能工作——>打磨下个层次工作的核心关键能力……
4、核心竞争力,是指你拥有的(独特的)知识经验组合,经过你思维逻辑的组织梳理,在实践中产生无可替代的价值。打造自己的TMS系统(T:专业技术;M:沟通管理、S:行业解决方案),利用复利效应,让系统为自己工作。
参数校验,分为两大类:参数字段属性合法性校验、参数业务属性校验
其中参数字段属性校验,包含字段的长度、格式、数据字典等字段级合法性校验。
而参数业务属性校验,是指有业务含义的校验,例如参数是一个账号,业务校验条件可能有这个账号不能是信用卡账号,只能是单位定期存款账号。
在方法入口的参数校验的方式,初级程序员可能自己写,在方法入口,有大量的if冗余判断语句。
if (componentCode != null && componentCode.length() != 0)
if……参数判断
if……参数判断
或者可能使用Spring框架中StringUtils.java或guava中的工具类,如下:
//校验 组件号
if (!StringUtils.hasText(componentCode)) {
log.error("组件号componentCode是{},不能为空",componentCode);
throw new EStatusException……
}
//校验商户号
if (!StringUtils.hasText(merchantNum)) {
log.error("参数merchantNum:["+merchantNum+"]不能为空");
throw new EStatusException(LogConstants.FTR_REQ_MHT_EMPTY, "参数merchantNum:……
}
……
很明显,虽然使用了框架提供的工具类,但是整个的校验逻辑都重复了。
对于程序员来说,一旦重复,就意味着可以复用!
接下来,我们看一下开源框架中的实现方式
1
开源框架中的参数校验 Assert
Spring框架
在Spring的核心包中,org.springframework.retry.interceptor.RetryInterceptorBuilder.java
有一个方法:Assert.isNull
public RetryInterceptorBuilder<T> maxAttempts(int maxAttempts) {
Assert.isNull(this.retryOperations, "cannot alter the retry policy when a custom retryOperations has been set");
Assert.isTrue(!this.retryPolicySet, "cannot alter the retry policy when a custom retryPolicy has been set");
this.simpleRetryPolicy.setMaxAttempts(maxAttempts);
this.retryTemplate.setRetryPolicy(this.simpleRetryPolicy);
this.templateAltered = true;
return this;
}
可以看到,框架中所有校验,已经使用了统一的Assert类来封装,代码整齐规范。
dubbo框架
在dubbo的实现中,com.alibaba.dubbo.remoting.transport.netty.NettyBackedChannelBuffer.java,也有类似代码:Assert.notNull
public NettyBackedChannelBuffer(org.jboss.netty.buffer.ChannelBuffer buffer) {
Assert.notNull(buffer, "buffer == null");
this.buffer = buffer;
}
与Spring是同样的思路。
这个参数校验的思路,实际上是参考的JUnit中的断言。
某些情况下,我们在应用中,要抛出来自己应用封装的异常,更适合使用这个封装校验。
2
进阶,参数校验外部化
还要一点,尤其是在对外暴露服务的入口方法,需要对传入参数进行校验。
这种情况下,我们希望在方法中做的是业务逻辑,而不是很多的参数校验逻辑,将参数校验的部分外部化,跟业务逻辑隔离。
这种情况下hibernate-validation就派上用场了,具体可见下一篇文章。