1. 程式人生 > >springMVC restful風格

springMVC restful風格

RESTful簡介

1.REST架構是一個抽象的概念,目前主要是基於HTTP協議實現,其目的是為了提高系統的可伸縮性,降低應用之間的耦合度,便於框架分散式處理程式。

2.REST主要對以下兩方面進行了規範

-定位資源的URL風格,例如

 http://baidu.com/admin/1234

 http://baidu.com/admin/1234/10/11

-如何對資源操作

 採用HTTP協議規定的GET、POST、PUT、DELETE動作處理資源的增刪該查操作

 

3.什麼是RESTful?

 -符合REST約束風格和原則的應用程式或設計就是RESTful.

 eg:  /emp/1  HTTP GET      查詢id=1的emp

       /emp/1  HTTP DELETE    刪除id=1的emp,實驗中直接刪除會報405錯誤,但是採用$.ajax非同步刪除就沒問題

       /emp/1  HTTP PUT    更新emp

       /emp/add  HTTP POST     新增emp

4.Spring對RESTful的支援

- Spring MVC 對 RESTful應用提供了以下支援

- 利用@RequestMapping 指定要處理請求的URI模板和HTTP請求的動作型別

- 利用@PathVariable講URI請求模板中的變數對映到處理方法引數上

- 利用Ajax,在客戶端發出PUT、DELETE動作的請求

具體例子

瀏覽器 form 表單只支援 GET 與 POST 請求,(官網:www.fhadmin.org) 而DELETE、PUT 等 method 並不支 持,Spring3.0  添加了一個過濾器----HiddenHttpMethodFilter,

可以將這些請求轉換 為標準的 http 方法,使得支援 GET、POST、PUT 與 DELETE 請求。

在web.xml中配置

 <!-- configure the HiddenHttpMethodFilter,convert the post method to put or delete -->
  <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>

查詢

先在index.jsp上放上兩個超連結, 用於獲取所有員工資料, 訪問emps是通過get請求

  <body>
    <a href="emps">list all employees</a> <br>
  </body>

應控制器的方法如下,@RequestMapping 預設的請求方式是get, 所以method引數可以不用寫

    @RequestMapping("/emps", method=RequestMethod.GET)
    public String list(Map<String, Object> map){
        map.put("employees", employeeDao.getAll());
        return "list";
    }

用map資料模型儲存員工資訊 然後帶入到list.jsp頁面上,在WEB-INF/view目錄下建立list.jsp

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<head>
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/jquery.min.js"></script>
<script>
</script>
<title></title>
</head>
<body>
    <div>
        <c:if test="${empty requestScope.employees }">
            沒有員工資訊
        </c:if>
        <c:if test="${!empty requestScope.employees }">
            <table border="1" >
                <tr>
                    <th>ID</th>
                    <th>lastName</th>
                    <th>email</th>
                    <th>gender</th>
                    <th>department</th>
                    <th>edit</th>
                    <th>delete</th>
                </tr>

                <c:forEach items="${requestScope.employees }" var="emp">
                    <tr>
                        <td>${emp.id }</td>
                        <td>${emp.lastName }</td>
                        <td>${emp.email }</td>
                        <td>${emp.gender == 0 ? 'Female' : 'Male' }</td>
                        <td>${emp.department.departmentName }</td>
                        <td><a href="">Edit</a></td>
                        <!-- 因為a標籤是get請求, 要轉成Delete請求, 可以使用jquery -->
                        <td><a class="delete" href="">Delete</a></td>
                    </tr>
                </c:forEach>
            </table>
        </c:if>
    </div>
</body>
</html>

顯示如下: 這裡寫圖片描述

刪除

接著做刪除,給list.jsp新增刪除請求的地址: <a class="delete" href="emp/${emp.id }">Delete</a>

