最近被安排了一个城市级的数据汇聚任务,数据种类一共上百种,数据质量的校验要十分的严格,必须全部符合标准才能入库,经过思考之后,我决定采用策略模式对对象进行反射,然后使用@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注解实现通用数据接收校验部分代码。