通过Swagger管理API:API Management学习第一篇

前言

本文仅代表作者的个人观点;

本篇书写过程中,咨询了我的同事舒力,Kylin,在此表示感谢;

本文的内容仅限于技术探讨,不能作为指导生产环境的素材;

本文素材是红帽公司产品技术和手册;

本文分为系列文章,将会有多篇,初步预计将会有26篇。

一、Swagger

3 Scale有个很好的功能,它提供ActiveDocs实时文档。它基于Swagger框架,提供了一种记录API的方法,并包含在Developer Portal中。

随着互联网技术的发展,现在的网站架构基本都由原来的后端渲染,变成了:前端渲染、先后端分离的形态,而且前端技术和后端技术在各自的道路上越走越远。 前端和后端的唯一联系,变成了API接口;API文档变成了前后端开发人员联系的纽带,变得越来越重要,swagger就是一款让你更好的书写API文档的框架。

那么,swagger档如何生成?

在源码中进行如下定义,应用运行的时候,会自动生成。

二、一个Restful API例子的源码分析

我们看一个Restful API,这个API是可以查询种子信息的。

的两个源码文件:

我们看一下这个Restful API的源码:

查看第一个源码文件,它定义了root 上下文:

$ cat ProductsApplication.java

package com.redhat.service;

import javax.ws.rs.ApplicationPath;

import javax.ws.rs.core.Application;

import io.swagger.jaxrs.config.BeanConfig;

@ApplicationPath("rest")

public class ProductsApplication extends Application {

public ProductsApplication(){

BeanConfig beanConfig = new BeanConfig();

beanConfig.setVersion("1.0.2");

beanConfig.setSchemes(new String[]{"http"});

beanConfig.setHost("localhost:8080");

beanConfig.setBasePath("/rest");

beanConfig.setResourcePackage("com.redhat.service");

beanConfig.setScan(true);

beanConfig.setTitle("Products");

beanConfig.setDescription("RHMart's Products API");

beanConfig.setPrettyPrint(true);

}

}

查看第二个源码文件,ProductServices.java它定义了http方法和path:

$ cat ProductServices.java

package com.redhat.service;

import java.util.List;

import javax.inject.Inject;

import javax.ws.rs.Consumes;

import javax.ws.rs.DELETE;

import javax.ws.rs.GET;

import javax.ws.rs.POST;

import javax.ws.rs.Path;

import javax.ws.rs.PathParam;

import javax.ws.rs.Produces;

import javax.ws.rs.core.MediaType;

import com.redhat.model.JsonResponse;

import com.redhat.model.Product;

import com.redhat.model.ProductDao;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

@Path("/services")

@Api(value="services")

@Produces("application/json")

public class ProductServices {

@Inject

ProductDao productDAO;

@ApiOperation(value="Get all Products")

@Path("/products")

@GET

@Produces(MediaType.APPLICATION_JSON)

public List<Product> getAllProducts(){

List<Product> prod= productDAO.getAll();

return prod;

}

@ApiOperation(value="Get a Product by ID")

@Path("/product/{productId}")

@GET

@Produces(MediaType.APPLICATION_JSON)

public Product getProduct(@PathParam("productId") Integer productId){

return productDAO.getProductById(productId);

}

@ApiOperation(value="Create a new Product")

@Path("/product")

@POST

@Consumes(MediaType.APPLICATION_JSON)

@Produces(MediaType.APPLICATION_JSON)

public JsonResponse createProduct(Product product){

JsonResponse jr = new JsonResponse("");

try{

productDAO.createProduct(product);

}catch(Exception e){jr.setMessage(e.getMessage()); return jr;};

jr.setMessage("Product created");

return jr;

}

@ApiOperation(value="Delete a Product by ID")

@Path("/product/{productId}")

@DELETE

@Produces(MediaType.APPLICATION_JSON)

public JsonResponse deleteProduct(@PathParam("productId") Integer productId){

JsonResponse jr = new JsonResponse("");

try{

productDAO.deleteProduct(productId);

}catch (Exception e) { jr.setMessage(e.getMessage()); return jr;};

jr.setMessage("Product " + productId + " deleted");

return jr;

}

}

