SpringMVC实现表单验证功能详解
本章节内容很丰富,主要有基本的表单操作,数据的格式化,数据的校验,以及提示信息的国际化等实用技能。 项目结构图 接下来用代码重点学习SpringMVC的表单操作,数据格式化,数据校验以及错误提示信息国际化。请读者将重点放在UserController.java,User.java,input.jsp三个文件中。 <?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), 数据格式化思路:只需要在实体类中加上注解即可。 信息国际化思路: 第一步,在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,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,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类型就需要进行数据格式化 ** @DateTimeFormat 日期格式化 ** 数据校验 空检查 其中有几点需要注意: 空判断注解 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 属性值(如果没有默认为实体类首字母小写).注解修饰的属性 其他文件,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",new Position(2,"高级工程师"),15555.55)); users.put(3,new User(3,"Welcome","33@xl.com",new Position(3,"中级工程师"),8888.88)); users.put(4,new User(4,"To","44@xl.com",new Position(4,"初级工程师"),5555.55)); users.put(5,new User(5,"You","55@xl.com",new Position(5,"java实习生"),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,"架构师")); positions.put(2,"高级工程师")); positions.put(3,"中级工程师")); positions.put(4,"初级工程师")); positions.put(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 ' 如果在基本类型上面用NotEmpty或者NotBlank 会出现上面的错,笔者将@NotEmpty用到了Date上,导致出了这个问题。若还有问题,还继续在这里补充。 以上便是SpringMVC的表单操作,其中包含了常用知识,如数据的格式化,数据的校验,提示信息国际化,Form标签的用法。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 什么是JavaBean、bean? 什么是POJO、PO、DTO、VO、BO ? 什么
- java – 我的viewpager中每个片段的不同标题
- oop – ORM是面向对象编程特有的问题吗?
- 最新IntelliJ IDEA2017.3 激活方式
- java – 如何禁用JButton在禁用时变灰?
- java – JTable不显示列标题
- Struts2 ServletActionContext.getServletContext()方法:获
- java – 使用secp256r1曲线和SHA256算法生成ECDSA签名 – B
- 使用套接字编程将数据从Java发送到C.
- SpringBoot 文件上传和下载的实现源码