设为首页 加入收藏

TOP

Spring方法级别数据校验:@Validated + MethodValidationPostProcessor(一)
2019-09-02 23:19:05 】 浏览:45
Tags:Spring 方法 级别 数据 校验 @Validated MethodValidationPostProcessor

每篇一句

在《深度工作》中作者提出这么一个公式:高质量产出=时间*专注度。所以高质量的产出不是靠时间熬出来的,而是效率为王

相关阅读

【小家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...


对Spring感兴趣可扫码加入wx群:`Java高工、架构师3群`(文末有二维码)

前言

你在书写业务逻辑的时候,是否会经常书写大量的判空校验。比如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相关约束注解,就非常简单明了,语义清晰的优雅的完成了方法级别(入参校验、返回值校验)的校验。
校验不通过的错误信息,再来个全局统一的异常处理,就能让整个工程都能尽显完美之势。(错误消息可以从异常ConstraintViolationExceptiongetConstraintViolations()方法里获得的~)


MethodValidationPostProcessor

它是Spring提供的来实现基于方法MethodJSR校验的核心处理器~它能让约束作用在方法入参、返回值上,如:

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
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇SpringBoot 2.x (4):配置文件.. 下一篇调用wsdl接口,参数是xml格式

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目