前言
在前面的章节中,壹哥 给大家介绍了在前后端不分离的开发模式中,SpringBoot是如何处理静态资源的。但是现在真正的企业开发中,前后端分离才是比较流行的开发模式。而在这种开发模式中,前端团队负责UI界面,后端团队负责实现Web接口和核心业务逻辑,两个团队之间密切配合,共同完成项目开发。
前端需要调用后端的Web接口,而后端团队也需要把数据以合适的格式传递给前端,现在主流的数据载体是用JSON格式。另外因为Web接口是后端团队开发的,前端团队并不知道这个Web接口的定义和使用规则,所以现在比较流行基于RESTful风格的Web接口设计,这样设计出来的Web接口就都遵循着一定的规范,前端调用时就会比较安全、方便。
接下来 壹哥 就会给大家介绍基于RESTful的接口设计风格,并且在SpringBoot中设计出符合该风格的URL接口。
一. RESTful架构简介
在进行真正的代码实战之前,我们先来了解一下RESTful风格到底是咋回事。
1. RESTful架构概述
所谓的RESTful架构,其实是目前最流行的一种互联网软件架构风格,它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多的网站采用。
但是,RESTful架构到底是怎么一回事呢?
2. RESTful架构起源
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Roy Thomas Fielding是一个很重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。
所以,他的这篇论文一发表,就引起了很多人的关注,并且立即对互联网开发产生了深远的影响。
Roy Thomas Fielding将他对互联网软件的架构原则,定名为REST,也就是REpresentational State Transfer(3个单词的首字母)的缩写,一般翻译为"表现层状态转化"或者是”表述性状态转移“。
3. RESTful架构含义
如果我们想理解RESTful的架构风格,可以先来看看RESTful这个单词的组成。
- 资源(Resources):REST的名称是"表现层状态转化",其实是资源(Resources)的"表现层状态转化"。这里所谓的"资源",其实就是网络上存储的一个具体信息或数据,它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的数据。我们可以用一个URI(统一资源标识符)指向这些资源,每种资源都对应一个特定的URI。要获取这个资源,通过访问它对应的URI就可以了,因此该URI就代表了每一个资源的地址或独一无二的识别符号。
- 表述性(REpresentational): "资源"是一种信息实体,它可以有多种外在的表现形式,我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。REST 资源实际上可以用各种形式来进行表现,比如文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现,我们可以使用最适合资源的任意形式。
- 状态(State): 当使用 REST 的时候,我们更关注资源的状态而不是对资源采取的行为。
- 转义(Transfer): REST 涉及到转移资源数据,它以某种表述性形式从一个应用转移到另一个应用。
如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer),而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。
通过对RESTful单词的解释,相信你对其含义多少会有所理解。
4. RESTful架构
综合上面的解释,我们总结一下什么是RESTful架构,其核心包括如下:
- 每一个URI都代表着一种资源;
- 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化”。
简单的说,RESTful就是将资源的状态以适合客户端或服务端的形式从服务端转移到客户端(或者反过来)。在 RESTful中,资源通过 URI 进行识别和定位,然后通过某种行为(即 HTTP的方法)来完成某种功能。也就是说如果一个架构符合REST原则,就称它为RESTful架构。
以上虽然讲解了很多关于RESTful的理论知识,但是想必各位一时之间也很难理解,大家可以来千锋教育学习Java的线下课程,我们会有更详细的讲解哦。
二. 实例讲解
如果你还是不理解,别急,接下来 壹哥 会结合具体的案例进一步讲解RESTful风格。
1. Http请求方法
我们在平时的 Web 开发中,常用的http请求方法是 GET 和 POST,但是实际上,HTTP 方法还有 PATCH、DELETE、PUT 等其他方法,这些方法通常会匹配为如下的 CRUD 动作:
但这并不是严格的限制,有时候 PUT 也可以用来创建新的资源,POST 也可以用来更新资源。实际上,POST 请求非幂等的特性(即同一个 URL 可以得到不同的结果)使其成一个非常灵活地方法,对于无法适应其他 HTTP 方法语义的操作,它都能够胜任。
2. HTTP请求方法的用法
HTTP方法中的GET和HEAD请求都是安全的,无论请求多少次,都不会改变服务器状态。GET、HEAD、PUT和DELETE请求都是满足幂等性要求的,也就是无论对资源操作多少次,结果总是一样的,后面的请求并不会产生比第一次更多的影响。
- 幂等性:对同一REST接口的多次访问,得到的资源状态是相同的。
- 安全性:对该REST的接口访问,不会使服务器端资源的状态发生改变。
- GET:安全且幂等;
- POST:不安全且不幂等;
- PUT:不安全但幂等;
- DELETE:不安全但幂等。
3. RESTful案例
在使用 RESTful 风格之前,我们如果想要增加一条分类数据通常是这样的:
/addCategory?name=xxx
但是使用了 RESTful 风格之后就会变成:
/category
我们可以使用同一个 URI ,通过约定不同的 HTTP 方法来实现不同的业务,例如下图所示:
4. RESTful的反面案例
RESTful风格的接口要求使用标准的HTTP方法对资源进行操作,所以URI只应该用来表示资源的名称,而不应该包括对资源的动作操作。
通俗来说,URI不应该使用动作来描述。例如,下面是一些不符合统一接口要求的URI:
GET/getUser/1POST /createUserPUT /updateUser/1DELETE /deleteUser/1
三. SpringBoot中实现RESTful架构风格
理论知识分析完毕,咱们就通过代码来实操一把,看看基于RESTful风格设计出来的URL接口到底长什么样。
1. 需求分析
我们以操作用户相关的业务为例,如果采用RESTful API 设计,可以如下所示:
2. 添加依赖包
这里我们添加必要的核心依赖包。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--简化bean代码--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
3. 创建一个实体类User
创建一个实体类,封装我们测试时的用户信息,各位可以随便创建一个自己的实体类。
packagecom.yyg.boot.domain; importlombok.Data; importjava.io.Serializable; /*** @Author 一一哥Sun* @Date Created in 2020/5/13* @Description Description*/publicclassUserimplementsSerializable { privateLongid; privateStringname; privateIntegerage; }
4. 创建Controller接口方法
我们的RESTful风格的URL接口,主要就是在这里实现的,这里我把核心代码一股脑都粘贴过来了,各位可以参考着实现,每个方法的含义在注释中都有说明。
packagecom.yyg.boot.web; importcom.yyg.boot.domain.User; importlombok.extern.slf4j.Slf4j; importorg.springframework.web.bind.annotation.*; importjava.util.*; /*** @Author 一一哥Sun* @Date Created in 2020/5/13* @Description Description*/"/users") (publicclassUserController { /*** 创建线程安全的Map*/privatestaticMap<Long, User>users=Collections.synchronizedMap(newHashMap<>()); /*** 处理GET请求,用来获取用户列表.* 可以通过@RequestParam获取从页面中传递进来的查询条件或者翻页信息等参数.*/value="/") (publicList<User>getUserList() { returnnewArrayList<>(users.values()); } /*** 处理POST请求,用来创建User.* 除了@ModelAttribute绑定参数之外,还可以通过@RequestParam从页面中传递参数.*/value="/") (publicStringaddUser(Useruser) { users.put(user.getId(), user); log.warn("user==="+users.get(user.getId())); return"success"; } /*** 处理GET请求,用来获取url中id值的User信息;* url中的id可通过@PathVariable绑定到函数的参数中.*/value="/{id}") (publicUsergetUser(Longid) { returnusers.get(id); } /*** 处理PUT请求,用来更新User信息.*/value="/{id}") (publicStringupdateUser(Longid, Useruser) { Useru=users.get(id); u.setName(user.getName()); u.setAge(user.getAge()); users.put(id, u); return"success"; } /*** 处理DELETE请求,用来删除User*/value="/{id}") (publicStringdeleteUser(Longid) { users.remove(id); return"success"; } }
5. 创建入口类
最后我们创建一个入口类,启动该入口类进行项目测试。
packagecom.yyg.boot; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; /*** @Author 一一哥Sun* @Date Created in 2020/5/13* @Description Description*/publicclassRestfulApplication { publicstaticvoidmain(String[] args){ SpringApplication.run(RestfulApplication.class,args); } }
四. 运行测试
代码编写完毕之后,我们就开始进行接口测试了。这里我采用后端开发时比较流行的Postman来作为测试工具,这是后端开发人员必备工具,各位直接百度下载一个即可。
1. 添加一个新用户
在Postman中,我们执行一个post请求,传递json格式的参数。
可以看到执行结果是success,说明该接口成功的执行了。
2. 查询全部用户
执行get请求,查询刚才添加的用户,不需要传递任何参数。
3. 更新用户信息
执行put请求,传递id作为参数。
4. 查询更新后的结果
5. 删除用户
执行delete请求,删除id为1的用户。
6. 查询删除后的结果
至此我们实现了SpringBoot中的RESTful风格的uri设计。
结语
至此,壹哥 就把RESTful风格的url接口设计出来了,并且带大家学习了如何使用PostMan这样的测试工具,以后各位再设计接口时,不要再随意编写你的Web接口了,请一定要遵循RESTful风格哦。
今日小作业:
基于RESTful风格,规划学生信息管理系统的Web接口,实现学生信息的增删改查功能。