1. 程式人生 > >SpringMVC RESTful風格CURD並整合Swagger2

SpringMVC RESTful風格CURD並整合Swagger2

RESTful風格的URL,每個網址代表一種資源,其顯著的特徵就是對於資源的具體操作型別,由HTTP動詞表示。SpringMVC 本身是支援 PUT,DELETE 等 HTTP 請求方式的,但由於某些客戶端(如:瀏覽器)並不支援這些,所以 spring 提供了HiddenHttpMethodFilter過濾器來解決這一問題。

員工CRUD操作

首先,配置HiddenHttpMethodFilter,將post請求轉為delete或者put請求 。

web.xml檔案中配置

<filter>
    <filter-name>HiddenHttpMethodFilter</filter
-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter>

其他,一些前期配置這裡就不列出來了。所以在搭建一個基本的SpringMVC的基礎上再配置上面的內容。

程式碼編寫

  • 目錄結構

這裡寫圖片描述

後端程式碼

  • 實體類

部門類(Department )

public class Department {

    private Integer id;
    private String departmentName;

    public
Department() { } public Department(int i, String string) { this.id = i; this.departmentName = string; } //省略setter/getter ...... }

員工類(Employee )

public class Employee {

    private Integer id;
    @NotEmpty
    private String lastName;

    @Email
    private String email;
    //1 male, 0 female
private Integer gender; private Department department; @Past @DateTimeFormat(pattern="yyyy-MM-dd") private Date birth; @NumberFormat(pattern="#,###,###.#") private Float salary; 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 } //省略setter/getter ...... }
  • DAO層

這裡DAO層不是直接從資料庫取資料,為了方便用集合來模擬資料一下資料庫。

@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);
    }

}

上面是關於部門的資料,接著定義一些員工的資料,指定員工部門。

@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", "[email protected]", 1, new Department(101, "D-AA")));
        employees.put(1002, new Employee(1002, "E-BB", "[email protected]", 1, new Department(102, "D-BB")));
        employees.put(1003, new Employee(1003, "E-CC", "[email protected]", 0, new Department(103, "D-CC")));
        employees.put(1004, new Employee(1004, "E-DD", "[email protected]", 0, new Department(104, "D-DD")));
        employees.put(1005, new Employee(1005, "E-EE", "[email protected]", 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);
    }
}
  • 控制器類
@Controller
public class EmployeeHandler {

    @Autowired
    private EmployeeDao employeeDao;

    @Autowired
    private DepartmentDao departmentDao;

    @ModelAttribute
    public void getEmployee(@RequestParam(value="id",required=false) Integer id,
            Map<String, Object> map){
        if(id != null){
            map.put("employee", employeeDao.get(id));
        }
    }

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

        return "redirect:/emps";
    }

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

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

    @RequestMapping(value="/emp", method=RequestMethod.POST)
    public String save(@Valid Employee employee, Errors result, 
            Map<String, Object> map){
        System.out.println("save: " + employee);

        if(result.getErrorCount() > 0){
            System.out.println("出錯了�!");

            for(FieldError error:result.getFieldErrors()){
                System.out.println(error.getField() + ":" + error.getDefaultMessage());
            }

            //若頁面出錯,則跳轉到指定頁面
            map.put("departments", departmentDao.getDepartments());
            return "input";
        }

        employeeDao.save(employee);
        return "redirect:/emps";
    }

    @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";
    }

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

//  @InitBinder
//  public void initBinder(WebDataBinder binder){
//      binder.setDisallowedFields("lastName");
//  }

}

前端頁面

  • 列表頁面(list.jsp)
<%@ 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>
<!--  
    SpringMVC 處理靜態資源:
    1. 為什麼會有這樣的問題:
    優雅的 REST 風格的資源URL 不希望帶 .html 或 .do 等字尾
    若將 DispatcherServlet 請求對映配置為 /, 則 Spring MVC 將捕獲 WEB 容器的所有請求, 包括靜態資源的請求, SpringMVC 會將他們當成一個普通請求處理, 因找不到對應處理器將導致錯誤。
    2. 解決: 在 SpringMVC 的配置檔案中配置 <mvc:default-servlet-handler/>
-->
<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>
</head>
<body>

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

    <c:if test="${empty requestScope.employees }">
        沒有任何員工資訊.
    </c:if>
    <c:if test="${!empty requestScope.employees }">
        <table border="1" cellpadding="10" cellspacing="0">
            <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="emp/${emp.id}">Edit</a></td>
                    <td><a class="delete" href="emp/${emp.id}">Delete</a></td>
                </tr>
            </c:forEach>
        </table>
    </c:if>

    <br><br>

    <a href="emp">Add New Employee</a>

