一、Spring 的表单标签
1、form 表单标签
通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显。
2、form 标签
(1)一般情况下,通过 GET 请求获取表单页面,而通过 POST 请求提交表单页面,因此获取表单页面和提交表单页面的 URL 是相同的。
(2)只要满足该最佳条件的契约,<form:form> 标签就无需通过 action 属性指定表单提交的 URL;
(3)可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取 command 的表单 bean,如果该属性值也不存在,则会发生错误。
3、表单组件标签
(1)SpringMVC 提供了多个表单组件标签,如<form:input/> 、<form:select/> 等,用以绑定表单字段的属性值,它们的共有属性如下:
path:表单字段,对应 html 元素的 name 属性,支持级联属性
htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值为 true
cssClass:表单组件对应的 css 样式类名
cssErrorClass:表单组件的数据存在错误时,采取的 css 样式
(2)常用标签
① form:input、form:password、form:hidden、form:textarea:对应 HTML 表单的 text、password、hidden、textare 标签。
② form:radiobutton :单选框组件标签,当表单 bean 对应的属性值和 value 值相等时,单选框被选中;
③ form:radiobuttons:单选框组标签,用于构造多个单选框
items:可以是一个 List、String[] 或 map
itemValue:指定 radio 的value 值,可以是集合中 bean 的一个属性值
itemLabel:指定 radio 的 label 值
delimiter:多个单选框可以通过 delimiter 指定分隔符
④ form:checkbox:复选框组件,用于构造单个复选框
⑤ form:checkboxs:用于构造多个复选框,使用方式同 form:radiobuttons 标签
⑥ form:select:用于构造下拉框组件,使用方式同 form:radiobutons 标签
⑦ form:option:下拉框选项组件标签。使用方式同 form:radiobuttons 标签
⑧ form:errors:显示表单组件或数据校验所对应的错误
<form:errors path= "*" /> :显示表单所有的错误
<form:errors path= "user*" /> :显示所有以 user 为前缀的属性对应的错误
<form:errors path= "username" /> :显示特定表单对象属性的错误
4、使用 form 表单标签
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
二、使用 form 标签重构添加页面
1、去添加页面
<a href="/toAddPage">ADD</a>
2、控制器方法
/**
* 去添加页面,把需要的部门信息放在请求域中带到页面
* @param model
* @return
*/
@RequestMapping(value = "/toAddPage", method = RequestMethod.GET)
public String toAddPage(Model model) {
Collection<Department> depts = departmentDao.getDepartments();
//默认放到 request 域中
model.addAttribute("depts", depts);
model.addAttribute("command", new Employee(null, "张三", "san@126.com", 0, departmentDao.getDepartment(101)));
model.addAttribute("employee", new Employee());
return "add";
}
3、添加页面
<%--
form 表单标签
通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显
1、SpringMVC 认为,表单数据中每一项最终都是要回显的;
path 指定的是一个属性,这个属性是从隐含模型(请求域中取出的某个对象的属性);
path 指定的每一个属性,请求域中必须有一个对象,拥有这个属性;
这个对象就是请求域中的 command
modelAttribute=""
modelAttribute="employee"
1、以前我们表单标签会从请求域中获取一个 command 对象,把这个对象中的每一个属性对应的显示出来;
2、可以告诉SpringMVC 不要去取 command 的值,放了一个 modelAttribute 指定的值
取对象用的key就用 modelAttribute 指定的;
--%>
<%
pageContext.setAttribute("ctx", request.getContextPath());
%>
<form:form action="${ctx}/emp" modelAttribute="employee" method="POST">
<!--
path 就是原来 html-input的name项,需要写
1、path 当做原生的 name 项
2、自动回显隐含模型中某个对象对应的这个属性的值
-->
lastName:<form:input path="lastName" /><br/>
email:<form:input path="email" /><br/>
gender:<br>
男 <form:radiobutton path="gender" value="1"/><br/>
女 <form:radiobutton path="gender" value="0" /><br/>
dept:
<!--
items:指定要遍历的集合,自动遍历,遍历出的每一个元素是一个 department 对象
itemLabel="属性" :指定遍历出的这个对象的那个属性是作为 option 标签体的值
itemValue="属性" :指定刚才遍历出来的这个对象的哪个属性是作为要提交的 value 值
-->
<form:select path="department.id" items="${depts}" itemLabel="departmentName" itemValue="id"></form:select>
<br>
<input type="submit" value="保存">
</form:form>
4、常见错误
可以通过 modelAttribute 指定绑定的模型属性,若没有指定该属性,则默认从 request 域中查找 command 的表单 bean,如果该属性也不存在,则会发生错误。
错误:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
没有指定 command 属性。
三、使用 form 标签重构修改页面
修改流程图:
1、修改链接
<a href="${ctp}/emp/${emp.id}">UPDARE</a>
2、根据id查询员工
/**
* 根据id查询员工信息
* @param id
* @return
*/
@RequestMapping(value = "/emp/{id}", method = RequestMethod.GET)
public String getEmpById(@PathVariable("id") Integer id, Model model) {
Employee employee = employeeDao.get(id);
model.addAttribute("emp", employee);
Collection<Department> depts = departmentDao.getDepartments();
model.addAttribute("depts", depts);
return "edit";
}
3、修改页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<html>
<head>
<title>员工修改页面</title>
</head>
<body>
<%
pageContext.setAttribute("ctp", request.getContextPath());
%>
<%-- modelAttribute="emp" 这个表单的所有内容显示绑定的是请求域中 emp 的值 --%>
<form:form action="${ctp}/emp/${emp.id}" modelAttribute="emp" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="id" value="${emp.id}">
email:<form:input path="email" /><br/>
gender:<br>
男 <form:radiobutton path="gender" value="1"/><br/>
女 <form:radiobutton path="gender" value="0" /><br/>
dept:
<form:select path="department.id" items="${depts}" itemLabel="departmentName" itemValue="id"></form:select>
<br>
<input type="submit" value="保存">
</form:form>
</body>
</html>
4、修改控制器
/**
* 修改员工信息
* @param id
* @param employee
* @return
*/
@RequestMapping(value = "/emp/{id}", method = RequestMethod.PUT)
public String updateEmpById(@PathVariable("id") Integer id, @ModelAttribute(value = "employee") Employee employee) {
System.out.println("employee = " + employee);
employeeDao.save(employee);
return "redirect:/emps";
}
@ModelAttribute
public void myModelAttribute(@RequestParam(value = "id", required = false)Integer id, Model model) {
if (id != null) {
Employee employee = employeeDao.get(id);
System.out.println("查询出的类型:employee = " + employee);
model.addAttribute("employee", employee);
}
System.out.println("ModelAttribute运行了");
}