Spring Boot 2实战权威指南——分布式篇

作者: 李家智
译者:
编辑: 曹修山

图书目录:

详情

本专栏是Spring Boot 2权威实战指南分布式篇。涉及分布式常用的技术:REST,MongDB,Redis,Elastic Search,分布式缓存,Spring Session,还有分布式中非常重要的分布协调技术Zookeeper,能使读者快速从单体应用提升到分布式应用。区别于Spring Cloud,本专栏介绍的知识是构建大型分布式系统必备技术。

图书摘要

版权信息

书名:Spring Boot 2实战权威指南——分布式篇

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


著    李家智

责任编辑 曹修山

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


本专栏是Spring Boot 2权威实战指南分布式篇。涉及分布式常用的技术:REST,MongDB,Redis,Elastic Search,分布式缓存,Spring Session,还有分布式中非常重要的分布协调技术Zookeeper,能使读者快速从单体应用提升到分布式应用。区别于Spring Cloud,本专栏介绍的知识是构建大型分布式系统必备技术。


李家智,网名闲大赋,是国内Beetl,BeetlSQL等基础软件开源作者,具有近20年的 Java编程经验,至今还在一线开发。经常在博客上发表自己的技术见解。现定居于北京,曾就职于一流的电信厂商、外企、互联网电商等,现就职于京东交易中台架构组,负责分布式系统架构升级和优化。熟悉JavaEE,Spring,分布式等技术。


9年前我在惠普公司工作的时候,接到一个工作是给某央企设计消息系统,该系统需要连接各省的业务系统,也要连接数百个全国业务系统并提供业务信息交换等功能,该系统每日处理的消息多达数亿条,而每条消息包含的业务信息又非常大。当时参与该项目竞标的都是国内外最好的消息中间件生产商。

经过数月的测试和评估,惠普公司的基于HTTP的Web应用系统方案获得了客户的赞赏。尽管在消息处理速度和可靠性上,HTTP方案会稍逊于消息中间件,但HTTP方案被认可,还是因为具有如下优点。

(1)HTTP协议较为简单,协议公开透明。

(2)HTTP的成熟性,HTTP有大量可选的Web服务器,如Tomcat,Undertow,Jetty,以及商业服务器,还有配套的Web框架,如本书讲的SpringBoot,以及配套的负载均衡工具Nginx,Apache,还有性能监控工具等。可伸缩性和性能都非常优秀。

(3)技术的松耦合,Web方案并没有与其他技术捆绑在在一起,但又能将这些技术任意集成进来

(4)Web方案成本低。Web方案,无论是购买商业服务器,还是在选用技术开发人员,成本都相对较低,可选范围广。

HTTPP方案的成功并不是偶然的,而是当时“Web即应用平台”的概念已经深入人心。当系统在对外提供服务的时候,无论是系统与系统之间,还是终端与系统之间(如PC终端、移动终端、平板终端等),双方总是会优先考虑建立在Web方式上的接口,如较早的XML-RPC、曾经流行的WebService、以及现在被广泛使用的RESTfull风格接口。

本章将介绍RESTful风格接口,讲解如何通过SpringBoot来实现RESTful,介绍Swager工具如何来增强RESTfull的维护与开发。

“REST”这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Fielding是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。所以,他的这篇论文发表后,就引起了广泛关注,并且对互联网开发产生了深远地影响。

Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写,翻译成中文意思是“表现层状态转化”。如果一个架构符合REST原则,就称它为RESTful架构。

要理解RESTful架构,最好的方法就是去理解Representational State Transfer这个词组到底是什么意思,它的每一个词代表了什么涵义。如果你把这个名称搞懂了,也就不难体会REST是一种什么样的设计。

(1)资源(Resources)

REST的全文名称“表现层状态转化”中,其实省略了主语。“表现层”指的是“资源”(Resources)的“表现层”。

所谓“资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。

(2)表现层(Representation )

“资源”是一种信息实体,它可以有多种外在表现形式。我们把“资源”具体呈现出来的形式,叫做它的“表现层”(Representation)。 比如,文本内容可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式表现,图片可以用JPG格式表现,也可以用PNG格式表现。

URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的“.html”后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而URI应该只代表“资源”的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段的内容才是对“表现层”的描述,不过在大部分应用里,通过后缀区分表现层已经足够了。

(3)状态转化(State Transfer)

访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。

互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。

客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,有5个常用来表示操作方式的动词:GET、POST、PUT、DELETE、PATCH。它们分别对应4种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,PATCH 用来更新资源部分属性。

