SpringMVC实现表单验证功能详解

网友投稿 235 2023-03-23


SpringMVC实现表单验证功能详解

本章节内容很丰富,主要有基本的表单操作,数据的格式化,数据的校验,以及提示信息的国际化等实用技能。

首先看效果图

项目结构图

接下来用代码重点学习SpringMVC的表单操作,数据格式化,数据校验以及错误提示信息国际化。请读者将重点放在UserController.java,User.java,input.jsp三个文件中。

maven 项目必不可少的pom.xml文件。里面有该功能需要的所有jar包。

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.springmvc

springmvc

0.0.1-SNAPSHOT

war

maven-compiler-plugin

1.7

1.7

UTF-8

4.1.3.RELEASE

org.springframework

spring-webmvc

${spring.version}

org.springframework

spring-context

${spring.version}

org.springframework

spring-aop

${spring.version}

org.springframework

spring-core

${spring.version}

org.springframework

spring-web

${spring.version}

javax.servlet

javax.servlet-api

4.0.0

provided

javax.servlet

jstl

1.2

taglibs

standard

1.1.2

javax.servlet.jsp

jsp-api

2.2

provided

org.hibernate

hibernate-validator

5.4.1.Final

javax.validation

validation-api

1.1.0.Final

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.springmvc

springmvc

0.0.1-SNAPSHOT

war

maven-compiler-plugin

1.7

1.7

UTF-8

4.1.3.RELEASE

org.springframework

spring-webmvc

${spring.version}

org.springframework

spring-context

${spring.version}

org.springframework

spring-aop

${spring.version}

org.springframework

spring-core

${spring.version}

org.springframework

spring-web

${spring.version}

javax.servlet

javax.servlet-api

4.0.0

provided

javax.servlet

jstl

1.2

taglibs

standard

1.1.2

javax.servlet.jsp

jsp-api

2.2

provided

org.hibernate

hibernate-validator

5.4.1.Final

javax.validation

validation-api

1.1.0.Final

SpringMVC的核心配置文件

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:context="http://springframework.org/schema/context"

xmlns:mvc="http://springframework.org/schema/mvc"

xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/context http://springframework.org/schema/context/spring-context-4.0.xsd

http://springframework.org/schema/mvc http://springframework.org/schema/mvc/spring-mvc-4.0.xsd">

class="org.springframework.context.support.ResourceBundleMessageSource">

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:context="http://springframework.org/schema/context"

xmlns:mvc="http://springframework.org/schema/mvc"

xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/context http://springframework.org/schema/context/spring-context-4.0.xsd

http://springframework.org/schema/mvc http://springframework.org/schema/mvc/spring-mvc-4.0.xsd">

class="org.springframework.context.support.ResourceBundleMessageSource">

class="org.springframework.context.support.ResourceBundleMessageSource">

以上是准备工作。下面开始核心代码介绍。

数据的校验思路:

第一步,在实体类中指定属性添加校验注解(如@NotEmpty),

第二步,在控制层目标方法实体类参数添加注解@Valid,

第三步,在返回页面加上显示提示错误信息

数据格式化思路:只需要在实体类中加上注解即可。

信息国际化思路:

第一步,在SpringMVC配置文件中配置国际化资源文件

第二步,创建文件i18n_zh_CN.properties文件

第三步,在i18n_zh_CN.properties文件配置国际化信息(要严格按照SpringMVC的语法)

UserController.java,两个重点知识。一个是SpringMVC的rest风格的增删改查。另一个是@Valid注解用法。具体看代码。

import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.validation.Errors;

import org.springframework.validation.FieldError;

import org.springframework.web.bind.annotation.ModelAttribute;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RequestParam;

import com.itdragon.springmvc.crud.dao.PositionDao;

import com.itdragon.springmvc.crud.dao.UserDao;

import com.itdragon.springmvc.crud.orm.User;

@Controller

