SpringMVC中form标签

在低版本的Spring中,你必须通过JSTL或<spring:bind>将表单对象绑定到HTML表单页面中,对于习惯了Struts表单标签的开发者来说,Spring MVC的这一表现确实让人失望。不过这一情况已经一去不复返了,从Spring 2.0开始,Spring MVC开始全面支持表单标签,通过Spring MVC表单标签,我们可以很容易地将控制器相关的表单对象绑定到HTML表单元素中。
在上一篇文章《Spring MVC的表单控制器》中(http://tech.it168.com/j/2007-07-26/200707261434046.shtml)我们已经使用到了部分的Spring MVC表单标签,在本文中我们将对Spring MVC表单标签进行全面的介绍,让我们首先从<form:form>标签开始吧。

form标签
    和使用任何JSP扩展标签一样,在使用Spring表单标签之前,你必须在JSP页面中添加一行引用Spring表单标签的声明,如下所示:

Jsp代码 复制代码

  1. <%@ page language=”java” contentType=”text/html; charset=UTF-8” pageEncoding=”UTF-8”%>   
  2. <%@ taglib prefix=”form” uri=”http://www.springframework.org/tags/form”%> ①引入标签的声明   
  3. <html>   
  4. … ②声明后,在页面中就可以使用任意Spring表单标签了   
  5. </html>   

Jsp代码   收藏代码
  1. <%@ page language=“java” contentType=“text/html; charset=UTF-8” pageEncoding=“UTF-8”%>  
  2. <%@ taglib prefix=”form” uri=“http://www.springframework.org/tags/form”%> ①引入标签的声明  
  3. <html>  
  4. … ②声明后,在页面中就可以使用任意Spring表单标签了  
  5. </html>   
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> ①引入标签的声明
<html>
… ②声明后,在页面中就可以使用任意Spring表单标签了
</html> 


    一般情况下,我们使用“form”作为Spring MVC表单标签的前缀,当然只要愿意,你可以调整为其它的前缀名。在声明好标签引用后,就可以在该JSP文件中使用所有Spring MVC的表单标签了。下面是一个使用<form:form>表单标签的示例,它将最终生成一个HTML的 form表单:

Jsp代码 复制代码

  1. <form:form>   
  2. 用户名:<form:input path=”userName” /> <br>   
  3. 密 码:<form:password path=”password” /><br>   
  4. Email:<form:input path=”email” /><br>   
  5. <input type=”submit” value=”注册” name=”testSubmit”/>   
  6. <input type=”reset” value=”重置” />   
  7. </form:form>  

Jsp代码   收藏代码
  1. <form:form>  
  2. 用户名:<form:input path=”userName” /> <br>  
  3. 密 码:<form:password path=”password” /><br>  
  4. Email:<form:input path=”email” /><br>  
  5. <input type=”submit” value=“注册” name=“testSubmit”/>  
  6. <input type=”reset” value=“重置” />  
  7. </form:form>  
<form:form>
用户名:<form:input path="userName" /> <br>
密 码:<form:password path="password" /><br>
Email:<form:input path="email" /><br>
<input type="submit" value="注册" name="testSubmit"/>
<input type="reset" value="重置" />
</form:form>


     回忆一下我们在《Spring MVC的表单控制器》(http://tech.it168.com/j/2007-07-26/200707261434046.shtml)文章中介绍的用户注册表单控制器,用户通过GET请求调用表单控制器时,表单控制器生成一个新的表单对象,然后重定向到表单输入页面。正因为表单页面是通过访问表单控制器导向过来的,所以<form:form>标签本身无需做额外的设置就可以达到以下两个目标:
    1) 它不需要象HTML的<form>标签或Struts的表单标签一样通过action属性指定表单提交的地址。假设和<form:form>标签对应的控制器的URL是“/registerUser.html”,应用部署目录为“baobaotao”,则最后产生的HTML代码自动包含表单提交地址:
<form id=”command” method=”post” action=”/baobaotao//registerUser.html”>…</form>
    2) <form:form>标签内部的组件标签(如<form:input>、<form:password>等)可以直接和表单控制器所对应的表单对象进行值绑定。

    默认情况下,表单控制器将表单对象以“command”为名放到PageContext中,你可以通过表单控制器commandName属性的设置使用其它的名字(假设设置为“user”),这时你必须通过<form:form commandName=”user”>显式指定绑定的表单对象名称。

    除了commandName属性外,Spring表单标签拥有丰富的可设置属性,这些属性大都是HTML表单标签属性的镜像,如onclick、ondblclick、tabindex等等。需要注意的一点是这些属性都是小写的,而对应的HTML标签的属性则没有这个限制。但是有几个和HTML标签有区别的属性,我们通过表 1进行说明:
    表 1 表单元素标签特殊属性