</body>
</html>
  • input.jsp
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ 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>

    <form action="testConversionServiceConverer" method="POST">
        <!-- lastname-email-gender-department.id 例如: [email protected] -->
        Employee: <input type="text" name="employee"/>
        <input type="submit" value="Submit"/>
    </form>
    <br><br>

    <!--  
        1. WHY 使用 form 標籤呢 ?
        可以更快速的開發出表單頁面, 而且可以更方便的進行表單值的回顯
        2. 注意:
        可以通過 modelAttribute 屬性指定繫結的模型屬性,
        若沒有指定該屬性,則預設從 request 域物件中讀取 command 的表單 bean
        如果該屬性值也不存在,則會發生錯誤。
    -->
    <br><br>
    <form:form action="${pageContext.request.contextPath }/emp" method="POST" 
        modelAttribute="employee">

        <form:errors path="*"></form:errors>
        <br>

        <c:if test="${employee.id == null }">
            <!-- path 屬性對應 html 表單標籤的 name 屬性值 -->
            LastName: <form:input path="lastName"/>
            <form:errors path="lastName"></form:errors>
        </c:if>
        <c:if test="${employee.id != null }">
            <form:hidden path="id"/>
            <input type="hidden" name="_method" value="PUT"/>
            <%-- 對於 _method 不能使用 form:hidden 標籤, 因為 modelAttribute 對應的 bean 中沒有 _method 這個屬性 --%>
            <%-- 
            <form:hidden path="_method" value="PUT"/>
            --%>
        </c:if>

        <br>
        Email: <form:input path="email"/>
        <form:errors path="email"></form:errors>
        <br>
        <% 
            Map<String, String> genders = new HashMap();
            genders.put("1", "Male");
            genders.put("0", "Female");

            request.setAttribute("genders", genders);
        %>
        Gender: 
        <br>
        <form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/>
        <br>
        Department: <form:select path="department.id" 
            items="${departments }" itemLabel="departmentName" itemValue="id"></form:select>
        <br>
        <!--  
            1. 資料型別轉換
            2. 資料型別格式化
            3. 資料校驗. 
            1). 如何校驗 ? 註解 ?
            ①. 使用 JSR 303 驗證標準
            ②. 加入 hibernate validator 驗證框架的 jar 包
            ③. 在 SpringMVC 配置檔案中新增 <mvc:annotation-driven />
            ④. 需要在 bean 的屬性上新增對應的註解
            ⑤. 在目標方法 bean 型別的前面新增 @Valid 註解
            2). 驗證出錯轉向到哪一個頁面 ?
            注意: 需校驗的 Bean 物件和其繫結結果物件或錯誤物件時成對出現的,它們之間不允許宣告其他的入參
            3). 錯誤訊息 ? 如何顯示, 如何把錯誤訊息進行國際化
        -->
        Birth: <form:input path="birth"/>
        <form:errors path="birth"></form:errors>
        <br>
        Salary: <form:input path="salary"/>
        <br>
        <input type="submit" value="Submit"/>
    </form:form>

</body>
</html>

至此,我們完成了對員工增刪查改的所有功能。以上內容主要參考尚矽谷教程。

整合Swagger2

1、在pom.xml檔案中新增如下jar包。

<dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.2.2</version>
    </dependency>
    <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.2.2</version>
    </dependency>
    <!-- swagger2需要jackson -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.5.4</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.5.4</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.5.4</version>
    </dependency>
  </dependencies>

2、Swagger2配置

@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket addUserDocket(){
        Docket docket = new Docket(DocumentationType.SWAGGER_2);
        ApiInfo apiInfo = new ApiInfo("restful API", "API Document","V1.0", "www.baidu.com", "我的郵箱", "", "");
        docket.apiInfo(apiInfo);
        return docket;
    }
}

3、在spring-mvc.xml檔案中配置

<bean name="swaggerConfig" class="org.chm.swagger.SwaggerConfig"/>
    <!--<bean class="springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration" id="swagger2Config"/>--> <!-- swagger預設配置 -->
    <mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"/>
    <mvc:resources location="classpath:/META-INF/resources/webjars/" mapping="/webjars/**"/>

4、在Controller類中上新增@Api註解,用於描述接著類。

@Api(value = "員工類",tags = "員工增刪查改")
@Controller
public class EmployeeHandler 

下面是一些Swagger中常見的註解:

1、swagger類註釋
@Api(value = “訂單類”,tags = “訂單類測試介面”)

swagger介面註釋
@ApiOperation(“訂單列表”)

swagger引數註釋
@ApiParam(“訂單ID”)

2、swagger實體類註釋
@ApiModel(“訂單實體類”)

swagger實體類中隱藏屬性
@ApiModelProperty(hidden = true)

swagger實體屬性備註
@ApiModelProperty(“訂單編號”)

Swagger2預設將所有的Controller中的RequestMapping方法都會暴露, 然而在實際開發中,我們並不一定需要把所有API都提現在文件中檢視,這種情況下,使用註解@ApiIgnore來解決。

這裡寫圖片描述

相關推薦

SpringMVC RESTful風格CURD整合Swagger2

RESTful風格的URL,每個網址代表一種資源,其顯著的特徵就是對於資源的具體操作型別,由HTTP動詞表示。SpringMVC 本身是支援 PUT,DELETE 等 HTTP 請求方式的,但由於某些客戶端(如:瀏覽器)並不支援這些,所以 spring 提供了H