public class UserController {

@Autowired

private UserDao userDao;

@Autowired

private PositionDao positionDao;

private static final String INPUT = "input"; // 跳转到编辑页面

private static final String LIST = "list"; // 跳转到用户列表页面

@ModelAttribute

public void getUser(@RequestParam(value="id",required=false) Integer id,

Map map){

if(id != null){

map.put("user", userDao.getUserById(id));

}

}

// 更新用户,用put请求方式区别get请求方式,属于SpringMVC rest 风格的crud

@RequestMapping(value="/user", method=RequestMethod.PUT)

public String updateUser(User user){

userDao.save(user);

return "redirect:/users";

}

// 点击编辑跳转编辑页面

@RequestMapping(value="/user/{id}", method=RequestMethod.GET)

public String input(@PathVariable("id") Integer id, Map map){

map.put("user", userDao.getUserById(id));

map.put("positions", positionDao.queryAllPositions());

return INPUT;

}

// 通过id删除用户

@RequestMapping(value="/delete/{id}", method=RequestMethod.GET)

public String delete(@PathVariable("id") Integer id){

userDao.deleteUserById(id);

return "redirect:/users";

}

/**

* 新增用户,若保存成功则跳转到用户列表页面,若失败则跳转到编辑页面

* @param user 用 @Valid 注解修饰后,可实现数据校验的逻辑

* @param result 数据校验结果

* @param map 数据模型

* @return

*/

@RequestMapping(value="/user", method=RequestMethod.POST)

public String save(@Valid User user, Errors result, Map map){

if(result.getErrorCount() > 0){

for(FieldError error : result.getFieldErrors()){

System.out.println(error.getField() + " : " + error.getDefaultMessage());

}

map.put("positions", positionDao.queryAllPositions());

return INPUT;

}

userDao.save(user);

return "redirect:/users";

}

@RequestMapping(value="/user", method=RequestMethod.GET)

public String input(Map map){

map.put("positions", positionDao.queryAllPositions());

map.put("user", new User());

return INPUT;

}

// 跳转用户列表页面

@RequestMapping("/users")

public String list(Map map){

map.put("users", userDao.queryAllUsers());

return LIST;

}

}

User.java,两个重点知识。一个是数据的格式化(包括日期格式化和数值格式化)。另一个是使用 JSR 303 验证标准数据校验。

数据格式化,由于前端传给后台的是字符串,对于比较特殊的属性,比如Date,Float类型就需要进行数据格式化

** @NumberFormat 数值格式化 **

可以格式化/解析的数字类型:Short、Integer、Long、Float、Double、BigDecimal、BigInteger。

属性参数有:pattern="###,###.##"(重点)。

style= org.springframework.format.annotation.NumberFormat.Style.NUMBER(CURRENCY / PERCENT)。其中Style.NUMBER(通用样式,默认值);Style.CURRENCY(货币样式);Style.PERCENT(百分数样式)

** @DateTimeFormat 日期格式化 **

可以格式化/解析的数字类型:java.util.Date 、java.util.Calendar 、java.long.Long。

属性参数有:pattern="yyyy-MM-dd hh:mm:ss"(重点)。

iso=指定解析/格式化字段数据的ISO模式,包括四种:ISO.NONE(不使用ISO模式,默认值),ISO.DATE(yyyy-MM-dd),ISO.TIME(hh:mm:ss.SSSZ),ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ);style=指定用于格式化的样式模式,默认“SS”,优先级: pattern 大于 iso 大于 style,后两个很少用。http://

数据校验

空检查

** @Null ** 验证对象是否为null

** @NotNull ** 验证对象是否不为null, 无法查检长度为0的字符串

** @NotBlank ** 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,

且会去掉前后空格

** @NotEmpty ** 检查约束元素是否为NULL或者是EMPTY

Booelan检查

** @AssertTrue ** 验证 Boolean 对象是否为 true

** @AssertFalse ** 验证 Boolean 对象是否为 false

长度检查

** @Size(min=, max=) ** 验证对象(Array,Collection,Map,String)值是否在给定的范围之内

