API生命週期第三階段:API實施:使用swagger codegen生成可部署工程,擇取一個做爲mock service

在分享培訓了swagger對於API的設計以後,有一些人問我說:你看,如今我們前端使用web_API作爲mock data在進行測試,後端也有mock 測試。而後咱們再進行聯調,這之中確定會出現一些誤差。有沒有一種方案是:前端不用寫mock數據測試,從一開始,就由後端提供一個在線運行的服務,以此減小後期聯調的工做量!   答案是:能夠!css


固然,在最開始,因爲我近期在作API網關的一些工做,我直接簡單粗暴的,將swagger的API文檔,導入了網關,由網關作了一個mock服務提供。額,如今想來很不負責哈(由於我在作那一塊的內容,圖省事兒,並無過多去想當時那個項目的現狀),後來想了想,那個項目並不須要專門搭建網關去作這麼個服務,而且因爲它的架構設計,若是再增長網關服務,會額外增添一些工做量和難度。而後,我看了看筆記,再溜了一圈swagger的網站,得出的解決方案爲:html

1,利用codegen當即生成可運行的工程前端

2,直接將服務註冊到Dubbo,以供前端使用java


備註:公司對於Dubbo這塊內容很熟悉了,我主要介紹一下從swagger的API文檔,生成可部署工程的過程(其實,這中間還有不少須要進行我的總結,好比嵌入式服務器Jetty,還有我解決一些問題的過程思考和思路總結)!git

1、使用swagger Codegen生成可部署工程

這個特別簡單,真的特別簡單,簡單得不能再簡單。(固然,我用百度,或者說查到的中文資料,關於從API生成到工程,幾乎爲零。不過,好在後期集成swagger的還很多,雖然比較複雜)github

首先,是看swagger官方對於codegen是怎麼說的:https://swagger.io/docs/swagger-tools/#installation-11 web

而後,再看看具體的命令怎麼寫:https://github.com/swagger-api/swagger-codegen/wiki/Server-stub-generator-HOWTOspring

最後,看看對於swagger editor示例中的API,在各類語言下生成的工程示例:https://github.com/swagger-api/swagger-codegen  備註:具體的語言示例路徑爲:https://github.com/swagger-api/swagger-codegen/tree/master/samples/server/petstorejson


實例:好比說我用swagger編輯了一個basic API,那麼生成JAX-RS(Jersey)的工程命令以下:後端

java -jar J:\swagger-codegen-cli-2.2.1.jar generate -i "C:\Users\10283_000\Desktop\API lifecycle\Basic.json" -l jaxrs -o jaxrs/jersey2


簡單粗暴,而後,運行方式爲,在工程的Pom.xml同路徑下,執行:mvn jetty:run

而後,沒你啥事兒了,開始用吧!  這是一個運行狀態的服務,你有兩種方式,能夠把這個服務變成一個mock service,第一:也就是比較省事兒的,直接在編輯API文檔的時候,給設置一個example值; 第二:在這個工程中,設置其指定返回值


這個過程,對於我我的來講,要反思的內容,有點多,額!!!我感受,頗有必要給貼一下代碼,再次強調,我只執行了一行命令,別的,我什麼都沒有作:看看主要的幾個點吧(以JAX-RS:Jersey爲例):


這是整個項目工程的結構圖,全部的代碼均是自動生成。開發人員,只須要專一於我用紅圈畫起來的類的實現就OK了!  其餘的一些公共問題,好比說跨域,JSON,異常等,已經被簡單處理過。若是要求不是特別高,特別嚴密,那麼直接使用是徹底能夠的! 再,展現一下關鍵的類(額,用的swagger API 是我第一次學的時候導出的JSON文件,並非很完善,吐槽不要太過度)

API接口類:

package io.swagger.api;

import io.swagger.model.*;
import io.swagger.api.ResourcesApiService;
import io.swagger.api.factories.ResourcesApiServiceFactory;

import io.swagger.annotations.ApiParam;
import io.swagger.jaxrs.*;

import io.swagger.model.Build;

import java.util.List;
import io.swagger.api.NotFoundException;

import java.io.InputStream;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.*;

@Path("/resources")
@Consumes({ "application/json" })
@Produces({ "application/json" })
@io.swagger.annotations.Api(description = "the resources API")
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2017-08-21T09:59:53.975+08:00")
public class ResourcesApi  {
   private final ResourcesApiService delegate = ResourcesApiServiceFactory.getResourcesApi();

