本文屬於原創,轉載註明出處,歡迎關注微信小程序小白AI博客
微信公衆號小白AI
或者網站 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,如碼雲(gitee.com/api/v5/swag…)小程序
特例講述:用戶登陸和登出的 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 應用劃分爲模型、視圖與控制器三個部分:
下圖框架是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的開發。接下來,繼續!