** @Length(min=, max=) ** 验证对象(CharSequence子类型)长度是否在给定的范围之内

日期检查

** @Past ** 验证 Date 和 Calendar 对象是否在当前时间之前

** @Future ** 验证 Date 和 Calendar 对象是否在当前时间之后

** @Pattern ** 验证 String 对象是否符合正则表达式的规则

数值检查

** @Min ** 验证 Number 和 String 对象是否大等于指定的值

** @Max ** 验证 Number 和 String 对象是否小等于指定的值

** @DecimalMax ** 被标注的值必须不大于约束中指定的最大值. 这个约束的参数

是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度

** @DecimalMin ** 被标注的值必须不小于约束中指定的最小值. 这个约束的参数

是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度

** @Digits ** 验证 Number 和 String 的构成是否合法

** @Digits(integer=,fraction=) ** 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度

** @Range(min=, max=) ** 检查数字是否介于min和max之间

** @CreditCardNumber ** 信用卡验证

** @Email ** 验证是否是邮件地址,如果为null,不进行验证,算通过验证

** @ScriptAssert(lang= ,script=, alias=) ** 通过脚本验证

其中有几点需要注意:

空判断注解

String name @NotNull @NotEmpty @NotBlank

null false false false

"" true false false

" " true true false

"ITDragon!" true true true

数值检查:建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null

import java.util.Date;

import javax.validation.constraints.DecimalMin;

import org.hibernate.validator.constraints.Email;

import org.hibernate.validator.constraints.NotEmpty;

import org.springframework.format.annotation.DateTimeFormat;

import org.springframework.format.annotation.NumberFormat;