——————–
目录    |    说明
——————–
cssClass  |  使用该属性指定表单元素CSS样式名,相当于HTML元素的class属性。示例:<form:input path=”userName” cssClass=”inputStyle”/>。

cssStyle  |  直接通过该属性指定样式,相当于HTML元素的style属性。示例:
<form:input path=”userName” cssStyle=”width:100px”/>。

cssErrorClass  |  cssClass表示表单元素未发生错误时对应的样式,而cssErrorClass表示表单元素发生错误时对应的样式,示例:
<form:input path=”userName” cssClass=”sty1” cssErrorClass= “sty2”/>
——————–

输入组件标签
    表单中有一些用于接受输入值的组件,如单行文本框、多行文本框以及密码框,Spring为它们提供了对应的表单标签,请看下面的例子:
代码清单 1 使用输入组件标签的表单

Jsp代码 复制代码

  1. <form:form>   
  2. 用户名:<form:input path=”userName” /> <br> ①单行文件框标签   
  3. 密 码:<form:password path=”password” /><br> ②密码框标签   
  4. 描 述:<form:textarea path=”desc” cols=”20” rows=”3”/><br> ③多行文件框标签   
  5. <form:hidden path=”times”/> ④隐藏组件的值   
  6. <input type=”submit” value=”注册” name=”testSubmit”/>   
  7. <input type=”reset” value=”重置” />   
  8. </form:form>   

Jsp代码   收藏代码
  1. <form:form>  
  2. 用户名:<form:input path=”userName” /> <br> ①单行文件框标签  
  3. 密 码:<form:password path=”password” /><br> ②密码框标签  
  4. 描 述:<form:textarea path=”desc” cols=“20” rows=“3”/><br> ③多行文件框标签  
  5. <form:hidden path=”times”/> ④隐藏组件的值  
  6. <input type=”submit” value=“注册” name=“testSubmit”/>  
  7. <input type=”reset” value=“重置” />  
  8. </form:form>   
<form:form>
用户名:<form:input path="userName" /> <br> ①单行文件框标签
密 码:<form:password path="password" /><br> ②密码框标签
描 述:<form:textarea path="desc" cols="20" rows="3"/><br> ③多行文件框标签
<form:hidden path="times"/> ④隐藏组件的值
<input type="submit" value="注册" name="testSubmit"/>
<input type="reset" value="重置" />
</form:form> 


    正如你看到的,所有表单组件标签都通过path属性绑定表单对象的属性值,它支持级联属性,比如path=”user.userName”将调用表单对象getUser.getUserName()绑定表单对象的属性值。这些表单组件标签拥有大多数HTML组件标签的镜像属性,如③处的<form:textarea>就使用了cols和rows属性设定列数和行数。

以上使用表单标签的页面的对应HTML页面如下所示:

Jsp代码 复制代码

  1. <form id=”command” method=”post” action=”/baobaotao//registerUser.html”>   
  2. 用户名:<input id=”userName” name=”userName” type=”text” value=”“/><br>   
  3. 密 码: <input id=”password” name=”password” type=”password” value=”“/><br>   
  4. 描 述:<textarea id=”desc” name=”desc” rows=”3” cols=”20”></textarea><br>   
  5. <input id=”times” name=”times” type=”hidden” value=”0”/>   
  6. <input type=”submit” value=”注册” name=”testSubmit”/>   
  7. <input type=”reset” value=”重置” />   
  8. </form>   

Jsp代码   收藏代码
  1. <form id=“command” method=“post” action=“/baobaotao//registerUser.html”>  
  2. 用户名:<input id=”userName” name=“userName” type=“text” value=“”/><br>  
  3. 密 码: <input id=”password” name=“password” type=“password” value=“”/><br>  
  4. 描 述:<textarea id=”desc” name=“desc” rows=“3” cols=“20”></textarea><br>  
  5. <input id=”times” name=“times” type=“hidden” value=“0”/>  
  6. <input type=”submit” value=“注册” name=“testSubmit”/>  
  7. <input type=”reset” value=“重置” />  
  8. </form>   
<form id="command" method="post" action="/baobaotao//registerUser.html">
用户名:<input id="userName" name="userName" type="text" value=""/><br>
密 码: <input id="password" name="password" type="password" value=""/><br>
描 述:<textarea id="desc" name="desc" rows="3" cols="20"></textarea><br>
<input id="times" name="times" type="hidden" value="0"/>
<input type="submit" value="注册" name="testSubmit"/>
<input type="reset" value="重置" />
</form> 



