SpringBoot+@Validated实现参数验证(非空、类型、范围、格式等)-若依前后端导入Excel数据并校验为例
创始人
2024-01-21 04:23:57

场景

若依管理系统前后端分离版基于ElementUI和SpringBoot怎样实现Excel导入和导出:

若依管理系统前后端分离版基于ElementUI和SpringBoot怎样实现Excel导入和导出_霸道流氓气质的博客-CSDN博客

SpringBoot+Vue实现excel导入带格式化的时间参数(moment格式化明天日期并设置el-date-picker默认值):

SpringBoot+Vue实现excel导入带格式化的时间参数(moment格式化明天日期并设置el-date-picker默认值)_霸道流氓气质的博客-CSDN博客

在上面搭建SpringBoot+Vue并实现Excel导入的基础上,为避免导入的excel中数据格式不规范

导致产生大量脏数据,所以需要对excel的数据进行校验,比如不能为空、类型是否为数字、数字范围等等规则。

若依官方对这块有专门说明

后台手册 | RuoYi

 

说明比较简单,具体实现流程如下,也可参考其用户导入的实现代码和流程。

 

这里对用户账号做了非空校验,需要在实体类上对应属性添加

    @Xss(message = "用户账号不能包含脚本字符")@NotBlank(message = "用户账号不能为空")@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")public String getUserName(){return userName;}

查看@NotBlank注解的实现

 

发现其来自javax.validation。

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

后台实现流程

Hibernate Validator 是 Bean Validation 的参考实现 。Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,

除此之外还有一些附加的 constraint 在日常开发中,Hibernate Validator经常用来验证bean的字段,基于注解,方便快捷高效。

在SpringBoot中可以使用@Validated,注解Hibernate Validator加强版,也可以使用@Valid原来Bean Validation java版本

添加pom依赖

        org.springframework.bootspring-boot-starter-validation

若依框架添加在common模块中

 

使用 Validation API 进行参数效验步骤整个过程如下图所示,用户访问接口,然后进行参数效验 ,

如果效验通过,则进入业务逻辑,否则抛出异常,交由全局异常处理器进行处理

 

 

自定义全局捕获异常

/*** 全局异常处理器** @author ruoyi*/
@RestControllerAdvice
public class GlobalExceptionHandler
{private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);/*** 自定义验证异常*/@ExceptionHandler(BindException.class)public AjaxResult handleBindException(BindException e){log.error(e.getMessage(), e);String message = e.getAllErrors().get(0).getDefaultMessage();return AjaxResult.error(message);}/*** 自定义验证异常*/@ExceptionHandler(MethodArgumentNotValidException.class)public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e){log.error(e.getMessage(), e);String message = e.getBindingResult().getFieldError().getDefaultMessage();return AjaxResult.error(message);}
}

若依框架中将其定义在framework模块下

 

@ExceptionHandler用于指定异常处理方法。当与@RestControllerAdvice配合使用时,用于全局处理控制器里的异常。

在需要校验的实体类属性上或者get方法上添加校验规则注解 ,比如下面

    @Xss(message = "用户昵称不能包含脚本字符")@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")public String getNickName(){return nickName;}public void setNickName(String nickName){this.nickName = nickName;}@Xss(message = "用户账号不能包含脚本字符")@NotBlank(message = "用户账号不能为空")@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")public String getUserName(){return userName;}public void setUserName(String userName){this.userName = userName;}@Email(message = "邮箱格式不正确")@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")public String getEmail(){return email;}public void setEmail(String email){this.email = email;}@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")public String getPhonenumber(){return phonenumber;}

注解参数说明

注解名称功能
@Xss检查该字段是否存在跨站脚本工具
@Null检查该字段为空
@NotNull不能为null
@NotBlank不能为空,常用于检查空字符串
@NotEmpty不能为空,多用于检测list是否size是0
@Max该字段的值只能小于或等于该值
@Min该字段的值只能大于或等于该值
@Past检查该字段的日期是在过去
@Future检查该字段的日期是否是属于将来的日期
@Email检查是否是一个有效的email地址
@Pattern(regex=,flag=)被注释的元素必须符合指定的正则表达式
@Range(min=,max=,message=)被注释的元素必须在合适的范围内
@Size(min=, max=)检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等
@Length(min=,max=)检查所属的字段的长度是否在min和max之间,只能用于字符串
@AssertTrue用于boolean字段,该字段只能为true
@AssertFalse该字段的值只能为false