public class User {

private Integer id;

@NotEmpty

private String account;

@Email

@NotEmpty

private String email;

private Integer sex;

private Position position;

@DateTimeFormat(pattern="yyyy-MM-dd")

private Date createdDate;

@NumberFormat(pattern="###,###.#")

@DecimalMin("2000")

private Double salary;

public User() {

}

public User(Integer id, String account, String email, Integer sex,

Position position, Date createdDate, Double salary) {

this.id = id;

this.account = account;

this.email = email;

this.sex = sex;

this.position = position;

this.createdDate = createdDate;

this.salary = salary;

}

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getAccount() {

return account;

}

public void setAccount(String account) {

this.account = account;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

public Integer getSex() {

return sex;

}

public voifyWLgyd setSex(Integer sex) {

this.sex = sex;

}

public Position getPosition() {

return position;

}

public void setPosition(Position position) {

this.position = position;

}

public Date getCreatedDate() {

return createdDate;

}

public void setCreatedDate(Date createdDate) {

this.createdDate = createdDate;

}

public Double getSalary() {

return salary;

}

public void setSalary(Double salary) {

this.salary = salary;

}

@Override

public String toString() {

return "User [id=" + id + ", account=" + account + ", email=" + email

+ ", sex=" + sex + ", position=" + position + ", createdDate="

+ createdDate + ", salary=" + salary + "]";

}

}

input.jsp,SpringMVC 表单标签知识点详解

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@page import="java.util.HashMap"%>

<%@page import="java.util.Map"%>

<%@ taglib prefix="form" uri="http://springframework.org/tags/form" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

modelAttribute="user" class="form-horizontal" role="form">

modelAttribute="user" class="form-horizontal" role="form">

<%-- 对于 _method 不能使用 form:hidden 标签, 因为 modelAttribute 对应的 bean 中没有 _method 这个属性 --%>

<%--

--%>

<%

Map genders = new HashMap();

genders.put("1", "Male");

genders.put("0", "Female");

request.setAttribute("genders", genders);

%>

i18n国际化文件

#语法:实体类上属性的注解.验证目标方法的modleAttribute 属性值(如果没有默认为实体类首字母小写).注解修饰的属性 

#以第一个为例:User实体类中 属性account用了NotEmpty注解修饰,表示不能为空。所以前缀是NotEmpty 

#验证的目标方法 public String save(@Valid User user, ...) User被注解@Valid 修饰,但没有被modleAttribute修饰。所以中间是user 

#后缀就是被注解修饰的属性名 account 

NotEmpty.user.account=用户名不能为空 

Email.user.email=Email地址不合法 

 

#typeMismatch 数据类型不匹配时提示 

typeMismatch.user.createdDate=不是一个日期 

#required 必要参数不存在时提示 

#methodInvocation 调用目标方法出错的时提示

其他文件,Position 实体类

public class Position {

private Integer id;

private String level;

public Position() {

}

public Position(Integer id, String level) {

this.id = id;

this.level = level;

}

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getLevel() {

return level;

}

public void setLevel(String level) {

this.level = level;

}

@Override

public String toString() {

return "Position [id=" + id + ", level=" + level + "]";

}

}

模拟用户操作的dao,UserDao.java

import java.util.Collection;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;

import com.itdragon.springmvc.crud.orm.Position;

import com.itdragon.springmvc.crud.orm.User;

@Repository

public class UserDao {

private static Map users = null;

@Autowired

private PositionDao positionDao;

// 模拟数据库查询数据

static{

users = new HashMap();

users.put(1, new User(1, "ITDragon", "11@xl.com", 1, new Position(1, "架构师"), new Date(), 18888.88));

users.put(2, new User(2, "Blog", "22@xl.com", 1, new Position(2, "高级工程师"), new Date(), 15555.55));

users.put(3, new User(3, "Welcome", "33@xl.com", 0, new Position(3, "中级工程师"), new Date(), 8888.88));

users.put(4, new User(4, "To", "44@xl.com", 0, new Position(4, "初级工程师"), new Date(), 5555.55));

users.put(5, new User(5, "You", "55@xl.com", 1, new Position(5, "java实习生"), new Date(), 2222.22));

}

// 下一次存储的下标id

private static Integer initId = 6;

public void save(User user){

if(user.getId() == null){

user.setId(initId++);

}

user.setPosition(positionDao.getPositionById(user.getPosition().getId()));

users.put(user.getId(), user);

}

public Collection queryAllUsers(){

return users.values();

}

public User getUserById(Integer id){

return users.get(id);

}

public void deleteUserById(Integer id){

users.remove(id);

}

}

import java.util.Collection;

import java.util.HashMap;

import java.util.Map;

import org.springframework.stereotype.Repository;

import com.itdragon.springmvc.crud.orm.Position;

@Repository

public class PositionDao {

private static Map positions = null;

static{

positions = new HashMap();

positions.put(1, new Position(1, "架构师"));

positions.put(2, new Position(2, "高级工程师"));

positions.put(3, new Position(3, "中级工程师"));

positions.put(4, new Position(4, "初级工程师"));

positions.put(5, new Position(5, "java实习生"));

}

// 模拟查询所有数据

public Collection queryAllPositions(){

return positions.values();

}

// 模拟通过id查询数据

public Position getPositionById(Integer id){

return positions.get(id);

}

}

用户列表页面的list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%&fyWLgygt;

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

没有任何员工信息.

用户编码

账号名

邮箱

性别

职位

薪水

时间

编辑

删除

注意事项

javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint '

使用hibernate validator出现上面的错误, 需要 注意

@NotNull 和 @NotEmpty 和@NotBlank 区别

@NotEmpty 用在集合类上面

@NotBlank 用在String上面

@NotNull 用在基本类型上

如果在基本类型上面用NotEmpty或者NotBlank 会出现上面的错,笔者将@NotEmpty用到了Date上,导致出了这个问题。若还有问题,还继续在这里补充。

以上便是SpringMVC的表单操作,其中包含了常用知识,如数据的格式化,数据的校验,提示信息国际化,Form标签的用法。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:c 短信接口开发(C#短信接口)
下一篇:Java数据结构之循环队列简单定义与用法示例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~