SpringMVC实现表单验证功能详解

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

项目结构图

接下来用代码重点学习SpringMVC的表单操作,数据格式化,数据校验以及错误提示信息国际化。请读者将重点放在UserController.java,User.java,input.jsp三个文件中。
maven 项目必不可少的pom.xml文件。里面有该功能需要的所有jar包。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.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">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.springmvc</groupId>
 <artifactId>springmvc</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging> 

 <!-- 若不配置,打包时会提示错误信息
 Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project springmvc: Compilation failure:
 提示 未结束的字符串文字 ,若字符串后面加上空格后可以打包成功,但会乱码。
 原因是:maven使用的是默认的compile插件来进行编译的。complier是maven的核心插件之一,然而complier插件默认只支持编译Java 1.4
 -->
 <build>
 <plugins>
  <plugin>
   <artifactId>maven-compiler-plugin</artifactId>
   <configuration>
    <source>1.7</source>
    <target>1.7</target>
    <encoding>UTF-8</encoding>
   </configuration>
  </plugin>
 </plugins>
 </build> 

 <properties>
 <spring.version>4.1.3.RELEASE</spring.version>
 </properties>
 <dependencies>
 <!-- spring begin -->
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>${spring.version}</version>
 </dependency> 

 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>${spring.version}</version>
 </dependency> 

 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>${spring.version}</version>
 </dependency> 

 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>${spring.version}</version>
 </dependency> 

 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>${spring.version}</version>
 </dependency> 

 <!-- spring end -->
 <dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.0</version>
  <scope>provided</scope>
 </dependency>
 <dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
 </dependency>
 <dependency>
  <groupId>taglibs</groupId>
  <artifactId>standard</artifactId>
  <version>1.1.2</version>
 </dependency>
 <!-- 缺少jsp-api 则提示 javax.servlet.jsp.JspException cannot be resolved to a type -->
 <dependency>
  <groupId>javax.servlet.jsp</groupId>
  <artifactId>jsp-api</artifactId>
  <version>2.2</version>
  <scope>provided</scope>
 </dependency>
 <!-- JSR 303 start -->
 <dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>5.4.1.Final</version>
 </dependency>
 <dependency>
  <groupId>javax.validation</groupId>
  <artifactId>validation-api</artifactId>
  <version>1.1.0.Final</version>
 </dependency>
 <!-- JSR 303 end --> 

 </dependencies>
</project>

SpringMVC的核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> 

 <!-- 配置自定扫描的包 -->
 <context:component-scan base-package="com.itdragon.springmvc" /> 

 <!-- 配置视图解析器 -->
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/views/"></property>
  <property name="suffix" value=".jsp"></property>
 </bean> 

 <!-- 配置注解驱动 -->
 <mvc:annotation-driven /> 

 <!-- 配置视图 BeanNameViewResolver 解析器
  使用视图的名字来解析视图
  通过 order 属性来定义视图解析器的优先级, order 值越小优先级越高
 -->
 <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
  <property name="order" value="100"></property>
 </bean> 

 <!-- 配置直接跳转的页面,无需经过Controller层
  http://localhost:8080/springmvc/index
  然后会跳转到 WEB-INF/views/index.jsp 页面
 -->
 <mvc:view-controller path="/index" view-name="index"/> 

 <mvc:default-servlet-handler/> 

 <!-- 配置国际化资源文件 -->
 <bean id="messageSource"
  class="org.springframework.context.support.ResourceBundleMessageSource">
  <property name="basename" value="i18n"></property>
 </bean> 

</beans> 

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

数据的校验思路:

第一步,在实体类中指定属性添加校验注解(如@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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> map){
  map.put("positions", positionDao.queryAllPositions());
  map.put("user", new User());
  return INPUT;
 } 

 // 跳转用户列表页面
 @RequestMapping("/users")
 public String list(Map<String, Object> 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,后两个很少用。

数据校验

空检查
** @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 void 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://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 

<!DOCTYPE html">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SpringMVC 表单操作</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="stylesheet">
</head>
<body> 

 <!--
 1. 使用 form 标签可以更快速的开发出表单页面, 而且可以更方便的进行表单值的回显。
 step1 导入标签 taglib prefix="form" uri="http://www.springframework.org/tags/form"
 step2 和普通的form用法差不多。path 相当于 普通的form的name,form:hidden 隐藏域,form:errors 提示错误信息。
 2. 使用form 标签需要注意:
 通过 modelAttribute 属性指定绑定的模型属性, 该数据模型必须是实例化过的。
 若没有 modelAttribute 指定该属性,则默认从 request 域对象中读取 command 的表单 bean (如果该属性值也不存在,则会发生错误)。
 java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
 -->
 <div class="container">
 <div class="row">
  <div class="col-sm-6">
  <div class="panel panel-info" style="margin-top:10px;">
  <div class="panel-heading">
   <h3 class="panel-title">修改或创建用户信息</h3>
  </div>
  <div class="panel-body">
   <form:form action="${pageContext.request.contextPath }/user" method="POST"
   modelAttribute="user" class="form-horizontal" role="form">
   <c:if test="${user.id == null }">
    <!-- path 属性对应 html 表单标签的 name 属性值 -->
    <div class="form-group">
    <label class="col-sm-2 control-label">Account</label>
    <div class="col-sm-10">
     <form:input class="form-control" path="account"/>
     <form:errors style="color:red" path="account"></form:errors>
    </div>
    </div>
   </c:if>
   <c:if test="${user.id != null }">
    <form:hidden path="id"/>
    <input type="hidden" name="_method" value="PUT"/>
    <%-- 对于 _method 不能使用 form:hidden 标签, 因为 modelAttribute 对应的 bean 中没有 _method 这个属性 --%>
    <%--
    <form:hidden path="_method" value="PUT"/>
    --%>
   </c:if>
   <div class="form-group">
    <label class="col-sm-2 control-label">Email</label>
    <div class="col-sm-10">
    <form:input class="form-control" path="email"/>
    <form:errors style="color:red" path="email"></form:errors>
    </div>
   </div>
   <!-- 这是SpringMVC 不足之处 -->
   <%
    Map<String, String> genders = new HashMap();
    genders.put("1", "Male");
    genders.put("0", "Female");
    request.setAttribute("genders", genders);
   %>
   <div class="form-group">
    <label class="col-sm-2 control-label">Sex</label>
    <div class="col-sm-10">
    <form:radiobuttons path="sex" items="${genders }" />
    </div>
   </div>
   <div class="form-group">
    <label class="col-sm-2 control-label">Position</label>
    <div class="col-sm-10">
    <form:select class="form-control" path="position.id" items="${positions}" itemLabel="level" itemValue="id">
    </form:select>
    </div>
   </div>
   <div class="form-group">
    <label class="col-sm-2 control-label">Date</label>
    <div class="col-sm-10">
    <form:input class="form-control" path="createdDate"/>
    <form:errors style="color:red" path="createdDate"></form:errors>
    </div>
   </div>
   <div class="form-group">
    <label class="col-sm-2 control-label">Salary</label>
    <div class="col-sm-10">
    <form:input class="form-control" path="salary"/>
    <form:errors style="color:red" path="salary"></form:errors>
    </div>
   </div>
   <input class="btn btn-success" type="submit" value="Submit"/>
   </form:form>
  </div>
  </div>
  </div>
 </div>
 </div> 

</body>
</html>

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<Integer, User> users = null; 

 @Autowired
 private PositionDao positionDao; 

 // 模拟数据库查询数据
 static{
 users = new HashMap<Integer, User>();
 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<User> 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<Integer, Position> positions = null; 

 static{
 positions = new HashMap<Integer, Position>(); 

 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<Position> 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"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 

<!DOCTYPE html">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SpringMVC 表单操作</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="stylesheet">
<script src="https://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
 $(function(){
 $(".delete").click(function(){
  var msg = confirm("确定要删除这条数据?");
  if (true == msg) {
  $(this).onclick();
  } else {
  return false;
  }
 });
 })
</script>
</head>
<body> 

 <!-- 用于删除的form -->
 <form action="" method="POST" id="deleteForm">
 <input type="hidden" name="_method" value="DELETE"/>
 </form> 

 <div class="container">
 <div class="row">
  <div class="col-sm-9">
  <c:if test="${empty requestScope.users }">
  没有任何员工信息.
  </c:if>
  <c:if test="${!empty requestScope.users }">
  <div class="table-responsive">
   <table class="table table-bordered">
   <caption>用户信息表 <a href="user" rel="external nofollow" class="btn btn-default" >Add Account</a></caption>
   <thead>
   <tr>
    <th>用户编码</th>
    <th>账号名</th>
    <th>邮箱</th>
    <th>性别</th>
    <th>职位</th>
    <th>薪水</th>
    <th>时间</th>
    <th>编辑</th>
    <th>删除</th>
   </tr>
   </thead>
   <tbody>
   <c:forEach items="${requestScope.users }" var="user">
    <tr>
    <td>${user.id }</td>
    <td>${user.account }</td>
    <td>${user.email }</td>
    <td>${user.sex == 0 ? 'Female' : 'Male' }</td>
    <td>${user.position.level }</td>
    <td>${user.salary }</td>
    <td><fmt:formatDate value="${user.createdDate }" pattern="yyyy-MM-dd HH:mm:ss"/></td>
    <td><a href="user/${user.id}" rel="external nofollow" >Edit</a></td>
    <td><a class="delete" href="delete/${user.id}" rel="external nofollow" >Delete</a></td>
    </tr>
   </c:forEach>
   </tbody>
   </table>
  </div>
  </c:if>
  </div>
 </div>
 </div> 

</body>
</html> 

注意事项

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标签的用法。

(0)

相关推荐

  • Spring Boot学习入门之表单验证

    前言 所谓表单验证,即校验用户提交的数据的合理性的,比如是否为空了,密码长度是否大于6位,是否是纯数字的,等等.spring boot是如何帮我们实现表单验证的呢?下面话不多说了,来一起看看详细的介绍吧. 假设现在我们存在这么一个注册界面: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>hello spring boot</title>

  • Spring Boot 表单验证篇

    一. spring-boot-starter-validation 依赖概述 上一篇 <Spring Boot Web 开发注解篇>,就可以快速地进行 Web 开发.那么在表单提交的时候,我们需要进行验证.前端验证可以挡住 99% 的小白用户,这里要实现服务端验证. Starters 机制告诉我们,只要加入 spring-boot-starter-validation 这个 Starter ,就可以使用其实现验证.那什么是 spring-boot-starter-validation? spr

  • SpringMVC实现表单验证功能详解

    本章节内容很丰富,主要有基本的表单操作,数据的格式化,数据的校验,以及提示信息的国际化等实用技能. 首先看效果图 项目结构图 接下来用代码重点学习SpringMVC的表单操作,数据格式化,数据校验以及错误提示信息国际化.请读者将重点放在UserController.java,User.java,input.jsp三个文件中. maven 项目必不可少的pom.xml文件.里面有该功能需要的所有jar包. <?xml version="1.0" encoding="UTF

  • AngularJS实现表单验证功能详解

    在ng中,针对表单和空间提供了属性,用于验证控件交互的状态 布尔类型: ng-valid 表单通过验证时设置 ng-invalid 表单未通过验证时设置 ng-pristine 表单没有改动时设置 ng-dirty 表单有改动时设置 对象: $error 注意事项: ①给表单以及表单组件 加上name属性 ②给需要用到的表单组件 ,加上ngModel ③属性的用法 myForm.t_age.dirty/pristine/valid/invalid/$error 案例如下 <!DOCTYPE ht

  • Angular4表单验证代码详解

     背景: 最近在itoo页面调整的时候,发现页面表单或者是文本框没有做基本的判断操作,所以着手demo一篇,希望对大家有帮助!! -------------------------------------------------------------------------------- 1.创建表单组件: ng g c login1 2.1单规则验证: <label>用户名:</label> <input type="text" #userNameRe

  • Angular表单验证实例详解

    表单验证 我去,我感觉我这个人其实还是一个很傻逼的一个人,老是因为拼错了一个单词或者怎么样就浪费我很长时间,这样真的不行不行,要正确对待这个问题,好了,说正题吧,angular也有表单验证minlength,maxlength,required呀这些个东西,还有也支持h5的那些验证,h5的那些验证,就是type啦,type='email',number,url呀这些,然后现在要用angular来验证,可以定义样式哈,不错,然后怎么验证呢,好的上代码 <!DOCTYPE html> <ht

  • Spring Boot 2 Thymeleaf服务器端表单验证实现详解

    这篇文章主要介绍了Spring Boot 2 Thymeleaf服务器端表单验证实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 表单验证分为前端验证和服务器端验证. 服务器端验证方面,Java提供了主要用于数据验证的JSR 303规范,而Hibernate Validator实现了JSR 303规范. 项目依赖加入spring-boot-starter-thymeleaf时,默认就会加入Hibernate Validator的依赖. 开

  • AngularJs表单验证实例详解

    常用的表单验证指令 1. 必填项验证 某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可: 复制代码 代码如下: <input type="text" required /> 2. 最小长度 验证表单输入的文本长度是否大于某个最小值,在输入字段上使用指令ng-minleng= "{number}": 复制代码 代码如下: <input type="text" ng-minlength="

  • ASP.NET表单验证方法详解第1/2页

    1.使用验证控件 这属于客户端验证,微软开发人员将最常用的验证功能进行了封装,使得我们开发效率明显提高,而且特别是自定义验证控件,非常灵活,我们可以自行设计验证逻辑.但是验证控件收到了浏览器的限制,记得在一次开发过程中,使用FireFox浏览器进行浏览,发现所有的验证控件失灵,这个并非是ASP.NET设计的漏洞,只能说浏览器标准的不唯一造成的. ASP.NET公有六种验证控件,分别如下: RequiredFieldValidator(必须字段验证) 用于检查是否有输入值 CompareValid

  • 正则表达式基本语法及表单验证操作详解【基于JS】

    本文实例讲述了正则表达式基本语法及表单验证操作.分享给大家供大家参考,具体如下: 正则表达式是一种可以用于模式匹配和替换的强有力的工具,是数据的有效性验证. 一.基本语法 位于"/"定界符之间的部分就是将要在目标对象中进行匹配的模式.用户只要把希望查找匹配对象的模式内容放入"/"定界符之间即可.为了能够使用户更加灵活的定制模式内容,正则表达式提供了专门的"元字符".所谓元字符就是指那些在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(

  • CI框架表单验证实例详解

    本文实例讲述了CI框架表单验证的方法.分享给大家供大家参考,具体如下: 1.form头部信息的自动输出函数(view) <?php $attributes = array('class' => 'email', 'id' => 'myform'); echo form_open('email/send', $attributes); //上面一行代码输出: //<form method="post" accept-charset="utf-8"

  • JQurey Validation表单验证使用详解

    是一款优秀的插件,它能对客户端表单进行验证,并且提供了许多可以定制的属性和方法,良好的扩展性.本文就是通过讲解这个实例来理解Validation的应用. 本实例涉及到的验证有: 用户名:长度.字符验证,重复性ajax验证(是否已存在). 密码:长度验证,重复输入密码验证. 邮件:邮件地址验证. 固定电话:中国大陆固定电话号码验证. 手机号:中国大陆手机号码验证. 网址:网站URL地址验证. 日期:标准日期格式验证. 数字:整数.正整数验证,数字范围验证. 身份证:大陆身份证号码验证. 邮政编码:

随机推荐