码迷,mamicode.com
首页 > 编程语言 > 详细

SpringMVC学习记录(五)--表单标签

时间:2018-01-17 22:02:33      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:err   后台   script   errors   种类型   lang   注入   art   erro   

在使用SpringMVC的时候我们能够使用Spring封装的一系列表单标签,这些标签都能够訪问到ModelMap中的内容。

以下将对这些标签一一介绍。


1.引入标签头文件

在正式介绍SpringMVC的表单标签之前,我们须要先在JSP中声明使用的标签。详细做法是在JSP文件的顶部加入以下指令:

<%@taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>

2.form标签

使用Spring的form标签主要有两个作用。第一是它会自己主动的绑定来自Model中的一个属性值到当前form相应的实体对象。默认是command属性(一般都用modelAttribute,两者本质上没有差别),这样我们就能够在form表单体里面方便的使用该对象的属性了;第二是它支持我们在提交表单的时候使用除GET和POST之外的其它方法进行提交,包括DELETE和PUT等。

  • 代码实例
        // 这里使用modelAttribute换成commandName也是一样的效果
 <sf:form action="formTag/form.do" method="post" modelAttribute="user">
    <table>
        <tr>
            <td>Name:</td><td><form:input path="name"/></td>
        </tr>
        <tr>
            <td>Age:</td><td><form:input path="age"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</sf:form>

这个时候假设Model中存在一个属性名称为user的javaBean,而且该javaBean拥有属性name和age的时候。在渲染上面的代码时就会取command的相应属性值赋给相应标签的值。

如在上面的代码中,假设Model中存在一个属性名称为user的javaBean,且它的name和age属性分别为“Zhangsan”和“36”时。那么它在渲染时就会生成例如以下一段代码:

<form id="user" action="formTag/form.do" method="post">
    <table>
        <tr>
            <td>Name:</td><td><input id="name" name="name" type="text" value="ZhangSan"/></td>
        </tr>
        <tr>
            <td>Age:</td><td><input id="age" name="age" type="text" value="36"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form>

从上面生成的代码中。我们能够看出,当没有指定form标签的id时它会自己主动获取该form标签绑定的Model中相应属性名称作为id,而对于input标签在没有指定id的情况下它会自己主动获取path指定的属性作为id和name。

2.支持隐藏域请求

看以下代码,我们能够把form的method设为delete

<form:form action="formTag/form.do" method="delete" modelAttribute="user">
    <table>
        <tr>
            <td>Name:</td><td><form:input path="name"/></td>
        </tr>
        <tr>
            <td>Age:</td><td><form:input path="age"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

在上面代码中我们设定了该form的提交方法是delete,这样在后台我们就能够给相应的请求方法的RequestMapping加上method为RequestMethod.DELETE的限制。

我们来看一下上面的代码在进行渲染的时候会生成怎样的Html代码,其生成的代码例如以下所看到的:

<form id="user" action="formTag/form.do" method="post">
    <input type="hidden" name="_method" value="delete"/>
    <table>
        <tr>
            <td>Name:</td><td><input id="name" name="name" type="text" value="ZhangSan"/></td>
        </tr>
        <tr>
            <td>Age:</td><td><input id="age" name="age" type="text" value="36"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form>

从它生成的代码我们能够看出,Spring在实现除GET和POST之外的请求方法时,还是使用的POST方法进行请求,然后给表单加上了一个隐藏域。用以表示真正的请求方法。这个隐藏域的名称默认是“_method”。

上面这样定义之后是不是就意味着我们能够以delete方式訪问到“formTag/form.do”了呢?答案是不行的。

这样定义我们仅仅是多加了一个用以表示请求方法的隐藏域而已,实际的请求方式还是POST。Spring为我们提供了一个Filter——HiddenHttpMethodFilter,通过这个Filter我们能够把以POST方式传递过来的表示实际请求方式的參数转换为相应的真正的Http请求方法。

所以这个时候我们还须要在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>

注意:HiddenHttpMethodFilter仅仅能对以POST方式进行传递的表示请求方式的隐藏域转换为真正的Http请求方式。当我们直接在form:form标签的method中使用除GET和POST方法以外的其它方法时,Spring会自己主动生成以POST方式进行传递的表单以及相应的隐藏域。所以当我们须要手动的设置表示请求方法的隐藏域时。我们就须要指定表单的请求方式为POST,为GET将不会生效。

