一、REST簡介
REST(Representational State Transfer),表現(xiàn)形式狀態(tài)轉(zhuǎn)換,它是一種軟件架構(gòu)風(fēng)格
當(dāng)我們想表示一個(gè)網(wǎng)絡(luò)資源的時(shí)候,可以使用兩種方式:
- 傳統(tǒng)風(fēng)格資源描述形式
-
http://localhost/user/getById?id=1
查詢id為1的用戶信息 -
http://localhost/user/saveUser
保存用戶信息
-
- REST風(fēng)格描述形式
http://localhost/user/1
http://localhost/user
REST的優(yōu)點(diǎn)有:
- 隱藏資源的訪問行為,無法通過地址得知對資源是何種操作
- 書寫簡化
按照REST風(fēng)格訪問資源時(shí)使用行為動作區(qū)分對資源進(jìn)行了何種操作
-
http://localhost/users
查詢?nèi)坑脩粜畔?GET(查詢) -
http://localhost/users/1
查詢指定用戶信息 GET(查詢) -
http://localhost/users
添加用戶信息 POST(新增/保存) -
http://localhost/users
修改用戶信息 PUT(修改/更新) -
http://localhost/users/1
刪除用戶信息 DELETE(刪除)
請求的方式比較多,但是比較常用的就4種,分別是GET
,POST
,PUT
,DELETE
,按照不同的請求方式代表不同的操作類型。
- 發(fā)送GET請求是用來做查詢
- 發(fā)送POST請求是用來做新增
- 發(fā)送PUT請求是用來做修改
- 發(fā)送DELETE請求是用來做刪除
清楚了什么是REST風(fēng)格后,我們后期會經(jīng)常提到一個(gè)概念叫RESTful
,那什么又是RESTful呢?
- 根據(jù)REST風(fēng)格對資源進(jìn)行訪問稱為RESTful
二、RESTful入門案例
2.1、環(huán)境準(zhǔn)備
- 創(chuàng)建一個(gè)Web的Maven項(xiàng)目 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.liming</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>
- 創(chuàng)建對應(yīng)的配置類
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數(shù)據(jù)類型自動轉(zhuǎn)換
@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'}";
}
}
最終創(chuàng)建好的項(xiàng)目結(jié)構(gòu)如下:
2.2、修改RESTful風(fēng)格
新增
@Controller
public class UserController {
//設(shè)置當(dāng)前請求方法為POST,表示REST風(fēng)格中的添加操作
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save() {
System.out.println("user save...");
return "{'module':'user save'}";
}
}
刪除
@Controller
public class UserController {
//設(shè)置當(dāng)前請求方法為DELETE,表示REST風(fēng)格中的刪除操作
@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
- 訪問該方法使用 DELETE:
訪問成功,但是刪除方法沒有攜帶所要?jiǎng)h除數(shù)據(jù)的id,所以針對RESTful的開發(fā),如何攜帶數(shù)據(jù)參數(shù)?
傳遞路徑參數(shù)
前端發(fā)送請求的時(shí)候使用:http://localhost/users/1
,路徑中的1
就是我們想要傳遞的參數(shù)。
后端獲取參數(shù),需要做如下修改:
- 修改@RequestMapping的value屬性,將其中修改為
/users/{id}
,目的是和路徑匹配 - 在方法的形參前添加@PathVariable注解
@Controller
public class UserController {
//設(shè)置當(dāng)前請求方法為DELETE,表示REST風(fēng)格中的刪除操作
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
}
思考如下兩個(gè)問題:
(1)如果方法形參的名稱和路徑{}
中的值不一致,該怎么辦?
(2)如果有多個(gè)參數(shù)需要傳遞該如何編寫?
前端發(fā)送請求的時(shí)候使用:http://localhost/users/1/tom
,路徑中的1
和tom
就是我們想要傳遞的兩個(gè)參數(shù)。
后端獲取參數(shù),需要做如下修改:
@Controller
public class UserController {
//設(shè)置當(dāng)前請求方法為DELETE,表示REST風(fēng)格中的刪除操作
@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 {
//設(shè)置當(dāng)前請求方法為PUT,表示REST風(fēng)格中的修改操作
@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
- 訪問該方法使用 PUT:
-
訪問并攜帶參數(shù):
根據(jù)ID查詢
@Controller
public class UserController {
//設(shè)置當(dāng)前請求方法為GET,表示REST風(fēng)格中的查詢操作
@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 {
//設(shè)置當(dāng)前請求方法為GET,表示REST風(fēng)格中的查詢操作
@RequestMapping(value = "/users" ,method = RequestMethod.GET)
@ResponseBody
public String getAll() {
System.out.println("user getAll...");
return "{'module':'user getAll'}";
}
}
將請求路徑更改為/users
- 訪問該方法使用 GET:
http://localhost/users
小結(jié)
RESTful入門案例,我們需要學(xué)習(xí)的內(nèi)容如下:
(1)設(shè)定Http請求動作(動詞)
@RequestMapping(value=“”,method = RequestMethod.POST|GET|PUT|DELETE)
(2)設(shè)定請求參數(shù)(路徑變量)
@RequestMapping(value=“/users/{id}”,method = RequestMethod.DELETE)
@ReponseBody
public String delete(@PathVariable Integer id){
}
知識點(diǎn)1:@PathVariable
名稱 | @PathVariable |
---|---|
類型 | 形參注解 |
位置 | SpringMVC控制器方法形參定義前面 |
作用 | 綁定路徑參數(shù)與處理器方法形參間的關(guān)系,要求路徑參數(shù)名與形參名一一對應(yīng) |
關(guān)于接收參數(shù),我們學(xué)過三個(gè)注解@RequestBody
、@RequestParam
、@PathVariable
,這三個(gè)注解之間的區(qū)別和應(yīng)用分別是什么?
- 區(qū)別
- @RequestParam用于接收url地址傳參或表單傳參
- @RequestBody用于接收json數(shù)據(jù)
- @PathVariable用于接收路徑參數(shù),使用{參數(shù)名稱}描述路徑參數(shù)
- 應(yīng)用
- 后期開發(fā)中,發(fā)送請求參數(shù)超過1個(gè)時(shí),以json格式為主,@RequestBody應(yīng)用較廣
- 如果發(fā)送非json格式數(shù)據(jù),選用@RequestParam接收請求參數(shù)
- 采用RESTful進(jìn)行開發(fā),當(dāng)參數(shù)數(shù)量較少時(shí),例如1個(gè),可以采用@PathVariable接收請求路徑變量,通常用于傳遞id值
三、RESTful快速開發(fā)
做完了RESTful的開發(fā),你會發(fā)現(xiàn)好麻煩,麻煩在哪?
問題1:每個(gè)方法的@RequestMapping注解中都定義了訪問路徑/books,重復(fù)性太高。
問題2:每個(gè)方法的@RequestMapping注解中都要使用method屬性定義請求方式,重復(fù)性太高。
問題3:每個(gè)方法響應(yīng)json都需要加上@ResponseBody注解,重復(fù)性太高。
對于上面所提的這三個(gè)問題,具體該如何解決?
@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'}";
}
}
對于剛才的問題,我們都有對應(yīng)的解決方案:
問題1:每個(gè)方法的@RequestMapping注解中都定義了訪問路徑/books,重復(fù)性太高。
將@RequestMapping提到類上面,用來定義所有方法共同的訪問路徑。
問題2:每個(gè)方法的@RequestMapping注解中都要使用method屬性定義請求方式,重復(fù)性太高。文章來源:http://www.zghlxwxcb.cn/news/detail-414112.html
使用@GetMapping @PostMapping @PutMapping @DeleteMapping代替
問題3:每個(gè)方法響應(yīng)json都需要加上@ResponseBody注解,重復(fù)性太高。文章來源地址http://www.zghlxwxcb.cn/news/detail-414112.html
1.將ResponseBody提到類上面,讓所有的方法都有@ResponseBody的功能
2.使用@RestController注解替換@Controller與@ResponseBody注解,簡化書寫
知識點(diǎn)1:@RestController
名稱 | @RestController |
---|---|
類型 | 類注解 |
位置 | 基于SpringMVC的RESTful開發(fā)控制器類定義上方 |
作用 | 設(shè)置當(dāng)前控制器類為RESTful風(fēng)格, 等同于@Controller與@ResponseBody兩個(gè)注解組合功能 |
知識點(diǎn)2:@GetMapping @PostMapping @PutMapping @DeleteMapping
名稱 | @GetMapping @PostMapping @PutMapping @DeleteMapping |
---|---|
類型 | 方法注解 |
位置 | 基于SpringMVC的RESTful開發(fā)控制器方法定義上方 |
作用 | 設(shè)置當(dāng)前控制器方法請求訪問路徑與請求動作,每種對應(yīng)一個(gè)請求動作, 例如@GetMapping對應(yīng)GET請求 |
相關(guān)屬性 | value(默認(rèn)):請求訪問路徑 |
到了這里,關(guān)于Rest風(fēng)格的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!