SpringMVC的form表单标签使用(八)

你未看此花时,则此花与汝心同归于寂, 你来看此花时,此花颜色一时明白起来,便知此花不在你的心外。

上一章简单介绍了SpringMVC的JSON处理及FastJSON的整合使用(七),如果没有看过,请观看上一章

一. 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 原生的。

三. 简单的普通属性框

后端 toLogin 返回普通的属性值,用于前端的接收。

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("两个蝴蝶飞");
		user.setAge(24);
		user.setPassword("123456");
		user.setId(1);
		user.setDescription("一个快乐的程序员");
		model.addAttribute("user",user);
		return "user/login";
	}

可以设置样式, 用 cssClass, cssStyle.

也可以设置事件, 如onblur,onchange

事件有:

有图片。

三.一 form:input 标签

表达的是 input type=“text”

1 .

<form:label path="name">姓名:</form:label><form:input path="name"/> <br/>

前端正常的显示,显示后的源代码为:

<form id="user" action="login.action" method="post"><input type="hidden" name="_method" value="delete"/>
		<label for="name">姓名:</label><input id="name" name="name" type="text" value="两个蝴蝶飞"/> <br/>
	</form>

2 .
设置样式,如利用 cssClass:

<style>
	.red{
		color:red;
	}
</style>
<!--cssClass 中直接写类名即可-->
<form:label path="name">姓名:</form:label><form:input path="name" cssClass="red"/> <br/>

前端页面展示:

有图片。

<form id="user" action="login.action" method="post"><input type="hidden" name="_method" value="delete"/>
		<label for="name">姓名:</label><input id="name" name="name" class="red" type="text" value="两个蝴蝶飞"/> <br/>
	</form>

解析成了正常的html+css . cssStyle 也是一样的。

3 . 设置 事件

<form:label path="name">姓名:</form:label><form:input path="name" cssClass="red" onblur="A()"/> <br/>

	<script>
		function A(){
			alert("你好,两个蝴蝶飞");
		}	
	</script>

当移出去之后,会触发这个事件。
在这里插入图片描述

三.二 form:password 标签

密码框, input type=“password”

<form:label path="password">密码:</form:label><form:password path="password"/> <br/>

会发现,什么都没有。密码那一栏也并不会显示什么东西。 就像没有回显一样。
有图片。
查看源代码

在这里插入图片描述

需添加 showPassword 属性。

<form:label path="password">密码:</form:label><form:password path="password" showPassword="true"/> <br/>

这样会展示密码。
在这里插入图片描述
查看源代码,可以获取密码值。

有图片

三.三 form:hidden

input type=“hidden”

<form:hidden path="id"/>

源代码:

三.四 form:textarea

<textarea> </textarea>


<form:label path="description">自我介绍:</form:label> <form:textarea path="description"/>

在这里插入图片描述

源代码显示:

<label for="description">自我介绍:</label> <textarea id="description" name="description">一个快乐的程序员</textarea>

三.五 form:button

type=“submit”

<form:button disabled="disabled" id="button" name="submitValue">提交</form:button>

源代码:

<button id="button" name="submitValue" type="submit" value="Submit">提交</button>

三.六 form:label

label for ,用于指定焦点。

<form:label path="name">姓名:</form:label>

源代码:

<label for="name">姓名:</label>

四. 单选按钮

四.一 单个单选按钮 form:radiobutton

input type=“radio”, 来选中单选按钮。

属性有:

有图片。

1 . 普通的 字符串选中

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("两个蝴蝶飞");
		//设置性别为 男
		user.setSex("男");
		model.addAttribute("user",user);
		return "user/login";
	}

前端页面显示:

<form:label path="sex">性别:</form:label>
		
		<form:radiobutton path="sex" value="男"/>男
		<form:radiobutton path="sex" value="女"/>女

访问路径,前端即可回显数据为:

有图片。

也可以用 label 的形式。

<form:radiobutton path="sex" value="男" label="男"/>
		<form:radiobutton path="sex" value="女" label="女"/>

2 .普通数字

上面,在数据库中存储的是 男,女, 有时候,存储的只是单纯的数字, 如1 为男, 2为女。 这个时候,要回显的是数字,但是前端展示的是 男,女。

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("精灵妹");
		//设置性别为 男
		user.setSex("2");
		model.addAttribute("user",user);
		return "user/login";
	}

