1.1. 概述
当提交的表单带有_method字段时,通过HiddenHttpMethodFilter 将 POST 请求转换成 DELETE、PUT请求,加上@PathVariable注解从而实现 RESTful 风格的CRUD
1.2. 配置信息
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_3_0.xsd"
- version="3.0" >
- <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
- <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:spring-mvc.xml</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <!-- Map all requests to the DispatcherServlet for handling -->
- <servlet-mapping>
- <servlet-name>springDispatcherServlet</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- <!--配置 HiddenHttpMethodFilter 可以将 POST 请求转为 DELETE、PUT 请求 -->
- <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>
- </web-app>
1.3. 效果
① 通过POST 请求增加员工信息
② 通过PUT 请求修改员工信息
③ 通过DELETE 请求删除员工信息
④ 通过GET 请求 获取所有的 员工信息
1.4. 代码
Employee.Java
- package com.ibigsea.springmvc.model;
- public class Employee {
- private Integer id;
- private String name;
- private String email;
- private int sex;
- private Department department;
- public Employee(Integer id, String name, String email, int sex,
- Department department) {
- super();
- this.id = id;
- this.name = name;
- this.email = email;
- this.sex = sex;
- this.department = department;
- }
- public Employee() {
- super();
- }
- 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;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public int getSex() {
- return sex;
- }
- public void setSex(int sex) {
- this.sex = sex;
- }
- public Department getDepartment() {
- return department;
- }
- public void setDepartment(Department department) {
- this.department = department;
- }
- @Override
- public String toString() {
- return "Employee [id=" + id + ", name=" + name + ", email=" + email
- + ", sex=" + sex + ", department=" + department + "]";
- }
- }
Department.java
- package com.ibigsea.springmvc.model;
- import java.io.Serializable;
- public class Department implements Serializable {
- private static final long serialVersionUID = 6881984318733090395L;
- 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 String toString() {
- return "Department [id=" + id + ", name=" + name + "]";
- }
- }
RestfulController.java
- package com.ibigsea.springmvc.rest;
- import java.util.Map;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.ModelAttribute;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import com.ibigsea.springmvc.dao.DepartmentDao;
- import com.ibigsea.springmvc.dao.EmployeeDao;
- import com.ibigsea.springmvc.model.Employee;
- /**
- * 基于Restful风格的增删改查
- * @author bigsea
- */
- @Controller
- @RequestMapping("/restful")
- public class RestfulController {
- @Autowired
- private EmployeeDao employeeDao;
- @Autowired
- private DepartmentDao departmentDao;
- /**
- * 因为修改的时候不能修改员工姓名,
- * 所以通过 @ModelAttribute 注解,
- * 表示在执行目标方法时,先获取该员工对象
- * 将员工对象存入 implicitMode 中
- * @param id 员工ID
- * @param map 实际传入的是implicitMode
- */
- @ModelAttribute
- public void getEmployee(@RequestParam(value="id",required=false) Integer id,Map<String,Object> map){
- if (id != null) {
- map.put("employee", employeeDao.getEmpById(id));
- }
- }
- /**
- * 查看所有的员工信息
- * @param map
- * @return
- */
- @RequestMapping("/list")
- public String list(Map<String, Object> map){
- map.put("emps", employeeDao.getAll());
- return "list";
- }
- /**
- * 跳转到员工添加页面
- * @param map
- * @return
- */
- @RequestMapping(value="/add",method=RequestMethod.GET)
- public String add(Map<String, Object> map){
- map.put("depts", departmentDao.getAll());
- map.put("action", "add");
- return "emp";
- }
- /**
- * 添加员工
- * @param emp
- * @return
- */
- @RequestMapping(value="/add",method=RequestMethod.POST)
- public String add(Employee emp){
- if (emp == null) {
- return "emp";
- }
- if (emp.getDepartment().getId() != null) {
- emp.setDepartment(departmentDao.getDepartmentById(emp.getDepartment().getId()));
- }
- employeeDao.save(emp);
- return "redirect:/restful/list";
- }
- /**
- * 删除员工信息
- * @param id
- * @return
- */
- @RequestMapping(value="/delete/{id}",method=RequestMethod.DELETE)
- public String delete(@PathVariable("id") Integer id){
- employeeDao.delEmpById(id);
- return "redirect:/restful/list";
- }
- /**
- * 因为先执行了 @ModelAttribute 注解的方法,
- * 获取了该员工ID所对应的员工信息
- * 然后在将前台获取的员工数据存入获取的员工信息中,
- * 这样就不用提交name属性也可以获取到值
- * @param emp
- * @return
- */
- @RequestMapping(value="/edit",method=RequestMethod.PUT)
- public String edit(Employee emp){
- if (emp == null) {
- return "emp";
- }
- if (emp.getDepartment().getId() != null) {
- emp.setDepartment(departmentDao.getDepartmentById(emp.getDepartment().getId()));
- }
- employeeDao.save(emp);
- return "redirect:/restful/list";
- }
- /**
- * 跳转到员工修改页面
- * @param id 员工ID
- * @param map implicitMode
- * @return
- */
- @RequestMapping(value="/edit/{id}",method=RequestMethod.GET)
- public String edit(@PathVariable("id") Integer id,Map<String, Object> map){
- map.put("emp", employeeDao.getEmpById(id));
- map.put("depts", departmentDao.getAll());
- map.put("action", "edit");
- return "emp";
- }
- }
EmployeeDao.java
- package com.ibigsea.springmvc.dao;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Map;
- import org.springframework.stereotype.Component;
- import com.ibigsea.springmvc.model.Department;
- import com.ibigsea.springmvc.model.Employee;
- @Component
- public class EmployeeDao {
- private static Map<Integer,Employee> emps = new HashMap<Integer, Employee>();
- /**
- * 初始化员工信息
- */
- static {
- emps.put(1001, new Employee(1001,"AA","AA@ibigsea.com",0,new Department(101, "JAVA")));
- emps.put(1002, new Employee(1002,"BB","BB@ibigsea.com",0,new Department(102, ".NET")));
- emps.put(1003, new Employee(1003,"CC","CC@ibigsea.com",1,new Department(103, "PHP")));
- emps.put(1004, new Employee(1004,"DD","DD@ibigsea.com",0,new Department(104, "C")));
- }
- private static int employeeId = 1005;
- /**
- * 保存员工信息
- * @param emp
- */
- public void save(Employee emp){
- if (emp.getId() == null) {
- emp.setId(employeeId++);
- }
- emps.put(emp.getId(), emp);
- }
- /**
- * 获取所有的员工信息
- * @return
- */
- public Collection<Employee> getAll(){
- return emps.values();
- }
- /**
- * 根据ID获取员工信息
- * @param id
- * @return
- */
- public Employee getEmpById(Integer id){
- return emps.get(id);
- }
- /**
- * 根据ID删除员工信息
- * @param id
- */
- public void delEmpById(Integer id){
- emps.remove(id);
- }
- }
DepartmentDao.java
- package com.ibigsea.springmvc.dao;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Map;
- import org.springframework.stereotype.Component;
- import com.ibigsea.springmvc.model.Department;
- @Component
- public class DepartmentDao {
- public static Map<Integer, Department> depts = new HashMap<Integer, Department>();
- /**
- * 初始化部门信息
- */
- static {
- depts.put(101, new Department(101,"JAVA"));
- depts.put(102, new Department(102,".NET"));
- depts.put(103, new Department(103,"PHP"));
- depts.put(104, new Department(104,"C"));
- }
- /**
- * 获取所有的部门信息
- * @return
- */
- public Collection<Department> getAll(){
- return depts.values();
- }
- /**
- * 根据ID获取部门信息
- * @param id
- * @return
- */
- public Department getDepartmentById(Integer id){
- return depts.get(id);
- }
- }
List.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
- <!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>
- <c:if test="${ empty emps }">
- 没有员工信息
- </c:if>
- <c:if test="${ !empty emps }">
- <table border="1" bordercolor="black" cellspacing="0">
- <tr>
- <td width="40px">id</td>
- <td width="30px">name</td>
- <td width="80px">email</td>
- <td width="30px">sex</td>
- <td width="40px">编辑</td>
- <td width="40px">删除</td>
- </tr>
- <c:forEach items="${emps }" var="emp">
- <tr>
- <td>${emp.id }</td>
- <td>${emp.name }</td>
- <td>${emp.email }</td>
- <td>${emp.sex == 0 ? '男' : '女'}</td>
- <td><a href="${pageContext.request.contextPath}/restful/edit/${emp.id }">Edit</a></td>
- <td><form action="${pageContext.request.contextPath}/restful/delete/${emp.id }" method="post">
- <input type="hidden" name="_method" value="DELETE">
- <input type="submit" value="Delete">
- </form>
- </td>
- </tr>
- </c:forEach>
- </table>
- </c:if>
- <br><br>
- <a href="${pageContext.request.contextPath}/restful/add">添加员工</a>
- </body>
- </html>
Emp.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
- <!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 action="${pageContext.request.contextPath}/restful/${action}" method="post">
- <c:if test="${!empty emp}">
- <input type="hidden" name="_method" value="PUT">
- <input type="hidden" name="id" value="${emp.id }"><br/><br/>
- </c:if>
- <c:if test="${empty emp}">name : <input type="text" name="name" value="${emp.name }"><br/><br/></c:if>
- email : <input type="text" name="email" value="${emp.email }"><br/><br/>
- sex :<input type="radio" name="sex" value="0" <c:if test="${emp.sex == 0}">checked</c:if>>男
- <input type="radio" name="sex" value="1" <c:if test="${emp.sex == 1}">checked</c:if>>女<br/><br/>
- department :<select name="department.id">
- <c:forEach items="${depts }" var="dept">
- <option value="${dept.id }" <c:if test="${emp.department.id == dept.id}">selected</c:if>>${dept.name }</option>
- </c:forEach>
- </select>
- <br><br/>
- <input type="submit" value="提交">
- </form>
- </body>
- </html>
1.5. 静态资源问题
因为配置了DispatcherServlet并且拦截了所有的请求,所以在添加静态资源的时候会访问不到静态资源,在springMVC.xml配置
mvc:default-servlet-handler
将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由DispatcherServlet 继续处理
mvc:annotation-driven
会自动注册
RequestMappingHandlerMapping
RequestMappingHandlerAdapter
ExceptionHandlerExceptionResolver 三个bean。
就能访问到静态资源了
1.6. mvc:annotation-driven和mvc:default-servlet-handler
在配置SpringMVC配置文件时添加mvc:annotation-driven
<mvc:annotation-driven /> 会自动注册三个Bean
² RequestMappingHandlerMapping
² RequestMappingHandlerAdapter
² ExceptionHandlerExceptionResolver
还将提供以下支持:
– 支持使用 ConversionService 实例对表单参数进行类型转换
– 支持使用 @NumberFormat 、@DateTimeFormat注解完成数据类型的格式化
– 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
– 支持使用 @RequestBody 和 @ResponseBody 注解