開始的時候說了restful風格 用來刪除資源的請求是DELETE,DELETE請求是由POST改造成的, 而現在是GET請求,現在要做的是把這get請求改成post請求 ,然後在改造成delete請求, 操作方法是當點選刪除連結時, 通過jquery提交一個我們從新生成的form表單,在這個form表單上新增隱藏域標識這個表單是由post改成delete請求,給web.xml中配置的HiddenHttpMethodFilter類處理。

在list.jsp中建立一個新的表單, action先不寫, 等會通過jquery進行修改, 新增隱藏域, name和value的值必須正確填寫

        <form action="" method="post">
            <input type="hidden" name="_method" value="DELETE"/>
        </form>

js如下: 獲取請求地址並提交

    $(function(){
        $(".delete").click(function(){
            var href = $(this).attr("href");
            $("form").attr("action", href).submit();
            return false;
        })
    })

對應控制器的方法如下, 指定method為DELETE, 這樣刪除的請求才會找到這個方法

    @RequestMapping(value="/emp/{id}", method=RequestMethod.DELETE)
    public String delete(@PathVariable("id") Integer id){
        employeeDao.delete(id);
        return "redirect:/emps";
    }

新增

完成了刪除在來寫新增, 在index.jsp 新增進入新增介面的入口

  <body>
    <a href="emps">list all employees</a> <br>
    <a href="emp">add new employees</a> <br>
  </body>

請求emp對應的控制器方法;

    @RequestMapping(value="/emp", method=RequestMethod.GET)
    public String input(Map<String, Object> map){
        map.put("departments", departmentDao.getDepartments());
        map.put("employee", new Employee()); 
        return "input";
    }

接著在views目錄下建立input.jsp, 這個介面作為新增和修改同時使用, 當id存在時, 表示是修改操作,新增隱藏域將表單標記為PUT。 當id不存時, 是新增操作,保持post提交

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<head>
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
    <div>
        <form:form action="${pageContext.request.contextPath }/emp" method="post" modelAttribute="employee" >
            <c:if test="${employee.id == null }">
                <!-- 新增 -->
                lastName: <form:input path="lastName" /><br/>
            </c:if>
            <c:if test="${employee.id != null }">
                <!--修改-->
                <form:hidden path="id" />
                <input type="hidden" name="_method" value="PUT" />
            </c:if>

            email: <form:input path="email" /><br/>
            <%
                Map<String , String> genders = new HashMap<String , String>();
                genders.put("1", "male");
                genders.put("0", "female");
                request.setAttribute("genders",genders); //必須放在域物件中,才可以被${}訪問到
            %>
            gender:<form:radiobuttons path="gender" items="${genders }" /><br/>
            department:<form:select path="department.id" items="${departments }" itemLabel="departmentName" itemValue="id"></form:select><br/>
            <input type="submit" />
        </form:form>
    </div>
</body>
</html>

emp對應的新增方法,post請求, 新增完成後重定向到員工列表

    @RequestMapping(value="/emp", method=RequestMethod.POST)
    public String save(Employee employee){
        employeeDao.save(employee);
        return "redirect:/emps";
    }

修改

完成了新增操作, 再到list.jsp中, 將編輯連結新增請求地址 

修改請求的方法, 如下, 將值帶到input.jsp介面

    @RequestMapping(value="/emp/{id}", method=RequestMethod.GET)
    public String input(@PathVariable("id") Integer id ,Map<String, Object> map){
        map.put("departments", departmentDao.getDepartments());
        map.put("employee", employeeDao.get(id));
        return "input";
    }

此時進入了input.jsp頁面, 其中的

            <c:if test="${employee.id != null }">
                <form:hidden path="id" />
                <input type="hidden" name="_method" value="PUT" />
            </c:if>

條件成立, 當提交表單時, 將以PUT的方式請求 , 對應控制器方法如下

    @RequestMapping(value="/emp", method=RequestMethod.PUT)
    public String update(Employee employee){
        employeeDao.save(employee);
        return "redirect:/emps";
    }