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啊!

接下来,会总结一些在这个过程之中的一些思惟方式,以及遇到的一些问题和解决过程、解决方案!

相关文章
相关标签/搜索