    @POST
    @Path("/api/tb-build")
    @io.swagger.annotations.ApiOperation(value = "", notes = "新增一個建築", response = void.class, tags={ "建築", })
    @io.swagger.annotations.ApiResponses(value = { 
        @io.swagger.annotations.ApiResponse(code = 200, message = "新增建築成功!", response = void.class),
        
        @io.swagger.annotations.ApiResponse(code = 404, message = "找不到API服務", response = void.class),
        
        @io.swagger.annotations.ApiResponse(code = 200, message = "未知錯誤", response = void.class) })
    public Response addBuild(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true) Build body
,@Context SecurityContext securityContext)
    throws NotFoundException {
        return delegate.addBuild(body,securityContext);
    }
    @GET
    @Path("/api/tb-build")
    @io.swagger.annotations.ApiOperation(value = "", notes = "獲取全部的建築信息", response = void.class, tags={ "建築", })
    @io.swagger.annotations.ApiResponses(value = { 
        @io.swagger.annotations.ApiResponse(code = 200, message = "操做成功", response = void.class),
        
        @io.swagger.annotations.ApiResponse(code = 404, message = "找不到API服務", response = void.class),
        
        @io.swagger.annotations.ApiResponse(code = 200, message = "未知錯誤", response = void.class) })
    public Response getBuild(@ApiParam(value = "Status values that need to be considered for filter",required=true) @QueryParam("buildId") String buildId
,@Context SecurityContext securityContext)
    throws NotFoundException {
        return delegate.getBuild(buildId,securityContext);
    }
}
APIService類:

package io.swagger.api;

import io.swagger.api.*;
import io.swagger.model.*;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;

import io.swagger.model.Build;

import java.util.List;
import io.swagger.api.NotFoundException;

import java.io.InputStream;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;

@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2017-08-21T09:59:53.975+08:00")
public abstract class ResourcesApiService {
    public abstract Response addBuild(Build body,SecurityContext securityContext) throws NotFoundException;
    public abstract Response getBuild(String buildId,SecurityContext securityContext) throws NotFoundException;
}
APIServiceImpl類:

package io.swagger.api.impl;

import io.swagger.api.*;
import io.swagger.model.*;

import io.swagger.model.Build;

import java.util.List;
import io.swagger.api.NotFoundException;

import java.io.InputStream;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;

@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2017-08-21T09:59:53.975+08:00")
public class ResourcesApiServiceImpl extends ResourcesApiService {
    @Override
    public Response addBuild(Build body, SecurityContext securityContext) throws NotFoundException {
        // do some magic!
        return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
    }
    @Override
    public Response getBuild(String buildId, SecurityContext securityContext) throws NotFoundException {
        // do some magic!
        return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
    }
}

額,其餘具體的,還得本身去看看,也不用本身寫,就拿提供的示例看看就行! 有些仍是有點區別,好比說JAX-RS(Jersey)這裏面用到的是抽象類,而springmvc用的是接口

2、從項目工程集成Swagger生成在線API文檔

其實,我很不想說這一點的,由於寫這個集成的有不少,我也看了不少,我之因此寫它,是由於我感受我找到的這種方式,是相對比較簡單的。代碼寫完後,集成swagger作基本的文檔處理,其實特別簡單,簡單到只有兩步:

第一:在pom文件中,添加依賴(版本的話,你隨意)

        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.5.0</version>
        </dependency>
 
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.5.0</version>
        </dependency>

第二:在springmvc的配置文件中,添加對於swagger文檔靜態資源的訪問受權

    <bean class="springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration" id="swagger2Config"/>  
    <mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"/>  
    <mvc:resources location="classpath:/META-INF/resources/webjars/" mapping="/webjars/**"/> 

有了這兩步以後,就能夠獲得一個這樣的文檔

第三步:經過使用swagger的API註解,增添一些額外的註釋說明

3、總結

其實,這些東西,都挺容易的。但中間也遇到了一些問題,也包括由於本身主要所在項目是java EE體系的,本身就主要關心、解決java EE這邊可能會面臨的問題,但對於公司其餘項目,相對來講,並不那麼上心。這個態度,真是很low啊!

接下來,會總結一些在這個過程之中的一些思惟方式,以及遇到的一些問題和解決過程、解決方案!

相關文章
相關標籤/搜索