前端页面展示:

<form:label path="sex">性别:</form:label>
		
		<form:radiobutton path="sex" value="1"/>男
		<form:radiobutton path="sex" value="2"/>女

数据回显展示:

有图片。

四.二 多个单选按钮 form:radiobuttons

属性有:

有图片。

上面的例子可以看到,性别是后端传递过来的,但是前端的性别集合,如 男,女,是前端固化下来的。 如果再添加一个 保密 类型的话,难道前台都得改变吗?

前端的性别集合,也应该是全部取出来的。 用form:radiobuttons

1 . 集合或者是数组的形式。 数组与其一样。 存储的是单个值。

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("精灵妹");
		//设置性别为 男
		user.setSex("女");
		model.addAttribute("user",user);
		
		List<String> sexList=new ArrayList<String>();
		sexList.add("男");
		sexList.add("女");
		sexList.add("保密");
		// 存储 性别的集合
		model.addAttribute("sexList",sexList);
		return "user/login";
	}

前端:

<form:label path="sex">性别:</form:label>
<form:radiobuttons path="sex" items="${sexList}"/>

数据前台展示:

有图片。

页面源代码为:

<label for="sex">性别:</label>
		
		<span><input id="sex1" name="sex" type="radio" value="男"/><label for="sex1">男</label></span>
		<span><input id="sex2" name="sex" type="radio" value="女" checked="checked"/><label for="sex2">女</label></span>
		<span><input id="sex3" name="sex" type="radio" value="保密"/><label for="sex3">保密</label></span>

2 . 存储为Map 形式。

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("精灵妹");
		//设置性别为 男
		user.setSex("2");
		model.addAttribute("user",user);
		
		Map<String,String> sexMap=new HashMap<String,String>();
		sexMap.put("1","男");
		sexMap.put("2","女");
		sexMap.put("3","保密");
		// 存储 性别的集合
		model.addAttribute("sexMap",sexMap);
		return "user/login";
	}

如果是数字形式的话, Map 就为 Map<Integer,String> 的形式。
前端展示为:

<form:label path="sex">性别:</form:label>
		<form:radiobuttons path="sex" items="${sexMap}"/>

前端展示为:

有图片。

源代码显示为:

<label for="sex">性别:</label>
		<span><input id="sex1" name="sex" type="radio" value="1"/><label for="sex1">男</label></span><span><input id="sex2" name="sex" type="radio" value="2" checked="checked"/><label for="sex2">女</label></span><span><input id="sex3" name="sex" type="radio" value="3"/><label for="sex3">保密</label></span>
		

可知, map中的key 为单选按钮的value, map中的value 为单选按钮的text .

3 . List 或者是数组的形式,存储的为JavaBean 对象。

举简单的例子吧。 将性别 封装一下。 有一个性别的类,如 SystemConn.

package com.yjl.pojo;

public class SystemConn {
	/**
	 * @param name 键
	 * @param value 值
	 */
	private String name;
	private String value;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	
}

后端处理为:

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("老蝴蝶");
		//设置性别为 男
		user.setSex("3");
		model.addAttribute("user",user);
		
		SystemConn conn1=new SystemConn();
		conn1.setName("1");
		conn1.setValue("男");
		
		SystemConn conn2=new SystemConn();
		conn2.setName("2");
		conn2.setValue("女");
		
		SystemConn conn3=new SystemConn();
		conn3.setName("3");
		conn3.setValue("保密");
		
		List<SystemConn> sexList=new ArrayList<SystemConn>();
		sexList.add(conn1);
		sexList.add(conn2);
		sexList.add(conn3);
		
		model.addAttribute("sexList",sexList);
		return "user/login";
	}

前端显示为:

<form:label path="sex">性别:</form:label>
		<!--name 为sexList 单bean 即SystemConn 里面的 name 和value属性。itemValue 为值,itemLable 为展示值。  -->
		<form:radiobuttons path="sex" items="${sexList}" itemValue="name" itemLabel="value"/>
		

页面可以选择出数据。

有图片。