<form:form action="formTag/form.do" method="post" modelAttribute="user">
    <input type="hidden" name="_method" value="head"/>
    <table>
        <tr>
            <td>Name:</td><td><form:input path="name"/></td>
        </tr>
        <tr>
            <td>Age:</td><td><form:input path="age"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

上面代码就是一个手动定义请求方式的隐藏域的演示样例。这里表示请求方式的隐藏域的名称默认是“_method”,假设不想使用这个默认值的话。我们也能够通过form:form标签的methodParam属性来指定。如以下这个演示样例:

<form:form action="formTag/form.do" method="post" methodParam="requestMethod" modelAttribute="user">
    <input type="hidden" name="requestMethod" value="head"/>
    <table>
        <tr>
            <td>Name:</td><td><form:input path="name"/></td>
        </tr>
        <tr>
            <td>Age:</td><td><form:input path="age"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

同一时候我们也要告诉HiddenHttpMethodFilter我们是使用哪个表单參数作为methodParam。所以我们须要在配置HiddenHttpMethodFilter的时候指明methodParam相应的值。

    <filter>
       <filter-name>hiddenHttpMethodFilter</filter-name>
       <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
       <init-param>
           <param-name>methodParam</param-name>
           <param-value>requestMethod</param-value>
       </init-param>
    </filter>
    <filter-mapping>
       <filter-name>hiddenHttpMethodFilter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

另外须要注意的是在有Multipart请求处理的时候HiddenHttpMethodFilter须要在Multipart处理之后运行。由于在处理Multipart时须要从POST请求体中获取參数。所以我们一般会在HiddenHttpMethodFilter之前设立一个MultipartFilter。MultipartFilter默认会去寻找一个名称为filterMultipartResolver的MultipartResolver bean对象来对当前的请求进行封装。所以当你定义的MultipartResolver的名称不为filterMultipartResolver的时候就须要在定义MultipartFilter的时候通过參数multipartResolverBeanName来指定。

    <filter>
       <filter-name>multipartFilter</filter-name>
       <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
       <init-param>
           <param-name>multipartResolverBeanName</param-name>
           <param-value>multipartResolver</param-value>
       </init-param>
    </filter>
    <filter-mapping>
       <filter-name>multipartFilter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
       <filter-name>hiddenHttpMethodFilter</filter-name>
       <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
       <init-param>
           <param-name>methodParam</param-name>
           <param-value>requestMethod</param-value>
       </init-param>
    </filter>
    <filter-mapping>
       <filter-name>hiddenHttpMethodFilter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

2.input标签

SpringMVC的input标签会被渲染为一个type为text的普通Html input标签。使用SpringMVC的input标签的唯一作用就是它能绑定表单数据。SpringMVC表单标签最大的优点就是它支持数据绑定,当我们的表单标签不须要绑定的数据的时候,我们应该使用普通的Html标签。

关于input标签绑定表单数据的方法已经在介绍form标签的时候顺带介绍过了,这里就不再过多的赘述了。

<form:form action="formTag/form.do" method="head" modelAttribute="user" methodParam="requestMethod">
    <table>
        <tr>
            <td>Name:</td><td><form:input path="name"/></td>
        </tr>
        <tr>
            <td>Age:</td><td><form:input path="age"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

3.hidden标签

hidden标签会被渲染为一个type为hidden的普通Html input标签。使用方法跟input标签一样,也能绑定表单数据,仅仅是它生成的是一个隐藏域。


4.checkbox标签

checkbox标签会被渲染为一个type为checkbox的普通HTML input标签。checkbox标签也是支持绑定数据的。

我们知道checkbox就是一个复选框,有选中和不选中两种状态。那么我们在使用checkbox标签的时候是怎样来设定它的状态的呢?checkbox标签的选中与否状态是依据它绑定的值来推断的

  • 绑定boolean数据
<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>Male:</td><td><form:checkbox path="male"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

看上面这段代码,这个时候假设我们在渲染该视图之前往ModelMap中加入了一个user属性。而且该user对象有一个类型为boolean的属性male,那么这个时候假设male属性为true则Male那一栏的复选框将会被选中。

  • 绑定列表数据
    这里的列表数据包括数组、List和Set。

    以下将以List为例讲一下checkbox是怎样依据绑定的列表数据来设定选中状态的。如今假设有一个类User。其有一个类型为List的属性roles。例如以下所看到的:

public class User {

    private List<String> roles;

    public List<String> getRoles() {
       return roles;
    }

    public void setRoles(List<String> roles) {
       this.roles = roles;
    }
}

那么当我们须要展现该User是否拥有某一个Role的时候,我们能够使用checkbox标签来绑定roles数据进行展现。当checkbox标签的value在我们绑定的列表数据中存在的时候该checkbox将为选中状态。来看以下一段代码:

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>Roles:</td>
            <td>
               <form:checkbox path="roles" value="role1"/>Role1<br/>
               <form:checkbox path="roles" value="role2"/>Role2<br/>
               <form:checkbox path="roles" value="role3"/>Role3
            </td>
        </tr>
    </table>
</form:form>

就上面代码而言就是当User拥有role1的时候相应的就会为选中状态。也就是说roles列表中包括role1的时候该checkbox就会为选中状态。

  • 绑定一个Object数据
    checkbox还支持绑定数据类型为Object的数据,这样的情况下Spring会拿所绑定对象数据的toString结果跟当前checkbox的value进行比較,假设能够进行匹配则该checkbox将为选中状态。


5.Checkboxes标签

相对于一个checkbox标签仅仅能生成一个相应的复选框而言,一个checkboxes标签将依据其绑定的数据生成N个复选框。checkboxes绑定的数据能够是数组、集合和Map。在使用checkboxes时我们有两个属性是必须指定的。一个是path,还有一个是items。Items表示当前要用来展现的项有哪些,而path所绑定的表单对象的属性表示当前表单对象拥有的项,即在items所展现的全部项中表单对象拥有的项会被设定为选中状态。先来看以下一段代码:

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
           <td>Roles:</td>
            <td>
               <form:checkboxes path="roles" items="${roleList}"/> 
            </td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

上面的JSP视图相应着例如以下的处理器方法:

    @RequestMapping(value="form", method=RequestMethod.GET)
    public String formTag(Map<String, Object> map) {
       User user = new User();
       List<String> roles = new ArrayList<String>();
       roles.add("role1");
       roles.add("role3");
       user.setRoles(roles);
       List<String> roleList = new ArrayList<String>();
       roleList.add("role1");
       roleList.add("role2");
       roleList.add("role3");
       map.put("user", user);
       map.put("roleList", roleList);
       return "formTag/form";
    }

从以上代码中我们能够看到我们放在ModelMap中的roleList对象有三个元素,各自是role1、role2和role3,而我们的表单对象User的roles属性仅仅拥有两个元素。各自是role1和role3,,所以当我们訪问该处理器方法返回如上所看到的的视图页面时,我们要展现的复选框项是roleList,也就是role1、role2和role3,而我们表单对象仅仅拥有role1和role3,所以在页面进行渲染的时候会展示3个复选框项。但仅仅有role1和role3会被设定为选中状态。


上面介绍的这样的情况是使用List作为展现复选框项的数据源。这样的情况我们已经看到了它所呈现出来的标签Label和它的值是一样的。使用Array和Set作为数据源也是这样的情况。那么假设要让checkboxes呈现出来的Label和实际上送的value不同的话应该怎么做呢?这个时候我们就能够使用Map作为数据源了。使用Map作为checkboxes的items属性的数据源时Key将作为真正的复选框的value,而Map的value将作为Label进行展示。

当使用Map作为checkboxes的items属性的数据源时我们绑定的表单对象属性的类型能够是Array、集合和Map,这样的情况就是推断items Map中是否含有相应的key来决定当前的复选框是否处于选中状态。我们来看以下一个处理器方法以及其相应的视图代码。

    @RequestMapping(value="form", method=RequestMethod.GET)
    public String formTag(Map<String, Object> map) {
       User user = new User();
       List<String> roles = new ArrayList<String>();
       roles.add("role1");
       roles.add("role3");
       user.setRoles(roles);
       Map<String, String> roleMap = new HashMap<String, String>();
       roleMap.put("role1", "角色1");
       roleMap.put("role2", "角色2");
       roleMap.put("role3", "角色3");
       map.put("user", user);
       map.put("roleMap", roleMap);
       return "formTag/form";
    }