idea搭建SSM專案SpringMVC Restful風格簡單示例

首先建立一個Maven工程groupId:com.dygartifactId:ssmpom.xml檔案如下:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org

springMVC restful風格

RESTful簡介 1.REST架構是一個抽象的概念,目前主要是基於HTTP協議實現,其目的是為了提高系統的可伸縮性,降低應用之間的耦合度,便於框架分散式處理程式。 2.REST主要對以下兩方面進行了規範 -定位資源的URL風格,例如  http://baidu.co

IDEA開發環境中,SpringMVCSwagger2整合。完成restful風格的API開發

專案結構Swapper2在POM中的依賴<!-- springfox依賴 --> <dependency> <groupId>io.springfox</groupId> <artifactId>sp

Spring boot 整合SSM框架三層架構前後臺restful風格互動

pom.xml檔案 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/PO

spring boot 整合 swagger2 定製RestFul API介面

1、新增maven依賴: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <versi

springMVC+json構建restful風格的服務

響應 driver 服務 dispatch project ado test idle ransac 首先。要知道什麽是rest服務,什麽是rest服務呢? REST(英文:Representational State Transfer,簡稱REST)

springmvc中配置RESTful風格控制器

控制 最好 我們 connect toc ajax cti 直觀 let 一般的http請求中其實只需要get和post就可以滿足項目需求了,而為什麽還要使用restful可能就是為了使請求url看起來更加直觀,好看吧。。 restful常用的請求方式:get,post,p

Spring Boot 整合 swagger2 自動生成 RESTFul API 文檔

pat turn ket config 文件 pen 用戶 配置文件 方式 1)首先編輯pom.xml添加依賴 <dependency>   <groupId>io.springfox</groupId>   <artifactI

springMvcrestful風格的api路徑中把小數點當參數,SpringMvc中url有小數點

pub springmvc line name object ews mapping html 兩種 在springMvc web項目中restful風格的api路徑中有小數點會被過濾後臺拿不到最後一個小數點的問題, 有兩種解決方案:

整合swagger2生成Restful Api介面文件 webapi文件描述-swagger

整合swagger2生成Restful Api介面文件 swagger Restful文件生成工具 2017-9-30 官方地址:https://swagger.io/docs/specification/about/ 官方Github:https://github.com/swagger-

Springboot整合Restful風格《SpringBoot學習六》

1. restful介紹 REST:英文representational state transfer直譯為表現層狀態轉移,或者表述性狀態轉移;Rest是web服務的一種架構風格,一種設計風格,是一種思想;同時Rest不是針對某一種程式語言的。 以webService為例通俗

SpringMVC 構建Restful風格 及問題處理

轉自:http://www.cnblogs.com/loveincode/p/7520340.html 章節目錄 1. 查詢 GET   2. 新增 POST 3. 更新 PUT 4. 刪除 D

理解設計RestFul風格介面

RestFul API是目前比較成熟的一套網際網路應用程式的API設計理論。 一、協議 API與使用者的通訊協議,總是使用HTTPS協議。 二、域名 應該儘量將API部署在專用域名之下。 https://api.example.com 如果確定API很簡單,不會有進

springMvcrestful風格的api路徑中把小數點當引數

在springMvc web專案中restful風格的api路徑中有小數點會被過濾後臺拿不到最後一個小數點的問題, 有兩種解決方案: 1:在api路徑中加入:.+ @RequestMapping("/findByIp/{ip:.+}") public Object t

javaEE SpringmvcRestFul風格的開發,@PathVariable從URL路徑中獲取請求引數

ItemController.java(Controller後端控制器,RestFul風格開發,@PathVariable接收引數): package com.xxx.springmvc.controller; import org.springframework

SpringMVC的學習(七)——RESTful風格

一、RESTful介紹 REST:即Representational State Transfer , (資源)表現層狀態轉化,是目前最流行的一種網際網路軟體架構。它結構清晰、符合標註、易於理解、方便擴充套件,所以越來越多的網站採用! 具體說,就是HTTP協議裡面,四個表示操作方式的動詞:

第六篇:Spring Boot整合Swagger2構建RESTful API文件

由於Spring Boot有快速開發、便捷部署等特性,所以很大一部分Spring Boot的使用者會用來構建RESTfulAPI。而我們構建RESTfulAPI的目的通常都是由於多終端的原因,這些終端會共用很多底層業務邏輯,因此我們會抽象出這樣一層來同時服務於多個移動端或者Web前端。

springMVC實現restful風格

/** * 使用springMVC實現restful跳轉頁面 * @return */ @RequestMapping(value="toPage/{page}",method = RequestMethod.GET) public String

SpringMVC/SpringBoot下restful風格URL,以及Http method的選擇、傳值問題

一、Http 請求方法 HTTP/1.1 協議規定的 HTTP 請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 8種,常用的有GET DELETE POST PUT四種。這些方法最大的區別是語義的區別,分別代表獲取、