URI (Uniform Resource Identifier)是统一资源的标示符,如http://baidu.com,ftp://xxxx。而URL(Uniform Resource Locator)是统一资源的定位符,是较早的概念,专门用于HTTP协议。

这一小节REST的定义参考了 阮一峰先生对REST的理解以及百度词条。

今天流行的各种Web框架,包括Spring Boot没有不支持REST开发的,REST并非是一种技术或者规范,而是一种架构风格。这种架构风格,逐渐被各种编程语言的各种Web框架所支持。它包括了REST 架构中如何标示资源,如何标识操作接口以及操作的版本,如何标示操作的结果等,主要内容如下。

(1)使用api作为Web上下文

(2)增加版本标识

(3)标识资源

(4)REST 中的 HTTP Method

(5)REST 中的HTTP Status

1. 使用api作为上下文

建议使用api作为上下文,如http://192.168.0.1/api

也有的使用api作为二级域名,如http://api.xxxx.com

2. 增加一个版本标示

http://192.168.0.1/api/v1.1

也有一种做法是将版本信息放到HTTP头里,但这里推荐还是通过URL 来体现,这样使得RESST相关代码更加容易阅读。

3. 标识资源

将资源名称放到URL里,如果资源有层级关系,则放入层级关系

http://192.168.0.1/api/v1.1/user。如果用户属于系统管理,也可以这么写http://192.168.0.1/api/v1.1/system/user。

4. 确定HTTP METHOD

在REST里,HTTP METHOD 常常对应如下含义。

(1)POST 代表增加资源。

(2)PUT 代表更改资源,客户端提供需完整的资源属性。

(3)GET 代表查询资源。

(4)PATCH 更新资源,客户端提供仅需要更改的资源属性。

(5)DELETE,通常用于删除资源。

(6)HEAD,类似GET,但仅仅只有HTTP 头信息,头信息包含了所需要查找的信息。

(7)OPTIONS,用于获取URI所支持的方法,响应信息会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET、POST”。

在业务系统里,删除往往并不是指物理的删除,而是逻辑删除,资源通常仍然存在数据库里,只是状态设置为删除状态。比如下面这个例子。新增用户

POST http://192.168.0.1/api/v1.1/system/user

查询用户id为451

GET http://192.168.0.1/api/v1.1/system/user/451

查询所有用户

GET http://192.168.0.1/api/v1.1/system/user

如果有翻页,可以在后面增加类似offset、limit参数,比如:

GET http://192.168.0.1/api/v1.1/system/user?offset=1&limit=20&sortBy=name&sortOrder=desc

更新用户ID为451的用户

PUT http://192.168.0.1/api/v1.1/system/user/451

删除用户ID为451的用户

DELETE http://192.168.0.1/api/v1.1/system/user/451

可以为资源标识添加后缀使得REST代码更加容易阅读,比如:

GET http://192.168.0.1/api/v1.1/system/user/451.json

返回id为451的用户信息,返回格式是JSON。

现在也有一种设计REST URI的方式,就是把操作也放到URI里,http方法主要采用GET和POST,这样做的好处同样是易于阅读。

5. 确定HTTP Status

服务器像客户端返回HTTP Status以表示操作是否成功,常用的数值包含如下。

(1)200,OK,用户请求成功,如查询数据成功返回。

(2)400 ,错误的请求,在第3章 内容里会提到,URI匹配上Spring Boot里的Controller,但方法参数匹配错误,就会抛出错误信息值。

(3)404 NOT Found,用户发出的请求针对的资源不存在,通常是Spring Boot里的Controller没有匹配上URI,或者匹配上了Controller方法,但渲染的视图不存在。

(4)405 ,用来访问本页面的 HTTP Method 不被允许,比如通过HTTP GET方式访问了一个@PostMapping的Controller方法。

(5)406,表示无法使用请求的内容特性来响应请求的资源,比如在Spring Boot里,请求后缀以html结尾,但同时请求的HTTP头里又包含Accept:application/json。.

(6)500,服务器内部错误,无法完成请求,通常是Controller抛出的异常。

6. REST VS WebService

WebService是曾经流行的一种基于HTTP的接口方式,它的初衷现在看起来仍然是那么美好。比如

(1)建立在SOAP协议上,SOAP协议是一种功能完备的消息交换协议。

(2)WSDL,WebService描述语言,能描述WebService提供的服务名称、参数、调用协议等。还通过WSDL代码生成客户端调用代码。