其它格式校验的注解可自行搜索,用法较多。

如果是在Controller中传参时进行校验,可以直接添加注解@Validated

比如添加用户的Controller

    @PreAuthorize("@ss.hasPermi('system:user:add')")@Log(title = "用户管理", businessType = BusinessType.INSERT)@PostMappingpublic AjaxResult add(@Validated @RequestBody SysUser user){}

但是形如Excel导入时,Controller接收的是MultipartFile数据,无法在Controller添加校验

    @PostMapping("/importData")public AjaxResult importData(MultipartFile file, String planDateString) throws Exception {ExcelUtil util = new ExcelUtil(LimitQuotaStatistics.class);List limitQuotaStatisticsList = util.importExcel(file.getInputStream());String message =limitQuotaStatisticsService.insertLimitQuotaStatisticsBatch(limitQuotaStatisticsList,planDateString);return success(message);}

就需要在serviceImpl中通过如下方式进行注入和使用

先通过

    @Autowiredprotected Validator validator;

注入依赖

再通过

  BeanValidators.validateWithException(validator, limitQuotaStatistics);

进行参数校验

@Service
public class LimitQuotaStatisticsServiceImpl implements ILimitQuotaStatisticsService {private static final Logger log = LoggerFactory.getLogger(LimitQuotaStatisticsServiceImpl.class);@Autowiredprivate LimitQuotaStatisticsMapper limitQuotaStatisticsMapper;@Autowiredprotected Validator validator;@Overridepublic String insertLimitQuotaStatisticsBatch(List limitQuotaStatisticsList, String planDateString) throws ParseException {if (StringUtils.isNull(limitQuotaStatisticsList) || limitQuotaStatisticsList.size() == 0) {throw new ServiceException("导入数据不能为空!");}int successNum = 0;int failureNum = 0;StringBuilder successMsg = new StringBuilder();StringBuilder failureMsg = new StringBuilder();Date plaeDate = new SimpleDateFormat("yyyy-MM-dd").parse(planDateString);for (LimitQuotaStatistics limitQuotaStatistics : limitQuotaStatisticsList) {try {BeanValidators.validateWithException(validator, limitQuotaStatistics);limitQuotaStatistics.setPlanDate(plaeDate);this.insertLimitQuotaStatistics(limitQuotaStatistics);successNum++;successMsg.append("
" + successNum + "、" + limitQuotaStatistics.getDeptName() + " 导入成功");} catch (Exception e) {failureNum++;String msg = "
" + failureNum + "、" + limitQuotaStatistics.getDeptName() + " 导入失败:";failureMsg.append(msg + e.getMessage());log.error(msg, e);}}if (failureNum > 0) {failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");throw new ServiceException(failureMsg.toString());} else {successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");}return successMsg.toString();} }

其中BeanValidators的实现如下

package com.bdtd.limit.common.utils.bean;import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;/*** bean对象属性验证** @author ruoyi*/
public class BeanValidators
{public static void validateWithException(Validator validator, Object object, Class... groups)throws ConstraintViolationException{Set> constraintViolations = validator.validate(object, groups);if (!constraintViolations.isEmpty()){throw new ConstraintViolationException(constraintViolations);}}
}

这里要校验的实体类添加规则为

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LimitQuotaStatistics extends BaseEntity
{private static final long serialVersionUID = 1L;/** id */private Long id;/** 部门id */private Long deptId;/** 部门名称 */@Excel(name = "部门名称")@NotNull(message = "部门名称为空")private String deptName;/** 夜班人数 */@Excel(name = "夜班人数")@NotNull(message = "夜班人数为空或格式不对")@Range(max = 1000, min = 1, message = "夜班人数需在1-1000之间")private Long nightShiftNum;
}

部分字段,仅供参考。

前端页面组件实现

组件实现代码参考若依官方文档中示例

导入测试效果

 

相关内容

热门资讯

长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
不用扬鞭自奋蹄 乘势而上千帆竞... 思明区正全力向“两个进位”目标发起冲刺,努力为建设高素质高颜值现代化国际化的厦门作出“思明贡献”。(...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
好听的民谣歌曲 2021最火的... #我的年度歌单#在2021年里听过很多民谣,但是最能触及心中温柔的还是下面的几首。不听民谣的理由有很...