可以设置分隔符, 用 delimiter 属性。

<form:radiobuttons path="sex" items="${sexList}" itemValue="name" itemLabel="value"
		delimiter=","/>

用 ,进行分隔。

前端显示为:

有图片。

五. 复选框

复选框与单选框的用法,几乎是一样的。 这里也简单讲解一下。

五.一 单个复选框 form:checkbox

属性:

有图片。

1 . 存放的是单值, 如 是否同意协议 这样的单个复选框。 为boolean 类型的值。

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("老蝴蝶");
		//设置性别为 男
		user.setAgree(true);
		model.addAttribute("user",user);
		return "user/login";
	}

前端页面展示:

<form:label path="agree"> 是否同意协议:</form:label>
		<!-- 注意,path用的是agree,而不是isAgree. 这就是boolean 属性值的区别 -->
		<form:checkbox path="agree"/>

前端展示:

有图片。

源代码处理为:

<label for="agree"> 是否同意协议:</label>
<input id="agree1" name="agree" type="checkbox" value="true" checked="checked"/><input type="hidden" name="_agree" value="on"/>

多添加了一个隐藏域 为_agree的值。

2 . 绑定多个单值, 与radiobutton 是一致的。

后端:

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("老蝴蝶");
		//设置爱好集合。
		List<String> hobby=new ArrayList<String> ();
		hobby.add("打游戏");
		hobby.add("编程");
		user.setHobby(hobby);
		model.addAttribute("user",user);
		return "user/login";
	}

前端展示:

<form:label path="hobby"> 爱好:</form:label>
		<!--用label来代替显示值 -->
		<form:checkbox path="hobby" value="读书" label="读书"/>
		<form:checkbox path="hobby" value="编程" label="编程"/>
		<form:checkbox path="hobby" value="打游戏" label="打游戏"/>
		<form:checkbox path="hobby" value="写作" label="写作"/>

前端回显展示:

有图片。

绑定 int值,与上面的是一样的。 不详细介绍了。

可以将前台的爱好集合,也从后端读取。 这样,需要用复选框的集合形式。

五.二 单个复选框 form:checkboxes

属性有:

有图片。

1 . 存储集合的形式, 单值的样式。

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("老蝴蝶");
		//设置爱好集合。
		List<String> hobby=new ArrayList<String> ();
		hobby.add("打游戏");
		hobby.add("编程");
		user.setHobby(hobby);
		model.addAttribute("user",user);
		
		//后端返回 爱好的集合。 应该从数据库中查询。
		List<String> hobbyList=new ArrayList<String>();
		hobbyList.add("读书");
		hobbyList.add("打游戏");
		hobbyList.add("编程");
		hobbyList.add("唱歌");
		hobbyList.add("看小说");
		
		model.addAttribute("hobbyList",hobbyList);
		return "user/login";
	}

前端展示为:

<form:label path="hobby"> 爱好:</form:label>
		<form:checkboxes items="${hobbyList}" path="hobby"/>

页面显示

有图片。

如果值相同,那么就进行勾选。

可以用delimiter 属性来进行分隔, 如 , 的形式。

<form:checkboxes items="${hobbyList}" path="hobby" delimiter=","/>

有图片。

2 . 存储 Map 的形式, 也是单值。

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("精灵妹");
		//设置爱好集合。
		List<String> hobby=new ArrayList<String> ();
		hobby.add("1");
		hobby.add("4");
		hobby.add("5");
		user.setHobby(hobby);
		model.addAttribute("user",user);
		
		//后端返回 爱好的集合。 应该从数据库中查询。
		Map<String,String> hobbyMap=new HashMap<String,String>();
		hobbyMap.put("1","读书");
		hobbyMap.put("2","打游戏");
		hobbyMap.put("3","编程");
		hobbyMap.put("4","唱歌");
		hobbyMap.put("5","看小说");
		
		model.addAttribute("hobbyMap",hobbyMap);
		return "user/login";
	}

前端代码:

<form:label path="hobby"> 爱好:</form:label>
		<!--用label来代替显示值 -->
		<form:checkboxes items="${hobbyMap}" path="hobby"/>

前台展示:
有图片。

3 .存储为集合的形式, 是javaBean的样式。

