我用自定义注解优雅的实现了业务的复杂校验

我用自定义注解优雅的实现了业务的复杂校验

点击上方蓝字关注我!



背景

假设我们要开发一个创建超级俱乐部会员的功能,要求创建的条件为:

  1. 会员的id要求为【1-10】
  2. 电话号码要求为185开头
  3. 注册日期不能小于5月15日

通常情况下我们会这么写:

public void creatSupperClubMember(Member member) {
  //1.校验会员id
  //2.校验电话号码
  //3.校验注册日期
  
  //4.创建超级俱乐部会员
}
我用自定义注解优雅的实现了业务的复杂校验

上面这个方法中,我们发现除了超级会员的创建,我们有一大半的代码是在校验参数。这样有个问题就是我们正真需要的代码是4,从某种程度上来说1、2、3是多余的代码。

如果我们的校验非常复杂,那么这个方法就会显得难以阅读,通过分析我们发现这个方法其实做了两件事

  1. 校验参数
  2. 创建超级会员

因此我们将代码重构下:

public void creatSupperClubMember(Member member) {
 //1.参数校验
    validatorBeforeCreate()
 //2.创建超级俱乐部会员
}

public void validatorBeforeCreate() {
  //1.校验会员id
  //2.校验电话号码
  //3.校验注册日期
}

这样我们的代码会显得更加清晰。事实上,我们在编写方法时,需要考虑单一职责原则,业务的参数校验从某种程度上来说属于非业务代码,上面的功能我们可以抽象出:

我用自定义注解优雅的实现了业务的复杂校验
校验

没错,就是业务逻辑与非业务逻辑,我们有没有方法可以将业务逻辑与非业务逻辑解耦呢。

我们可以使用注解校验。我用自定义注解优雅的实现了业务的复杂校验

其实我们在平时的开发中,很多地方都是用了注解的校验:

我用自定义注解优雅的实现了业务的复杂校验

上面的代码相信大家都写过,我们不需要在方法中去写参数的校验,我们在字段上使用注解,就是实现了参数的必填校验,范围校验。

但是已有的注解无法满足我们的要求,实际的参数校验比较复杂。因此我决定自己写一个参数校验的注解。

注解模型

我想要的需求是

@ValidatorHandler(validators = XXXXValidator.class)
public int createXXX(XXX xxx
{

}

我们在写的业务代码上面添加一个@ValidatorHandler注解,注解里面的XXXXValidator类就是真正写校验功能的类,会把业务参数传到这个校验类中。

public class XXXValidator extends AbstractValidator {
 @Override
 public void check(Object o) {
        //获取参数
  XXXx xxx = (XXX)o;
        //相关的业务校验
 }
}

校验类模型如上所示。

我用自定义注解优雅的实现了业务的复杂校验
注解

我们通过注解将业务代码与校验代码分开。

编写校验注解

首先我们来定义注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidatorHandler {
    /**
     *  校验的类
     */

    Class<?> validators();
}

该注解作用与方法上,里面的参数validators为校验类的class。

然后编写实现校验注解的功能

我用自定义注解优雅的实现了业务的复杂校验

为了清晰展现代码,我用图片表示。

上述代码实现了几个功能:

实例化validators对应的校验类

获取业务参数,并将参数传递到校验类中的check方法的参数中

执行校验类中的check方法

执行业务代码

为了规范校验类编写,我们需要定义一个接口

public interface AbstractValidator {
    void check(Object o);
}

所有的校验类都要是AbstractValidator的实现,并实现check方法。

这里的注解实现功能中,我只获取了业务功能中第一个参数,也就是说我们的业务方法的第一个参数会被校验,大家可以思考下:如果业务功能的参数有多个,该注解的功能类怎么编写?

代码测试

以上我们的注解就开发好了,我们开始测试下功能:

首先我们编写校验类:

我用自定义注解优雅的实现了业务的复杂校验

如上图,校验类中我们实现了文章开头要求的三个校验功能。

然后我们编写业务代码,创建超级俱乐部会员

@ValidatorHandler(validators = MemberValidator.class)
public void creatSupperClubMember(Member member
{
    System.out.println("member开始新增");
    //这里就是我们的业务代码
    System.out.println("member新增结束");
}

我们再写一个方法,模拟前端传入的数据:

我用自定义注解优雅的实现了业务的复杂校验

测试方法如下:

@Test
public void testCreateMember() {
    Member member = initData();
    testMemberService.creatSupperClubMember(member);
    System.out.println("创建结束");
}

校验id

private Member initData() {
    Member member = new Member();
    member.setId("11");
    member.setMobile("17790990033");
    member.setCreateBy("李老师");
    member.setCreateDate(new Date());
    member.setIsActive("Y");
    return member;
}

执行测试方法,发现控制台打印如下,我们发现id = 11不符合要求,校验成功。

我用自定义注解优雅的实现了业务的复杂校验

我们修改id = 5,id的校验通过。

member.setId("5");

校验电话号码moblie

然后我们再次执行发现手机号不是185开头,这里的校验也成功。

我用自定义注解优雅的实现了业务的复杂校验

修改手机号为185的,校验通过。

member.setMobile("18590990033");

校验注册日期

member的参数中,注册日期为:2021-05-15小于2021-05-20,不满足要求。

private Member initData() {
    String registerDateStr = "2021-05-15";
    Date registerDate = DateUtil.parse(registerDateStr);

    Member member = new Member();
    member.setId("5");
    member.setMobile("18590990033");
    member.setCreateBy("李老师");
    member.setCreateDate(registerDate);
    member.setIsActive("Y");
    return member;
}

控制台会出现如下错误,校验成功。

我用自定义注解优雅的实现了业务的复杂校验

校验全部通过

private Member initData() {
    Member member = new Member();
    member.setId("5");
    member.setMobile("18590990033");
    member.setCreateBy("李老师");
    member.setCreateDate(new Date());
    member.setIsActive("Y");
    return member;
}

当我们的参数全部满足业务校验需求时,我们的校验通过,就会创建超级俱乐部会员。

我用自定义注解优雅的实现了业务的复杂校验

以上就是这篇文章的全部内容了,当我们的业务逻辑校验很复杂时,我们可以使用上面的校验注解将校验逻辑与业务逻辑分开,这样有利于业务与非业务解耦,也满足设计原则的单一职责原则。除了方便阅读,还有的好处就是,当我们不需要校验时,我们可以将业务方法上的校验注解注释掉,这样我们就不必在业务代码中去修改了,从而减少了因修改业务代码导致bug的风险。

如果文章对你有用,欢迎点赞转发😀。




往期推荐




我用自定义注解优雅的实现了业务的复杂校验
我用自定义注解优雅的实现了业务的复杂校验

扫码二维码

获取更多精彩

Lvshen_9

我用自定义注解优雅的实现了业务的复杂校验
我用自定义注解优雅的实现了业务的复杂校验

原文始发于微信公众号(Lvshen的技术小屋):我用自定义注解优雅的实现了业务的复杂校验

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/261924.html

(0)
Java朝阳的头像Java朝阳

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!