单选框和复选框组件标签
    单选框和复选框组件虽然在HTML中都对应<input>元素标签,但在Spring MVC表单标签中,它们分别对应两个更达意的标签:   

Jsp代码 复制代码

  1. <form:radiobutton>和<form:checkbox>。   
  2. radiobutton   
  3. 单选框组件由两个同名的标签组件组成,当表单对象对应属性值和value值相等时,单选框选中。下面是一个代表性别的单选框:   
  4. <form:form>   
  5. 性 别:<form:radiobutton path=”sex” value=”0”/>男   
  6. <form:radiobutton path=”sex” value=”1”/>女   
  7. </form:form>   
  8. 当表单对象的sex属性为0时(可以是String、int等可以自动转换为String的类型),所生成的HTML代码如下所示:   
  9. <form id=”command” method=”post” action=”/baobaotao//registerUser.html”>   
  10. 性 别:<input id=”sex1” name=”sex” type=”radio” value=”0” checked=”checked”/>男   
  11. <input id=”sex2” name=”sex” type=”radio” value=”1”/>女   
  12. </form>    

Jsp代码   收藏代码
  1. <form:radiobutton>和<form:checkbox>。  
  2. radiobutton  
  3. 单选框组件由两个同名的标签组件组成,当表单对象对应属性值和value值相等时,单选框选中。下面是一个代表性别的单选框:  
  4. <form:form>  
  5. 性 别:<form:radiobutton path=”sex” value=“0”/>男  
  6. <form:radiobutton path=”sex” value=“1”/>女  
  7. </form:form>  
  8. 当表单对象的sex属性为0时(可以是String、int等可以自动转换为String的类型),所生成的HTML代码如下所示:  
  9. <form id=”command” method=“post” action=“/baobaotao//registerUser.html”>  
  10. 性 别:<input id=”sex1” name=“sex” type=“radio” value=“0” checked=“checked”/>男  
  11. <input id=”sex2” name=“sex” type=“radio” value=“1”/>女  
  12. </form>    
<form:radiobutton>和<form:checkbox>。
radiobutton
单选框组件由两个同名的标签组件组成,当表单对象对应属性值和value值相等时,单选框选中。下面是一个代表性别的单选框:
<form:form>
性 别:<form:radiobutton path="sex" value="0"/>男
<form:radiobutton path="sex" value="1"/>女
</form:form>
当表单对象的sex属性为0时(可以是String、int等可以自动转换为String的类型),所生成的HTML代码如下所示:
<form id="command" method="post" action="/baobaotao//registerUser.html">
性 别:<input id="sex1" name="sex" type="radio" value="0" checked="checked"/>男
<input id="sex2" name="sex" type="radio" value="1"/>女
</form>  



checkbox
    复选框组件标签相对来说复杂一些,复选框组件对应的表单属性不但可以boolean类型,还可以是String[]、Collection,Enum等类型。针对不同属性类型,复选框的选中状态的判断条件是不一样的:
 boolean类型:当对应属性为true时,该复选框选中(一个属性仅对应一个复选框);
 String[]、Collection或Enum类型:复选框对应值出现在对应属性列表中,该复选框选中;
 其它类型:当复选框对应的值可以转换为对应属性值,该复选框选中。
假设用户注册的User表单对象包含了一个List类型的favorites属性:

Java代码 复制代码

  1. import java.util.List;    
  2. public class User {    
  3. private List favorites;    
  4. public List getFavorites() {    
  5. return favorites;    
  6. }    
  7. public void setFavorites(List favorites) {    
  8. this.favorites = favorites;    
  9. }    
  10. }   

Java代码   收藏代码
  1. import java.util.List;   
  2. public class User {   
  3. private List favorites;   
  4. public List getFavorites() {   
  5. return favorites;   
  6. }   
  7. public void setFavorites(List favorites) {   
  8. this.favorites = favorites;   
  9. }   
  10. }   
import java.util.List; 
public class User { 
private List favorites; 
public List getFavorites() { 
return favorites; 
} 
public void setFavorites(List favorites) { 
this.favorites = favorites; 
} 
} 


我们希望将其在页面中使用一个复选框组件绑定这个属性,则可以使用以下的代码:
代码清单 2 复选框标签的使用

