特别好用的swagger ui 封装

Swagger简单介绍

Swagger是一个Restful风格接口的文档在线自动生成和测试的框架 
官网:http://swagger.io 
官方描述:The World’s Most Popular Framework for APIs.

Swagger ui 的原生UI界面如下:

现在市面上的UI不足之处

1、原生UI显示的有些不够漂亮和清晰,特别是request 的model部分 

2、每个服务都需要引入一套资源文件,不能作为一个中间件为其他API使用

3、默认通用配置繁琐,每个项目都需要复制重新配置一份swagger信息

后来在网上看到了别人封装的swagger-layer-ui,界面看起来不错,但是还是有些问题在。

新设计,新封装,即插即用

于是乎,结合上面的问题,采用了spring boot 的思想:约定大于配置,通用的配置全部帮大家封装好了,如有特殊业务,可单独配置

 考虑到微服务和单服务版本的封装,做了一些特殊的打包配置:

微服务版本:中心UI服务需要访问API服务的接口,需要考虑一些跨域问题,简单的跨域问题,可以通过spring mvc配置来实现

单服务版本:即插即用,但是每个API服务需要加载一些资源包

 

我已经将代码上传到github上,有兴趣的小伙伴可以下载来看看。https://github.com/huanshare/huan-swagger

代码实现

huan-swagger-core(主要实现了一些swagger的默认配置,跨域通用配置,自定义注解的实现)

/**
 * 实现了swagger的默认配置,和跨域问题
 */
@Configuration
public class HuanSwagger {
    @Value("${swagger.enable:true}")
    boolean enable;
    @Value("${swagger.title:API查看器}")
    String title;
    @Value("${swagger.description:API服务的说明,请在配置文件中说明服务的作用}")
    String description;
    @Value("${swagger.contact.name:huanshare}")
    String contactName;
    @Value("${swagger.contact.url:www.huanshare.com}")
    String contactUrl;
    @Value("${swagger.contact.mail:huanshare@live.com}")
    String contactMail;
    @Value("${swagger.version:0.0.0}")
    String version;

    public HuanSwagger() {
    }

