策略模式结合@Valid注解实现通用数据接收校验

244 阅读2分钟

        最近被安排了一个城市级的数据汇聚任务,数据种类一共上百种,数据质量的校验要十分的严格,必须全部符合标准才能入库,经过思考之后,我决定采用策略模式对对象进行反射,然后使用@Valid注解,因为类库的通用参数校验不太满足业务需求,又使用自定义注解添加了一些日期、身份证、经纬度等字段校验规则。经过一下午的思考和编码,自认为写的还可以,下面直接上代码。

@PostMapping("SC/{resourceCode}")
public Response SC(@PathVariable("resourceCode") String resourceCode, @RequestBody @Validated RequestBean requestBean) throws ClassNotFoundException {
    /*根据信息资源类型从枚举中获取class类路径*/
    String method = DataResourceEnum.getMethod(resourceCode);
    if (StringUtils.isBlank(method)) {
        return Response.resourceError();
    }
    /*初始化要进行校验的类*/
    Class clz = Class.forName(method);

      方法入口的resourceCode为信息资源标识,标明了数据的种类,然后在枚举类中定义了信息资源标识和类路径,便于用来反射进行类初始化。找不到类路径的则抛出ClassNotFoundException,统一异常处理器拦截到之后会返回调用方信息资源类型不存在。

         /*获取密文进行解密*/
        String reqeustData = requestBean.getData();
        List dataList = SM2Utils.decode(secret.getPrivateKey(), secret.getSecret(), reqeustData, clz);
        if (CollectionUtils.isEmpty(dataList)) {
            return Response.decryptionError();
        }

        /*执行数据校验逻辑*/
        Map<String, List<Map>> result = commonService.check(dataList, clz);
        List errorInfoList = result.get(ResultEnum.ERROR.name());
        List successList = result.get(ResultEnum.SUCCESS.name());

 

public Map check(List list, Class classz) {
        Map<String, List<Map<String, Object>>> resultMap = new HashMap<>();
        List<Map<String, Object>> errorInfoList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            try {
                dataCheckService.dataCheck(list.get(i));
            } catch (ConstraintViolationException e) {
                String errorMessage = ConstraintViolationExceptionHandler.getMessage(e, i);
                Map<String, Object> itemMap = GsonUtil.parseJsonWithGson(GsonUtil.toJson(list.get(i)), Map.class);
                itemMap.put("CWXX", errorMessage);
                errorInfoList.add(itemMap);
                list.remove(i);
                i--;
            }
        }
        resultMap.put(ResultEnum.SUCCESS.name(), list);
        resultMap.put(ResultEnum.ERROR.name(), errorInfoList);
        return resultMap;
    }

       check方法是对数据进行校验,校验逻辑是dataCheckService的dataCheck方法,dataCheck方法是个没有实现类的接口,在接口的参数上加了@Valid注解,在循环中,未通过类中校验注解的数据将会抛出异常,异常信息会在catch中进行封装成异常信息对象。

@Validated
public interface DataCheckService<E> {

    void dataCheck(@Valid E e);

}

下面是对象的示例

    @IDCARD(message = "DJR_GMSFZHM校验失败,请检查证件号码准确性")
    private String DJR_GMSFZHM;

    /**
     * 登记人_联系电话
     */
    @NotBlank(message = "DJR_LXDH不能为空")
    @Size(min = 1, max = 50, message = "DJR_LXDH长度应为1-50")
    private String DJR_LXDH;

    /**
     * 数据更新时间
     */
    @NotBlank(message = "GXSJ不能为空")
    @DateTime(format = "yyyyMMddHHmmss", message = "GXSJ格式错误,正确格式为:yyyyMMddHHmmss")
    private String GXSJ;

    /**
     * 治安管理信息所属警务责任区代码
     */
    @NotBlank(message = "ZAGLXXSSJWZRQDM不能为空")
    @Size(min = 12, max = 12, message = "ZAGLXXSSJWZRQDM长度应为12")
    private String ZAGLXXSSJWZRQDM;

以上就是策略模式结合@Valid注解实现通用数据接收校验部分代码。