Jsp代码 复制代码

  1. <form:form>    
  2. 兴趣爱好:    
  3. <form:checkbox path=”favorites” value=”1”/>computer    
  4. <form:checkbox path=”favorites” value=”2”/>sport    
  5. <form:checkbox path=”favorites” value=”3”/>entertainment    
  6. <form:checkbox path=”favorites” value=”4”/>literature    
  7. </form:form>   

Jsp代码   收藏代码
  1. <form:form>   
  2. 兴趣爱好:   
  3. <form:checkbox path=”favorites” value=“1”/>computer   
  4. <form:checkbox path=”favorites” value=“2”/>sport   
  5. <form:checkbox path=”favorites” value=“3”/>entertainment   
  6. <form:checkbox path=”favorites” value=“4”/>literature   
  7. </form:form>   
<form:form> 
兴趣爱好: 
<form:checkbox path="favorites" value="1"/>computer 
<form:checkbox path="favorites" value="2"/>sport 
<form:checkbox path="favorites" value="3"/>entertainment 
<form:checkbox path="favorites" value="4"/>literature 
</form:form> 


除了正常的path属性名外,还必须提供一个value属性,假设User表单对象的favorites属性包括了1和3的值,那么产生的HTML页面为:

Html代码 复制代码

  1. <form id=”command” method=”post” action=”/baobaotao//registerUser.html”>    
  2. 兴趣爱好:<input id=”favorites1” name=”favorites” type=”checkbox” value=”1” checked=”checked”/>    
  3. <input type=”hidden” value=”1” name=”_favorites”/>computer    
  4. <input id=”favorites2” name=”favorites” type=”checkbox” value=”2” />    
  5. <input type=”hidden” value=”1” name=”_favorites”/>sport    
  6. <input id=”favorites3” name=”favorites” type=”checkbox” value=”3” checked=”checked”/>    
  7. <input type=”hidden” value=”1” name=”_favorites”/>entertainment    
  8. <input id=”favorites4” name=”favorites” type=”checkbox” value=”4”/>    
  9. <input type=”hidden” value=”1” name=”_favorites”/>literature    
  10. </form>   

Html代码   收藏代码
  1. <form id=“command” method=“post” action=“/baobaotao//registerUser.html”>   
  2. 兴趣爱好:<input id=“favorites1” name=“favorites” type=“checkbox” value=“1” checked=“checked”/>   
  3. <input type=“hidden” value=“1” name=“_favorites”/>computer   
  4. <input id=“favorites2” name=“favorites” type=“checkbox” value=“2” />   
  5. <input type=“hidden” value=“1” name=“_favorites”/>sport   
  6. <input id=“favorites3” name=“favorites” type=“checkbox” value=“3” checked=“checked”/>   
  7. <input type=“hidden” value=“1” name=“_favorites”/>entertainment   
  8. <input id=“favorites4” name=“favorites” type=“checkbox” value=“4”/>   
  9. <input type=“hidden” value=“1” name=“_favorites”/>literature   
  10. </form>   
<form id="command" method="post" action="/baobaotao//registerUser.html"> 
兴趣爱好:<input id="favorites1" name="favorites" type="checkbox" value="1" checked="checked"/> 
<input type="hidden" value="1" name="_favorites"/>computer 
<input id="favorites2" name="favorites" type="checkbox" value="2" /> 
<input type="hidden" value="1" name="_favorites"/>sport 
<input id="favorites3" name="favorites" type="checkbox" value="3" checked="checked"/> 
<input type="hidden" value="1" name="_favorites"/>entertainment 
<input id="favorites4" name="favorites" type="checkbox" value="4"/> 
<input type="hidden" value="1" name="_favorites"/>literature 
</form> 



大家可能已经注意到每个复选框组件的后台都跟着一个隐藏组件,这是因为当HTML页面中的复选框没有被选中时,这个复选框的值不会在表单提交时作为HTTP请求参数发送到服务器端,这给Spring的表单数据绑定造成了麻烦——因为无法触发setFavorites()方法的调用(如果原来已经有值,这个值不会被设置为空)。解决方法就是在每个复选框后面加一个隐藏组件,并且将对应的复选框名字前添加一个下划线(”_”)作为隐藏组件的名字。这样一来,你相当于告诉Spring“这个表单中存在这样一个复选框,我希望表单对象中对应的属性和这个checkbox的状态保持一致”。
假设复选框对应的选项在数据库或配置文件中定义,那么页面复选框标签就不能通过硬编码的方式指定,相反必须根据配置的选项数据动态产生。对于这样的需求,代码清单 2的编写方式显然不能满足需求。回忆一下表单控制器的工作流程,我们知道可以通过复写referenceData()方法在表单显示前准备一些需要的数据,现在终于派上用场了,来看一下具体的实现:

代码清单 3 UserRegisterController:准备表单显示数据

Java代码 复制代码

  1. package com.baobaotao.web.user;   
  2. …   
  3. import org.springframework.ui.ModelMap;   
  4. public class UserRegisterController extends SimpleFormController {   
  5. private BbtForum bbtForum;   
  6. ①创建初始表单对象   
  7. protected Object formBackingObject(HttpServletRequest request)   
  8. throws Exception {   
  9. int userId = ServletRequestUtils.getIntParameter(request, ”userId”,-1);   
  10. User user = bbtForum.getUser(userId);   
  11. user.setUserName(”tom”);   
  12. List favorites = new ArrayList();①-1默认选中值为13的选项   
  13. favorites.add(”1”);   
  14. favorites.add(”3”);   
  15. user.setFavorites(favorites);   
  16. return user;   
  17. }   
  18. @Override ②准备表单显示时需要的数据   
  19. protected Map referenceData(HttpServletRequest request) throws Exception {   
  20. Map favoriteMap = new LinkedHashMap();   
  21. favoriteMap.put(”1””computer”);   
  22. favoriteMap.put(”2””sport”);   
  23. favoriteMap.put(”3””entertainment”);   
  24. favoriteMap.put(”4””literature”);   
  25. ②-1将表单页面需要的对象以ModelMap返回,最终将以属性名值对方式出现在请求属性中   
  26. return new ModelMap().addObject(”favoriteMap”, favoriteMap);   
  27. }   
  28. @Override  
  29. protected ModelAndView onSubmit(Object command, BindException errors)   
  30. throws Exception {   
  31. User user = (User) command;   
  32. bbtForum.registerUser(user);   
  33. return new ModelAndView(getSuccessView(), ”user”, user);   
  34. }   
  35. }   

Java代码   收藏代码
  1. package com.baobaotao.web.user;  
  2. …  
  3. import org.springframework.ui.ModelMap;  
  4. public class UserRegisterController extends SimpleFormController {  
  5. private BbtForum bbtForum;  
  6. ①创建初始表单对象  
  7. protected Object formBackingObject(HttpServletRequest request)  
  8. throws Exception {  
  9. int userId = ServletRequestUtils.getIntParameter(request, “userId”,-1);  
  10. User user = bbtForum.getUser(userId);  
  11. user.setUserName(”tom”);  
  12. List favorites = new ArrayList();①-1默认选中值为13的选项  
  13. favorites.add(”1”);  
  14. favorites.add(”3”);  
  15. user.setFavorites(favorites);  
  16. return user;  
  17. }  
  18. @Override ②准备表单显示时需要的数据  
  19. protected Map referenceData(HttpServletRequest request) throws Exception {  
  20. Map favoriteMap = new LinkedHashMap();  
  21. favoriteMap.put(”1”“computer”);  
  22. favoriteMap.put(”2”“sport”);  
  23. favoriteMap.put(”3”“entertainment”);  
  24. favoriteMap.put(”4”“literature”);  
  25. ②-1将表单页面需要的对象以ModelMap返回,最终将以属性名值对方式出现在请求属性中  
  26. return new ModelMap().addObject(“favoriteMap”, favoriteMap);  
  27. }  
  28. @Override  
  29. protected ModelAndView onSubmit(Object command, BindException errors)  
  30. throws Exception {  
  31. User user = (User) command;  
  32. bbtForum.registerUser(user);  
  33. return new ModelAndView(getSuccessView(), “user”, user);  
  34. }  
  35. }   
package com.baobaotao.web.user;
…
import org.springframework.ui.ModelMap;
public class UserRegisterController extends SimpleFormController {
private BbtForum bbtForum;
①创建初始表单对象
protected Object formBackingObject(HttpServletRequest request)
throws Exception {
int userId = ServletRequestUtils.getIntParameter(request, "userId",-1);
User user = bbtForum.getUser(userId);
user.setUserName("tom");
List favorites = new ArrayList();①-1默认选中值为1和3的选项
favorites.add("1");
favorites.add("3");
user.setFavorites(favorites);
return user;
}
@Override ②准备表单显示时需要的数据
protected Map referenceData(HttpServletRequest request) throws Exception {
Map favoriteMap = new LinkedHashMap();
favoriteMap.put("1", "computer");
favoriteMap.put("2", "sport");
favoriteMap.put("3", "entertainment");
favoriteMap.put("4", "literature");
②-1将表单页面需要的对象以ModelMap返回,最终将以属性名值对方式出现在请求属性中
return new ModelMap().addObject("favoriteMap", favoriteMap);
}
@Override
protected ModelAndView onSubmit(Object command, BindException errors)
throws Exception {
User user = (User) command;
bbtForum.registerUser(user);
return new ModelAndView(getSuccessView(), "user", user);
}
} 