我们再看看之前curl的链接:curl -v -k http://products-api-david-products-api.apps.na39.openshift.opentlc.com/rest/services/product/1

上面黄色部分的rest,就是root上下文,在 ProductsApplication.java中定义的;

红色部分的/service,是定义的path,在ProductServices.java中定义的;

绿色部分的/product/{productId},是定义的path,在ProductServices.java中定义的;

那么,源码如何与数据库进行通讯呢?

查看源码中的数据访问对象: List<Product> prod= productDAO.getAll(),找到import的内容:

import com.redhat.model.ProductDao;

切换到import com.redhat.model目录中,查看源码文件:

先查看ProductDao.java,它定义了接口:

在查看访问数据库的实现,可以看到,通过CDJ注入了EM,也就是一个实体类,unitName="primary"

接下来,我们再查看unitName="primary"的出处,查看./src/main/resources/META-INF/persistence.xml文件,里面定义了primary的datasource,通过JPA的方式访问数据库:

/Products/src/main/webapp/WEB-INF/Products-ds.xml中进行查看:

上图可以看出,应用对jdbc的访问,最终是:

jdbc:postgresql://productsdb:5432/RHMart

而productsdb:5432/,实际上就是数据库的pod SVC。也就是说,应用的pod,通过SVC方式访问数据库。这方访问方式,叫application datasource。

还有一种叫server datasource。这种情况下,将JDBC的配置在app server的配置文件中,如EAP的standalone.xml中。

三、Restful API在OCP上的部署

在OCP上,为Products API应用程序创建一个新项目:

部署和测试产品API服务

将products-api模板导入OpenShift环境:

使用products-api模板创建一个新应用程序:

测试product API服务是否接受请求并返回正确的响应:

返回结果:

可以通过执行以下命令检索所有产品的列表:

[

{

"productid": 1,

"productname": "Ninja Blender",

"productprice": 320.0

},

{

"productid": 2,

"productname": "Ninja Blender Pro",

"productprice": 515.0

},

{

"productid": 3,

"productname": "Kicthenhelp Juicer",

"productprice": 149.99

},

{

"productid": 4,

"productname": "ArtCuisine Toaster",

"productprice": 79.99

},

{

"productid": 5,

"productname": "White and Decor Toaster Oven",

"productprice": 49.99

},

{

"productid": 6,

"productname": "Mexpresso Maker",

"productprice": 199.99

},

{

"productid": 7,

"productname": "Mini Fridge",

"productprice": 229.99

},

{

"productid": 8,

"productname": "Slow-Cooker Pot",

"productprice": 44.99

},

{

"productid": 9,

"productname": "SungSamn 4-Door Refrigerator",

"productprice": 2199.99

},

{

"productid": 10,

"productname": "Hanilton 12 cup Food Processor",

"productprice": 49.99

}

]

于PostgreSQL的Products数据库中的种子列表。

四、通过swagger工具分析swagger文件

product service提供了一个swagger.yaml配置文件,用于记录它公开的资源。

要访刚才应用的swagger.yaml配置文件,请将浏览器指向以下命令的输出:

echo http://"$(oc get route/products-api -o template --template {{.spec.host}})"/rest/swagger.yaml

结果:

http://products-api-david-products-api.apps.na39.openshift.opentlc.com/rest/swagger.yaml

我们看一下swagger文件中的内容:

---

swagger: "2.0"

info:

description: "RHMart's Products API"

version: "1.0.2"

title: "Products"

host: "localhost:8080"

basePath: "/rest"

tags:

- name: "services"

schemes:

- "http"

paths:

/services/product:

post:

tags:

- "services"

summary: "Create a new Product"

description: ""

operationId: "createProduct"

consumes:

- "application/json"

produces:

- "application/json"

parameters:

- in: "body"

name: "body"

required: false

schema:

$ref: "#/definitions/Product"

responses:

200:

description: "successful operation"

schema:

$ref: "#/definitions/JsonResponse"

/services/product/{productId}:

get:

tags:

- "services"

summary: "Get a Product by ID"

description: ""

operationId: "getProduct"

produces:

- "application/json"

parameters:

- name: "productId"

in: "path"

required: true

type: "integer"

format: "int32"

responses:

200:

description: "successful operation"

schema:

$ref: "#/definitions/Product"

delete:

tags:

- "services"

summary: "Delete a Product by ID"

description: ""

operationId: "deleteProduct"

produces:

- "application/json"

parameters:

- name: "productId"

in: "path"

required: true

type: "integer"

format: "int32"

responses:

200:

description: "successful operation"

schema:

$ref: "#/definitions/JsonResponse"

/services/products:

get:

tags:

- "services"

summary: "Get all Products"

description: ""

operationId: "getAllProducts"

produces:

- "application/json"

parameters: []

responses:

200:

description: "successful operation"

schema:

type: "array"

items:

$ref: "#/definitions/Product"

definitions:

Product:

type: "object"

properties:

productid:

type: "integer"

format: "int32"

productname:

type: "string"

productprice:

type: "number"

format: "double"

JsonResponse:

type: "object"

properties:

message:

type: "string"

我们使用在线https://editor.swagger.io/编辑器,导入刚下载的yaml文件。

导入以后,就可以看到四个http定义的方法:

将代码的地址从localhost:8080改成实际地址(第六行):

我们展开GET,点击try it out:

ID号输入1

查看执行方法:

查看执行结果:

接下来,我们换一个path测试,使用:

点击try it out:

输出结果是所有信息:

魏新宇

  • 红帽资深解决方案架构师
  • 专注开源云计算、容器及自动化运维在金融行业的推广
  • 拥有MBA、ITIL V3、Cobit5、C-STAR、TOGAF9.1(鉴定级)等管理认证。
  • 拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、AIX、HPUX等技术认证。

原文发布于微信公众号 - 大魏分享(david-share)

原文发表时间:2018-07-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏GopherCoder

『No18: Go 实现世界杯后台管理系统』

趁着周末更新一期,上一期讲到 如何快速熟悉一个项目, 文章的最后讲到,最好的方法是借用相同的技术栈重新实现一个项目。

1731
来自专栏技术博文

excel导入与导出

基本上导出的文件分为两种: 1:类Excel格式,这个其实不是传统意义上的Excel文件,只是因为Excel的兼容能力强,能够正确打开而已。修改这种文件后再保存...

2976
来自专栏coding...

iOS开发实战-NetworkExtension食用教程写在前面项目介绍项目准备我不是广告结语

由于未知原因苹果在mac OS 10.12中删除了这个文件,因此我们需要从10.11系统中提取或下载--百度网盘 安装完毕后,在新增build target中...

1.2K2
来自专栏美团技术团队

Android App包瘦身优化实践

随着业务的快速迭代增长,美团App里不断引入新的业务逻辑代码、图片资源和第三方SDK,直接导致APK体积不断增长。包体积增长带来的问题越来越多,如CDN流量费用...

4773
来自专栏草根专栏

从头编写 asp.net core 2.0 web api 基础框架 (3)

Github源码地址:https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-...

4917
来自专栏程序员的SOD蜜

PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引

一、框架的由来  快速入门 有关框架的更多信息,请看框架官方主页! 本套框架的思想是借鉴Java平台的Hibernate 和 iBatis 而来,兼有...

2909
来自专栏FreeBuf

远程RPC溢出EXP编写实战之MS06-040

0x01 前言 MS06-040算是个比较老的洞了,在当年影响十分之广,基本上Microsoft大部分操作系统都受到了影响,威力不亚于17年爆出的”永恒之蓝”漏...

29210
来自专栏社区的朋友们

Node 架构从三层到 N 层,实现代码重用和解耦

三层架构通常意义上是将整个业务应用划分为:控制层、业务逻辑层以及数据访问层,三层架构在 Java Web 项目中很常见,那么这种架构能否运用在 Node 项目中...

2.1K2
来自专栏JackieZheng

Spring实战——XML和JavaConfig的混合配置

前言 看了园龄已经两年多了,再不能写完内容直接点击发布,留下一片密密麻麻的文字让别人看的头昏脑涨。所以现在每次写完主要内容后,还需要对于格式稍稍调整下。那么有没...

3176
来自专栏影子

springboot添加多数据源连接池并配置Mybatis

4743

扫码关注云+社区

领取腾讯云代金券