在前面的快速入門教程中,我們利用5分鐘構建了一個非常簡單的RESTful Webservice,現在我們來利用Spring Boot來構建一個復雜一點的RestFul API。
關于RESTful API如何設計,大家可以自行去阮一峰的博客學習一下。話說阮老師真是一個全才,感覺他都懂,程序猿楷模啊!
我們來設計一個Book的RESTful API,如下所示:
請求類型 | URL | 功能說明 |
---|---|---|
GET | /books | 查詢書籍列表 |
POST | /books | 創建書籍 |
GET | /books/id | 根據ID查詢一本書籍 |
PUT | /books/id | 根據ID更新一本書籍 |
DELETE | /books/id | 根據ID刪除一本書籍 |
Book的實體類定義如下:
public class Book {
private Long bookId;
private String title;
private String author;
//getter/setter方法省略
}
針對Book資源操作的RESTful接口實現如下:
@RestController
@RequestMapping(value="/books")
public class BookController {
// 創建線程安全的Map
static Map<Long, Book> books = Collections.synchronizedMap(new HashMap<Long, Book>());
@RequestMapping(value="/", method= RequestMethod.GET)
public List<Book> getUserList() {
// 處理"/books/"的GET請求,用來獲取圖書列表
// 還可以通過@RequestParam傳遞參數來進行查詢條件或者翻頁信息的傳遞
List<Book> r = new ArrayList<Book>(books.values());
return r;
}
@RequestMapping(value="/", method=RequestMethod.POST,produces = "application/json")
public String createBook(@RequestBody Book book) {
// 處理"/books/"的POST請求,用來創建User
// 除了@ModelAttribute綁定參數之外,還可以通過@RequestParam從頁面中傳遞參數
books.put(book.getBookId(), book);
return "success";
}
@RequestMapping(value="/{bookId}", method=RequestMethod.GET)
public Book getBook(@PathVariable Long bookId) {
// 處理"/books/{id}"的GET請求,用來獲取url中id值的Book信息
// url中的id可通過@PathVariable綁定到函數的參數中
return books.get(bookId);
}
@RequestMapping(value="/{bookId}", method=RequestMethod.PUT)
public String putBook(@PathVariable Long bookId, @RequestBody Book book) {
// 處理"/books/{bookId}"的PUT請求,用來更新Book信息
Book b = books.get(bookId);
b.setTitile(book.getTitile());
b.setAuthor(book.getAuthor());
books.put(bookId, b);
return "success";
}
@RequestMapping(value="/{bookId}", method=RequestMethod.DELETE)
public String deleteBook(@PathVariable Long bookId) {
// 處理"/books/{bookId}"的DELETE請求,用來刪除Book
books.remove(bookId);
return "success";
}
}
單元測試
之前我們在入門教程中使用了Postman來進行測試,現在我們使用Spring自家的MockMvc框架來寫單元測試,MockMvc的使用很簡單,更詳細的用法大家可以自行Google或百度。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class TestBookController {
private MockMvc mvc;
private RequestBuilder request = null;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new BookController()).build();
request = null;
}
public void testGet() throws Exception{
request = get("/books/");
mvc.perform(request)
.andExpect(status().isOk())
.andExpect(content().string(equalTo("[]")));
}
public void testPost() throws Exception{
Book book = new Book();
book.setBookId(Long.parseLong("1"));
book.setTitile("Spring Boot Tutorial");
book.setAuthor("bluecoffee");
ObjectMapper objectMapper = new ObjectMapper();
String jsonBook = objectMapper.writeValueAsString(book);
request = post("/books/")
.contentType(MediaType.APPLICATION_JSON)
.content(jsonBook.getBytes());
mvc.perform(request)
.andExpect(status().isOk())
.andExpect(content().string(equalTo("success")));
String respStr = mvc.perform(get("/books/"))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("[" + jsonBook + "]")))
.andReturn().getResponse().getContentAsString();
System.out.println("testPost.resp:"+respStr);
}
public void testPut() throws Exception{
Book book = new Book();
book.setBookId(Long.parseLong("1"));
book.setTitile("Spring Boot學習教程");
book.setAuthor("Alex Qian");
ObjectMapper objectMapper = new ObjectMapper();
String jsonBook = objectMapper.writeValueAsString(book);
request = put("/books/" + book.getBookId())
.contentType(MediaType.APPLICATION_JSON)
.content(jsonBook.getBytes());
mvc.perform(request)
.andExpect(status().isOk())
.andExpect(content().string(equalTo("success")));
String respStr = mvc.perform(get("/books/"+book.getBookId()))
.andExpect(status().isOk())
.andExpect(content().string(equalTo(jsonBook)))
.andReturn().getResponse().getContentAsString();
System.out.println("testPut.resp:"+respStr);
}
public void testDelete() throws Exception{
request = delete("/books/1");
mvc.perform(request)
.andExpect(status().isOk())
.andExpect(content().string(equalTo("success")));
String respStr = mvc.perform(get("/books/"))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("[]")))
.andReturn().getResponse().getContentAsString();
System.out.println("testDelete.resp:"+respStr);
}
@Test
public void testSuite() throws Exception{
this.testGet();//獲取一本書籍
this.testPost();//創建一本書籍
this.testPut();//更新一本書籍
this.testDelete();//刪除一本書籍
}
}
小結
在這次教程里面,我們僅引入Spring Boot的web模塊,并且沒有引入任何配置文件,就構建了一個較完整的RESTful API,文中還簡要介紹了@PathVariable,@RequestBody,@RequestParam等參數綁定注解的用法,更多的用法大家可以自行去網上查詢資料。
完整代碼戳這里: Chapter 3-1-1 - 構建復雜RESTful API及單元測試