在以上代码中我们覆盖了SimpleFormController的referenceData()和formBackingObject ()方法。参照《Spring MVC的表单控制器》中(http://tech.it168.com/j/2007-07-26/200707261434046.shtml)介绍的表单控制器工作流程,可以知道formBackingObject()方法用于表单页面初始化时使用的表单对象。我们在formBackingObject()方法中,将User的favorites属性的初始值设置为1和3(分别对应computer和entertainment的选项),如①所示。
在②处,我们覆盖了referenceData()方法,该方法为表单页面准备一些数据。该方法返回值类型为Map,该Map的键值将会绑定到请求的属性中。ModelMap是Spring 2.0新增的Map实现类,它提供了链式方法和默认键值的机制。这里,我们使用ModelMap绑定了一个键为“favoriteMap”,值为favoriteMap的数据对象。favoriteMap是所有兴趣爱好的选项,在实际的应用中,你可以从数据库中或配置文件中进行加载。
当请求中绑定了favoriteMap时,对应的表单页面就可以遍历该Map并动态构造出复选框列表了:

Jsp代码 复制代码

  1. <%@ page language=”java” contentType=”text/html; charset=UTF-8” pageEncoding=”UTF-8”%>   
  2. <%@ taglib prefix=”form” uri=”http://www.springframework.org/tags/form”%>   
  3. <%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c”%>   
  4. <html>   
  5. <head>   
  6. <title>宝宝淘论坛用户注册</title>   
  7. </head>   
  8. <body>   
  9. <form:form>   
  10. …   
  11. 兴趣爱好:   
  12. <c:forEach items=”${favoriteMap}” var=”favorite”>①引用favoriteMap的请求属性   
  13. ②引用Map的键和值   
  14. <form:checkbox path=”favorites” value={favorite.key}"</span></span><span>&nbsp;/&gt;{favorite.value}   
  15. </c:forEach>   
  16. <input type=”submit” value=”注册” name=”testSubmit”/>   
  17. <input type=”reset” value=”重置” />   
  18. </form:form>   
  19. </body>   
  20. </html>   

Jsp代码   收藏代码
  1. <%@ page language=“java” contentType=“text/html; charset=UTF-8” pageEncoding=“UTF-8”%>  
  2. <%@ taglib prefix=”form” uri=“http://www.springframework.org/tags/form”%>  
  3. <%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=“c”%>  
  4. <html>  
  5. <head>  
  6. <title>宝宝淘论坛用户注册</title>  
  7. </head>  
  8. <body>  
  9. <form:form>  
  10. …  
  11. 兴趣爱好:  
  12. <c:forEach items={favoriteMap}"</span><span>&nbsp;var=</span><span class="string">"favorite"</span><span>&gt;①引用favoriteMap的请求属性&nbsp;&nbsp;</span></span></li><li><span>②引用Map的键和值&nbsp;&nbsp;</span></li><li><span>&lt;form:checkbox&nbsp;path=<span class="string">"favorites"</span><span>&nbsp;value=</span><span class="string">"{favorite.key}” />${favorite.value}  
  13. </c:forEach>  
  14. <input type=”submit” value=“注册” name=“testSubmit”/>  
  15. <input type=”reset” value=“重置” />  
  16. </form:form>  
  17. </body>  
  18. </html>   
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>宝宝淘论坛用户注册</title>
</head>
<body>
<form:form>
…
兴趣爱好:
<c:forEach items="${favoriteMap}" var="favorite">①引用favoriteMap的请求属性
②引用Map的键和值
<form:checkbox path="favorites" value="${favorite.key}" /&gt;${favorite.value}
</c:forEach>
<input type="submit" value="注册" name="testSubmit"/>
<input type="reset" value="重置" />
</form:form>
</body>
</html> 



    在①处,我们通过JSTL标签对属性名为favoriteMap的模型数据对象进行遍历,为每一个元素项生成一个复选框。注意②处的复选框代码,它有两个明显的特征:1)使用Spring复选框标签;2)通过EL引用Map类型的模型数据。由于favorite是Map类型,所以我们可以通过 favorite.key {favorite.value}引用Map元素的键和值。

    提示:
    对于同时使用JSTL和Spring表单标签的JSP文件,JSTL的标签会被首先解析,然后再解析Spring表单标签,因此如实例那样混合使用二者可以如预期一样输出正确的结果。