相应的视图代码:

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>Roles:</td>
            <td>
               <form:checkboxes path="roles" items="${roleMap}"/>  
            </td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

这个时候我们知道会呈现出3个复选框。而checkboxes绑定的表单对象user的roles属性是一个集合对象,其包括的两个元素都能在checkboxes的items数据源中找到相应的Key,所以以这两个元素为value的checkbox将处于选中状态

当我们使用Array或者集合作为数据源,且里面的元素都是一个一个POJO时。我们还能够使用checkboxes标签的itemLabel和itemValue属性来表示使用数组或者集合中元素对象的哪一个属性作为须要呈现的单选框的label和value。


6.radiobutton标签

radiobutton标签会被渲染为一个type为radio的普通HTML input标签。radiobutton标签也是能够绑定数据的。

以下是一个radiobutton的简单应用演示样例:

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>性别:</td>
            <td>
               <form:radiobutton path="sex" value="1"/><form:radiobutton path="sex" value="0"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

在上面代码中我们的radiobutton标签都是绑定了表单对象user的sex属性,当sex为1的时候就代表性别为男,上面性别为男的那一行就会被选中,当sex为0的时候就代表性别为女,上面性别为女的那一行就会被选中。


7.radiobuttons标签

radiobuttons标签跟radiobutton标签的差别如同checkbox标签对checkboxes标签的差别。

使用radiobuttons标签的时候将生成多个单选按钮。使用radiobuttons有两个属性也是我们必须指定的,一个是path属性,表示绑定的表单对象相应的属性,还有一个是items属性,表示用于生成单选按钮的数据源。跟checkboxes一样,radiobuttons的items属性和path属性都能够是Array、集合或者是Map。如今我们假设user在篮球、足球、乒乓球、羽毛球和排球这5种运动中选择一种作为自己最喜欢的球类运动。

处理器方法和返回的相应的视图代码例如以下:

    @RequestMapping(value="form", method=RequestMethod.GET)
    public String formTag(Map<String, Object> map) {
       User user = new User();
       user.setFavoriteBall(4);//设置我最喜爱的球类运动是4羽毛球
       Map<Integer, String> ballMap = new HashMap<Integer, String>();
       ballMap.put(1, "篮球");
       ballMap.put(2, "足球");
       ballMap.put(3, "乒乓球");
       ballMap.put(4, "羽毛球");
       ballMap.put(5, "排球");
       map.put("user", user);
       map.put("ballMap", ballMap);
       return "formTag/form";
    }

JSP视图

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>最喜欢的球类:</td>
            <td>
               <form:radiobuttons path="favoriteBall" items="${ballMap}" delimiter="&nbsp;"/>
            </td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

在上述代码中我们能够看到我们使用了radiobuttons的delimiter属性,该属性表示进行展示的radiobutton之间的分隔符。这里用的是一个空格。结果页面例如以下所看到的:


8.password标签

password标签将会被渲染为一个type为password的普通HTML input标签。


9.select标签

select标签将会被渲染为一个普通的HTML select标签。这里还拿前面的user最喜欢的球类运动来做演示样例,有例如以下这样一个处理器方法和相应的视图页面:

    @RequestMapping(value="form", method=RequestMethod.GET)
    public String formTag(Map<String, Object> map) {
       User user = new User();
       user.setFavoriteBall(4);//设置我最喜爱的球类运动是4羽毛球
       Map<Integer, String> ballMap = new HashMap<Integer, String>();
       ballMap.put(1, "篮球");
       ballMap.put(2, "足球");
       ballMap.put(3, "乒乓球");
       ballMap.put(4, "羽毛球");
       ballMap.put(5, "排球");
       map.put("user", user);
       map.put("ballMap", ballMap);
       return "formTag/form";
    }

JSP视图

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>最喜欢的运动:</td>
            <td>
               <form:select path="favoriteBall" items="${ballMap}"/>
            </td>
        </tr>
       <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