添加一个角色的类,Role . 为员工配置多个角色的形式。 这里,直接将Radio 单选框的SystemConn 进行扩展后进行测试。

后端:

//转到登录的页面
	@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("精灵妹");
		//设置该员工角色的集合。
		List<Role> roles=new ArrayList<Role>();
		Role urole1=new Role();
		urole1.setId(1);
		urole1.setName("超级管理员");
		Role urole2=new Role();
		urole2.setId(4);
		urole2.setName("一般用户");
		roles.add(urole1);
		roles.add(urole2);
		user.setRoles(roles);
		
		model.addAttribute("user",user);
		
		//后端返回 角色的集合。 应该从数据库中查询。
		List<Role> roleList=new ArrayList<Role>();
		
		Role role1=new Role();
		role1.setId(1);
		role1.setName("超级管理员");
		
		Role role2=new Role();
		role2.setId(2);
		role2.setName("机构管理员");
		
		Role role3=new Role();
		role3.setId(3);
		role3.setName("系统管理员");
		
		Role role4=new Role();
		role4.setId(4);
		role4.setName("一般用户");
		
		roleList.add(role1);
		roleList.add(role2);
		roleList.add(role3);
		roleList.add(role4);
		model.addAttribute("roleList",roleList);
		return "user/login";
	}

前端展示:

<form:form modelAttribute="user" action="login.action" method="delete">
		<form:label path="name">姓名:</form:label>
		<form:input path="name" cssClass="red"/> <br/>
		<form:label path="roles"> 角色:</form:label>
		<!--用label来代替显示值 -->
		<form:checkboxes items="${roleList}" path="roles" itemLabel="name" itemValue="id"/>
	</form:form>

运行服务器,前端显示:

有图片。

发现,可以显示角色的集合,但是不能回显。
原因是对象不一致导致的。 role 的id 和name 虽然一一致,但是并不能说明两个对象是一致的。

可以简单做个测试。

roleList 集合中添加 urole1 对象。

roleList.add(urole1);

这时,前端展示为:

有图片。

发现, urole1, 也就是最后面的 超级管理员被选中了。 可以进行回显。

最好的做法,是重写 Role 中的hashcode() 和equals() 方法,来表明当 id一致时, 这个角色就相同。

Role.java

package com.yjl.pojo;

public class Role {
	private Integer id;
	private String name;
	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;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Role other = (Role) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
	
}

后端处理代码:

//转到登录的页面
	@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("精灵妹");
		//设置该员工角色的集合。
		List<Role> roles=new ArrayList<Role>();
		Role urole1=new Role();
		urole1.setId(1);
		Role urole2=new Role();
		urole2.setId(4);
		roles.add(urole1);
		roles.add(urole2);
		user.setRoles(roles);
		
		model.addAttribute("user",user);
		
		//后端返回 角色的集合。 应该从数据库中查询。
		List<Role> roleList=new ArrayList<Role>();
		
		Role role1=new Role();
		role1.setId(1);
		role1.setName("超级管理员");
		
		Role role2=new Role();
		role2.setId(2);
		role2.setName("机构管理员");
		
		Role role3=new Role();
		role3.setId(3);
		role3.setName("系统管理员");
		
		Role role4=new Role();
		role4.setId(4);
		role4.setName("一般用户");
		
		roleList.add(role1);
		roleList.add(role2);
		roleList.add(role3);
		roleList.add(role4);
		model.addAttribute("roleList",roleList);
		return "user/login";
	}

前端的代码,是一致的。不需要改变。

<form:label path="roles"> 角色:</form:label>
		<!--用label来代替显示值 -->
		<form:checkboxes items="${roleList}" path="roles" itemLabel="name" itemValue="id"/>

测试页面展示:

有图片。

查看源代码为:

<label for="roles"> 角色:</label>
		<!--用label来代替显示值 -->
		<span><input id="roles1" name="roles" type="checkbox" value="1" checked="checked"/><label for="roles1">超级管理员</label></span><span><input id="roles2" name="roles" type="checkbox" value="2"/><label for="roles2">机构管理员</label></span><span><input id="roles3" name="roles" type="checkbox" value="3"/><label for="roles3">系统管理员</label></span><span><input id="roles4" name="roles" type="checkbox" value="4" checked="checked"/><label for="roles4">一般用户</label></span><input type="hidden" name="_roles" value="on"/>