下拉框组件标签
    下拉框标签的典型形式为: <form:select path=”city” items=”${cityList}”/>,它包括两方面的数据:1)对应表单对象属性值(city);2)用于构造整个下拉框选项的数据(cityList)。严格地说,下拉框组件分为单选和多选两种形式,当表单对象对应属性为复数形态的类型时(如String[]、List、Set),产生的目标组件为多选下拉框,反之为单选下拉框。
用于构造下拉框选项的数据也必须在referenceData()方法中准备好(可能从数据库字典表中加载或从外部配置文件中加载):
代码清单 4 UserRegisterController:为下拉框标签准备数据

Java代码 复制代码

  1. package com.baobaotao.web.user;   
  2. …   
  3. public class UserRegisterController extends SimpleFormController {   
  4. @Override  
  5. protected Map referenceData(HttpServletRequest request) throws Exception {   
  6. Map favoriteMap = new LinkedHashMap();   
  7. favoriteMap.put(”1””computer”);   
  8. favoriteMap.put(”2””sport”);   
  9. favoriteMap.put(”3””entertainment”);   
  10. favoriteMap.put(”4””literature”);   
  11. List cityList = new ArrayList();①为下拉框选项准备的数据   
  12. cityList.add(”北京”);   
  13. cityList.add(”上海”);   
  14. cityList.add(”天津”);   
  15. cityList.add(”厦门”);   
  16. return new ModelMap()   
  17. .addObject(”favoriteMap”, favoriteMap)   
  18. .addObject(”cityList”, cityList);   
  19. }   
  20. …   
  21. }  

Java代码   收藏代码
  1. package com.baobaotao.web.user;  
  2. …  
  3. public class UserRegisterController extends SimpleFormController {  
  4. @Override  
  5. protected Map referenceData(HttpServletRequest request) throws Exception {  
  6. Map favoriteMap = new LinkedHashMap();  
  7. favoriteMap.put(”1”“computer”);  
  8. favoriteMap.put(”2”“sport”);  
  9. favoriteMap.put(”3”“entertainment”);  
  10. favoriteMap.put(”4”“literature”);  
  11. List cityList = new ArrayList();①为下拉框选项准备的数据  
  12. cityList.add(”北京”);  
  13. cityList.add(”上海”);  
  14. cityList.add(”天津”);  
  15. cityList.add(”厦门”);  
  16. return new ModelMap()  
  17. .addObject(”favoriteMap”, favoriteMap)  
  18. .addObject(”cityList”, cityList);  
  19. }  
  20. …  
  21. }  
package com.baobaotao.web.user;
…
public class UserRegisterController extends SimpleFormController {
@Override
protected Map referenceData(HttpServletRequest request) throws Exception {
Map favoriteMap = new LinkedHashMap();
favoriteMap.put("1", "computer");
favoriteMap.put("2", "sport");
favoriteMap.put("3", "entertainment");
favoriteMap.put("4", "literature");
List cityList = new ArrayList();①为下拉框选项准备的数据
cityList.add("北京");
cityList.add("上海");
cityList.add("天津");
cityList.add("厦门");
return new ModelMap()
.addObject("favoriteMap", favoriteMap)
.addObject("cityList", cityList);
}
…
}



这时,生成的下拉框HTML代码如下所示:

Html代码 复制代码

  1. <select id=”city” name=”city” > ①   
  2. <option value=”北京”>北京</option>  
  3. <option value=”上海”>上海</option>  
  4. <option value=”天津”>天津</option>  
  5. <option value=”厦门”>厦门</option>  
  6. </select>  
  7. <input type=”hidden” name=”_city” value=”1”/> ②   

Html代码   收藏代码
  1. <select id=“city” name=“city” > ①  
  2. <option value=“北京”>北京</option>  
  3. <option value=“上海”>上海</option>  
  4. <option value=“天津”>天津</option>  
  5. <option value=“厦门”>厦门</option>  
  6. </select>  
  7. <input type=“hidden” name=“_city” value=“1”/> ②   
<select id="city" name="city" > ①
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="天津">天津</option>
<option value="厦门">厦门</option>
</select>
<input type="hidden" name="_city" value="1"/> ② 




    首先,我们注意到②处有一个和复选框组件相似的配套隐藏组件,之所以会需要这个隐藏组件是出于和复选框相同的原因。下拉框的值和标签是相同的,都是cityList列表中的元素值。在实际应用中,我们一般为每一个选项提供一个代码,而非采用和标签相同的值,这样可以使用规范简短的代码保存数据,为后续的查询、引用带来方便。这时,可以采用下拉框标签的另一种属性设置方式:
<form:select path=”city” items=”{cityMap}" itemValue="key" itemLabel="value"/&gt; <br>cityMap是一个已经通过referenceData()方法准备好的Map对象,itemValue对应下拉框的value属性,而itemValue="key"表示使用cityMap元素的键,itemLable对应下拉框的标签值, itemLabel="value"表示使用cityMap元素的值。实际上,items属性所绑定的也可以是一个List对象,其元素可以是一个JavaBean,这时可以通过itemValue和itemLabel指定引用JavaBean的属性。如下所示: <br>&lt;form:select path="city" items="{cities}” itemValue=”code” itemLabel=”name”/>
cities对应一个通过referenceData()方法准备好的List对象,其元素为City对象,City对象包括code和name两个属性。通过以上这些方式,我们可以得到一个选项的值和标签不相同的下拉框:
<select id=”city” name=”city”>
<option value=”1”>北京</option>
<option value=”2”>上海</option>
<option value=”3”>天津</option>
<option value=”4” >厦门</option>
</select>
<input type=”hidden” name=”_city” value=”1”/>
一般情况下,下拉框会提供一个类似于“请选择”或“–未选择–”的默认选项,这个选项本身不是有效的数据项,它们的存在仅仅为提示用户作选择或代表一个未作选择的空值。这时,我们可能会考虑手工提供一个下拉框选项,而其它的选项通过referenceData()提供的数据动态生成:
<form:select path=”city”>
<form:option value=”” label=”–请选择–”/> ①提示性的选项
<form:options items=”${cityMap}” itemValue=”key” itemLabel=”value”/>②真实的选项数据
</form:select>
这样产生的下拉框在默认情况下将显示①处对应的选项,如果用户没有选择,选项相当于是一个空值。②处对应的<form:options>会将cityMap的数据转换为下拉框选项列表。


错误标签
    错误标签是和服务端校验信息关联的对应物,假设在服务端通过以下代码对表单数据进行校验:
ValidationUtils.rejectIfEmptyOrWhitespace(errors, “userName”,”required.username”, “用户名必须填写”);
ValidationUtils.rejectIfEmptyOrWhitespace(errors, “password”,”required.password”, “密码不能为空”);

    当提交的表单数据不合法引发校验错误时,提交的表单将被驳回,请求被重定向到表单输入页面,在该页面中通过

Jsp代码 复制代码

  1. <form:errors>标签就可以显示出校验的错误信息:   
  2. <form:form>   
  3. 用户名:<form:input path=”userName” cssClass=”inputStyle” cssErrorClass=”asdfe”/>   
  4. <font color=”red”><form:errors path=”userName” /></font>   
  5. <br>   
  6. 密 码:<form:password path=”password” />   
  7. <font color=”red”><form:errors path=”password” /></font>   
  8. <br>   
  9. </form:form>   

Jsp代码   收藏代码
  1. <form:errors>标签就可以显示出校验的错误信息:  
  2. <form:form>  
  3. 用户名:<form:input path=”userName” cssClass=“inputStyle” cssErrorClass=“asdfe”/>  
  4. <font color=”red”><form:errors path=“userName” /></font>  
  5. <br>  
  6. 密 码:<form:password path=”password” />  
  7. <font color=”red”><form:errors path=“password” /></font>  
  8. <br>  
  9. </form:form>   
<form:errors>标签就可以显示出校验的错误信息:
<form:form>
用户名:<form:input path="userName" cssClass="inputStyle" cssErrorClass="asdfe"/>
<font color="red"><form:errors path="userName" /></font>
<br>
密 码:<form:password path="password" />
<font color="red"><form:errors path="password" /></font>
<br>
</form:form> 



    通过path和表单对象特定属性错误信息进行绑定,一个表单对象属性可能包括一个或多个错误信息,也可以没有错误信息,<form:errors>会根据错误信息的情况进行合理的展示。此外,path还支持通配符匹配的表示方式:
 path=”*”: 显示所有的错误信息;
 path=”lastName*”: 显示所有属性名前缀为lastName的错误信息。

小结
    在Spring 2.0中,新增的表单标签是Spring MVC的一个显著的升级,它可以绑定服务端的表单对象,让页面数据的渲染工作变得轻松。因为Spring MVC框架本身的优越性,使得许多Spring MVC表单标签无需进行过多的属性设置就可以正确使用,因此相比于Struts的表单标签,Spring MVC在使用上更加方便,更加轻松。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值