第7章 综合案例RESTRUL_CRUD
7.1 RESTRUL_CRUD_需求
7.1.1 显示所有员工信息
1) URI:emps
2) 请求方式:GET
3) 显示效果
id | LastName | Gender | Department | Edit | Delete | |
---|---|---|---|---|---|---|
1001 | AA | aa@163.com | Male | AA | Edie | Delete |
7
7.1.2 添加操作-去往添加页面
1) 显示添加页面:
2) URI:emp
3) 请求方式:GET
4) 显示效果
7.1.3 添加操作-添加员工
1) 添加员工信息:
2) URI:emp
3) 请求方式:POST
4) 显示效果:完成添加,重定向到 list 页面。
7.1.4 删除操作
1) URL:emp/{id}
2) 请求方式:DELETE
3) 删除后效果:对应记录从数据表中删除
7.1.5 修改操作-去往修改页面
1) URI:emp/{id}
2) 请求方式:GET
3) 显示效果:回显表单。
7.1.6 修改操作-修改员工
1) URI:emp
2) 请求方式:PUT
3) 显示效果:完成修改,重定向到 list 页面。
7.1.7 相关的类
省略了Service层,为了教学方便
1) 实体类:Employee、Department
2) Handler:EmployeeHandler
3) Dao:EmployeeDao、DepartmentDao
7.1.8 相关的页面
1) WebContent\WEB-INF\views\index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 导入JSTL的标签库 -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>Insert title here</title>
<!-- 引入JQuery
Springmvc处理静态资源的问题:
静态资源: .js .css .html .txt .png .jpg .avi 等.
因为DispatcherServlet的 <url-pattern> 配置的是/ , 会匹配到所有的请求(排除jsp的请求).
因为请求的.js文件,是一个静态资源请求,交给DispatcherServlet后就会出现no mapping found 问题。
解决问题:
1. 修改<url-pattern>为后缀匹配. 但是不建议这么做, 对REST的支持不好. 因为一个优秀的REST 不希望请求
URL带有任何后缀.
2. 在springmvc.xml中加上一个配置: <mvc:default-servlet-handler/>
<mvc:annotation-driven/>
-->
<script type="text/javascript" src="scripts/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
$(function(){
//给删除的<a>动态绑定事件
$(".del").click(function(){
//确认是否要删除
var flag = window.confirm("是否要删除?");
if(!flag){
return false ;
}
//this :当前点击的dom对象
//获取点击的超连接的href的值
var href = $(this).attr("href");
//将href的值设置到表单的action上,并提交
$("form").attr("action",href).submit();
//取消<a>的默认行为
return false;
});
});
</script>
</head>
<body>
<form action="" method="post">
<input type="hidden" name="_method" value="DELETE">
</form>
<h1 align="center">员工信息列表</h1>
<table border="1px" align="center" width="70%" cellspacing="0px">
<tr>
<th>Id</th>
<th>LastName</th>
<th>Email</th>
<th>Gender</th>
<th>DeptName</th>
<th>Operation</th>
</tr>
<!-- 通过迭代模型数据,生成表格 -->
<c:forEach items="${emps }" var="emp">
<tr align="center">
<td>${emp.id }</td>
<td>${emp.lastName }</td>
<td>${emp.email }</td>
<td>${emp.gender==0?"女":"男"}</td>
<td>${emp.department.departmentName }</td>
<td>
<a href="emp/${emp.id}">Edit </a>
<!--
解决思路:
给删除的超链接绑定事件, 当触发了点击事件,可以在事件处理函数中获取到要发送的请求URL,
再将获取到的请求URL设置到某个表单的action属性上,再将表单提交。
最终将<a>的默认行为取消掉。
-->
<a class="del" href="emp/${emp.id}">Delete</a>
</td>
</tr>
</c:forEach>
</table>
<!--
去往添加页面,不能直接进行页面的简单跳转,因为添加页面中需要用到部门数据,因此需要
到Handler中先查询到部门数据。再转发到添加页面.
-->
<h2 align="center"><a href="emp">Add New Emp</a></h2>
</body>
</html>
2) WebContent\WEB-INF\views\input.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 导入Springmvc表单标签库 -->
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- 导入JSTL标签库 -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>Insert title here</title>
</head>
<body>
<!-- Springmvc的表单标签:
1. 可以快速的开发表单
2. 可以更加方便的回显数据.
Springmvc表单标签遇到的问题:
Neither BindingResult nor plain target object
for bean name 'command' available as request attribute
问题原因: Springmvc的表单标签必须要进行数据的回显。 默认会使用"command"这个key到request中
找回显的数据。如果找不到,则抛出异常。
问题解决: 让Springmvc可以通过"command"从request中找到要回显的数据.
还可以通过modelAttribute来指定一个key替换默认的command
表单标签在最终执行时会转化成原始的HTML标签.
-->
<form:form action="${pageContext.request.contextPath }/emp" method="post" modelAttribute="employee">
<!--
判断是添加操作还是修改操作:
根据回显的Employee对象的id值来判断: 如果有id就是修改 如果没有id就是添加操作
-->
<c:if test="${!empty employee.id }" var="flag">
<!-- 修改操作 -->
<form:hidden path="id"/>
<!-- 隐藏PUT -->
<input type="hidden" name="_method" value="PUT"/>
</c:if>
lastName:<form:input path="lastName" /> <!-- path就相当于HTML中input标签中的name属性 -->
<!-- <input type="text" name="lastName"/> -->
<br/>
Email: <form:input path="email"/>
<br/>
<!-- radiobuttons 可以根据Map数据来生成单选框 -->
Gender:<form:radiobuttons path="gender" items="${genders }" />
<br/>
deptName:<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"></form:select>
<!-- <select name="department.id">
<option value="1">开发部</option>
<option value="2">测试部</option>
</select> -->
<br/>
<c:if test="${flag }">
<input type="submit" value="Edit"/>
</c:if>
<c:if test="${!flag }">
<input type="submit" value="ADD"/>
</c:if>
</form:form>
</body>
</html>
3) edit.jsp
7.2 搭建开发环境
1) 拷贝jar包WebContent\WEB-INF\lib
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
commons-logging-1.1.3.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
2) src-springmvc.xml
创建配置文件:springmvc.xml 增加context,mvc,beans名称空间。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 组件扫描 -->
<context:component-scan base-package="com.atguigu.springmvc"></context:component-scan>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--
将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,
它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,
就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果是由映射的请求,才由 DispatcherServlet 继续处理
如果web应用服务器的默认的Serlvet的名字不叫"default",则需要通过default-servlet-name来进行指定.
配置了default-serlvet-handler后,RequestMapping的映射会失效,需要加上annotation-driven的配置。
-->
<mvc:default-servlet-handler />
<!-- 以后讲 -->
<mvc:annotation-driven/>
</beans>
3) WebContent/WEB-INF/web.xml
配置核心控制器:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<!-- 字符编码过滤器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- REST 过滤器 -->
<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>
<!-- 前端控制器 -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
5) WebContent/index.jsp
创建相关页面
/WEB-INF/views/list.jsp
index.jsp
<%@ 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">
<title>Insert title here</title>
</head>
<body>
<a href="emps">List All Emps</a>
</body>
</html>
6) 增加实体类src/beans/Employee Department
package com.atguigu.springmvc.beans;
public class Department {
private Integer id;
private String departmentName;
public Department() {
// TODO Auto-generated constructor stub
}
public Department(int i, String string) {
this.id = i;
this.departmentName = string;
}
setter getter toString省略........
}
----------------------------------------------------------------
package com.atguigu.springmvc.beans;
public class Employee {
private Integer id;
private String lastName;
private String email;
//1 male, 0 female
private Integer gender;
private Department department;
setter getter toString省略........
public Employee(Integer id, String lastName, String email, Integer gender,
Department department) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.department = department;
}
public Employee() {
// TODO Auto-generated constructor stub
}
}
7) 增加DAO类
src/dao
package com.atguigu.springmvc.dao;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.atguigu.springmvc.beans.Department;
import com.atguigu.springmvc.beans.Employee;
@Repository
public class EmployeeDao {
private static Map<Integer, Employee> employees = null;
@Autowired
private DepartmentDao departmentDao;
static{
employees = new HashMap<Integer, Employee>();
employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1, new Department(101, "D-AA")));
employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));
employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));
employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));
employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE")));
}
private static Integer initId = 1006;
public void save(Employee employee){
if(employee.getId() == null){
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));
employees.put(employee.getId(), employee);
}
public Collection<Employee> getAll(){
return employees.values();
}
public Employee get(Integer id){
return employees.get(id);
}
public void delete(Integer id){
employees.remove(id);
}
}
---------------------------------------------------------------------
package com.atguigu.springmvc.dao;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Repository;
import com.atguigu.springmvc.beans.Department;
@Repository
public class DepartmentDao {
private static Map<Integer, Department> departments = null;
static{
departments = new HashMap<Integer, Department>();
departments.put(101, new Department(101, "D-AA"));
departments.put(102, new Department(102, "D-BB"));
departments.put(103, new Department(103, "D-CC"));
departments.put(104, new Department(104, "D-DD"));
departments.put(105, new Department(105, "D-EE"));
}
public Collection<Department> getDepartments(){
return departments.values();
}
public Department getDepartment(Integer id){
return departments.get(id);
}
}
src/handler
package com.atguigu.springmvc.handler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.atguigu.springmvc.beans.User;
@Controller
//@RequestMapping(value="/springmvc")
public class SpringmvcHandler {
/**
* 测试原生的Servlet API
* @throws IOException
* @throws ServletException
*/
@RequestMapping("/testServletAPI")
public void testServletAPI(HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException {
System.out.println("request: " + request );
System.out.println("response: " + response );
// 转发
//request.getRequestDispatcher("/WEB-INF/views/success.jsp").forward(request, response);
// 重定向 将数据写给客户端
//response.sendRedirect("http://www.baidu.com");
response.getWriter().println("Hello Springmvc ");
}
/**
* POJO
*/
@RequestMapping("/testPOJO")
public String testPOJO(User user) {
System.out.println("user:" + user);
return "success";
}
/**
* @CookieValue 映射cookie信息到请求处理方法的形参中
*/
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID")String sessionId) {
System.out.println("sessionid:" + sessionId);
return "success";
}
/**
* @RequestHeader 映射请求头信息到请求处理方法的形参中
*/
@RequestMapping("testRequestHeader")
public String testRequestHeader(@RequestHeader("Accept-Language")String acceptLanguage) {
System.out.println("acceptLanguage:" + acceptLanguage);
return "success";
}
/**
* @RequestParam 映射请求参数到请求处理方法的形参
* 1. 如果请求参数名与形参名一致, 则可以省略@RequestParam的指定。
* 2. @RequestParam 注解标注的形参必须要赋值。 必须要能从请求对象中获取到对应的请求参数。
* 可以使用required来设置为不是必须的。
* 3. 可以使用defaultValue来指定一个默认值取代null
* 客户端的请求:testRequestParam?username=Tom&age=22
*/
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam("username")String username,
@RequestParam(value="age",required=false,defaultValue="0")int age ) {
//web: request.getParameter() request.getParameterMap()
System.out.println(username + " , " + age);
return "success";
}
/**
* REST PUT
*/
@RequestMapping(value="/order",method=RequestMethod.PUT)
public String testRestPUT() {
System.out.println("REST PUT");
return "success";
}
/**
* REST POST
*/
@RequestMapping(value="/order",method=RequestMethod.POST)
public String testRestPOST() {
System.out.println("REST POST");
return "success";
}
/**
* REST DELETE
*/
@RequestMapping(value="/order/{id}",method=RequestMethod.DELETE)
public String testRestDELETE(@PathVariable("id")Integer id ) {
System.out.println("REST DELETE: " + id );
return "success";
}
/**
* REST GET
*/
@RequestMapping(value="/order/{id}",method=RequestMethod.GET)
public String testRestGET(@PathVariable("id")Integer id ) {
System.out.println("REST GET: " + id );
return "success";
}
/**
* 带占位符的URL
*
* 浏览器: http://localhost:8888/Springmvc01/testPathVariable/admin/1001
*/
@RequestMapping(value="/testPathVariable/{name}/{id}")
public String testPathVariable(@PathVariable("name")String name, @PathVariable("id")Integer id ) {
System.out.println(name + " : " + id);
return "success";
}
/**
* @RequestMapping 映射请求参数 以及 请求头信息
*
* params : username=tom&age=22
* headers
*/
@RequestMapping(value="/testRequestMappingParamsAndHeaders",
params= {"username","age=22"},
headers= {"!Accept-Language"})
public String testRequestMappingParamsAndHeaders() {
return "success";
}
/**
* @RequestMapping method 映射请求方式
*
*/
@RequestMapping(value="/testRequestMappingMethod",method= {RequestMethod.POST,RequestMethod.GET})
public String testRequestMappingMethod() {
return "success";
}
/**
* @RequestMapping
*/
@RequestMapping(value="/testRequestMapping")
public String testRequestMapping() {
return "success";
}
}
7.3 RESTRUL_CRUD_显示所有员工信息
1) 增加页面链接
<a href="empList">To Employee List</a>
2) 增加处理器
package com.atguigu.springmvc.crud.handlers;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.atguigu.springmvc.crud.dao.EmployeeDao;
@Controller
public class EmployeeHandler {
@Autowired
private EmployeeDao employeeDao ;
@RequestMapping("/empList")
public String empList(Map<String,Object> map){
map.put("empList", employeeDao.getAll()); //默认存放到request域中
return "list";
}
}
package com.atguigu.springmvc.handler;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.atguigu.springmvc.beans.Department;
import com.atguigu.springmvc.beans.Employee;
import com.atguigu.springmvc.dao.DepartmentDao;
import com.atguigu.springmvc.dao.EmployeeDao;
@Controller
public class RestCrudHandler {
@Autowired
private EmployeeDao employeeDao ;
@Autowired
private DepartmentDao departmentDao ;
/**
* 修改功能: 具体的修改操作
*/
@RequestMapping(value = "/emp",method= RequestMethod.PUT)
public String updateEmp(Employee employee) {
employeeDao.save(employee);
return "redirect:/emps";
}
/**
* 修改功能: 去往修改页面
*/
@RequestMapping(value="/emp/{id}",method=RequestMethod.GET)
public String toUpdatePage(@PathVariable("id")Integer id,Map<String,Object> map ) {
//查询要修改的员工信息
Employee employee = employeeDao.get(id);
map.put("employee", employee);
//页面中显示部门下拉列表的数据
Collection<Department> depts = departmentDao.getDepartments();
map.put("depts", depts);
//页面中生成性别单选框的数据
Map<String,String > genders = new HashMap<>();
genders.put("0", "女");
genders.put("1", "男");
map.put("genders", genders);
//去往修改页面
return "input";
}
/**
* 删除功能
*/
@RequestMapping(value="/emp/{id}",method=RequestMethod.DELETE)
public String deleteEmp(@PathVariable("id")Integer id ) {
//删除员工
employeeDao.delete(id);
//重定向到列表
return "redirect:/emps";
}
/**
* 添加功能 : 具体的添加操作
*/
@RequestMapping(value="/emp",method=RequestMethod.POST)
public String addEmp(Employee employee) {
//添加员工
employeeDao.save(employee);
//回到列表页面 :重定向到显示所有员工信息列表的请求.
return "redirect:/emps";
}
/**
* 添加功能: 去往添加页面
*
* 添加页面需要部门数据
*/
@RequestMapping(value="/emp",method=RequestMethod.GET)
public String toAddPage(Map<String,Object> map) {
Collection<Department> depts = departmentDao.getDepartments();
map.put("depts", depts);
//2. 构造页面中生成单选框的数据
Map<String,String > genders = new HashMap<>();
genders.put("0", "女");
genders.put("1", "男");
map.put("genders", genders);
//3. 设置页面中要回显的数据
map.put("employee", new Employee());
return "input";
}
/**
* 显示所有的员工信息列表
*/
@RequestMapping(value="/emps",method=RequestMethod.GET)
public String listAllEmps(Map<String,Object> map ) {
Collection<Employee> emps = employeeDao.getAll();
map.put("emps", emps);
return "list";
}
}
3) SpringMVC中没遍历的标签,需要使用jstl标签进行集合遍历增加jstl标签库jar包
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>Insert title here</title>
</head>
<body>
<c:if test="${empty requestScope.empList }">
对不起,没有找到任何员工!
</c:if>
<c:if test="${!empty requestScope.empList }">
<table border="1" cellpadding="10" cellspacing="0">
<tr>
<td>EmpId</td>
<td>LastName</td>
<td>Gender</td>
<td>Email</td>
<td>DepartmentName</td>
<td>Edit</td>
<td>Delete</td>
</tr>
<c:forEach items="${requestScope.empList }" var="emp">
<tr>
<td>${emp.id }</td>
<td>${emp.lastName }</td>
<td>${emp.gender==0?"Female":"Male" }</td>
<td>${emp.email }</td>
<td>${emp.department.departmentName }</td>
<td><a href="">Edit</a></td>
<td><a href="">Delete</a></td>
</tr>
</c:forEach>
</table>
</c:if>
</body>
</html>
7.4 RESTRUL_CRUD_添加操作
1) 在list.jsp上增加连接
<a href="empInput">Add Employee</a>
2) 增加处理器方法
@RequestMapping(value="/empInput",method=RequestMethod.GET)
public String empInput(Map<String,Object> map){
map.put("deptList", departmentDao.getDepartments());
//解决错误:java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
Employee employee = new Employee();
//map.put("command", employee);
map.put("employee", employee);
return "add";
}
3) 显示添加页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ 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>Insert title here</title>
</head>
<body>
<!--
1.为什么使用SpringMVC的form标签
① 快速开发
② 表单回显
2.可以通过modelAttribute指定绑定的模型属性,
若没有指定该属性,则默认从request域中查找command的表单的bean
如果该属性也不存在,那么,则会发生错误。
-->
<form:form action="empAdd" method="POST" modelAttribute="employee">
LastName : <form:input path="lastName"/><br><br>
Email : <form:input path="email"/><br><br>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("1", "Male");
map.put("0","Female");
request.setAttribute("genders", map);
%>
Gender : <br><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br><br>
DeptName :
<form:select path="department.id"
items="${deptList }"
itemLabel="departmentName"
itemValue="id"></form:select><br><br>
<input type="submit" value="Submit"><br><br>
</form:form>
</body>
</html>
4) 显示表单信息时,会报错:
7.5 使用Spring的表单标签
input.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 导入Springmvc表单标签库 -->
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- 导入JSTL标签库 -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>Insert title here</title>
</head>
<body>
<!-- Springmvc的表单标签:
1. 可以快速的开发表单
2. 可以更加方便的回显数据.
Springmvc表单标签遇到的问题:
Neither BindingResult nor plain target object
for bean name 'command' available as request attribute
问题原因: Springmvc的表单标签必须要进行数据的回显。 默认会使用"command"这个key到request中
找回显的数据。如果找不到,则抛出异常。
问题解决: 让Springmvc可以通过"command"从request中找到要回显的数据.
还可以通过modelAttribute来指定一个key替换默认的command
表单标签在最终执行时会转化成原始的HTML标签.
-->
<form:form action="${pageContext.request.contextPath }/emp" method="post" modelAttribute="employee">
<!--
判断是添加操作还是修改操作:
根据回显的Employee对象的id值来判断: 如果有id就是修改 如果没有id就是添加操作
-->
<c:if test="${!empty employee.id }" var="flag">
<!-- 修改操作 -->
<form:hidden path="id"/>
<!-- 隐藏PUT -->
<input type="hidden" name="_method" value="PUT"/>
</c:if>
lastName:<form:input path="lastName" />
<!-- path就相当于HTML中input标签中的name属性 -->
<!-- <input type="text" name="lastName"/> -->
<br/>
Email: <form:input path="email"/>
<br/>
<!-- radiobuttons 可以根据Map数据来生成单选框 -->
Gender:<form:radiobuttons path="gender" items="${genders }" />
<br/>
deptName:<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"></form:select>
<!--itemLabel指定下拉列表的key,itemValue指定下拉列表的值-->
<!-- <select name="department.id">
<option value="1">开发部</option>
<option value="2">测试部</option>
</select> -->
<br/>
<c:if test="${flag }">
<input type="submit" value="Edit"/>
</c:if>
<c:if test="${!flag }">
<input type="submit" value="ADD"/>
</c:if>
</form:form>
</body>
</html>
1) 通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显
2) form 标签
一般情况下,通过 GET 请求获取表单页面,而通过 POST 请求提交表单页面,因此获取表单页面和提交表单页面的 URL 是相同的。
只要满足该最佳条件的契约,form:form 标签就无需通过 action 属性指定表单提交的 URL
可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取 command 的表单 bean,如果该属性值也不存在,则会发生错误。
3) SpringMVC 提供了多个表单组件标签,如 form:input/、form:select/ 等,用以绑定表单字段的属性值,它们的共有属性如下:
path:表单字段,对应 html 元素的 name 属性,支持级联属性
htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值为 true
cssClass:表单组件对应的 CSS 样式类名
cssErrorClass:表单组件的数据存在错误时,采取的 CSS 样式
4) form:input、form:password、form:hidden、form:textarea:对应 HTML 表单的 text、password、hidden、textarea 标签
5) form:radiobutton:单选框组件标签,当表单 bean 对应的属性值和 value 值相等时,单选框被选中
6) form:radiobuttons:单选框组标签,用于构造多个单选框
items:可以是一个 List、String[] 或 Map
itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值
itemLabel:指定 radio 的 label 值
delimiter:多个单选框可以通过 delimiter 指定分隔符
7) form:checkbox:复选框组件。用于构造单个复选框
8) form:checkboxs:用于构造多个复选框。使用方式同 form:radiobuttons 标签
9) form:select:用于构造下拉框组件。使用方式同 form:radiobuttons 标签
10) form:option:下拉框选项组件标签。使用方式同 form:radiobuttons 标签
11) form:errors:显示表单组件或数据校验所对应的错误
<form:errors path= “” /> :显示表单所有的错误
<form:errors path= “user” /> :显示所有以 user 为前缀的属性对应的错误
<form:errors path= “username” /> :显示特定表单对象属性的错误
7.6 添加员工实验代码
1) 表单
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ 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>Insert title here</title>
</head>
<body>
<!--
1.为什么使用SpringMVC的form标签
① 快速开发
② 表单回显
2.可以通过modelAttribute指定绑定的模型属性,
若没有指定该属性,则默认从request域中查找command的表单的bean
如果该属性也不存在,那么,则会发生错误。
-->
<form:form action="empAdd" method="POST" modelAttribute="employee">
LastName : <form:input path="lastName" /><br><br>
Email : <form:input path="email" /><br><br>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("1", "Male");
map.put("0","Female");
request.setAttribute("genders", map);
%>
Gender : <br><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br><br>
DeptName :
<form:select path="department.id"
items="${deptList }"
itemLabel="departmentName"
itemValue="id"></form:select><br><br>
<input type="submit" value="Submit"><br><br>
</form:form>
</body>
</html>
2) 控制器方法
@Controller
public class EmployeeHandler {
@RequestMapping(value="/empAdd",method=RequestMethod.POST)
public String empAdd(Employee employee){
employeeDao.save(employee);
return "redirect:/empList";
}
}
7.7 RESTRUL_CRUD_删除操作&处理静态资源
7.7.1 删除实验代码
1) 页面链接
<td><a href="/empDelete/${emp.id }">Delete</a></td>
2) 控制器方法
@RequestMapping(value="/empDelete/{id}" ,method=RequestMethod.DELETE)
public String empDelete(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/empList";
}
7.7.2 HiddenHttpMethodFilter过滤器
发起请求,无法执行,因为delete请求必须通过post请求转换为delete请求,借助:HiddenHttpMethodFilter过滤器
7.7.3 需要使用jQuery来转换请求方式
1) 加入jQuery库文件
/scripts/jquery-1.9.1.min.js
2) jQuery库文件不起作用
2) jQuery库文件不起作用
警告: No mapping found for HTTP request with URI [/SpringMVC_03_RESTFul_CRUD/scripts/jquery-1.9.1.min.js] in DispatcherServlet with name 'springDispatcherServlet'
3) 解决办法,SpringMVC 处理静态资源
① 为什么会有这样的问题:
优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀,若将 DispatcherServlet 请求映射配置为 /, 则 Spring MVC 将捕获 WEB 容器的所有请求, 包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理, 因找不到对应处理器将导致错误。
②解决: 在 SpringMVC 的配置文件中配置 mvc:default-servlet-handler/
4) 配置后,原来的请求又不好使了
需要配置<mvc:annotation-driven />
7.7.4 关于<mvc:default-servlet-handler/>
作用
<!--
<mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,
它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,
就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet 继续处理
一般 WEB 应用服务器默认的 Servlet 的名称都是 default。
若所使用的 WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定
参考:CATALINA_HOME/config/web.xml
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
该标签属性default-servlet-name默认值是"default",可以省略。
<mvc:default-servlet-handler/>
-->
<mvc:default-servlet-handler default-servlet-name="default"/>
7.7.5 通过jQuery转换为DELETE请求
<td><a class="delete" href="empDelete/${emp.id }">Delete</a></td>
<form action="" method="post">
<input type="hidden" name="_method" value="DELETE"/>
</form>
<script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(function(){
$(".delete").click(function(){
var href = $(this).attr("href");
$("form").attr("action",href).submit();
return false ;
});
});
</script>
7.7.6 删除操作流程图解
7.8 RESTRUL_CRUD_修改操作
7.8.1 根据id查询员工对象,表单回显
1) 页面链接
<td><a href="empEdit/${emp.id }">Edit</a></td>
2) 控制器方法
//修改员工 - 表单回显
@RequestMapping(value="/empEdit/{id}",method=RequestMethod.GET)
public String empEdit(@PathVariable("id") Integer id,Map<String,Object> map){
map.put("employee", employeeDao.get(id));
map.put("deptList",departmentDao.getDepartments());
return "edit";
}
3) 修改页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>Insert title here</title>
</head>
<body>
<!--
1.为什么使用SpringMVC的form标签
① 快速开发
② 表单回显
2.可以通过modelAttribute指定绑定的模型属性,
若没有指定该属性,则默认从request域中查找command的表单的bean
如果该属性也不存在,那么,则会发生错误。
修改功能需要增加绝对路径,相对路径会报错,路径不对
-->
<form:form action="${pageContext.request.contextPath }/empUpdate"
method="POST" modelAttribute="employee">
<%--
LastName : <form:input path="lastName" /><br><br>
--%>
<form:hidden path="id"/>
<input type="hidden" name="_method" value="PUT">
<%-- 这里不要使用form:hidden标签,否则会报错。
<form:hidden path="_method" value="PUT"/>
Spring的隐含标签,没有value属性,同时,path指定的值,在模型对象中也没有这个属性(_method),所以回显时会报错。
org.springframework.beans.NotReadablePropertyException:
Invalid property '_method' of bean class [com.atguigu.springmvc.crud.entities.Employee]:
Bean property '_method' is not readable or has an invalid getter method:
Does the return type of the getter match the parameter type of the setter?
--%>
Email : <form:input path="email" /><br><br>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("1", "Male");
map.put("0","Female");
request.setAttribute("genders", map);
%>
Gender : <br><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br><br>
DeptName :
<form:select path="department.id"
items="${deptList }"
itemLabel="departmentName"
itemValue="id"></form:select><br><br>
<input type="submit" value="Submit"><br><br>
</form:form>
</body>
</html>
7.8.2 提交表单,修改数据
1) 控制器方法
@RequestMapping(value="/empUpdate",method=RequestMethod.PUT)
public String empUpdate(Employee employee){
employeeDao.save(employee);
return "redirect:/empList";
}