这就是 checkboxes 的基本的用法。

六. Select 选择框

input type=“select”, 关于select 框的表现,有三种标签。 一个是 form:select, 一个是 form:option, 还有一个是form:options

这些用法,与 复选框和单选框的用法是一致的。 可以类比化使用。 这里,只简单介绍一下。

form:select 的属性展示:

有图片。

六.一 form:select 的Map 形式。 单选。

后端代码:

	//转到登录的页面
	@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("两个蝴蝶飞");
		//设置该员工角色的集合。
		user.setAddr("2");
		
		Map<String,String> addrMap=new HashMap<String,String> ();
		addrMap.put("1","浦东新区");
		addrMap.put("2","松江");
		addrMap.put("3","徐汇");
		addrMap.put("4","杨浦");
		model.addAttribute("user",user);
		model.addAttribute("addrMap",addrMap);
		
		return "user/login";
	}

前端展示:

<form:label path="roles">城市:</form:label>
		<!--用label来代替显示值 -->
		<form:select items="${addrMap}" path="addr"/>

页面展示:

有图片。

select 框,可以单选,也可以进行多选。

六.二 form:select 的Map 形式, 多选。

后端:

	@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("两个蝴蝶飞");
		//设置该员工角色的集合。
		
		List<String> jobList=new ArrayList<String>();
		jobList.add("1");
		jobList.add("2");
		user.setJob(jobList);
		Map<String,String> jobMap=new HashMap<String,String> ();
		jobMap.put("1","Java");
		jobMap.put("2","数据库");
		jobMap.put("3","Python");
		jobMap.put("4","大数据");
		model.addAttribute("user",user);
		model.addAttribute("jobMap",jobMap);
		return "user/login";
	}

前端展示:

<form:label path="job">职业:</form:label>
		<!--不需要设置 multiple="multiple" -->
		<form:select items="${jobMap}" path="job"/>

展示:

有图片。

查看源代码:

<label for="job">职业:</label>
		<!--用label来代替显示值 -->
		<select id="job" name="job" multiple="multiple"><option value="1" selected="selected">Java</option><option value="2" selected="selected">数据库</option><option value="3">Python</option><option value="4">大数据</option></select><input type="hidden" name="_job" value="1"/>

六.三 form:option 单值选项

属性有:

有图片。

form:select 会直接将所有的选项都展示出来, 直接全部填充 option 中的值。 有的时候,不太友好 。 如 option 的开头常常有 ‘请选择’ 之类的提示语。

以单个选项值为例, 即与 addr 为例子看一下。

后端:

@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("两个蝴蝶飞");
		//设置该员工角色的集合。
		user.setAddr("2");
		Map<String,String> addrMap=new HashMap<String,String> ();
		addrMap.put("1","浦东新区");
		addrMap.put("2","松江");
		addrMap.put("3","徐汇");
		addrMap.put("4","杨浦");
		model.addAttribute("user",user);
		model.addAttribute("addrMap",addrMap);
		
		return "user/login";
	}

前台展示: option 是一个个手写的。

<form:label path="addr">城市:</form:label>
		<!--用label来代替显示值 -->
		<form:select path="addr">
			<!-- 单值的时候,option 与form:option 是一致的,没有差别。 -->
			<option value="">请选择</option>
			<option value="1">浦东新区</option>
			<form:option value="2">松江</form:option>
			<form:option value="3">徐汇</form:option>
			<form:option value="4">杨浦</form:option>
		</form:select>

前台样式:

在这里插入图片描述

六.四 form:select 与 form:option 同时出现,显示哪一个。

后端的代码保持不变。

前端代码:

<form:label path="addr">城市:</form:label>
		<!--用label来代替显示值 -->
		<form:select items="${addrMap}" path="addr">
			<!-- 单值的时候,option 与form:option 是一致的,没有差别。 -->
			<option value="">请选择1</option>
			<option value="5">浦东新区1</option>
			<form:option value="6">松江1</form:option>
			<form:option value="7">徐汇1</form:option>
			<form:option value="8">杨浦1</form:option>
		</form:select>