    @Bean
    public Docket allApi() { if (!this.enable) {
            return (new Docket(DocumentationType.SWAGGER_2)).select().apis(RequestHandlerSelectors.none()).paths(PathSelectors.none()).build();
        } else {
            ApiInfo apiInfo = (new ApiInfoBuilder()).title(this.title).description(this.description).contact(new Contact(this.contactName, this.contactUrl, this.contactMail)).version(this.version).build();
            ApiSelectorBuilder builder = (new Docket(DocumentationType.SWAGGER_2)).useDefaultResponseMessages(false).apiInfo(apiInfo).select();
            builder.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class));
            return builder.build();
        }
    }

    @Bean
    public CorsFilter apiCrosFilter() {
        if (!this.enable) {
            return new CorsFilter(new UrlBasedCorsConfigurationSource());
        } else {
            UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.setAllowCredentials(true);
            corsConfiguration.addAllowedHeader("*");
            corsConfiguration.addAllowedMethod("*");
            corsConfiguration.addAllowedOrigin("*");
            urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
            return new CorsFilter(urlBasedCorsConfigurationSource);
        }
    }
}
/**
 * 自定义注解,方便简单的注入
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@EnableSwagger2
@Import({HuanSwagger.class})
public @interface EnableHuanSwagger {
}

上面代码已经打成jar包,发布到maven库上了,具体版本使用

<dependency>
    <groupId>com.github.huanshare</groupId>
    <artifactId>huan-swagger-core</artifactId>
    <version>1.0.1</version>
</dependency>

huan-swagger-ui(微服务UI项目)

layui.config({
    base: 'assets/layext/'
}).extend({
    nlaytpl: 'nlaytpl',
    ncmntool: 'ncmntool',
    nswagger: 'nswagger',
    nupload: 'nupload'
});
//
layui.use(['layer', 'element', 'form', 'nlaytpl', 'nswagger', 'ncmntool', 'upload'], function () {
    var $ = layui.jquery,
        layer = layui.layer,
        element = layui.element,
        form = layui.form,
        ncmntool = layui.ncmntool,
        nlaytpl = layui.nlaytpl,
        nswagger = layui.nswagger;

    $(".logo").click(function () {
        $(".nav-home").click();
        $(".layui-side-scroll").scrollTop(0);
    });

    $("#iptApiUrl, .btn-clearurl").on('mouseover', function () {
        $(".btn-clearurl").show();
    }).on('mouseout', function () {
        $(".btn-clearurl").hide();
    });
    $(".btn-clearurl").click(function () {
        $("#iptApiUrl").val('');
    });
    $(".btn-gourl").click(function () {
        // 清理数据
        $(".api-main").empty();
        // 弹出加载框
        var loader = layer.load();
        // 拉取数据
        var iptApiUrl = $("#iptApiUrl").val() || location.hash;
        if (iptApiUrl.charAt(0) == "#") {
            iptApiUrl = iptApiUrl.substr(1);
        }
        if (iptApiUrl == "") {
            iptApiUrl = location.protocol + "//" + location.host + "/v2/api-docs";
            if (location.search && location.search.indexOf("_ijt=") != -1) {
                iptApiUrl = "example.json";
            }
        }
        if (iptApiUrl != "example.json") {
            if (!/\/v2\/api-docs$/.test(iptApiUrl)) {
                iptApiUrl = iptApiUrl + "/v2/api-docs";
            }

            if (!/^http/.test(iptApiUrl)) {
                iptApiUrl = "http://" + iptApiUrl;
            }
        }
        $("#iptApiUrl").val(iptApiUrl);
        // 获取配置文档
        $.ajax({
            url: iptApiUrl,
            dataType: "json",
            type: "get",
            success: function (apidoc) {
                // 解析数据
                try {
                    nswagger.resolve(apidoc);
                } catch (e) {
                    layer.msg('解析失败,请确认文档配置是否正确', {icon: 5});
                    console.error(e);
                    return;
                }
                // 设置页面标题
                document.title = apidoc.info.title;
                // 设置页面LOGO
                ncmntool.checkimg(apidoc.schemes[0] + "://" + apidoc.host + "/logo.png", function (imgurl) {
                    $(".logo img").attr("src", imgurl);
                });
                location.hash = apidoc.host;
                // 渲染左侧菜单导航
                nlaytpl.render(".api-main")("comp/tplApiMain.html", {tags: apidoc["tags"]}, function () {
                    // 重新渲染菜单效果
                    element.init();
                    // 监听导航点击事件
                    element.on("nav(left-nav)", function (ele) {
                        if ($(ele).hasClass("nav-home")) {
                            nlaytpl.render(".main-body")("comp/tplHomeBody.html", apidoc, function () {
                                // 重新渲染组件效果
                                element.init();
                            });
                        } else {
                            $((".layui-nav-itemed")).removeClass(("layui-nav-itemed"));
                            $(ele).parents(".layui-nav-item").addClass("layui-nav-itemed");
                            var _a = $(ele).children(':first-child');
                            $(".layui-side-scroll").scrollTop($(_a).offset().top - $(".layui-side").offset().top + $(".layui-side").scrollTop());
                            var _dpath = $(_a).attr("dpath"), _dhttpmethod = $(_a).attr("dhttpmethod");
                            nlaytpl.render(".main-body")("comp/tplApiBody.html", {
                                apidoc: apidoc,
                                tagname: $(_a).attr("dtag"),
                                dpath: _dpath,
                                dhttpmethod: _dhttpmethod,
                                mmeta: apidoc["paths"][_dpath][_dhttpmethod]
                            }, function () {
                                // 重新渲染组件效果
                                element.init();
                                form.render();
                            });
                        }
                    });
                    // 监听处理导航的悬浮提示
                    $('.layui-nav-item a[dtitle]').on('mouseover', function () {
                        var that = this;
                        layer.tips($(that).attr("dtitle"), that, {
                            time: 0
                        });
                    }).on('mouseout', function () {
                        layer.closeAll('tips');
                    });
                    // 渲染主页
                    $(".nav-home a").click();
                });
                // 渲染顶部导航搜索
                nlaytpl.render(".api-quick")("comp/tplApiQuick.html", {tags: apidoc["tags"]}, function () {
                    form.on('select(api-quick)', function (data) {
                        var pm = data.value.split("::");
                        $(".left-nav a[dpath='" + pm[1] + "'][dhttpmethod='" + pm[0] + "']").click();
                    });
                    // 重新渲染表单组件效果
                    form.render("select");
                });
            },
            error: function () {
                layer.msg('加载失败,请确认API文档的地址是否正确', {icon: 5});
            },
            complete: function () {
                layer.close(loader);
            }
        });
    }).on('mouseover', function () {
        var that = this;
        layer.tips("点击加载目标地址的API文档", that, {
            time: 0,
            tips: 3
        });
    }).on('mouseout', function () {
        layer.closeAll('tips');
    });
    //
    $(".btn-gourl").click();
});

swagger-ui-layer(单服务版本,即插即用),JS代码同huan-swagger-ui类似,只是引入jar包不同

<dependency>
    <groupId>com.github.huanshare</groupId>
    <artifactId>swagger-ui-layer</artifactId>
    <version>1.0.0</version>
</dependency>

使用说明

项目描述

由于考虑到大家的使用情况,结合网上 swagger-ui-layer的封装情况 现把 swagger-layui 分为 微服务版,单服务版。目前只支持 RestController

1)微服务版本:微服务与 layui 分离,layui 部署到新服务器上,供各个服务使用

    demo例子:http://106.12.9.238:8080/webjars/swagger-ui/index.html#106.12.9.238:8081

2)单服务版本:layui 部署在服务上,即插即用,非常方便

项目结构

huan-swagger-core swagger核心组件封装

swagger-ui-layer 单服务版本:供单服务即插即用

huan-swagger-ui 微服务版本:swagger UI页面,作为一个第三方服务来渲染接口,用来渲染远程服务器的接口说明 (aa.com)

spring-boot-demo swagger 微服务测试页面 (bb.com)

spring-mvc-demo swagger spring mvc单服务测试页面 (bb.com)

微服务访问形式:http://aa.com/webjars/swagger-ui/index.html#http://bb.com

微服务demo实例:http://106.12.9.238:8080/webjars/swagger-ui/index.html#106.12.9.238:8081

使用说明(spring boot)

一、微服务版本:

1、部署到服务器上:huan-swagger-ui项目

2、微服务项目修改

1) pom依赖

 <dependency>
       <groupId>com.github.huanshare</groupId>
       <artifactId>huan-swagger-core</artifactId>
       <version>1.0.1</version>
   </dependency>

 

2) spring boot项目启动项添加:

@EnableHuanSwagger

 

3) application.yml配置 (可选项配置)

 # Swagger设置  enable 默认为true,为false时,关闭接口展示
 swagger:
   enable: true,
   version: 版本号
   title: 项目标题
   description: 项目描述
   contact:
     name: 用户名
     url: url地址
     mail: 邮箱

 

3、页面访问:UI服务器地址/webjars/swagger-ui/index.html#API-服务器地址

4、具体使用方式,请参考 huan-swagger-test

二、单服务版本:

1、服务项目修改

1) pom依赖

<dependency>
   <groupId>com.github.huanshare</groupId>
   <artifactId>swagger-ui-layer</artifactId>
   <version>1.0.0</version>
 </dependency>

 

2) spring boot项目启动项添加:

 @EnableHuanSwagger

 

3) application.yml配置 (可选项配置)

# Swagger设置  enable 默认为true,为false时,关闭接口展示
  swagger:
    enable: true,
    version: 版本号
    title: 项目标题
    description: 项目描述
    contact:
      name: 用户名
      url: url地址
      mail: 邮箱

 

3、页面访问:UI服务器地址/api-doc.html

三、修改首页图标:根目录/logo.png(将图片地址映射到根目录下进行访问)

使用说明(spring mvc)

1、微服务版本:API需要在 添加pom依赖,需要手动解决跨域问题,具体可参考 spring-mvc-demo中的CORSFilter与web.xml中的跨域配置, 可参考 spring-mvc-demo---》CORSFilter

1) pom依赖

 <dependency>
       <groupId>com.github.huanshare</groupId>
       <artifactId>huan-swagger-core</artifactId>
       <version>1.0.1</version>
   </dependency>

 

2) Bean注入,Filter配置

@Configuration
    @EnableHuanSwagger
    @EnableWebMvc
    public class CORSFilter implements Filter {
    
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            chain.doFilter(req, res);
        }
    }

 

3) web.xml中配置过滤器

    <filter>
        <filter-name>cors</filter-name>
        <filter-class>com.huanshare.springMvcDemo.config.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>cors</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

2、单服务版本:添加pom依赖,注入各种Bean,可参考 spring-mvc-demo --》MySwaggerConfig

1) pom依赖

 <dependency>
      <groupId>com.github.huanshare</groupId>
      <artifactId>swagger-ui-layer</artifactId>
      <version>1.0.0</version>
 </dependency>

 

2) Bean注入

@Configuration
@EnableHuanSwagger
@EnableWebMvc
public class MySwaggerConfig {
}

 

3、修改首页图标:根目录/logo.png(将图片地址映射到根目录下进行访问)

特点

原来看过其他小伙伴的源码,页面交互不算太理想

无论单机版还是微服务版,整体UI在小伙伴基础上做了一些修改,整体内容进行了封装,不需要配置一些额外的选项,即插即用,非常方便

微服务版:实现了API与UI的分离,但是需要为UI单独部署一套服务器,增加了其他成本;如果微服务多的话,这也算是个不错的方案

单服务版:简单配置,即插即用,非常方便

    小伙伴的地址(https://github.com/ohcomeyes/swagger-ui-layer )
posted @ 2018-08-13 13:38  huanshare  阅读(54885)  评论(8编辑  收藏  举报