(3)WS-* 一系列跟WebService相关的辅助规范。

(4)异构系统之间一种互相调用的方式。这在早期异构系统之间是一种优势,然而现在基于Web应用的平台,REST也具备这个优点。

美好的事情也并不全是看上去的那个样子,REST和WebService 主要差别就是前者是一种轻量级的架构,而后者是一种重量级架构。前者即适合终端到服务器的调用,系统内部子系统的互相调用,也适合不同公司之间的系统互相调用,而WebService只适合不同公司之间系统的调用。其主要原因如下。

(5)SOAP协议过于复杂,是个重量级协议,SOAP协议基于XML,本来是要代替更早的XML-RPC协议,但自身却越来越复杂,开发一个WebService服务实现要比开发REST慢很多。

(6)WS- 协议的复杂性,只有一些商业机构实现了WS-的规范。

(7)在传输数据上,JSON比XML更为流行,XML数据封装,虽然数据表象能力强,但影响系统性能,比如XML解析曾经出现了一代比一代更好的方式,如DOM、SAX、XML Sta,也验证XML 在性能方面确实不理想。

(8)XML网络之间传输的数据量也比JSON大。

尽管WebService有诸多缺点,但WebService仍然是一种流行的大型系统之间的交互方式。WebService具备的一些功能,比如WSDL,REST并没有做出规定。本章最后会介绍Swager,一种REST辅助工具,用来增强REST应用。

WS-* 是指一些列跟WS相关的规范,比如:

(9)WS-Security 安全相关,还有WS-Trust ;

(10)WS-Addressing 访问调用相关;

(11)WS-BPEL 业务处理规范;

(12)WS-AtomicTransaction 事务相关,还有WS-Transaction;

(13)WS-Management 管理相关规范。

只要Spring-boot-starter-web 依赖在pom里,即自动支持REST

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

注解@RestController 用于描述REST服务,他相当于@Controller 和@ResponseBody的组合,下面两个例子是等价的。

@RestController
 @RequestMapping("/api/v1") 
 public class OrderApiCrontroller {

       @GetMapping("/order/{orderId}")
       public Order getOrder(@PathVariable String orderId) throws Exception{
       .....
       }
 }
  
 @Controller
 @RequestMapping("/api/v1") 
 public class OrderApiCrontroller {

       @GetMapping("/order/{orderId}")
       public @ResponseBody Order getOrder(@PathVariable String orderId) throws Exception{
       .....
       }
 }

记住,REST架构只是一种架构风格而不是一种特殊的技术,即使没有使用@RestController注解,你也能完成REST架构。

为了测试REST服务,我们可以使用curl命令。如果你是linux或者Mac系统,他们自带curl命令。如果你是window系统,如果安装了git,也会自带curl命令,否则就得先自行安装curl命令,详情参考第3章关于curl的介绍部分。

对于如下REST接口:

@PostMapping("/order")
 public String addOrder(@RequestBody Order order) throws Exception{
   return "{success:true,message:\"添加成功\"}";
 }

可以使用如下命令进行测试:

>curl -XPOST '127.0.0.1:8080/api/v1/order' -H 'Content-Type: application/json' -d'
 {
     "id" : "001",
     "name":"订单"
 }
 '

删除接口:

@DeleteMapping("/order/{orderId}")
 public String cancelOrder(@PathVariable String orderId) throws Exception{
   return "{success:true,message:\"订单取消成功\"}";
 }

可以使用如下命令进行测试:

>curl -XDELETE '127.0.0.1:8080/api/v1/order/100'

上面讲到如何在SpringBoot中提供RESTfull服务,下面来介绍系统之间如何发起REST请求。

SpringBoot提供了RestTemplate来辅助发起一个REST请求,默认JDK通过自带的HttpURLConnection来作为底层HTTP消息的发送,使用JackSon 来序列化服务器响应的JSON数据。

1. RestTemplate

RestTemplate是核心类,提供了所有访问Rest服务的接口,尽管实际上可以使用HTTP Client类或者java.net.URL 来完成,但RestTemplate提供了Restful风格的的API。

RestTemplate有6个主要方法对应于Restful的6个主要的Http Method。

HTTP Method

Java API

DELETE

Delete

GET

getForObject,getForEntity

HEAD

headForHeaders

OPTIONS

optionsForAllow

POST

postForObject,postForLocation

PUT

Put

其他

exchange(通用)

SpringBoot 提供了RestTemplateBuilder来创建一个RestTemplat。应用可以通过如下代码来创建一个RestTemplate实例。

@Autowired
 RestTemplateBuilder restTemplateBuilder;
 public void foo(){
   RestTemplate client = restTemplateBuilder.build();
 }

下面列举一下使用RestTemplate来查询订单和创建订单。

/*一个测试类*/
 @Controller
 @RequestMapping("/test") 
 public class RestClientTestCrontroller {
  
   @Value(value = "${api.order}")
   String base ;
   @Autowired
   RestTemplateBuilder restTemplateBuilder;
  
   @GetMapping("/get/{orderId}")
   public @ResponseBody Order testGetOrder(@PathVariable String orderId) throws Exception{
     RestTemplate client = restTemplateBuilder.build();
     String uri = base+"/order/{orderId}";
     //核心代码
     Order order = client.getForObject(uri, Order.class,orderId);
     return order;
   }
 }

base是在配置文件application.properties中配置的订单API地址

api.order=http://127.0.0.1:8080/api/v1

代码首先构造RestTemplate,然后调用getForObject,此方法接受3个参数,第1个是URI 模板,第2个参数是期望返回的对象,第3个是URI模板对应的参数列表。参数列表既可以是数组,也可以是个Map,上面的代码又可以写成如下。

Map map = new HashMap();
 map.put("orderId",orderId);
 Order order = client.getForObject(uri, Order.class,map);

如果还想获取相应的HTTP头的相关信息,可以调用client.getForEntity。此方法返回的ResponseEntity包含了头信息。

ResponseEntity<Order> responseEntity = client.getForEntity(uri, Order.class, orderId);
 Order order = responseEntity.getBody();
 HttpHeaders headers = responseEntity.getHeaders();

添加订单可以使用postForObject方法,此方法接受3个参数,第1个是URI,第2个是Post参数,可以是HttpEntity,或者是某个POJO对象,POJO对象在这种情况下会自动转成HTTPEntity,第3个参数是期望返回的类型,这个例子期望返回类型是String。

@GetMapping("/addorder")
 public @ResponseBody String testAddOrder() throws Exception{
   RestTemplate client = restTemplateBuilder.build();
   String uri = base+"/order";
   Order order = new Order();
   order.setName("test");
   String ret = client.postForObject(uri, order, String.class);
   <em>//{success:true,message:"添加成功"}</em>
   return ret;
 }

或者使用HttpEntity。

HttpEntity<Order> body = new HttpEntity<Order>(order);
 String ret = client.postForObject(uri, body, String.class);

使用HttpEnity的好处是可以提供额外的HTTP头信息。

如果期望返回的类型是一个列表,如List,不能简单调用xxxForObject,因为存在泛型的类型擦除,RestTemplate在反序列化的时候并不知道实际反序列化的类型,因此可以使用ParameterizedTypeReference来包含泛型类型,代码如下。

RestTemplate client = restTemplateBuilder.build();
 //根据条件查询一组订单
 String uri = base+"/orders?offset={offset}";
 Integer offset = 1;
 //无参数
 HttpEntity body = null;
 ParameterizedTypeReference> typeRef = new ParameterizedTypeReference>() {};
 ResponseEntity> rs = client.exchange(uri, HttpMethod.GET, body, typeRef, offset);
 List order = rs.getBody();

注意typeRef实际定义是用{}结束的,这里实际上创建了一个ParameterizedTypeReference子类,依据在类定义中的泛型信息是保留的原则,typeRef保留了期望返回的泛型List。

Exchange 是一个基础的Rest调用接口,除了需要指明HTTP Method外,调用跟其他方法都类似。

除了使用ParameterizedTypeReference来保留泛型信息外,也可以通过getForObject方法先映射成String,然后通过ObjectMapper来转为指定类型,可以参考第三章Jackson来了解。

2. 定制 RestTemplate

创建一个配置类实现RestTemplateCustomizer接口的customize方法,此方法代码如下。

@Configuration
 public class RestConf implements RestTemplateCustomizer {
  
       public void customize(RestTemplate restTemplate) {
             SimpleClientHttpRequestFactory jdkHttp = (SimpleClientHttpRequestFactory)restTemplate.getRequestFactory();
                  jdkHttp.setConnectTimeout(1000);        
       }
 }

如上代码customize方法会定制RestTemplate,上面的代码设置链接超时时间为1000毫秒。Spring Boot因为默认使用了JDK的URLConnection作为底层的HTTP工具,如果想使用OkHttp需要添加如下代码。

<dependency>
     <groupId>com.squareup.okhttp3</groupId>
     <artifactId>okhttp</artifactId>
     <version>4.0.1</version>
 </dependency>

那上面的代码应该是

public void customize(RestTemplate restTemplate) {
   OkHttp3ClientHttpRequestFactory okHttp = (OkHttp3ClientHttpRequestFactory)restTemplate.getRequestFactory();
   okHttp.setReadTimeout(5000);
   okHttp.setWriteTimeout(3000);
 }

前面说过,WS提供了WSDL来描述提供的WS调用参数。还有一系列辅助工具用来生成WS客户端代码和测试WebService。REST也有一个工具Swager来完成类似功能,可以通过Swager 规范来描述RESTFull接口,通过Swager UI来显示和测试RESTFull接口。

本书将要介绍的是Swager3.0的内容,与Swager2.0 的内容有较大差别。接口描述在3.0版本中将通过Swagger规范(一个JSON文件)来描述,2.0版本则是通过在接口中提供一系列注解来描述的。

Swagger 提供了一个客户端用于测试Rest https://inspector.swagger.io/,不需要再本地安装SwagerUI就可以在线测试REST服务,insspector与ui的区别是前者用于测试REST服务,后者既可以测试也可以描述REST服务。

Swagger提供了一组静态页面,你可以在你的SpringBoot应用里集成这些静态页面,直接访问静态页面,打开指定的Swagger 规范,就可以显示RESTFull接口,如图1-1所示。

图1-1 Swagger提供的静态页面

(1)进入Swagger 官网,选择Swagger UI产品,进入并选择选择下载。

(2)页面会提示进入github。

(3)在github里,进入该项目的release 页面,选择一个最新的版本下载,笔者在写此书的时候,最新版本是swagger-ui 3.18.3。

(4)解压后,找到dist目录,只需要到这一步操作即可。我们在工程里创建statics目录,并且创建swagger3目录,复制刚才dist目录下的所有文件到swagger3目录下面。

(5)访问http://127.0.0.1:8080/swagger3/index.html ,这时能看到如下页面,如图1-2所示。

图1-2 Swagger Petstore

该页面在加载的时候,会自动打开一个Swagger 接口规范文档,如上图右上角所示,http://petstore.swagger.io/v2/swagger.yml。 你可以在浏览器里打开此链接,获取到Swagger Petstore 的接口规范以便后续操作参考。

打开的页面分为两部分,第一部分为接口的基本信息,如上图所示,包含了项目名称、描述等信息,第二部分包含了每个接口的具体描述,如接口名字、参数名字、参数类型、是否必填等,还有返回结果的示例。你可以尝试选择一个接口,填入参数来调用接口。

除了Swagger UI外,Swagger还提供了Swagger Editor、Swagger Inspector、Swagger Hub平台等产品,限于篇幅不再介绍,你可以访问Swagger.io了解其全线产品。

OpenAPI 规范内容较多,按照其规范的接口描述,对使用者非常友好。本书只重点介绍OpenAPI的部分内容,足以描述和测试RESTFull接口即可。

OpenAPI的详细描述地址可访问 https://swagger.io/specification/。

OpenAPI规范是一个yml(json)格式文件,包含项目基本信息以及具体接口描述信息可以在static/swagger3下创建一个sample.yml文件,我们将在本节逐渐完善项目描述,访问的接口的地址。

openapi: 3.0.1
 info:
   description: 这是一个项目的简单实例
   version: '1.0'
   title: 某系统接口

属性openapi总是规范的第一个属性,目前为3.0.1。info描述了一个项目基本信息。这个时候,可以再次访问 http://127.0.0.1:8080/swagger3/index.html ,并且在页面填写规范地址,比如:

http://127.0.0.1:8080/swagger3/sample.yml。

单击“Explore” 按钮,等到页面刷新后,就能看到我们添加的swagger规范。我们将陆续往sample.yml 添加更多内容来描述我们的REST接口。

如果每次刷新页面都需要重新填写地址,这样会很麻烦,我们可以直接修改index.html 文件,找到JS片段 SwaggerUIBundle 初始化的地方,直接修改URL。

<script>
 window.onload = function() {
 // Build a system
 const ui = SwaggerUIBundle({
  url: "http://127.0.0.1:8080/swagger3/sample.yml",
  dom_id: '#swagger-ui',
  .....
 })
 }

添加测试服务器地址:

servers:
   - url: http://127.0.0.1:8080/test
   description: local
   - url: https://192.168.0.1/v1
   description: 测试服务器

接口描述以Path开始,包含了多个路径,每个路径又可以有GET、POST、PUT 等HTTP Method协议内容。

paths:
   '/get/{orderId}':
     get:
       tags:
         - 订单查询类
       summary: 获取订单详细信息
       description: 传入订单编号,获取订单信息
       parameters:
         - name: orderId
           in: path
           description: 订单id
           required: true
           schema:
             type: string
       responses:
         '200':
           description: 获取用户信息成功

每个接口都包含了如下信息。

(1)tags,接口所属分组,非必选项。

(2)summary , 接口的主要功能得简要描述。

(3)description,接口详细描述。

(4)parameters ,接口的参数,REST参数在swagger里分为4种类型,如上实例的参数类型是path的,也就是参数是从path中获取,其他的还有body,parameter等,我们将在下一小节详细描述。

(5)schema,设定参数类型,这里用的是String,其他还有integer、boolean。

(6)response 对应了Http status的提示信息,这里描述了成功的提示信息。

查询参数,in的值是query,类似/ordder?offset=0,这里的offset就是URL 参数,Swagger里,用如下代码表示。

parameters:
   - name: offset
     in: query
     description: 查询起始位置
     required: true
     schema:
                type: string

URI 模板中的参数,如/order/{orderId},in的值使用Path

parameters:
   - name: orderId
     in: path
     description: 订单id
     required: true
     schema:
                type: string

设置在HTTP头的参数,in的值使用header。

parameters:
   - name: X-Request-ID
     in: header
     schema:
                type: string

使用requestBody来表示POST请求,如下schema定义了一个Order对象。

'/addorder/':
     post:
       tags:
         - 订单更新
       summary: 保存订单
       description: 保存订单信息
       requestBody:
         content:
           application/x-www-form-urlencoded:
             schema:
               type: object
               properties:
                 id:
                   type: string
                 name:
                   type: string

通常是将JSON数据作为HTTP 内容体发送到服务器端。

'/add/':
     post:
       tags:
         - 订单更新
       summary: 保存订单另外一个接口
       description: 保存订单信息
       requestBody:
         content:
           application/json:
             schema:
               $ref: '#/components/schemas/Order'
       responses:
         '200':
           description: 保存订单信息成功

如上代码显示,定了content类型是application/json,schema我们自定义一个Order,以方便重用 。

components:
   schemas:
     Order:
       type: object
       properties:
         id:
           type: string
         name:
           type: string

如果打开Swagger UI,会有如图1-3所示的接口展示。

图1-3 接口展示

单击 “Try it Out” 按钮,Swagger UI会为你自动生成一个符合你定义的Schema的JSON样例数据,你可以修改后执行测试的REST服务。

整个yml文件如下代码所示。

openapi: 3.0.1
 info:
   description: 这是一个项目简单实例
   version: '1.0'
   title: 某系统接口
 servers:
   - url: http://127.0.0.1:8080/test
     description: local
   - url: https://192.168.0.1/v1
     description: Staging server
  
 paths:
   '/get/{orderId}':
     get:
       tags:
         - 订单查询
       summary: 获取订单详细信息
       description: 传入订单编号,获取订单信息
       parameters:
         - name: orderId
           in: path
           description: 订单id
           required: true
           schema:
             type: string
         - name: X-Request-ID
           in: header
           schema:
             type: string
         - name: offset
           in: query
           description: 范围
           required: false
           schema:
             type: string
       responses:
         '200':
           description: 获取订单成功
   '/addorder/':
     post:
       tags:
         - 订单更新
       summary: 保存订单
       description: 保存订单信息
       requestBody:
         content:
           application/x-www-form-urlencoded:
             schema:
               type: object
               properties:
                 id:
                   type: string
                 name:
                   type: string
       responses:
         '200':
           description: 保存订单信息成功
   '/add/':
     post:
       tags:
         - 订单更新
       summary: 保存订单另外一个接口
       description: 保存订单信息
       requestBody:
         content:
           application/json:
             schema:
               $ref: '#/components/schemas/Order'
       responses:
         '200':
           description: 保存订单信息成功
 components:
   schemas:
     Order:
       type: object
       properties:
         id:
           type: string
         name:
           type: string


相关图书

推荐系统:产品与算法解析
推荐系统:产品与算法解析
计算机科学概论(第13版)
计算机科学概论(第13版)
量子计算:新计算革命
量子计算:新计算革命
计算机科学概论 Python版
计算机科学概论 Python版
网空态势感知理论与模型
网空态势感知理论与模型

相关文章

相关课程