本文屬於原創,轉載註明出處,歡迎關注微信小程序小白AI博客
微信公衆號小白AI
或者網站 https://xiaobaiai.nethtml
[TOC]java
這一節咱們正式進入Spring Boot
的WEB服務開發,在WEB服務中,不可缺乏的咱們須要去提供API出來,那麼就少不了設計API,而當前流行的一套API設計風格就是REST API ,接下來咱們會介紹什麼是RESTful API以及它的特色和如何去設計。完成設計後,咱們會使用Spring Boot + MVC架構去實現一個RESTful Web Service。本文的全部內容都是通過多方面考察和參考官方資料,本着嚴謹的態度爲本身也爲一塊兒學習的同窗們負責,由淺入深,層層展開,讓本身有不同的收穫。一塊兒加油吧!git
名詞術語 | 釋義 |
---|---|
RESTful | RESTFUL是一種網絡應用程序的設計風格和開發方式,是目前流行的 API 設計規範,用於 Web 數據接口的設計。經過使用事先定義好的接口與不一樣的服務聯繫起來,瀏覽器使用POST,DELETE,PUT和GET四種主要請求方式分別對指定的URL資源進行增刪改查操做。所以,RESTful是經過URI實現對資源的管理及訪問,具備擴展性強、結構清晰的特色。 |
RESTful
是目前流行的 API
設計規範,用於 Web
數據接口的設計。web
RESTful
對 URL 或者 API 的設計總的原則就是將全部操做對象都看做一個資源,操做這個(些)資源(名詞)的方法經過 HTTP的方法類型(動詞)去實現:spring
# GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE GET:讀取(Read)資源信息 POST:新建(Create)資源 PUT:更新(Update)資源 PATCH:更新(Update)資源,一般是部分更新 DELETE:刪除(Delete)資源
經過對於上述概念的理解,咱們舉一些經常使用示例來判斷設計是否符合RESTful規範。json
POST /api/v1/users/login # 否,具體分析見後面 POST /api/v1/users # 是,建立一個新用戶 GET /api/v1/users/:username # 是,獲取全部用戶信息或者指定用戶名的信息 DELETE /api/v1/users/:username # 是,刪除全部用戶或者刪除指定用戶 GET /api/v1/getUserInfo # 否,自己就是利用HTTP的方法作動詞,無需另外添加
更多的 RESTful API 示例能夠參考主流網站的開發API,如碼雲(https://gitee.com/api/v5/swagger)小程序
特例講述:用戶登陸和登出的 RESTful API 怎麼設計呢?segmentfault
登陸(login)和登出(logout)是兩個動做,自己也是兩個動詞,所以從表面上看咱們是沒法設計成RESTful API的微信小程序
/api/v1/users/login
body參數爲username和password,這樣既不安全也不是RESTful APIOAuth
來實現受權操做由於,這裏的結論就是登陸登出僅做爲URL設計,並不做爲RESTful API
設計。api
注意:一些HTTP方法,例如HEAD,GET,OPTIONS和TRACE被定義爲安全的,這意味着它們僅用於信息獲取,而沒有更改服務器的狀態。而POST、PUT、DELETE就不是定義爲安全的,由於會更新信息狀態。
關於無狀態:無狀態意味着每一個HTTP請求都是徹底隔離的。客戶端發出HTTP請求時,它包含服務器完成該請求所需的全部信息。服務器從不依賴先前請求中的信息。若是該信息很重要,則客戶端將不得不在後續請求中再次發送該信息。無狀態也帶來了新功能。在負載平衡的服務器之間分發無狀態應用程序更加容易。無狀態應用程序也易於緩存。
在MVC/Model 2 中, 將Web 應用劃分爲模型、視圖與控制器三個部分:
控制器(Controller)的職責,橋樑
模型(Model)的職責
視圖(View)的職責
下圖框架是Model2
的結構。MVC框架有兩個版本,一個是Model1
,也就是MVC的第一個版本,它的視圖中存在着大量的流程控制和代碼開發,也就是控制器和視圖還具備部分的耦合。
那MVC/Model2
跟我這一篇的講述有什麼關聯呢?由於使用Spring Boot
構建WEB應用依賴的就是spring-boot-starter-web
,而這個依賴項裏就是使用的spring-webmvc
,採用MVC結構。接下來咱們就講述如何去建立WEB服務。分兩部分來說述,一部分就是隻有控制器和視圖的簡單RESTful WEB Service
,另外一部分利用@Service
Spring Boot
應用中完整的呈現MVC結構。
咱們實現的功能就是對用戶實現簡單的管理,如查詢,新增,刪除,更新操做。設計的API以下:
# 獲取全部用戶信息 GET /api/v1/users # 新增一個用戶 POST /api/v1/users # 刪除指定用戶 DELETE /api/v1/users/{id} # 更新指定用戶信息 PUT /api/v1/users/{id}
一樣地,咱們創建一個Spring Starter Project
項目,將Spring Boot Starter Web
依賴項添加到構建配置文件pom.xml(使用Marven構建)中:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
添加用戶屬性類 User.java
:
package com.xiaobaiai; public class User { private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
添加控制器類 UserServiceController.java
:
package com.xiaobaiai; import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/v1") public class UserServiceController { private static Map<String, User> userRepo = new HashMap<>(); static { User ethan = new User(); ethan.setId("1"); ethan.setName("Ethan"); userRepo.put(ethan.getId(), ethan); User xiaoming = new User(); xiaoming.setId("2"); xiaoming.setName("Xiaoming"); userRepo.put(xiaoming.getId(), xiaoming); } @RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE) public ResponseEntity<Object> delete(@PathVariable("id") String id) { userRepo.remove(id); return new ResponseEntity<>("User is deleted successsfully", HttpStatus.OK); } @RequestMapping(value = "/users/{id}", method = RequestMethod.PUT) public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody User user) { userRepo.remove(id); user.setId(id); userRepo.put(id, user); return new ResponseEntity<>("User is updated successsfully", HttpStatus.OK); } @RequestMapping(value = "/users", method = RequestMethod.POST) public ResponseEntity<Object> createProduct(@RequestBody User user) { userRepo.put(user.getId(), user); return new ResponseEntity<>("User is created successfully", HttpStatus.CREATED); } @GetMapping(value = "/users") public ResponseEntity<Object> getProduct() { return new ResponseEntity<>(userRepo.values(), HttpStatus.OK); } }
添加應用類 Test05HelloworldApplication.java
:
package com.xiaobaiai; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Test05HelloworldApplication { public static void main(String[] args) { SpringApplication.run(Test05HelloworldApplication.class, args); } }
編譯啓動,應用實際 RESTful API 有:
# 獲取全部用戶信息 GET http://localhost:8080/api/v1/users # 新增一個用戶,參數經過body傳遞 POST http://localhost:8080/api/v1/users # 更新一個用戶信息 PUT http://localhost:8080/api/v1/users/{id} # 刪除指定用戶 DELETE http://localhost:8080/api/v1/users/{id}
利用POSTMAN能夠測試接口的功能運轉:
在《Spring Boot從零入門3_建立Hello World及項目剖析》咱們就分析過代碼,咱們這裏仍是回顧下,咱們知道 @SpringBootApplication = @Configuration + @ComponentScan + @EnableAutoConfiguration
,@ComponentScan
掃描全部類Component,如Controller,Service,Repository。而@EnableAutoConfiguration
將自動解析視圖(views),視圖解析器(view resolvers)等。@RestController
是Spring4以後加入的註解,原來在@Controller
中返回json
須要@ResponseBody
來配合,若是直接用@RestController
替代@Controller
就不須要再配置@ResponseBody
,默認返回json
格式。@RequestMapping
用來配置url映射,如今更多的也會直接用以Http Method直接關聯的映射註解來定義,好比:GetMapping
、PostMapping
、DeleteMapping
、PutMapping
等,@RequestMapping
能夠映射到整個類或特定的處理方法上,一般,類級別的註解將特定的請求路徑(或路徑模式)映射到表單控制器上,其餘方法級別
的註解做用特定的HTTP請求方法。
在控制器代碼裏,經過@RequestMapping
將/api/v1
映射到整個User
控制器上,User控制器裏具體的方法則由@RequestMapping
做用到指定的HTTP請求方法上,即用戶的增刪查改。具體的@RequestMapping
參數設置就不展開了,後面博文會專門講述經常使用註解的做用和使用。
上面的簡單RESTful WEB Service構建,直接經過Controller去訪問和操做數據的,對於MVC結構,顯然缺乏了Model專門來處理數據,對業務的邏輯處理隔離度也不夠,簡單的WEB服務需求缺乏Model
也是能夠的,畢竟這樣設計不是很複雜,不過業務大了,咱們須要儘可能下降業務邏輯與上層視圖的耦合度,增長模塊的可重用性。下面咱們來實現MVC結構。
首先咱們建立一個業務操做接口 UserService.java
包括對用戶的增刪查改 :
package com.xiaobaiai; import java.util.Collection; public interface UserService { public abstract void createUser(User user); public abstract void updateUser(String id, User user); public abstract void deleteUser(String id); public abstract Collection<User> getUsers(); }
經過@Service
建立一個組件,用於在與@RestController
類文件分開的不一樣層中編寫業務邏輯,即對用戶的增刪查改的業務邏輯實現:
package com.xiaobaiai; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { private static Map<String, User> userRepo = new HashMap<>(); static { User ethan = new User(); ethan.setId("1"); ethan.setName("Ethan"); userRepo.put(ethan.getId(), ethan); User xiaoming = new User(); xiaoming.setId("2"); xiaoming.setName("Xiaoming"); userRepo.put(xiaoming.getId(), xiaoming); } @Override public void createUser(User user) { // TODO Auto-generated method stub userRepo.put(user.getId(), user); } @Override public void updateUser(String id, User user) { // TODO Auto-generated method stub userRepo.remove(id); user.setId(id); userRepo.put(id, user); } @Override public void deleteUser(String id) { // TODO Auto-generated method stub userRepo.remove(id); } @Override public Collection<User> getUsers() { // TODO Auto-generated method stub return userRepo.values(); } }
最後在控制器類裏使用@Autowired
將Service接口與實現組裝起來。
package com.xiaobaiai; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/v1") public class UserServiceController { @Autowired UserService userService; @RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE) public ResponseEntity<Object> delete(@PathVariable("id") String id) { userService.deleteUser(id); return new ResponseEntity<>("User is deleted successsfully", HttpStatus.OK); } @RequestMapping(value = "/users/{id}", method = RequestMethod.PUT) public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody User user) { userService.updateUser(id, user); return new ResponseEntity<>("User is updated successsfully", HttpStatus.OK); } @RequestMapping(value = "/users", method = RequestMethod.POST) public ResponseEntity<Object> createProduct(@RequestBody User user) { userService.createUser(user); return new ResponseEntity<>("User is created successfully", HttpStatus.CREATED); } @GetMapping(value = "/users") public ResponseEntity<Object> getProduct() { return new ResponseEntity<>(userService.getUsers(), HttpStatus.OK); } }
相對只有控制器的WEB服務,這裏加入了@Service
實現的Model層,而UserService接口的實體是經過@Autowired
鏈接起來的,即:
@Autowired UserService userService;
固然咱們還有一種主流寫法就是經過構造函數的形式,最後達到的效果是同樣的:
UserService userService;; @Autowired public UserServiceController(UserService userService) { this.userService = userService; }
若是UserService有多個實體類,這個時候@Autowired如何去綁定實體類的呢?
這個時候須要用到@Qualifier
來指定實體類的名稱:
@Service // 指定UserServiceImpl名稱爲a @Qualifier("a") public class UserServiceImpl implements UserService { }
@Service @Qualifier("b") public class UserServiceImpl1_1 implements UserService { }
最後在控制器裏自動組裝的時候指定具體的實體類名稱就能夠了:
// 寫法1 @Autowired @Qualifier("a") UserService userService; // 寫法2 UserService userService; @Autowired public UserServiceController(@Qualifier("a") UserService userService) { this.userService = userService; }
@Resource
也可以實現自動裝配Bean的功能,那@Autowired
與@Resource
有什麼區別呢?
有了比較完善的控制器和Model,那麼對於View層有什麼專用模板引擎嗎?
Thymeleaf
是基於Java用於建立Web應用程序的的模板引擎。它爲在Web應用程序中提供XHTML / HTML5提供了良好的支持。相似的還有Apache FreeMarker
、Mustache
、Groovy Templates
。後面博文會詳解介紹。
經過對RESTful API的介紹以及結合實例工程,咱們基本瞭解了一個RESTful WEB Service
在Spring Boot
框架下是怎麼實現的。經過對工程代碼的分析,讓咱們對@Autowired
、@Resource
、Qualifier
等註解也有了實質瞭解。感受如今正式步入JAVA WEB的開發。接下來,繼續!
本文屬於原創,轉載註明出處,歡迎關注CSDNfreeape或微信小程序小白AI博客
微信公衆號小白AI
或者網站 https://xiaobaiai.net