spring MVC组件开发-表单数据校验
在实际工作中,得到数据后的第一步就是校验数据的正确性,如果存在录入上的问题,一般先经过前端js进行验证,但是前端有多种方式可以绕过前端js验证(不是安全有效的),为了数据安全性一般还需要在服务器端做数据校验。这个时候就可以使用spring所提供的验证器(Validator)规则去验证。
所有的验证都是要先注册验证器,不过验证器也是springmvc自动加载的。我们使用JSR 303校验规范,hibernate提供的数据校验器进行数据校验。
使用JSR 303注解验证输入内容
Spring 提供了对Bean的功能校验,通过注解@Valid标明哪个Bean需要启用注解式的验证。在javax.validation.constrains.*中定义了一系列的JSR 303规范给出的注解:
限制 |
说明 |
@Null |
限制只能为null |
@NotNull |
限制必须不为null |
@AssertFalse |
限制必须为false |
@AssertTrue |
限制必须为true |
@DecimalMax(value) |
限制必须为一个不大于指定值的数字 |
@DecimalMin(value) |
限制必须为一个不小于指定值的数字 |
@Digits(integer,fraction) |
限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@Future |
限制必须是一个将来的日期 |
@Max(value) |
限制必须为一个不大于指定值的数字 |
@Min(value) |
限制必须为一个不小于指定值的数字 |
@Past |
限制必须是一个过去的日期 |
@Pattern(value) |
限制必须符合指定的正则表达式 |
@Size(max,min) |
限制字符长度必须在min到max之间 |
|
邮箱类型 |
@NotEmpty |
集合,不为空 |
@NotBlank |
不为空字符串 |
@Positive |
数字,正数 |
@PositiveOrZero |
数字,正数或0 |
@Negative |
数字,负数 |
@NegativeOrZero |
数字,负数或0 |
@PastOrPresent |
过去或者现在日期 |
@FutrueOrPresent |
将来或者现在日期 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html>
<html>
<head> <title>添加员工</title>
</head>
<body> <form action="${pageContext.request.contextPath }/control/emp/save" method="post" > 用户名:<input type="text" name="username" placeholder="请输入用户名,最小4位,最大12位" required/> <span></span> <br/> 密码:<input type="password" name="password" placeholder="请输入登录密码"/><br/> 电子邮箱:<input type="email" name="email" placeholder="请输入电子邮箱"/><br/> 员工生日:<input type="date" name="bornDate" /><br/> 薪水:<input type="number" name="salary" placeholder="请输入员工薪水" /><br/> 联系电话:<input type="text" name="phone" placeholder="请输入员工联系电话" pattern="^1[358]\d{9}$"/><br/> 员工简介: <textarea placeholder="请输入员工简介" name="intro"></textarea> <br/> <input type="submit" value="提交" /> <input type="reset"> </form> </body>
</html>
- 户名,密码,电子邮箱,入职日期不能为空
- 入职日期格式为yyyy-MM-dd,且只能大于今日
- 生日日期格式为yyyy-MM-dd,且只能是一个过去日期
- 邮箱需要符合格式:
- 简介内容不得多于256个字符
- 薪水最小值为2000,最大值为5万
- 联系方式需为正确的手机号码(使用正则表达式匹配)
建立pojo,确定校验规则:
public class Employee { private Integer id; /** * 用户名,不允许为空,最小4位,最大12位 */ @NotBlank(message = "用户名不能为空") @Size(min = 4,max = 12,message = "{employee.username.valid.size.message}") private String username; /** * 密码:不能为空,最小6位 */ @NotBlank(message = "密码不能为空") @Size(min = 6,max = 12,message = "密码最低6位") private String password; /** * 电子邮箱,不能为空,要满足邮箱基本格式 */ @NotNull(message = "邮箱不能为空") @Email(message="邮箱必须满足基本格式") private String email; /** * 员工生日,格式为:yyyy-MM-dd * 必须是一个过去的日期 */ @DateTimeFormat(iso = ISO.DATE) @Past(message = "你不能录用还未出生的员工") private LocalDate bornDate; /** * 入职日期,格式为:yyyy-MM-dd * 必须是一个现在或者将来的日期 */ @DateTimeFormat(iso = ISO.DATE) @FutureOrPresent private LocalDate entryDate = LocalDate.now(); /** * 员工联系(手机)电话 * 必须符合手机号码格式(正则表达式) */ @Pattern(regexp = "^1[358]\\d{9}$",message = "请输入正确的手机号码") private String phone; /** * 员工薪水,最低2000,最高5万 */ @Min(value = 2000,message="工资不能低于2000,否则麻烦了") @Max(value=50000,message="工资不能大于50000,否则交奢侈税") private float salary; /** * 员工简介,最大不超过200 */ @Size(min = 6,max = 12,message = "员工简介不能超过200字") private String intro; //***************setter and getter*************/
}
这样就定义了一个pojo,用于接收表单的信息。字段上面的注解反映了对每一个字段的验证要求,这样就可以加入对应校验,如果没有指定message属性,会生成默认的错误信息。message配置项用来定义当校验失败后的错误信息,这样就能启动Spring的检验规则来校验表单了。
用控制器验证表单:
@Controller
@RequestMapping("/control/emp")
public class EmployeeController { @RequestMapping("/save") public String save(@Validated Employee emp,BindingResult errors) { if(errors.hasErrors()) { return "emp/emp_save"; } return "redirect:./list"; }
}
使用了注解@Validated 标明这个Bean将会被校验,另外一个类型为BindingResult的参数(或者为Errors)是用于保存校验是否存在错误信息的,也就是当采用JSR 303规范进行校验后,它会将这个错误信息保存到这个参数中,在方法中判断是否有错误信息,如果有错误信息,跳转到填写表单页面告诉用户错误信息。
如何在jsp页面中显示错误信息呢?这时可以使用jsp提供给我们的标签库
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<span style="background-color: #fafafa; font-family: monospace;"><%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%></span>
<!DOCTYPE html>
<html>
<head> <title>添加员工</title>
</head>
<body> <form:form action="${pageContext.request.contextPath }/control/emp/save" method="post" modelAttribute="employee"> 用户名:<input type="text" name="username" placeholder="请输入用户名,最小4位,最大12位" required/> <span><span style="background-color: #fafafa; font-family: monospace;"><form:errors path="username" cssStyle="color: red"/></span></span> <br/> 密码:<input type="password" name="password" placeholder="请输入登录密码"/><br/> 电子邮箱:<input type="email" name="email" placeholder="请输入电子邮箱"/><br/> 员工生日:<input type="date" name="bornDate" /><br/> 薪水:<input type="number" name="salary" placeholder="请输入员工薪水" /><br/> 联系电话:<input type="text" name="phone" placeholder="请输入员工联系电话" pattern="^1[358]\d{9}$"/><br/> 员工简介: <textarea placeholder="请输入员工简介" name="intro"></textarea> <br/> <input type="submit" value="提交" /> <input type="reset"> </form:form>
</body>
</html>
看起来似乎非常不错,但是我们的message错误提示信息是硬编码在pojo身上,为了避免其硬编码而实现可配置,我们在src/main/resource下新建messageSource.properties文件:
employee.username.valid.notnull.message=用户名不能为空
employee.username.valid.size.message=用户名不能少于4位且不能超过12位
上面简单罗列了两个错误信息配置,其它道理一样,哪怎么应用(读取)指定的错误信息呢?在pojo验证规则之上:
/**
* 用户名,不允许为空,最小4位,最大12位
*/
@NotBlank(message = "{employee.username.valid.notnull.message}")
@Size(min = 4,max = 12,message = "{employee.username.valid.size.message}")
private String username;
可以采用{}表达式对配置文件的key加以读取其对应的value。其它字段同理,到这里还不能读取指定配置文件,需要告诉spring的检验器加载什么样的配置文件,配置代码如下:
@Configuration
@ComponentScan(basePackages = "com.wise.tiger.web")
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{ @Bean public InternalResourceViewResolver viewResolver() { var viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/pages/"); viewResolver.setSuffix(".jsp"); return viewResolver; } @Override //静态资源不被前端控制器拦截 public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**")//添加静态资源的url-pattern .addResourceLocations("/static/"); } @Bean public ReloadableResourceBundleMessageSource messageResource() { var messageResource = new ReloadableResourceBundleMessageSource(); //如果不指定,默认会去classpath下的messages.properties配置文件 messageResource.setBasename("classpath:resourceMessage"); return messageResource; } /** * 添加表单校验器 */ @Override public Validator getValidator() { var validator = new LocalValidatorFactoryBean(); validator.setProviderClass(HibernateValidator.class); validator.setValidationMessageSource(messageResource()); return validator; }
}
分组校验
1.定义分组:可以采用标识接口来进行分组区分
//分组校验1
public interface ValidationGroup1 {
} //分组校验2
public interface ValidationGroup2 {
}
2.在检验规则上添加分组
/**
* 用户名,不允许为空,最小4位,最大12位
*/
@NotBlank(message = "{employee.username.valid.notnull.message}",groups = ValidationGroup1.class)
@Size(min = 4,max = 12,message = "{employee.username.valid.size.message}",groups = ValidationGroup2.class)
private String username;</span>
3.在conroller中指定使用的分组校验
@Controller
@RequestMapping("/control/emp")
public class EmployeeController { @RequestMapping("/save") public String save( @Validated(ValidationGroup2.class) @ModelAttribute Employee emp,BindingResult errors,Model model) { if(errors.hasErrors()) { for (var i = 0; i < errors.getErrorCount();i++) { System.out.println(errors.getObjectName() + ":" + errors.getFieldError().getDefaultMessage()); } return "emp/emp_save"; } return "redirect:./list"; }
}
有时候除了简单的输入格式、非空性等校验,也需要一定的业务校验,Spring提供了Validator接口来实现校验,它将在进入控制器逻辑之前对参数的合法性进行校验。核心代码如下:
public interface Validator { /** * 判断当前校验器是否用于检验clazz类型的pojo * @param clazz -- pojo类型 * @return true 启动校验,false 不校验 */ @Override public boolean supports(Class<?> clazz) { return false; } /** * 检验pojo的合法性 * @param target 请求对象 * @param errors 错误信息 */ @Override public void validate(Object target, Errors errors) { } }
Validator接口是SpringMvc校验表单的核心接口,它只是一个验证器,在Spring中最终被注册到验证器的列表中,这样就可以提供给各个控制器去定义,然后通过supports方法判定是否会启用验证器去验证数据。对于校验的过程,则是通过validate方法去实现的。
package com.wise.tiger.pojo; import org.springframework.validation.Errors;
import org.springframework.validation.Validator; /** * @Description: 员工校验器 * @author: <a href="mailto:1020zhaodan@163.com">Adan</a> * @date: 2019年5月28日 下午7:23:40 * @version:1.0-snapshot */
public class EmployeeValidator implements Validator { /** * 判断当前校验器是否用于检验clazz类型的pojo * @param clazz -- pojo类型 * @return true 启动校验,false 不校验 */ @Override public boolean supports(Class<?> clazz) { //判断验证是否为Employee,如果是则进行校验 return Employee.class.equals(clazz); } /*** 检验pojo的合法性:提交过来的薪水不能低于职位的最低薪资* @param target 请求对象 (employee)* @param errors 错误信息*/@Overridepublic void validate(Object target, Errors errors) {var emp = (Employee)target;if(emp.getSalary() < emp.getJob().getLowSalary()){errors.rejectValue("job",null,String.format("薪水%.2f低于%s的最低薪资水平:%.2f",emp.getSalary(), emp.getJob().getValue(),emp.getJob().getLowSalary()));}}
}
在Employee实体上添加职位属性字段,该字段为枚举类型,定义如下:
@Getter
@RequiredArgsConstructor
public enum JOB {CLERK(2000,"业务员"),SALESMAN(2000,"销售员"),ANALYST(5000,"分析员"),SEARCHER(3000,"搜索员"),MANAGER(6000,"经理"),;@NonNullprivate float lowSalary;@NonNullprivate String value;
}
//================================Employee===========================
@NotNull(message = "{employee.job.notnull.message}")
private JOB job;//================================jsp================================职位:<select name="job"><option value="CLERK">业务员</option><option value="SALESMAN">销售员</option><option value="ANALYST" selected="selected">分析员</option><option value="SEARCHER">搜索员</option><option value="MANAGER">经理</option></select><span><spring:errors cssStyle="color: red;font-size: 12px" path="job"/></span><br/>
需要将该验证器捆绑到对应的控制器中,Spring MVC提供了注解@InitBinder,通过该注解就可以将验证器和控制器捆绑在一起,这样就能对请求表单进行验证了。
@Controller
@RequestMapping("/control/emp")
public class EmployeeController { @InitBinder public void initBinder(DataBinder binder){ //数据绑定器加入验证器 binder.setValidator(new EmployeeValidator()); } @RequestMapping("/save") public String save( @Validated(ValidationGroup2.class) @ModelAttribute Employee emp,
BindingResult errors,Model model) { if(errors.hasErrors()) { for (var i = 0; i < errors.getErrorCount();i++) { System.out.println(errors.getObjectName() + ":" + errors.getFieldError().getDefaultMessage()); } return "emp/emp_save"; } return "redirect:./list"; }
}
这样就能对比较复杂的逻辑关系进行校验了。@InitBinder的使用还有其它内容,后续讲解。。。。。。
附:依赖列表
dependencies { compile group: 'org.springframework', name: 'spring-context', version: '5.1.7.RELEASE' compile group: 'org.springframework', name: 'spring-webmvc', version: '5.1.7.RELEASE' compile group: 'org.springframework', name: 'spring-test', version: '5.1.7.RELEASE' providedCompile group: 'javax.servlet.jsp', name: 'javax.servlet.jsp-api', version: '2.3.3' providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1' compile group: 'taglibs', name: 'standard', version: '1.1.2' compile group: 'javax.servlet', name: 'jstl', version: '1.2' compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2' compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' compile group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.1' compile group: 'org.mybatis', name: 'mybatis', version: '3.5.1' compile group: 'com.alibaba', name: 'druid', version: '1.1.16' compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.16' compile group: 'org.springframework', name: 'spring-jdbc', version: '5.1.7.RELEASE' compile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final' compile group: 'org.hibernate', name: 'hibernate-validator', version: '6.0.16.Final' compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.9'
}
spring MVC组件开发-表单数据校验相关推荐
- Spring MVC 学习总结(五)——校验与文件上传 转自 张果 博客;已经编程校验;正确无误;...
Spring MVC 学习总结(五)--校验与文件上传 目录 一.Spring MVC验证器Validator 1.1.定义验证器 1.2.执行校验 1.3.在UI中添加错误标签 1.4.测试运行 二 ...
- VantUI(ZanUI)框架使用async-validator进行表单数据校验
原创文章, 转载请私信. 订阅号 tastejava 学习加思考, 仔细品味java之美 前端UI框架与async-validator介绍 VantUI是一款有赞出品的基于Vue的前端手机端开发框架 ...
- 分布式锁 动态代理 Java数据结构List,Set,Map,Spring执行流程,Spring MVC组件
这里对今日的内容进行总结: 分布式锁具备的条件: 具备的条件: 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行. 高可用的获取锁与释放锁. 高性能的获取锁与释放锁. 具备可重入的特 ...
- 视频教程-基础篇:Spring MVC快速开发-Java
基础篇:Spring MVC快速开发 毕业于清华大学软件学院软件工程专业,曾在Accenture.IBM等知名外企任管理及架构职位,近15年的JavaEE经验,近8年的Spring经验,一直致力于架构 ...
- struts表单数据校验
Struts2表单数据校验 前台校验 也称之为客户端校验,主要是通过JavaScript编程的方式进行表单数据的验证. 后台校验 也称之为服务器端校验,这里指的是使用Struts2通过XML配置的方式 ...
- Struts2表单数据校验
Struts2表单数据校验 手工方式 Struts2 如何进行表单验证( ( 手工方式) ) 定义需要校验的表单login.jsp(Struts2标签) Action继承ActionSupport(提 ...
- SSM项目实战之二十四:表单数据校验
表单数据校验 前言 前端页面 测试 前言 在前面的文章中我们并没有对表单提交的数据做校验,本文主要以添加用户为例介绍如何对表单数据添加校验. 前端页面 首先把原先的提交按钮换掉,设置一个点击函数 为表 ...
- form表单数字校验(二)——邮箱校验-当前页面
form表单数字校验(二)--邮箱校验-当前页面 效果 代码 index.vue <el-form-item v-if='!isDisabled' label='邮箱'><el-in ...
- Spring MVC 学习总结(五)——校验与文件上传
目录 一.Spring MVC验证器Validator 1.1.定义验证器 1.2.执行校验 1.3.在UI中添加错误标签 1.4.测试运行 二.JSR303验证器 2.1.添加hibernate-v ...
最新文章
- 大数据时代,如何构建精准用户画像,直击精细化运营
- pip和conda 换清华源
- BZOJ 2716: [Violet 3]天使玩偶
- 精通webpack的5大关键点
- 用matlab录制声音然后进行读取和播放
- Python企业微信机器人
- SQL2005数据库连接
- Setting property 'source' to 'org.eclipse.jst.jee.
- Assigning retained object to weak property object will be released after assignment
- 支付宝第三方在线支付接口详解
- python npv 计算公式_Python中IRR的计算
- 谈谈mysql的悲观和乐观锁 - 周伯通的麦田 - 博客园
- excel学习-日期计算函数DATEDIF函数(计算相隔年数、月数、天数)
- python赋值01_少说话多写代码之Python学习022——赋值语句的用户01(序列解包)...
- 同位语从句 vs 定语从句 区别
- 202007 软件市场分析
- 蚂蚁区块链第2课 如何申请获得100万创新大赛参赛资格?
- 图可视化工具Gephi使用教程
- 关于线上支付的实现思想方法与例子
- 高手都具备“向下兼容”的能力
热门文章
- 【目标检测】kera-yolo3模型计算mAP
- matlab中划出实线框,图纸上限定绘图区域的线框,必须用粗实线画出图框,格式分为留装订边和不留装订边。...
- 牛客 — 网络选择题练习中自己的错题(10)
- oracle scn参数,【学习笔记】Oracle数据库使用_MINIMUM_GIGA_SCN推进SCN案例
- 2019海南大学计算机研究生分数线,2019海南大学研究生分数线(含2016-2019历年复试)...
- iBATIS框架理论学习篇(公司内部培训文档)
- 初学者利用c语言解决简单的数学问题
- 如何入手C语言,怎样去学C语言
- 向死而生的跨境电商,还有几道救命符可用?
- 脑机接口科普0010——研究脑机接口的大学和机构