springmvc/springboot開發restful API


  非rest的url寫法:

查詢  GET /user/query?name=tom
詳情  GET /user/getinfo?id=1
創建  POST /user/create?name=tom
修改  POST /user/update?id=1&name=tom
刪除  GET /user/delete?id=1

  rest風格的寫法

查詢  GET /user?name=tom
詳情  GET /user/1
創建  POST /user
修改  PUT /user
刪除  DELETE /user/1

 

rest接口設計參考:https://github.com/huobiapi/API_Docs/wiki/REST_api_reference

https://github.com/huobiapi/API_Docs

coinflext api: https://github.com/coinflex-exchange/API

 

1、Rest概念,來自百度百科

  REST即表述性狀態傳遞(英文:Representational State Transfer,簡稱REST)是Roy Fielding博士在2000年他的博士論文中提出來的一種軟件架構風格。它是一種針對網絡應用的設計和開發方式,可以降低開發的復雜性,提高系統的可伸縮性。

  目前在三種主流的Web服務實現方案中,因為REST模式的Web服務與復雜的SOAP和XML-RPC對比來講明顯的更加簡潔,越來越多的web服務開始采用REST風格設計和實現。

  

2、RESTful API的要求

  1)用URL描述資源;

  2)使用HTTP方法描述行為;使用HTTP狀態碼來表示不同的結果;

  3)使用json來交互數據;

  4)RESTful只是一種風格,並不是強制的標准。

  總結:使用URL定位資源,使用HTTP方法操作資源。

GET     用來獲取資源;
POST    用來新建資源(也可以用於更新資源);
PUT     用來更新資源;
DELETE  用來刪除資源

 

3、Glory of REST

  REST是一種軟件接口設計的模型。REST 成熟度模型:(搜索關鍵字:steps toward the glory of REST)

  

  

  level0: 使用http作為傳輸方式;

  level1: 引入資源概念,每個資源都有對應的URL;

  level2: 使用http方法進行不同的操作,使用http狀態碼來表示不同的結果。

  level3: 使用超媒體,在資源的表達中包含了鏈接信息。

 

4、springmvc/springboot開發restful API

  IndexController

@RestController
public class IndexController {
    @Autowired
    private UserService userService;
    
    @GetMapping("/user/{id}")
    public Object getUserById(@PathVariable Integer id) {
        return userService.getUserById(id);
    }
}

  測試結果:

  

5、使用MockMVC 編寫測試用例(單元測試)

  參考:https://www.cnblogs.com/xy-ouyang/p/10681965.html

  選中IndexController,右鍵/new/Junit Test Case

  

   

 

   測試用例代碼:

package com.imooc.controller;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

/**
 * @author oy
 * @date 2019年6月22日 下午11:14:56
 * @version 1.0.0
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest {

    @Autowired
    private WebApplicationContext wac;
    
    private MockMvc mocMvc;
    
    @Before
    public void setUp() throws Exception {
        mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void testGetUserById() throws Exception {
        String mvcResult = mocMvc.perform(MockMvcRequestBuilders.get("/user/1")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andDo(MockMvcResultHandlers.print()) // 打印信息
                .andExpect(MockMvcResultMatchers.status().isOk()) // 期望返回的狀態碼為200
                .andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2)) // 期望返回的json數據中有兩個字段
                .andExpect(MockMvcResultMatchers.jsonPath("$.username").value("張三")) // 期望返回的json數據中username字段的值為"張三"
                .andReturn().getResponse().getContentAsString();
    
        System.out.println("mvcResult: " + mvcResult);
    }
}

 

   控制台打印結果:

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /user/1
       Parameters = {}
          Headers = {Content-Type=[application/x-www-form-urlencoded]}

Handler:
             Type = com.imooc.controller.IndexController
           Method = public java.lang.Object com.imooc.controller.IndexController.getUserById(java.lang.Integer)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {Content-Type=[application/json;charset=UTF-8]}
     Content type = application/json;charset=UTF-8
             Body = {"username":"張三","password":"123"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
mvcResult: {"username":"張三","password":"123"}

  

  測試用例的代碼簡潔寫法:使用靜態導入

  

package com.imooc.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

/**
 * @author oy
 * @date 2019年6月22日 下午11:14:56
 * @version 1.0.0
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest {

    @Autowired
    private WebApplicationContext wac;
    
    private MockMvc mocMvc;
    
    @Before
    public void setUp() throws Exception {
        mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void testGetUserById() throws Exception {
        String mvcResult = mocMvc.perform(get("/user/1")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andDo(print()) // 打印信息
                .andExpect(status().isOk()) // 期望返回的狀態碼為200
                .andExpect(jsonPath("$.length()").value(2)) // 期望返回的json數據中有兩個字段
                .andExpect(jsonPath("$.username").value("張三"))
                .andReturn().getResponse().getContentAsString();
    
        System.out.println("mvcResult: " + mvcResult);
    }
}

 

6、@PageableDefault指定默認的分頁參數

  

 

   測試代碼:

@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest {

    @Autowired
    private WebApplicationContext wac;
    
    private MockMvc mocMvc;
    
    @Before
    public void setUp() throws Exception {
        mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void testGetUserById() throws Exception {
        String mvcResult = mocMvc.perform(get("/user/1")
//                .param("page", "2")
//                .param("size", "10")
//                .param("sort", "id,desc")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andDo(print()) // 打印信息
                .andExpect(status().isOk()) // 期望返回的狀態碼為200
                .andExpect(jsonPath("$.length()").value(2)) // 期望返回的json數據中有兩個字段
                .andExpect(jsonPath("$.username").value("張三"))
                .andReturn().getResponse().getContentAsString();
    
        System.out.println("mvcResult: " + mvcResult);
    }
}

 

  IndexController

@RestController
public class IndexController {
    @Autowired
    private UserService userService;
    
    @GetMapping("/user/{id}")
    public Object getUserById(@PathVariable Integer id, 
            @PageableDefault(page = 1, size = 10, sort = "id,asc") Pageable pageable) {
        
        String str = ReflectionToStringBuilder.toString(pageable, ToStringStyle.MULTI_LINE_STYLE);
        System.out.println(str);
        
        return userService.getUserById(id);
    }
}

 

  控制台打印結果:

org.springframework.data.domain.PageRequest@7d522180[
  sort=id,asc: ASC
  page=1
  size=10
]

 

7、測試用例中jsonpath的用法

  github上面搜索jsonpath ==> https://github.com/json-path/JsonPath

  

8、@PathVariable 以及url映射中使用正則表達式

@GetMapping("/user/{id:\\d+}")
public Object getUserById(@PathVariable Integer id) {
    return userService.getUserById(id);
}

  此時,請求url為 /user/a 時,報404。

 

參考:

  1)詳解REST架構風格:http://www.uml.org.cn/zjjs/201805142.asp

  2)REST,以及RESTful的講解:https://blog.csdn.net/qq_21383435/article/details/80032375

  3) 阮一峰:RESTful API 設計指南


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM