每篇一句
在《深度工作》中作者提出这么一个公式:高质量产出=时间*专注度。所以高质量的产出不是靠时间熬出来的,而是效率为王
相关阅读
【小家Java】深入了解数据校验:Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validation 6.x使用案例
【小家Java】深入了解数据校验(Bean Validation):基础类打点(ValidationProvider、ConstraintDescriptor、ConstraintValidator)
【小家Spring】详述Spring对Bean Validation支持的核心API:Validator、SmartValidator、LocalValidatorFactoryBean...
前言
你在书写业务逻辑的时候,是否会经常书写大量的判空校验。比如Service
层或者Dao
层的方法入参、入参对象、出参中你是否都有自己的一套校验规则?比如有些字段必传,有的非必传;返回值中有些字段必须有值,有的非必须等等~
如上描述的校验逻辑,窥探一下你的代码,估摸里面有大量的if else
吧。此部分逻辑简单(因为和业务关系不大)却看起来眼花缭乱(赶紧偷偷去喵一下你自己的代码吧,哈哈)。在攻城主键变大的时候,你会发现会有大量的重复代码出现,这部分就是你入职一个新公司的吐槽点之一:垃圾代码。
若你追求干净的代码,甚至有代码洁癖
,如上众多if else
的重复无意义劳动无疑是你的痛点,那么本文应该能够帮到你。
Bean Validation
校验其实是基于DDD
思想设计的,我们虽然可以不完全的遵从这种思考方式编程,但是其优雅的优点还是可取的,本文将介绍Spring
为此提供的解决方案~
效果示例
在讲解之前,首先就来体验一把吧~
@Validated(Default.class)
public interface HelloService {
Object hello(@NotNull @Min(10) Integer id, @NotNull String name);
}
// 实现类如下
@Slf4j
@Service
public class HelloServiceImpl implements HelloService {
@Override
public Object hello(Integer id, String name) {
return null;
}
}
向容器里注册一个处理器:
@Configuration
public class RootConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
测试:
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class})
public class TestSpringBean {
@Autowired
private HelloService helloService;
@Test
public void test1() {
System.out.println(helloService.getClass());
helloService.hello(1, null);
}
}
结果如图:
完美的校验住了方法入参。
注意此处的一个小细节:若你自己运行这个案例你得到的参数名称可能是
hello.args0
等,而我此处是形参名。是因为我使用Java8的编译参数:-parameters
(此处说一点:若你的逻辑中强依赖于此参数,务必在你的maven中加入编译插件并且配置好此编译参数)
若需要校验方法返回值,改写如下:
@NotNull
Object hello(Integer id);
// 此种写法效果同上
//@NotNull Object hello(Integer id);
运行:
javax.validation.ConstraintViolationException: hello.<return value>: 不能为null
...
校验完成。就这样借助Spring
+JSR
相关约束注解,就非常简单明了,语义清晰的优雅的
完成了方法级别(入参校验、返回值校验)的校验。
校验不通过的错误信息,再来个全局统一的异常处理,就能让整个工程都能尽显完美之势。(错误消息可以从异常ConstraintViolationException
的getConstraintViolations()
方法里获得的~)
MethodValidationPostProcessor
它是Spring
提供的来实现基于方法Method
的JSR
校验的核心处理器~它能让约束作用在方法入参、返回值
上,如:
public @NotNull Object myValidMethod(@NotNull String arg1, @Max(10) int arg2)
官方说明:方法里写有JSR校验注解要想其生效的话,要求类型级别上必须使用@Validated
标注(还能指定验证的Group)
另外提示一点:这个处理器同处理@Async
的处理器AsyncAnnotationBeanPostProcessor
非常相似,都是继承自AbstractBeanFactoryAwareAdvisingPostProcessor
的,所以若有兴趣再次也推荐@Async的分析博文,可以对比着观看和记忆:【小家Spring】Spring异步处理@Async的使用以及原理、源码分析(@EnableAsync)
// @since 3.1
public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor implements InitializingBean {
// 备注:此处你标注@Valid是无用的~~~Spring可不提供识别
// 当然你也可以自定义注解(下面提供了set方法~~~)
// 但是注意:若自定义注解的话,此注解只决定了是否要代理,并不能指定分组哦 so,没啥事别给自己找麻烦吧
private Class<? extends Annotation> validatedAnnotationType = Validated.class;
// 这个是javax.validation.Validator
@Nullable
private Validator validator;
// 可以自定义生效的注解
public void setValidatedAnnotationType(Class<? extends Annotation> validatedAnnotationType) {
Assert.notNull(validatedAnnotationType, &qu