从上面演示样例我们能够看出,我们通过items属性给select标签指定了一个数据源,而且绑定了表单对象user的favoriteBall属性。Items属性是用于指定当前select的全部可选项的,可是它对于select标签而言不是必须的,由于我们还能够手动的在select标签中间加上option标签来指定select可选的option。Select标签支持的items属性的数据类型能够是Array、Collection和Map,当数据类型为Array或Collection时且当中的元素为一个POJO时,我们能够通过属性itemLabel和itemValue来指定将用于呈现的option Label和Value。其它情况下Array和Collection数据源中的元素将既作为可选项option的value又作为它的Label。当items的数据类型为Map时,Map的key将作为可选项option的value。而Map的value将作为option的Label标签。


10.option标签

option标签会被渲染为一个普通的HTML option标签。

当一个SpringMVC select标签没有通过items属性指定自己的数据源的时候,我们就能够在select标签中通过普通HTML option标签或者SpringMVC option标签来指定能够选择的项。

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>最喜欢的运动:</td>
            <td>
               <form:select path="favoriteBall">
                   <option>请选择</option>
                   <form:option value="1">篮球</form:option>
                   <option value="4">羽毛球</option>
               </form:select>
            </td>
        </tr>
       <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

我们能够看到在上面代码中我们是没有指定select标签的数据源的,而是通过在select标签体里面指定普通HTML option标签和SpringMVC option标签来指定可选项。


11.textarea标签

SpringMVC textarea标签将被渲染为普通HTML textarea标签。

简单示比例如以下:

<form:form action="formTag/form.do" method="post" commandName="user">
    <table>
        <tr>
            <td>自我介绍:</td>
            <td>
               <form:textarea path="introduction" cols="20" rows="10"/>
            </td>
        </tr>
       <tr>
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

12.errors标签

SpringMVC errors标签是相应于SpringMVC的Errors对象的。它的作用就是用于展现Errors对象中包括的错误信息的。我们利用errors标签来展现Errors的时候是通过errors标签的path属性来绑定一个错误信息的。我们能够通过path属性来展现两种类型的错误信息。


l 全部的错误信息,这个时候path的值应该置为“*”
l 当前对象的某一个域的错误信息,这个时候path的值应为所需展现的域的名称
看以下这样一个样例:
定义了一个UserValidator对象,专门用来对User对象进行验证。其代码例如以下:

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class UserValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
       // TODO Auto-generated method stub
       return User.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
       // TODO Auto-generated method stub
       ValidationUtils.rejectIfEmpty(errors, "name", null, "Name Is Empty");
       ValidationUtils.rejectIfEmpty(errors, "username", null, "Username Is Empty.");
    }

}

然后我们有这样一个控制器类:

 @Controller
@RequestMapping("formTag")
public class FormTagController {

    @RequestMapping(value="form", method=RequestMethod.GET)
    public String formTag(Map<String, Object> map) {
       User user = new User();
       map.put("user", user);
       return "formTag/form";
    }

    @InitBinder
    public void initBinder(DataBinder binder) {
       binder.setValidator(new UserValidator());
    }

    @RequestMapping(value="form", method=RequestMethod.POST)
    public String form(@Valid User user, Errors errors) {
       if (errors.hasFieldErrors())
           return "formTag/form";
       return "formTag/submit";
    }
}

我们能够看到我们在上述控制器类中通过DataBinder对象给该类设定了一个用于验证的UserValidator,这样当我们请求该控制器的时候UserValidator将生效。

我们有例如以下这样一段表单代码:

<form:form action="formTag/form.do" method="post" commandName="user">
    <table border="1px" bordercolor="blue">
        <tr align="center">
            <td width="100">姓名:</td>
            <td width="150"><form:input path="name"/></td>
        </tr>
        <tr align="center">
            <td>用户名:</td>
            <td><form:input path="username"/></td>
        </tr>
        <tr>
            <td>全部错误信息:</td>
            <td><form:errors path="*"/></td>
        </tr>
        <tr>
            <td>Name的错误信息:</td>
            <td><form:errors path="name"/></td>
        </tr>
        <tr align="center">
            <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form:form>

当我们提交上面的表单的时候会往Errors中注入两个错误信息

原文链接:http://haohaoxuexi.iteye.com/blog/1807330


项目演示样例能够參考:
SSM框架整合: https://github.com/nl101531/JavaWEB

SpringMVC学习记录(五)--表单标签

标签:err   后台   script   errors   种类型   lang   注入   art   erro   

原文地址:https://www.cnblogs.com/llguanli/p/8306026.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!