一. form 标签
在实际业务开发中,虽然不常用
可以与Struts2 的form 表单标签 进行区分性学习。可以参考老蝴蝶以前的文章: Struts2的%,#,$的区别,UI标签及其表单radio,checkbox,select回显数据(七)
如果引用 springmvc 中的form 标签的话,需要引入相应的约束,就像 jsp 里面的jstl 一样。
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
这个约束的文件 为spring-form.tld, 在spring-webaamvc.jar包里面。
注意,千万不要忘记引用 uri,不然标签是不会出来的。 下面的例子均默认带上了 uri。
重写一个 User.java,方便后面使用
package com.yjl.pojo; import java.io.Serializable; import java.util.List; import java.util.Map; /** * 所用的员工类 * @author 12905 * */ public class User{ private Integer id; private String name; private String password; private Integer age; private String sex; private String description; private List<String> hobby; private boolean isAgree; private String addr; private List<String> job; private Dept dept; private List<Role> roles; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex == null ? null : sex.trim(); } public String getDescription() { return description; } public void setDescription(String description) { this.description = description == null ? null : description.trim(); } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public List<String> getHobby() { return hobby; } public void setHobby(List<String> hobby) { this.hobby = hobby; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } public List<String> getJob() { return job; } public void setJob(List<String> job) { this.job = job; } public boolean isAgree() { return isAgree; } public void setAgree(boolean isAgree) { this.isAgree = isAgree; } public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", description=" + description + ", dept=" + dept + "]"; } }
Dept.java 与Role.java 还是与以前的一样。
Dept.java 有 id,name,description 属性。
Role.java 有 id,name 属性。
from 标签中所拥有的属性有:
根据属性名称可知,与其对应的 html 标签名。 如hidden 对应 type=hidden, button 对应 type=button.
均是用 toLogin.action 方法和 login.jsp 页面。
二. form: form 标签
这是form 表单的总标签。 有两个作用。
1 . 会自动绑定Model 中的属性值到 当前form 所对应的实体对象,默认为 command 属性,这样,就可以在form 表单中使用该对象的属性了,方便进行回显,可支持对象的级联。
2 . 支持其他的提交方式,除了常见的Get 和Post 之外,还支持PUT和Delete. 用于REST 风格。
二.一 form 标签的属性值
其中,commandName 与modelAttribute 的用法是一样的。 它可以绑定javaBean 对象, 用于快速回显。 如commandName 指定一个值 ,如"user", 后端Model 中有一个属性值 的key为 “user”, 如model.addAttribute(“user”,user); 那么这样,就可以将 这个form 与这个对象 user 进行关联起来, form 表单可以取出 user 对象里面的所有的属性值。 commandName的默认值是 command.
二.二 form 表单用于回显。
1 . 普通页面的回显
后端显示操作:
@RequestMapping(value="toLogin") public String toLogin(Model model){ User user=new User(); user.setName("两个蝴蝶飞"); user.setAge(24); //注意,此时名称是command model.addAttribute("command",user); return "user/login"; }
前端展示:
<h2>两个蝴蝶飞,form表单使用</h2> <!--名称是command,与默认的相同,故这里不指定--> <form:form> <!-- 用path来指定 哪一个input获取焦点。 --> <form:label path="name">姓名:</form:label><form:input path="name"/> <br/> <form:label path="age">年龄:</form:label>:<form:input path="age"/> </form:form>
开启服务器,进行测试: http://localhost:8027/SpringMVC04/user/toLogin.action
页面显示:
可以正确的进行回显。
ctrl+U 进行查看源代码,展示为:
<body> <h2>两个蝴蝶飞,form表单使用</h2> <form id="command" action="/SpringMVC04/user/toLogin.action" method="post"> <label for="name">姓名:</label><input id="name" name="name" type="text" value="两个蝴蝶飞"/> <br/> <label for="age">年龄:</label>:<input id="age" name="age" type="text" value="24"/> </form> </body>
默认设置 id=“command”, 所以才进行了关联。
2 . 为了更直观的展示javabean 对象信息,不能每一个Model 都设置成command, 希望 user对象设置成user,dept 对象设置成dept,这样更直观的展示这个表单是哪一个。
后端代码:
@RequestMapping(value="toLogin") public String toLogin(Model model){ User user=new User(); user.setName("两个蝴蝶飞"); user.setAge(24); //注意,这里设置成了 user . model.addAttribute("user",user); return "user/login"; }
如果此时,前端不改,form 里面不设置 commandName 的话,会出错。
将 form 中添加commandName 为"user", 就可以正常显示了。
<form:form commandName="user">
当然,换成 modelAttribute 也是可以的。
查看页面源代码,发现设置了一个 id=“user” 。 与Model 里面key=user 的对象进行了关联。
3 . 要特别注意, user 对象要与 表单user 中的属性进行一 一 对应。 如user 中没有 marriage 字段,如果在前端添加了这个字段,
<form:label path="marriage">婚姻:</form:label>:<form:input path="marriage"/>
也是会报错的。
如果不小心写错了,
4 . 支持级联的回显。 如回显添加一个 dept 部门字段。
后端代码处理
@RequestMapping(value="toLogin") public String toLogin(Model model){ User user=new User(); user.setName("两个蝴蝶飞"); user.setAge(24); Dept dept=new Dept(); dept.setName("信息管理部"); dept.setDescription("这是开发的部门"); user.setDept(dept); model.addAttribute("user",user); return "user/login"; }
前端处理显示,添加 部门的描述展示。
<form:form modelAttribute="user"> <!-- 用path来指定 哪一个input获取焦点。 --> <form:label path="name">姓名:</form:label><form:input path="name"/> <br/> <form:label path="age">年龄:</form:label><form:input path="age"/><br/> <!--添加部门的显示--> <form:label path="dept.name">部门名称:</form:label><form:input path="dept.name"/><br/> <form:label path="dept.description">部门名称:</form:label><form:input path="dept.description"/><br/> </form:form>
前端页面展示:
查看源代码显示:
二.三 form 用于支持其他提交方式,如PUT 和Delete
1 .添加一个login 的方法,看是否能够执行这个方法。
@RequestMapping(value="login") public String login(Model model){ System.out.println("可以正确的跳转过来"); return "user/list"; }
前端添加一个提交按钮,form 中写action 的跳转路径,指定方法为 delete.
<form:form modelAttribute="user" action="login.action" method="delete"> <!-- 用path来指定 哪一个input获取焦点。 --> <form:label path="name">姓名:</form:label><form:input path="name"/> <br/> <form:label path="age">年龄:</form:label><form:input path="age"/><br/> <form:label path="dept.name">部门名称:</form:label><form:input path="dept.name"/><br/> <form:label path="dept.description">部门名称:</form:label><form:input path="dept.description"/><br/> <form:button>提交</form:button> </form:form>
重启服务器,进行验证。
发现,控制台可以打印输出, 页面也跳转到了 list.jsp 页面。 不截图了。
查看一下, login.jsp 页面的源代码,看是什么样子的。
发现,表单的请求方式,还是 post, 在表单里面添加了一个隐藏字段hidden, 属性值为 “_method” , 值为 delete.
猜测,是这个_method 来指定请求的方式。
2 . 然而,这种方式指定之后,是否就可以delete 请求了呢?, 在login 方法上指定请求的方式为 delete.
指定请求的方式为 delete.
@RequestMapping(value="login",method=RequestMethod.DELETE) public String login(Model model){ System.out.println("可以正确的跳转过来"); return "user/list"; }
这时,重新访问一下,会抛出异常。
这说明,现在后端还不认 前端的 method=delete. 需要添加一个过滤器。
HiddenHttpMethodFilter。
需要放置在 web.xml 里面,放置在其他的过滤器之后,如字符乱码过滤器之后。
<!-- 配置隐藏请求方法过滤器 --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
重启服务器,进行访问。
这个时候,就可以正常的跳转,正常的访问了。
3 . 观察一下,这个HiddenHttpMethodFilter 过滤器,看看是什么原理。
参数默认为 _method.
4 . 手动扩展 _method,能否复现呢? 即将 method 改成post, 添加一个 _method 的隐藏域,值为delete, 看是否能够通过?
<form:form modelAttribute="user" action="login.action" method="post"> <!-- 手动造请求方法 --> <input type="hidden" name="_method" value="delete"/> <!-- 用path来指定 哪一个input获取焦点。 --> <form:label path="name">姓名:</form:label><form:input path="name"/> <br/> <form:label path="age">年龄:</form:label><form:input path="age"/><br/> <form:label path="dept.name">部门名称:</form:label><form:input path="dept.name"/><br/> <form:label path="dept.description">部门名称:</form:label><form:input path="dept.description"/><br/> <form:button>提交</form:button> </form:form>
这样,也是通过的。
如果将表单的 method=“post” ,改成 method=“get” 的话, 是错误的。
故,可知,只能是 post 提交的。
当然,也可以改变这个值。 需要 往 HiddenHttpMethodFilter 添加参数,动态的设置 methodParam 的值。
5 . 如请求参数设置为 ‘_requMethod’
<form:form modelAttribute="user" action="login.action" method="get"> <!-- 设置参数 为requMethod --> <input type="hidden" name="requMethod" value="delete"/> <!-- 用path来指定 哪一个input获取焦点。 --> <form:label path="name">姓名:</form:label><form:input path="name"/> <br/> <form:label path="age">年龄:</form:label><form:input path="age"/><br/> <form:label path="dept.name">部门名称:</form:label><form:input path="dept.name"/><br/> <form:label path="dept.description">部门名称:</form:label><form:input path="dept.description"/><br/> <form:button>提交</form:button> </form:form>
那么需要在过滤器里面注入 参数的值。
<!-- 配置隐藏请求方法过滤器 --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> <init-param> <param-name>methodParam</param-name> <param-value>requMethod</param-value> </init-param> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
这样是通过的。
但常常还是用 _method 原生的。