当前位置: 首页 > web >正文

数据合法性校验

实现方式

实现方式可分为隐式调用与显示调用两种,下面我分别的介绍一下这两种方式的使用。

隐式调用

应用场景

  • 服务间调用,例:对外提供的接口

使用方式

  • 请求参数定义
@Data
public class AddSpuRequest {@NotBlank(message = "spu名称不能为空")private String spuName;@NotBlank(message = "spu编码不能为空")private String spuCode;@NotEmpty(message = "sku不能为空")@Validprivate List<AddSkuRequest> skuList;// ... 其它字段
}@Data
public class AddSkuRequest {@NotBlank(message = "sku名称不能为空")private String skuName;@NotBlank(message = "sku编码不能为空")private String skuCode;@NotBlank(message = "upc不能为空")private String upc;@NotNull(message = "库存不能为空")private Integer stock;// ... 其它字段
}
  • Controller
@RestController
@RequestMapping(value = "/spu")
public class SpuController {@Resourcepublic SpuService spuService;@PostMapping(path = "/add")public Result<Boolean> addSpu(@RequestBody @Valid AddSpuRequest request) {spuService.addSpu(request);return Result.success();}
}
  • 统一异常捕获
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {@ExceptionHandler(BindException.class)public Result<?> notValidExceptionHandle(BindException e) {return Result.fail(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());}@ExceptionHandler(Exception.class)public Result<?> exceptionHandler(Exception ex) {log.error("其他错误, message:{}", ex.getMessage(), ex);return Result.error();}// ... 其它异常捕获处理
}

小结

        通过以上隐式调用的方式,我们可以处理项目中的接口请求参数的必传校验,并通过全局的异常捕获处理,将校验抛出的异常进行返回给客户端进行友好提示。

显示调用

应用场景

  • 服务内调用,例:数据导入

使用方式

  • 数据导入DTO对象
@Data
public class ImportSkuDTO {@NotBlank(message = "sku名称不能为空")private String skuName;@NotBlank(message = "sku编码不能为空")private String skuCode;@NotBlank(message = "upc不能为空")private String upc;@NotNull(message = "库存不能为空")private Integer stock;// ... 其它字段
}
  • 数据导入响应VO
@Data
public class ImportSkuVO {/*** 成功数量*/private Integer successCount;/*** 失败数量*/private Integer failCount;/*** 异常详细内容*/private List<ImportSkuFailVO> errorList;
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class ImportSkuFailVO {/*** 异常数据行数*/private Integer lineNumber;/*** 异常原因*/private String message;
}
  • 业务方法,以数据导入为例
@Slf4j
@Service
public class SkuService {@Resourceprivate Validator validator;private static final int MAX_IMPORT_SIZE = 100;@Overridepublic ImportSkuVO importSku(MultipartFile file) {ImportSkuVO importSkuVO = new ImportSkuVO();List<ImportSkuDTO> successList = new ArrayList<>();List<ImportSkuFailVO> errorList = new ArrayList<>();try (InputStream inputStream = file.getInputStream()) {ExcelReaderBuilder excelReaderBuilder = EasyExcel.read(inputStream).head(ImportSkuDTO.class);excelReaderBuilder.registerReadListener(new AnalysisEventListener<ImportSkuDTO>() {int currentRow = 1;@Overridepublic void invoke(ImportSkuDTO data, AnalysisContext context) {try {if (successList.size() >= MAX_IMPORT_SIZE) {throw new BizException("单次导入不得超过" + MAX_IMPORT_SIZE + "条");}validate(data);successList.add(data);} catch (Exception e) {errorList.add(new ImportSkuFailVO(currentRow, e.getMessage()));}currentRow++;}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {if (!errorList.isEmpty()) {log.info("导入完成,成功{}条,失败{}条", successList.size(), errorList.size());}}}).sheet().doRead();// 批量保存成功数据if (!successList.isEmpty()) {List<Sku> skuList = this.convertSkuList(successList);// 保存sku信息}importSkuVO.setSuccessCount(successList.size());importSkuVO.setFailCount(errorList.size());importSkuVO.setErrorList(errorList);} catch (Exception e) {log.error("import sku exception", e);throw new BizException("文件读取异常", e);}return importSkuVO;}private List<Sku> convertSkuList(List<ImportSkuDTO> successList) {List<Sku> skuList = new ArrayList<>();for (ImportSkuDTO importSkuDTO : successList) {// ... 数据转换赋值}return skuList;}/*** 显示调用校验参数,将参数异常,数据抛出业务异常,并在调用处捕获记录*/public void validate(ImportSkuDTO importSkuDTO) {Set<ConstraintViolation<ImportSkuDTO >> violations = validator.validate(importSkuDTO);if (!violations.isEmpty()) {String errorMsg = violations.stream().map(v -> v.getPropertyPath() + " " + v.getMessage()).collect(Collectors.joining("; "));throw new BizException(errorMsg);}}
}

小结

        显示调用的方式,更加的灵活,适用于数据已进入方法内部,业务逻辑处理运行时状态进行数据校验,此种方式更加的简洁,当然开发者也可以手动进行if判断,逐个字段取出,但如果没有业务逻辑属性,单纯空值,数据范围,基础性的校验时完全可以采用此方式。 

总结

  • 隐式调用更加常见,适用于服务间的接口调用,进入方法时进行拦截处理,减少业务逻辑的报错可能性,也可以使得代码更加的简洁。
  • 显示调用更适合于服务内部的调用,数据已进入业务逻辑中,在一个方法需要调用其它本服务的逻辑组件时,可以采取这种方式,如:数据导入时的校验
http://www.xdnf.cn/news/8568.html

相关文章:

  • 典型城市工况数据(Drive Cycle)用于车辆仿真
  • 与 JetBrains 官方沟通记录(PyCharm 相关问题反馈)
  • 怎么判断一个Android APP使用了Capacitor这个跨端框架
  • 智慧化工园区安全风险管控平台建设方案(Word)
  • PH热榜 | 2025-05-23
  • selinux基础知识
  • Linux虚拟机联网失败原因之一
  • 什么是软件压力测试,出压力测评报告的第三方软件检测公司推荐
  • 20250523-在Unity中创建角色动画(2D)(Set up Animator with State Machine)
  • LCS4110R加密芯片在打印机墨盒的应用
  • el-form表单规则验证
  • C# DataGrid扩展 - DataGrid不同模板切换
  • 电商美图设计工具,图生生-低成本打造高转化商品场景图
  • 【新品来袭】功耗降低56%爱普生研发新款晶体振荡器
  • 信息系统项目管理师考前练习9
  • InnoDB引擎底层解析(二)之InnoDB的Buffer Pool(二)
  • 嵌入式STM32学习——ESP8266 01S的基础介绍
  • ConvSearch-R1: 让LLM适应检索器的偏好或缺陷
  • 【数据架构03】数据治理架构篇
  • 六、OpenGL 2.0 通过引入可编程着色器,将渲染控制权从硬件厂商转移到开发者手中。这是如何实现的,或者说可编程着色器是如何实现的
  • mybatis-plus与jsqlparser共用时报sql解析错误
  • Golang 之 Context 源码解析(1.20+)
  • 电动伺服疲劳试验机
  • Nodejs导出excel文件 及复杂样式解决方案
  • Spring用到的设计模式
  • 20200201工作笔记常用命令要整理
  • 根据Cortex-M3(STM32F1)权威指南讲解MCU内存架构与如何查看编译器生成的地址具体位置
  • 科研经验贴:AI领域的研究方向总结
  • TASK05【Datawhale 组队学习】系统评估与优化
  • @Configuration 与 @Component 的区别