样式展示:

有图片。

发现, 是以 form:select 为主, form:option 中的值不显示。

六.五 form:options

属性有:

有图片。

当选项过多的时候,又想要添加’请选择’ 选项的时候,即结合 form:select 与form:option 的优点,可以用 form:options

后端代码保持不变。

前端代码:

<form:label path="addr">城市:</form:label>
		<!--用label来代替显示值 -->
		<form:select path="addr">
			<option value="">请选择城市</option>
			<form:options items="${addrMap}"/>
		</form:select>

前端展示:

有图片。

可以将 form:option 与form:options 连用

<form:select path="addr">
			<form:option value="">请选择城市</form:option>
			<form:options items="${addrMap}"/>
		</form:select>

相同的效果。

form:select, form:options 也可以用 itemLabel itemValue ,封闭 javaBean 的对象,如Role 对象。 与form:checkboxes 一致,不要忘记重写 Role 里面的equals() 和hashCode() 方法。 这里就不举例了。

七. form:errors 标签

属性有:

有图片。

验证,会有一个专门的章节讲解。 老蝴蝶在这里简单的举个例子吧。

七.一 先写一个 User的验证器 UserValidator

package com.yjl.validator;

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

import com.yjl.pojo.User;

public class UserValidator implements Validator{

	@Override
	public boolean supports(Class<?> arg0) {
		return User.class.equals(arg0);
	}

	@Override
	public void validate(Object arg0, Errors errors) {
		//后面是 提示的语句,在国际化时,需要进行提示语句的国际化
		ValidationUtils.rejectIfEmpty(errors, "name",null,"name is null");
		ValidationUtils.rejectIfEmpty(errors, "age",null,"age is null");
	}

}

七.二 后端数据处理,添加绑定验证器

	//初始化绑定
	@InitBinder  
    public void initBinder(DataBinder binder) {  
       binder.setValidator(new UserValidator());  
    }  
	
	//转到登录的页面
	@RequestMapping(value="toLogin")
	public String toLogin(Model model){
		User user=new User();
		user.setName("老蝴蝶");
		model.addAttribute("user",user);
		return "user/login";
	}
	//绑定到user对象。
	@RequestMapping(value="login") 
	public String login(@Validated User user, Errors errors){
		if(errors.hasFieldErrors()){ //有错误字段
			return "user/login";
		}
		return "user/list";
	}

七.三 前端显示

<h2>两个蝴蝶飞,form表单使用</h2>
	<form:form modelAttribute="user" action="login.action" method="post">
		<form:label path="name">姓名:</form:label>
		<form:input path="name"/> 
		
		<form:errors path="name"></form:errors>
		<br/>
		
		<form:label path="age">年龄:</form:label>
		<form:input path="age"/> 
		<form:errors path="age"></form:errors> <br/>
		<form:button>提交</form:button>
	</form:form>
</body>

当输入时, 不输入年龄,进行提交时,age提示错误。

有图片。

当年龄和名称都不输入时,提示两个都是空。

有图片。

七.四 form:errors 中path的写法

有三种写法。

1 .* , 即path=x (x实际 为 8键盘上的星星,打不出来。 下面的也是一样。) 时,是所有的。 所有的没有通过验证的字段,都放置在这里面。

<form:label path="age">年龄:</form:label>
		<form:input path="age"/> 
		<form:errors path="*"></form:errors> <br/>

年龄,名称都不输入时:

有图片。

2 . 前缀*, 即path= 前缀x, 是所有以这个为开头的 。

<form:label path="age">年龄:</form:label>
		<form:input path="age"/> 
		<form:errors path="ag*"></form:errors> <br/>

年龄不输入时,

有图片。

3 . 准确定位, 用path= 名称。 只接收该名称的错误。

<form:label path="age">年龄:</form:label>
		<form:input path="age"/> 
		<form:errors path="age"></form:errors> <br/>

年龄不输入时, 显示错误。 年龄输入,而姓名不输入时,不接收错误。

这就是form表单标签的使用。 老蝴蝶先歇会。

谢谢!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两个蝴蝶飞

你的鼓励,是老蝴蝶更努力写作的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值