0%

(四)SpringMVC学习笔记-表单标签&静态资源处理

1. 表单标签

通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显

SpringMVC 提供了多个表单组件标签,如 <form:input/>、<form:select/> 等,用以绑定表单字段的属性值,它们的共有属性如下:

  • path:表单字段,对应 html 元素的 name 属性,支持级联属性
  • htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值为 true
  • cssClass:表单组件对应的 CSS 样式类名
  • cssErrorClass:表单组件的数据存在错误时,采取的 CSS 样式。

form:input、form:password、form:hidden、form:textarea: 对应 HTML 表单的 text、password、hidden、textarea标签。

form:radiobutton:单选框组件标签,当表单 bean 对应的属性值和 form:radiobuttons: 单选框组标签,用于构造多个单选框。

  • items:可以是一个 List、String[] 或 Map
  • itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值
  • itemLabel:指定 radio 的 label 值
  • delimiter:多个单选框可以通过 delimiter 指定分隔符 value 值相等时,单选框被选中。

form:checkbox: 复选框组件。用于构造单个复选框。
form:checkboxs: 用于构造多个复选框。使用方式同form:radiobuttons 标签
form:select:用于构造下拉框组件。使用方式同form:radiobuttons 标签
form:option:下拉框选项组件标签。使用方式同form:radiobuttons 标签
form:errors:显示表单组件或数据校验所对应的错误

  • <form:errors path= “ *” /> :显示表单所有的错误
  • <form:errors path= “ user*” /> :显示所有以 user 为前缀的属性对应的错误
  • <form:errors path= “ username” /> :显示特定表单对象属性的错误

注意:form:errors将结合数据校验一起讲。

下面简单演示一下一些表单标签的使用:

  1. 首先需要在控制器类EmployeeHandler上添加如下方法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @RequestMapping(value="/emp",method=RequestMethod.GET)
    public String input(Map<String,Object> map) {
    Map<Integer,Department> departmentMap = new HashMap<>();
    departmentMap.put(101, new Department(101, "D-AA"));
    departmentMap.put(102, new Department(102, "D-BB"));
    //需要将所有部门信息放在请求域中,在员工信息添加页面以下拉列表的形式显示部门名称
    //values方法获取键对应的值
    map.put("departments", departmentMap.values());
    return "input";
    }

当我们在页面上点击超链接时会有该方法进行处理,将所有的部门信息添加到Map数据模型中,以方便在input.jsp页面进行数据的读取和回显。

  1. 下面是input.jsp界面的具体实现:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ page import="java.util.*" %>
    <!-- 导入SpringMVC的表单标签 -->
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>添加员工</title>
    </head>
    <body>
    <form:form action="${pageContext.request.contextPath }/emp" method="POST" >
    <!-- path:表单字段,对应 html 元素的 name 属性,支持级联属性
    对应指定类的属性名
    -->
    LastName: <form:input path="lastName"/><br/>
    Email: <form:input path="email"/><br/>
    <!--
    form:radiobuttons:单选框组标签,用于构造多个单选框.
    items:可以是一个 List、String[] 或 Map
    -->
    <%
    //注意:new HashMap<>();这种格式JDK1.7以上才支持,否则JSP编译出错
    Map<String,String> genders = new HashMap();
    genders.put("1", "Male");
    genders.put("0", "Female");
    //需要放入请求域中,否则EL表达式无法取到值
    request.setAttribute("genders", genders);
    %>
    <!-- 多个单选框可以通过 delimiter 指定分隔符 -->
    Gender: <br/><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br/>
    <!-- 下拉列表
    itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值
    itemLabel:指定 radio 的 label 值
    -->
    Department: <form:select path="department.id"
    items="${departments}" itemLabel="departmentName" itemValue="id"/><br/>
    <input type="submit" name="提交"/>
    </form:form>
    </body>
    </html>

注意: SpringMVC会通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取command 的表单 bean,如果该属性值也不在,则会发生错误java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name ‘command’ available as request attribute。

  1. 那么需要在<form:form>上配置modelAttribute属性,即modelAttribute=”employee”。接着需要在控制器类的input加上如下代码:

    1
    2
    //键"employee"匹配input.jsp页面的form表单的modelAttribute的属性值
    map.put("employee", new Employee());
  2. 运行结果如下所示:
    在这里插入图片描述

    2. 静态资源处理

    在web.xml文件中,若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获WEB 容器的所有请求,包括静态资源的请求, 如JQuery的请求。SpringMVC 会将他们当成一个普通请求处理,因找不到对应处理器将导致错误。

我们可以在 SpringMVC 的配置文件中配置 <mvc:default-servlethandler/> 的方式解决静态资源的问题:

  • <mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB应用服务器默认的 Servlet处理,如果不是静态资源的请求,才由DispatcherServlet 继续处理;因此,我们在配置上述的default-servlet时,同时还需要配置annotation-driven,以对非静态资源进行映射处理。
  • 一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的WEB 服务器的默认 Servlet 名称不是 default,则需要通过 defaultservlet-name 属性显式指定。

假如现在需要进行REST风格的操作,也就是点击超链接然后删除一个员工信息。显然,超链接是GET请求,而REST风格的删除操作则是DELETE请求,那么现在则需要导入JQuery以实现将GET请求转换为DELETE请求。具体示例如下:

  1. 编写如下index.jsp页面,具体代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <!-- 导入JQuery -->
    <script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>
    <script type="text/javascript">
    $(function(){
    //拦截delete的超链接,然后执行对应的表单
    $(".delete").click(function(){
    //获取链接
    var href = $(this).attr("href");
    //使用链接提交对应的form表单,从而完成get到delete请求的转化
    $("#deleteForm").attr("action",href).submit();
    return false;
    })

    })
    </script>
    <title>Insert title here</title>
    </head>
    <body>
    <!-- 实现将GET请求转化为DELETE请求,需借助JQuery -->
    <form id="deleteForm" action="" method="POST">
    <input type="hidden" name="_method" value="DELETE"/>
    </form>
    <a class="delete" href="emp/1">Delete Employee</a>
    </body>
    </html>
  2. 我们知道,Spring MVC 将捕获WEB 容器的所有请求,包括静态资源的请求。那么此时JQuery的导入和使用是不成功的,那么现在需要在MVC配置中进行如下配置:

    1
    2
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>
  3. 控制器类的对应方法如下所示:

    1
    2
    3
    4
    5
    @RequestMapping(value="/emp/{id}",method=RequestMethod.DELETE)
    public String delete(@PathVariable("id") Integer id) {
    System.out.println("删除了" + id + "号员工");
    return "list";
    }
------ 本文结束------