REST(Representational State Transfer),表現形式狀態轉換,它是一種軟體架構風格
當我們想表示一個網路資源的時候,可以使用兩種方式:
傳統風格資源描述形式
http://localhost/user/getById?id=1
查詢id為1的使用者資訊
http://localhost/user/saveUser
儲存使用者資訊
REST風格描述形式
http://localhost/user/1
http://localhost/user
傳統方式一般是一個請求url對應一種操作,這樣做不僅麻煩,也不安全,因為會程式的人讀取了你的請求url地址,就大概知道該url實現的是一個什麼樣的操作。
檢視REST風格的描述,你會發現請求地址變的簡單了,並且光看請求URL並不是很能猜出來該URL的具體功能
所以REST的優點有:
隱藏資源的存取行為,無法通過地址得知對資源是何種操作
書寫簡化
但是我們的問題也隨之而來了,一個相同的url地址即可以是新增也可以是修改或者查詢,那麼到底我們該如何區分該請求到底是什麼操作呢?
按照REST風格存取資源時使用行為動作區分對資源進行了何種操作
http://localhost/users
查詢全部使用者資訊 採用GET請求(查詢)
http://localhost/users/1
查詢指定使用者資訊 採用GET請求(查詢)
http://localhost/users
新增使用者資訊 採用POST請求(新增/儲存)
http://localhost/users
修改使用者資訊 採用PUT請求(修改/更新)
http://localhost/users/1
刪除使用者資訊 採用DELETE請求(刪除)
請求的方式比較多,但是比較常用的就4種,分別是GET
,POST
,PUT
,DELETE
。
按照不同的請求方式代表不同的操作型別。
傳送GET請求是用來做查詢
傳送POST請求是用來做新增
傳送PUT請求是用來做修改
傳送DELETE請求是用來做刪除
注意:
上述行為是約定方式,約定不是規範,可以打破,所以稱REST風格,而不是REST規範
REST提供了對應的架構方式,按照這種架構設計專案可以降低開發的複雜性,提高系統的可伸縮性
REST中規定GET/POST/PUT/DELETE針對的是查詢/新增/修改/刪除,但是我們如果非要用GET請求做刪除,這點在程式上執行是可以實現的
描述模組的名稱通常使用複數,也就是加s的格式描述,表示此類資源,而非單個資源,例如:users、books、accounts......
清楚了什麼是REST風格後,我們後期會經常提到一個概念叫RESTful
,那什麼又是RESTful呢?
根據REST風格對資源進行存取稱為RESTful。
後期我們在進行開發的過程中,大多是都是遵從REST風格來存取我們的後臺服務,所以可以說咱們以後都是基於RESTful來進行開發的。
建立一個Web的Maven專案
pom.xml新增Spring依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>springmvc_06_rest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
建立對應的設定類
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//亂碼處理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
@Configuration
@ComponentScan("com.itheima.controller")
//開啟json資料型別自動轉換
@EnableWebMvc
public class SpringMvcConfig {
}
編寫模型類User和Book
public class User {
private String name;
private int age;
//getter...setter...toString省略
}
public class Book {
private String name;
private double price;
//getter...setter...toString省略
}
編寫UserController和BookController
@Controller
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(@RequestBody User user) {
System.out.println("user save..."+user);
return "{'module':'user save'}";
}
@RequestMapping("/delete")
@ResponseBody
public String delete(Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
@RequestMapping("/update")
@ResponseBody
public String update(@RequestBody User user) {
System.out.println("user update..." + user);
return "{'module':'user update'}";
}
@RequestMapping("/getById")
@ResponseBody
public String getById(Integer id) {
System.out.println("user getById..." + id);
return "{'module':'user getById'}";
}
@RequestMapping("/findAll")
@ResponseBody
public String getAll() {
System.out.println("user getAll...");
return "{'module':'user getAll'}";
}
}
@Controller
public class BookController {
@RequestMapping(value = "/books",method = RequestMethod.POST)
@ResponseBody
public String save(@RequestBody Book book){
System.out.println("book save..." + book);
return "{'module':'book save'}";
}
@RequestMapping(value = "/books/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println("book delete..." + id);
return "{'module':'book delete'}";
}
@RequestMapping(value = "/books",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody Book book){
System.out.println("book update..." + book);
return "{'module':'book update'}";
}
@RequestMapping(value = "/books/{id}",method = RequestMethod.GET)
@ResponseBody
public String getById(@PathVariable Integer id){
System.out.println("book getById..." + id);
return "{'module':'book getById'}";
}
@RequestMapping(value = "/books",method = RequestMethod.GET)
@ResponseBody
public String getAll(){
System.out.println("book getAll...");
return "{'module':'book getAll'}";
}
}
最終建立好的專案結構如下:
需求:將增刪改查替換成RESTful的開發方式。
1.不同的請求有不同的路徑,現在要將其修改為統一的請求路徑
修改前: 新增: /save ,修改: /update,刪除 /delete...
修改後: 增刪改查: /users
2.根據GET查詢、POST新增、PUT修改、DELETE刪除對方法的請求方式進行限定
3.傳送請求的過程中如何設定請求引數?
@Controller
public class UserController {
//設定當前請求方法為POST,表示REST風格中的新增操作
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save() {
System.out.println("user save...");
return "{'module':'user save'}";
}
}
將請求路徑更改為/users
存取該方法使用 POST: http://localhost/users
使用method屬性限定該方法的存取方式為POST
如果傳送的不是POST請求,比如傳送GET請求,則會報錯
@Controller
public class UserController {
//設定當前請求方法為DELETE,表示REST風格中的刪除操作
@RequestMapping(value = "/users",method = RequestMethod.DELETE)
@ResponseBody
public String delete(Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
}
將請求路徑更改為/users
存取該方法使用 DELETE: http://localhost/users
存取成功,但是刪除方法沒有攜帶所要刪除資料的id,所以針對RESTful的開發,如何攜帶資料引數?
前端傳送請求的時候使用:http://localhost/users/1
,路徑中的1
就是我們想要傳遞的引數。
後端獲取引數,需要做如下修改:
修改@RequestMapping的value屬性,將其中修改為/users/{id}
,目的是和路徑匹配
在方法的形參前新增@PathVariable註解
@Controller
public class UserController {
//設定當前請求方法為DELETE,表示REST風格中的刪除操作
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
}
思考如下兩個問題:
(1)如果方法形參的名稱和路徑{}
中的值不一致,該怎麼辦?
(2)如果有多個引數需要傳遞該如何編寫?
前端傳送請求的時候使用:http://localhost/users/1/tom
,路徑中的1
和tom
就是我們想要傳遞的兩個引數。
後端獲取引數,需要做如下修改:
@Controller
public class UserController {
//設定當前請求方法為DELETE,表示REST風格中的刪除操作
@RequestMapping(value = "/users/{id}/{name}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id,@PathVariable String name) {
System.out.println("user delete..." + id+","+name);
return "{'module':'user delete'}";
}
}
@Controller
public class UserController {
//設定當前請求方法為PUT,表示REST風格中的修改操作
@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody User user) {
System.out.println("user update..." + user);
return "{'module':'user update'}";
}
}
將請求路徑更改為/users
存取該方法使用 PUT: http://localhost/users
存取並攜帶引數:
@Controller
public class UserController {
//設定當前請求方法為GET,表示REST風格中的查詢操作
@RequestMapping(value = "/users/{id}" ,method = RequestMethod.GET)
@ResponseBody
public String getById(@PathVariable Integer id){
System.out.println("user getById..."+id);
return "{'module':'user getById'}";
}
}
將請求路徑更改為/users
存取該方法使用 GET: http://localhost/users/666
@Controller
public class UserController {
//設定當前請求方法為GET,表示REST風格中的查詢操作
@RequestMapping(value = "/users" ,method = RequestMethod.GET)
@ResponseBody
public String getAll() {
System.out.println("user getAll...");
return "{'module':'user getAll'}";
}
}
將請求路徑更改為/users
存取該方法使用 GET: http://localhost/users
小結
RESTful入門案例,我們需要學習的內容如下:
(1)設定Http請求動作(動詞)
@RequestMapping(value="",method = RequestMethod.POST|GET|PUT|DELETE)
(2)設定請求引數(路徑變數)
@RequestMapping(value="/users/{id}",method = RequestMethod.DELETE)
@ReponseBody
public String delete(@PathVariable Integer id){
}
名稱 | @PathVariable |
---|---|
型別 | 形參註解 |
位置 | SpringMVC控制器方法形參定義前面 |
作用 | 繫結路徑引數與處理器方法形參間的關係,要求路徑引數名與形參名一一對應 |
關於接收引數三個註解@RequestBody
、@RequestParam
、@PathVariable
,這三個註解之間的區別和應用分別是什麼?
區別
@RequestParam用於接收url地址傳參或表單傳參
@RequestBody用於接收json資料
@PathVariable用於接收路徑引數,使用{引數名稱}描述路徑引數
應用
後期開發中,傳送請求引數超過1個時,以json格式為主,@RequestBody應用較廣
如果傳送非json格式資料,選用@RequestParam接收請求引數
採用RESTful進行開發,當引數數量較少時,例如1個,可以採用@PathVariable接收請求路徑變數,通常用於傳遞id值
做完了RESTful的開發,你會發現好麻煩,麻煩在哪?
對於上面所提的這三個問題,具體該如何解決?
@RestController //@Controller + ReponseBody
@RequestMapping("/books")
public class BookController {
//@RequestMapping(method = RequestMethod.POST)
@PostMapping
public String save(@RequestBody Book book){
System.out.println("book save..." + book);
return "{'module':'book save'}";
}
//@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("book delete..." + id);
return "{'module':'book delete'}";
}
//@RequestMapping(method = RequestMethod.PUT)
@PutMapping
public String update(@RequestBody Book book){
System.out.println("book update..." + book);
return "{'module':'book update'}";
}
//@RequestMapping(value = "/{id}",method = RequestMethod.GET)
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("book getById..." + id);
return "{'module':'book getById'}";
}
//@RequestMapping(method = RequestMethod.GET)
@GetMapping
public String getAll(){
System.out.println("book getAll...");
return "{'module':'book getAll'}";
}
}
對於剛才的問題,我們都有對應的解決方案:
每個方法的@RequestMapping註解中都定義了存取路徑/books,重複性太高。
將@RequestMapping提到類上面,用來定義所有方法共同的存取路徑。
每個方法的@RequestMapping註解中都要使用method屬性定義請求方式,重複性太高。
使用@GetMapping @PostMapping @PutMapping @DeleteMapping代替
每個方法響應json都需要加上@ResponseBody註解,重複性太高。
1.將ResponseBody提到類上面,讓所有的方法都有@ResponseBody的功能
2.使用@RestController註解替換@Controller與@ResponseBody註解,簡化書寫
名稱 | @RestController |
---|---|
型別 | 類註解 |
位置 | 基於SpringMVC的RESTful開發控制器類定義上方 |
作用 | 設定當前控制器類為RESTful風格, 等同於@Controller與@ResponseBody兩個註解組合功能 |
名稱 | @GetMapping @PostMapping @PutMapping @DeleteMapping |
---|---|
型別 | 方法註解 |
位置 | 基於SpringMVC的RESTful開發控制器方法定義上方 |
作用 | 設定當前控制器方法請求存取路徑與請求動作,每種對應一個請求動作, 例如@GetMapping對應GET請求 |
相關屬性 | value(預設):請求存取路徑 |
本文來自部落格園,作者:|舊市拾荒|,轉載請註明原文連結:https://www.cnblogs.com/xiaoyh/p/16444673.html