八、JSR-303基于由Hibernate-Validitor实现的后端服务器数据校验
-
- 1、JSR-303简介
- 2、JSR-303常用校验注解规则
- 3、JSR-303如何使用?
-
- 3.1、首先导入相关依赖(**规范**和**实现**)
- 3.2、对实体类SystemUserinfo==部分字段==进行校验注解
- 3.3、编写登录界面视图login.html
- 3.4、编写控制层SystemUserinfoController(登录控制方法)
- 3.5、登录校验测试
- 3.6、对实体类SystemUserinfo==全部字段==进行校验注解
- 3.7、编写修改用户信息界面updateUser.html
- 3.8、编写控制层SystemUserinfoController(修改用户信息控制方法)
- 3.9、修改用户信息校验
- 3.10、==回头再次测试登录校验==
- 3.11、==对实体类SystemUserinfo中的字段进行分组==
- 3.12、对控制层SystemUserinfoController中的方法进行(需求字段)分组
- 3.13、再再次测试登录界面:
- 4、写在最后
1、JSR-303简介
JSR是Java Specification Requests的缩写,意思是Java 规范提案,JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator。
此实现与 Hibernate ORM 没有任何关系。 JSR 303 用于对 Java Bean 中的字段的值进行验证。 Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中对表单提交的数据方便地验证。
即,JSR 303,Bean Validation规范 ,为Bean验证定义了元数据模型和API。默认的元数据模型是通过Annotations来描述的,但是也可以使用XML来重载或者扩展, 推荐使用注解的方式进行验证。
2、JSR-303常用校验注解规则
空检查:
注解 | 说明 |
---|---|
@Null | 元素必须为null |
@NotNull | 元素必须不为null |
@NotBlank(message) | 字符串不能为null,且trim后不能为空字符串(长度非0),message加以说明 |
@NotEmpty(message) | 被注释的字符串、集合、数组不能为空(长度非0) |
Boolean检查 :
注解 | 说明 |
---|---|
@AsserrtFalse | 验证Boolean对象是否为false |
@AssertTrue | 验证Boolean对象是否为true |
长度检查 :
注解 | 说明 |
---|---|
@Size(min,max,message) | 元素大小必须在指定范围内,message加以说明 |
@Length(min,max,message) | 必须是字符串,其值在指定范围内,message加以说明 |
日期检查 :
注解 | 说明 |
---|---|
@Past | 元素必须是一个过去的日期 |
@Furture | 元素必须是一个将来的日期 |
@Pattern | 元素符合指定的正则表达式 |
数值检查 (建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为 “”,Integer为null ):
注解 | 说明 |
---|---|
@Min(value) | 元素必须为数字,其值大于等于指定value |
@Max(value) | 元素必须为数字,其值小于等于指定value |
@DecimalMax(value) | 元素必须为数字,最大值为指定value |
@DecimalMin(value) | 元素必须为数字,最小值为指定value |
@Digits(integer,fraction) | 元素必须为数字,其值必须在可接受的范围内 |
以上是Bean Validation 中内置的 constraint。
Hibernate Validator 附加的 constraint
注解 | 说明 |
---|---|
元素必须为电子邮箱格式 | |
@Range | 元素在合适的范围内 |
@SafeHtml | 元素必须是安全Html |
@URL | 元素必须是有效URL |
3、JSR-303如何使用?
3.1、首先导入相关依赖(规范和实现)
JSR 303 是Bean验证的规范 ,Hibernate Validator 是该规范的参考实现,如果只有规范没有实现,则校验规范不会生效。
pom.xml
<!--JSR-303校验规范-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!--JSR-303基于由Hibernate-validator规范实现-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.22.Final</version>
</dependency>
3.2、对实体类SystemUserinfo部分字段进行校验注解
package com.kdcrm.pojo;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
public class SystemUserinfo implements Serializable {
private String userinfoUid;
@NotEmpty(message = "用户名不能为空")
private String userinfoLoginid;
private String userinfoName;
@NotEmpty(message = "登录密码不能为空")
private String userinfoPassword;
private String userinfoSex;
private String userinfoEmail;
private String userinfoMobile;
private Short userinfoStatus;
private String userinfoRoleid;
private SystemRole systemRole;
//setter和getter方法省略
}
我们暂时先对用户名(登录id)和登录密码两个字段进行@NotEmpty注解,用于登录界面用户名和密码的非可校验注解。
3.3、编写登录界面视图login.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>易买网 - 登录界面</title>
<link type="text/css" rel="stylesheet" href="css/style.css" />
<script type="text/javascript" src="scripts/function.js"></script>
</head>
<body>
<div id="login" class="wrap">
<div class="shadow">
<em class="corner lb"></em>
<em class="corner rt"></em>
<div class="box">
<h1>欢迎回到易买网</h1>
<form id="loginForm" method="post" action="doLogin" onsubmit="return checkForm(this)">
<table>
<tr>
<td class="field">用户名:</td>
<td><input class="text" type="text" name="userinfoLoginid" onfocus="FocusItem(this)" onblur="CheckItem(this);" /><span style="display: inline-block" th:text="${userinfoLoginid}"></span></td>
</tr>
<tr>
<td class="field">登录密码:</td>
<td><input class="text" type="password" name="userinfoPassword" onfocus="FocusItem(this)" onblur="CheckItem(this);" /><span style="display: inline-block" th:text="${userinfoPassword}"></span></td>
</tr>
<tr>
<td></td>
<td><label class="ui-green"><input type="submit" name="submit" value="立即登录" />
</label>
<label th:text="${MSG}" style="color: red"></label>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</body>
</html>
登录界面:
3.4、编写控制层SystemUserinfoController(登录控制方法)
//跳转至登录界面
@GetMapping("/toLogin")
public String toLogin(){
return "login";
}
//对登录信息进行处理
@RequestMapping("/doLogin")
public ModelAndView doLogin(@Valid SystemUserinfo systemUserinfo, BindingResult bindingResult, HttpServletRequest request, ModelAndView mav){
//当前是否是错误
if(bindingResult.hasErrors()) {
//获取所有错误信息
List<ObjectError> listError = bindingResult.getAllErrors();
//创建存储错误信息的map
Map<String, String> mapError = new HashMap<>();
//遍历错误信息集合
for (ObjectError objectError : listError) {
//强转为FieldError类型(用于获取错误字段名)
FieldError fieldError = (FieldError) objectError;
//校验字段 : 校验信息
System.out.println(fieldError.getField() + "\t" + objectError.getDefaultMessage());
//将要校验的字段和校验信息存入到map集合中
mapError.put(fieldError.getField(), objectError.getDefaultMessage());
//将map集合存入到ModelAndView中(其实内部机制也是将其存入到request作用域中)
mav.addAllObjects(mapError);
}
mav.setViewName("login");
return mav;
}else {
SystemUserinfo systemUserinfo1 = systemUserinfoService.login(systemUserinfo);
if(systemUserinfo1 != null){
System.out.println("登录成功!");
mav.addObject("USERS",systemUserinfo1);
mav.setViewName("redirect:/selectAll");
}else {
System.out.println("输入了,但是用户名或密码错误!");
mav.addObject("MSG","用户名或密码错误!");
mav.setViewName("login");
}
return mav;
}
}
实际上此处将出现错误信息的字段名和校验信息存入到request作用中还有一种简单的做法,就是将字段名和错误信息直接存入到request作用域中,如下:
//获取所有错误信息
List<ObjectError> listError = bindingResult.getAllErrors();
//遍历错误信息集合
for (ObjectError objectError : listError) {
//强转为FieldError类型(用于获取错误字段名)
FieldError fieldError = (FieldError) objectError;
//校验字段 : 校验信息
System.out.println(fieldError.getField() + "\t" + objectError.getDefaultMessage());
//直接存入request作用域中
request.setAttribute(fieldError.getField(),objectError.getDefaultMessage());
}
3.5、登录校验测试
查看控制台:
3.6、对实体类SystemUserinfo全部字段进行校验注解
上述登录演示说明我们的在后端的校验生效了,但是我们要考虑全面,对于实体类SystemUserinfo中的字段我们不可能只针对登录需要的两个字段进行校验,在添加、修改用户信息时,基本就需要用到全部字段的校验了,所有我们要对SystemUserinfo实体类中的所有字段进行非空注解信息,如下:
package com.kdcrm.pojo;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
public class SystemUserinfo implements Serializable {
//自动生成不用校验
private String userinfoUid;
@NotEmpty(message = "用户名不能为空")
private String userinfoLoginid;
@NotEmpty(message = "名字不能为空")
private String userinfoName;
@NotEmpty(message = "密码不能为空")
private String userinfoPassword;
@NotEmpty(message = "性别不能为空")
private String userinfoSex;
@NotEmpty(message = "邮箱不能为空")
private String userinfoEmail;
@NotEmpty(message = "电话不能为空")
private String userinfoMobile;
//状态暂时不考虑
private Short userinfoStatus;
@NotEmpty(message = "角色id不能为空")
private String userinfoRoleid;
private SystemRole systemRole;
//setter和getters方法省略
}
3.7、编写修改用户信息界面updateUser.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en" >
<head>
<meta charset="UTF-8">
<title>updateUser</title>
</head>
<body>
<form method="post" action="/doUpdateUser" id="userForm" style="margin: 100px auto;margin-left: 400px">
<input type="hidden" name="userinfoUid" th:value="${systemUserinfo.userinfoUid}"/>
登录名:<input type="text" id="userinfoLoginid" name="userinfoLoginid" th:value="${systemUserinfo.userinfoLoginid}" /><span th:text="${userinfoLoginid}"/><br/>
姓名:<input type="text" id="userinfoName" name="userinfoName" th:value="${systemUserinfo.userinfoName}" /><span th:text="${userinfoName}"/><br/>
密码:<input type="password" id="userinfoPassword" name="userinfoPassword" th:value="${systemUserinfo.userinfoPassword}"/><span th:text="${userinfoPassword}"/><br/>
性别:<input type="radio" name="userinfoSex" th:checked="${systemUserinfo.userinfoSex == '男'}" value="男"/>男
<input type="radio" name="userinfoSex" th:checked="${systemUserinfo.userinfoSex == '女'}" value="女"/>女<span th:text="${userinfoSex}"/><br/>
邮箱:<input type="text" id="userinfoEmail" name="userinfoEmail" th:value="${systemUserinfo.userinfoEmail}" /><span th:text="${userinfoEmail}"/><br/>
电话:<input type="text" id="userinfoMobile" name="userinfoMobile" th:value="${systemUserinfo.userinfoMobile}"/><span th:text="${roleId}"/><span th:text="${userinfoMobile}"/><br/>
角色:<select name="userinfoRoleid">
<option value="">--请选择--</option>
<option th:selected="${systemUserinfo.userinfoRoleid == role.roleId}" th:each="role:${roleList}" th:text="${role.roleName}" th:value="${role.roleId}" ></option>
</select>
<span th:text="${userinfoRoleid}"/><br/>
<input type="submit" value="提交修改"/>
</form>
<br/>
</body>
</html>
3.8、编写控制层SystemUserinfoController(修改用户信息控制方法)
@GetMapping("/toUpdateUser")
public String toUpdateUser(String userinfoUid,HttpServletRequest request){
List<SystemRole> roleList = systemRoleService.selectAll();
SystemUserinfo systemUserinfo = systemUserinfoService.selectByPrimaryKey(userinfoUid);
if(systemUserinfo != null && roleList != null){
request.setAttribute("systemUserinfo",systemUserinfo);
request.setAttribute("roleList",roleList);
}
return "updateUser";
}
@PostMapping("/doUpdateUser")
public String doUpdateUser(@Valid SystemUserinfo systemUserinfo,BindingResult bindingResult,HttpServletRequest request){
//当前是否是错误
if(bindingResult.hasErrors()) {
List<SystemRole> roleList = systemRoleService.selectAll();
request.setAttribute("roleList",roleList);
//获取所有错误信息
List<ObjectError> listError = bindingResult.getAllErrors();
for (ObjectError objectError : listError) {
FieldError fieldError = (FieldError) objectError;
//校验字段 : 校验信息
System.out.println(fieldError.getField() + "\t" + objectError.getDefaultMessage());
//request作用一样实现将字段和错误信息存入request作用域中
request.setAttribute(fieldError.getField(),objectError.getDefaultMessage());
}
return "updateUser";
}else {
int r = systemUserinfoService.updateByPrimaryKey(systemUserinfo);
if(r>0){
return "redirect:/selectAll";
}else {
request.setAttribute("msg","更新失败!请重新填写修改数据!");
return "updateUser";
}
}
}
3.9、修改用户信息校验
查看控制台:
3.10、回头再次测试登录校验
什么都不输直接提交:
当我们输入正确的用户名和密码时,再次提交:
查看控制台信息:
出现上述情况其实也是意料之中的事,当我们对应一个功能无论是登录还是修改、添加,只需要校验各自需要的字段时,其他字段自然也用不到,就不需要进行验证了,那我们怎么解决上述的问题呢?下述我们就引入注解分组的概念,使某个功能需要哪几个字段就对这几个字段进行分组。
3.11、对实体类SystemUserinfo中的字段进行分组
第一步先创建几个分组需要用到的空接口类:
//LoginGroup:
package com.kdcrm.util;
public interface LoginGroup {
}
//UpdateGroup:
package com.kdcrm.util;
public interface UpdateGroup {
}
//AddGroup:
package com.kdcrm.util;
public interface AddGroup {
}
第二步对实体类中的字段注解分类:
package com.kdcrm.pojo;
import com.kdcrm.util.AddGroup;
import com.kdcrm.util.LoginGroup;
import com.kdcrm.util.UpdateGroup;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
public class SystemUserinfo implements Serializable {
private String userinfoUid;
@NotEmpty(message = "用户名不能为空",groups = {LoginGroup.class, UpdateGroup.class, AddGroup.class})
private String userinfoLoginid;
@NotEmpty(message = "名字不能为空",groups = { UpdateGroup.class, AddGroup.class})
private String userinfoName;
@NotEmpty(message = "登录密码不能为空",groups = {LoginGroup.class, UpdateGroup.class, AddGroup.class})
private String userinfoPassword;
@NotEmpty(message = "性别不能为空",groups = {UpdateGroup.class, AddGroup.class})
private String userinfoSex;
@NotEmpty(message = "邮件不能为空",groups = {UpdateGroup.class, AddGroup.class})
private String userinfoEmail;
@NotEmpty(message = "手机号不能为空",groups = {UpdateGroup.class, AddGroup.class})
private String userinfoMobile;
private Short userinfoStatus;
@NotEmpty(message = "角色不能为空",groups = {UpdateGroup.class, AddGroup.class})
private String userinfoRoleid;
private SystemRole systemRole;
//setter和getters方法省略
}
3.12、对控制层SystemUserinfoController中的方法进行(需求字段)分组
@RequestMapping("/doLogin")
public ModelAndView doLogin(@Validated(value = {LoginGroup.class}) SystemUserinfo systemUserinfo, BindingResult bindingResult, HttpServletRequest request, ModelAndView mav){
//逻辑内容不变与上述一致,此处为了节省空间省略
}
@PostMapping("/doAddUser")
public String doAddUser(@Validated(value = {AddGroup.class}) SystemUserinfo systemUserinfo,BindingResult bindingResult, HttpServletRequest request){
//逻辑内容不变与上述一致,此处为了节省空间省略
}
@PostMapping("/doUpdateUser")
public String doUpdateUser(@Validated(value = {UpdateGroup.class}) SystemUserinfo systemUserinfo, BindingResult bindingResult, HttpServletRequest request){
//逻辑内容不变与上述一致,此处为了节省空间省略
}
3.13、再再次测试登录界面:
查看控制台:
输入正确的用户名和密码:
容易吗,不容易,欢迎一起撒花!!!
4、写在最后
每一篇文章的总结其实都是需要耗费不少时间和精力的,我们同是选择编程这条路的人,那么就要从始至终拥有享受孤独的勇气,这个精彩的世界,每一分每一秒都在瞬息万变,我们生来平庸,想要改变,眼下便是努力的最好时刻,永远不要臣服于现实,因为这个世界真的很美好,需要我们不断的去创造和发现它的美好,一起加油,陌生人。
我还是相信那句话:在我们的指尖有改变世界的力量!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/189434.html