策略模式+责任链模式配合Nacos实现参数校验链

1、业务场景

在SpringBoot项目中,针对接收的参数信息,根据需求要进行以下校验:

  • 校验客户的apikey是否合法;
  • 校验请求的ip地址是否是白名单;
  • 校验短信的签名;
  • 校验短信的模板;
  • 校验手机号的格式合法性;
  • 校验客户剩余的金额是否充足。

2、实现分析

对于接口需要校验的参数和信息,为了保证校验的方式做到动态可插拔,而且有利于后期的扩展,参考了Mybatis二级缓存的源码,采用策略模式+责任链模式的套路。实现的大致流程是向上声明一个接口,提供校验方法,然后后编写多个校验的实现类,在执行校验时,会拿到所有的校验接口实现类,然后以责任链的形式一个个校验执行。而且,配合Nacos提供的配置动态刷新,指定校验链执行的内容,需要改变时,只需要修改Nacos的配置参数。

3、代码编写

下面是整个校验链路的代码骨架,不涉及校验条件的具体实现细节。

1. 校验的父接口
/**
 * 做策略模式的父接口
 */
public interface CheckFilter {
    /**
     * 校验方法
     * @param obj
     */
    void check(Object obj);

}
2. 准备校验的实现类
/**
 * 校验客户的apikey是否合法
 */
@Service(value = "apikey")
@Slf4j
public class ApiKeyCheckFilter implements CheckFilter {
    @Override
    public void check(Object obj) {
        log.info("【接口模块-校验apikey】");
    }
}

/**
 * 校验请求的ip地址是否是白名单
 */
@Service(value = "ip")
@Slf4j
public class IPCheckFilter implements CheckFilter {
    @Override
    public void check(Object obj) {
        log.info("【接口模块-校验ip】");
    }
}

/**
 * 校验短信的签名
 */
@Service(value = "sign")
@Slf4j
public class SignCheckFilter implements CheckFilter {
    @Override
    public void check(Object obj) {
        log.info("【接口模块-校验签名】");
    }
}

/**
 * 校验短信的模板
 */
@Service(value = "template")
@Slf4j
public class TemplateCheckFilter implements CheckFilter {
    @Override
    public void check(Object obj) {
        log.info("【接口模块-校验模板】");
    }
}

/**
 * 校验手机号的格式合法性
 */
@Service(value = "mobile")
@Slf4j
public class MobileCheckFilter implements CheckFilter {

    @Override
    public void check(Object obj) {
        log.info("【接口模块-校验手机号】");
    }
}

/**
 * 校验客户剩余的金额是否充足
 */
@Service(value = "fee")
@Slf4j
public class FeeCheckFilter implements CheckFilter {
    @Override
    public void check(Object obj) {
        log.info("【接口模块-校验客户余额】");
    }
}
3. 准备上下文对象,拿到所有的校验接口实现类
/**
 * 策略模式的上下文对象
 */
@Component
@RefreshScope
public class CheckFilterContext {
    // Spring的IOC会将对象全部都放到Map集合中
    // 基于4.x中Spring提供的反省注解,基于Map只拿到需要的类型对象即可
    @Autowired
    private Map checkFiltersMap;

    // 基于Nacos获取到执行的顺序和需要执行的校验对象
    @Value("${filters:apikey,ip,sign,template}")
    private String filters;

    /**
     * 当前check方法用于管理校验链的顺序
     */
    public void check(Object obj){
        //1. 将获取到filters基于,做切分
        String[] filterArray = filters.split(",");
        //2. 遍历数组即可
        for (String filter : filterArray) {
            CheckFilter checkFilter = checkFiltersMap.get(filter);
            checkFilter.check(obj);
        }
    }
}
4. Nacos配置校验执行顺序
# 校验策略的执行内容和顺序 apikey,ip,sign,template,mobile,fee
filters: apikey,ip,sign,template,mobile,fee
5. 上下文对象的使用
@RestController
public class CheckController{
    @Autowired
    private CheckFilterContext checkFilterContext;
    /**
    * 测试使用 
    */
    @PostMapping
    public void check(Object obj){
        checkFilterContext.check(obj);
    }
}

你可能感兴趣的:(java)