記一次使用Spring REST Docs + travis + github自動生成API接口文檔的操做步驟(中)

上一篇中,咱們介紹了基本的API文檔的生成方法,並最後成功的發佈爲html文件。html

本節接上篇內容,進行文件的自動拼接,而且在出具API文件時,自動加入請求參數、主體的相關信息。html5

本文使用工具:java

springFoxgit

傳送門: SpringFox官方文檔

加入依賴

刪除依賴

咱們此時,修改測試代碼片斷的接拼方式,因此刪除原插件的配置信息。github

<plugin> 
            <groupId>org.asciidoctor</groupId>
            <artifactId>asciidoctor-maven-plugin</artifactId>
            <version>1.5.3</version>
            <executions>
                <execution>
                    <id>generate-docs</id>
                    <phase>prepare-package</phase> 
                    <goals>
                        <goal>process-asciidoc</goal>
                    </goals>
                    <configuration>
                        <backend>html</backend>
                        <doctype>book</doctype>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency> 
                    <groupId>org.springframework.restdocs</groupId>
                    <artifactId>spring-restdocs-asciidoctor</artifactId>
                    <version>2.0.1.RELEASE</version>
                </dependency>
            </dependencies>
        </plugin>

增長依賴

<repositories>
    <repository>
      <id>jcenter-snapshots</id>
      <name>jcenter</name>
      <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
    </repository>
</repositories>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-data-rest</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-bean-validators</artifactId>
            <version>2.9.0</version>
        </dependency>

注意 加入到 pom.xml中的相應標籤中。其中repositories爲一級標籤。即repositories標籤的父級爲<project>web

配置項目

新建SwaggerConfig.(注意,該文件應該位於項目啓動文件的同級或下級文件夾)spring

package com.mengyunzhi.check_apply_online.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableSwagger2 // 啓用Swagger2
@Configuration  // 代表這是個配置文件,Spring在啓動時,須要對本文件進行掃描
public class SwaggerConfig implements WebMvcConfigurer {

}

測試

啓動項目,訪問http://localhost:8080/swagger-ui.html, 將顯示如下界面。apache

clipboard.png

加入Swagger的相關注解後,會對應的生成中文說明。好比:json

package com.mengyunzhi.check_apply_online.controller;

import com.mengyunzhi.check_apply_online.entity.DanWei;
import com.mengyunzhi.check_apply_online.service.DanWeiService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.Principal;

@RestController
@RequestMapping("/DanWei")
@Api(value = "/DanWei", description = "單位")
public class DanWeiController {
    private final static Logger logger = LoggerFactory.getLogger(DanWeiController.class);

    @Autowired
    DanWeiService danWeiService;

    @GetMapping("/login")
    @ApiOperation(value = "登陸", nickname = "其實登陸不限地址,任意地址都可以登陸。")
    public DanWei login(Principal user) {
        DanWei currentLoginDanWei = danWeiService.getCurrentLoginDanWei();
        return currentLoginDanWei;
    }

    @GetMapping("/logout")
    @ApiOperation(value = "logout 註銷", nickname = "DanWei_logout",
            notes = "參考資料:http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/web/authentication/logout/SecurityContextLogoutHandler.html")
    public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        logger.info("-----------------註銷----------------");
        danWeiService.setCurrentLoginDanWei(null);
        // 獲取當前認證信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        // 若是存在認證信息則調用註銷操做
        if (null != authentication) {
            new SecurityContextLogoutHandler().logout(httpServletRequest, httpServletResponse, authentication);
        }

        return;
    }

    @PostMapping("/register")
    @ApiOperation(value = "註冊新單位")
    public void save(@RequestBody DanWei danWei) {
        danWeiService.save(danWei);
    }
}

則生成的中文說明以下:segmentfault

clipboard.png

自定義文檔

Swigger支持自定義文件,便可以對html的標題等信息進行定製。下面給出示例:

package com.mengyunzhi.check_apply_online.config;

import com.google.common.base.Predicates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.annotations.ApiIgnore;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableSwagger2 // 啓用Swagger2
@Configuration  // 代表這是個配置文件,Spring在啓動時,須要對本文件進行掃描
@ComponentScan(basePackageClasses = com.mengyunzhi.check_apply_online.controller.DanWeiController.class)
public class SwaggerConfig implements WebMvcConfigurer {
    private static final Logger logger = LoggerFactory.getLogger(SwaggerConfig.class);

    /**
     * 建立Docket,寫用配置信息
     * @return
     */
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(this.apiInfo())
                .select()
                // 加入除'error'外的全部請求信息
                .paths(Predicates.and(PathSelectors.ant("/**"), Predicates.not(PathSelectors.ant("/error"))))
                .build()
                // 忽略的參數類型(ApiIgnore註解的字段)
                .ignoredParameterTypes(ApiIgnore.class)
                .enableUrlTemplating(true);
    }

    /**
     * 返回一個帶有項目設置信息的ApiInfoBuilder
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("網上送檢系統API")
                .description("爲檢定軟件提供網上送檢的支持")
                .contact(new Contact("panjie", "http://www.mengyunzhi.com", "3792535@qq.com"))
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
                .version("1.0.0")
                .build();
    }
}

則再次啓動時,將使用咱們自定義的配置設置標題等信息。

Swigger與Spring REST Docs配置

swigger的優勢是能夠獲取到全部的控制器及方法,而且可以按列表的形式展示出來。 Spring REST Docs的優勢是隻能夠將測試數據直接展示給前臺的用戶。本節將闡述如何將兩者結合起來使用。

加入依賴

<!--jcenter倉庫插件地址 (必須有,否則有些包下載不到。。。)-->
    <pluginRepositories>
        <pluginRepository>
            <id>jcenter</id>
            <name>jcenter maven</name>
            <url>http://jcenter.bintray.com</url>
        </pluginRepository>
    </pluginRepositories>
    <properties>
        <!-- 其它配置信息-->

        <!--swgger2markup 配置信息-->
        <swagger2markup.version>1.2.0</swagger2markup.version>
        <asciidoctor.input.directory>${project.basedir}/src/main/asciidoc</asciidoctor.input.directory>
        <swagger.output.dir>${project.build.directory}/swagger</swagger.output.dir>
        <swagger.snippetOutput.dir>${project.build.directory}/generated-snippets</swagger.snippetOutput.dir>
        <generated.asciidoc.directory>${project.build.directory}/asciidoc/generated</generated.asciidoc.directory>
        <asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
        <asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
        <swagger.input>${swagger.output.dir}/swagger.json</swagger.input>
    </properties>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-staticdocs</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.robwin</groupId>
            <artifactId>assertj-swagger</artifactId>
            <version>0.2.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.github.swagger2markup</groupId>
            <artifactId>swagger2markup-spring-restdocs-ext</artifactId>
            <version>${swagger2markup.version}</version>
            <scope>test</scope>
        </dependency>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <systemPropertyVariables>
                        <!--設置變量信息-->
                        <io.springfox.staticdocs.outputDir>${swagger.output.dir}</io.springfox.staticdocs.outputDir>
                        <io.springfox.staticdocs.snippetsOutputDir>${swagger.snippetOutput.dir}</io.springfox.staticdocs.snippetsOutputDir>
                    </systemPropertyVariables>
                </configuration>
            </plugin>

            <!-- 首先,生成asciidoc(.adoc) -->
            <plugin>
                <groupId>io.github.swagger2markup</groupId>
                <artifactId>swagger2markup-maven-plugin</artifactId>
                <version>${swagger2markup.version}</version>
                <dependencies>
                    <dependency>
                        <groupId>io.github.swagger2markup</groupId>
                        <artifactId>swagger2markup-import-files-ext</artifactId>
                        <version>${swagger2markup.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>io.github.swagger2markup</groupId>
                        <artifactId>swagger2markup-spring-restdocs-ext</artifactId>
                        <version>${swagger2markup.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <swaggerInput>${swagger.input}</swaggerInput>
                    <outputDir>${generated.asciidoc.directory}</outputDir>
                    <config>
                        <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
                        <swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy>

                        <swagger2markup.extensions.dynamicOverview.contentPath>${project.basedir}/src/main/asciidoc/extensions/overview</swagger2markup.extensions.dynamicOverview.contentPath>
                        <swagger2markup.extensions.dynamicDefinitions.contentPath>${project.basedir}/src/main/asciidoc/extensions/definitions</swagger2markup.extensions.dynamicDefinitions.contentPath>
                        <swagger2markup.extensions.dynamicPaths.contentPath>${project.basedir}/src/main/asciidoc/extensions/paths</swagger2markup.extensions.dynamicPaths.contentPath>
                        <swagger2markup.extensions.dynamicSecurity.contentPath>${project.basedir}src/main/asciidoc/extensions/security/</swagger2markup.extensions.dynamicSecurity.contentPath>

                        <swagger2markup.extensions.springRestDocs.snippetBaseUri>${swagger.snippetOutput.dir}</swagger2markup.extensions.springRestDocs.snippetBaseUri>
                        <swagger2markup.extensions.springRestDocs.defaultSnippets>true</swagger2markup.extensions.springRestDocs.defaultSnippets>
                    </config>
                </configuration>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>convertSwagger2markup</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!-- 而後,使用Asciidoctor(前面在spring rest docs時已安裝,在這須要加部分依賴)將.adoc轉成pdf和html -->
            <plugin>
                <groupId>org.asciidoctor</groupId>
                <artifactId>asciidoctor-maven-plugin</artifactId>
                <version>1.5.3</version>
                <!-- PDF依賴 -->
                <dependencies>
                    <dependency>
                        <groupId>org.asciidoctor</groupId>
                        <artifactId>asciidoctorj-pdf</artifactId>
                        <version>1.5.0-alpha.10.1</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jruby</groupId>
                        <artifactId>jruby-complete</artifactId>
                        <version>1.7.21</version>
                    </dependency>
                </dependencies>
                <!-- 生成文件時的配置信息 -->
                <configuration>
                    <sourceDirectory>${asciidoctor.input.directory}</sourceDirectory>
                    <sourceDocumentName>index.adoc</sourceDocumentName>
                    <attributes>
                        <doctype>book</doctype>
                        <toc>left</toc>
                        <toclevels>3</toclevels>
                        <numbered></numbered>
                        <hardbreaks></hardbreaks>
                        <sectlinks></sectlinks>
                        <sectanchors></sectanchors>
                        <generated>${generated.asciidoc.directory}</generated>
                    </attributes>
                </configuration>
                <!-- Since each execution can only handle one backend, run
                     separate executions for each desired output type -->
                <executions>
                    <!--生成html-->
                    <execution>
                        <id>output-html</id>
                        <phase>test</phase>
                        <goals>
                            <goal>process-asciidoc</goal>
                        </goals>
                        <configuration>
                            <backend>html5</backend>
                            <outputDirectory>${asciidoctor.html.output.directory}</outputDirectory>
                        </configuration>
                    </execution>

                    <!--生成pdf-->
                    <execution>
                        <id>output-pdf</id>
                        <phase>test</phase>
                        <goals>
                            <goal>process-asciidoc</goal>
                        </goals>
                        <configuration>
                            <backend>pdf</backend>
                            <outputDirectory>${asciidoctor.pdf.output.directory}</outputDirectory>
                        </configuration>
                    </execution>

                </executions>
            </plugin>

測試

執行mvn package -Dmaven.test.skip=true跳過測試,直接進行打包。第一次會下載插件,時間長短看網速。
最終將獲得以下錯誤:

clipboard.png

target下的swagger.json未生成。該文件即上個章節中的查看/v2/api-docs提到的json文件。下面,咱們增長一個單元測試文件,運行其的做用是訪問/v2/api-docs,抓取返回的內容,並存儲爲:swagger.json文件。

package com.mengyunzhi.check_apply_online.controller;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;

import java.io.BufferedWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

public class SwaggerTest extends ControllerTest {
    private final static Logger logger = LoggerFactory.getLogger(SwaggerTest.class);
    @Test
    public void createSwaggerJson() throws Exception {
        logger.info("------ 獲取用於生成自動文檔的swagger.json文件 ------");
        String swaggerJson = this.mockMvc.perform(get("/v2/api-docs").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();

        // 對應pom.xml中 <systemPropertyVariables> 設置的屬性值
//        String outputDir = System.getProperty("io.springfox.staticdocs.outputDir");
        String outputDir = "target/swagger";
        Files.createDirectories(Paths.get(outputDir));

        try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputDir, "swagger.json"), StandardCharsets.UTF_8)) {
            writer.write(swaggerJson);
        }

        return;
    }
}

執行單元測試,將獲得target/swagger/swagger.json, 同時,咱們修改src/main/asciidoc/index.adoc文件,使其包含插件自動生成的四個文件。

include::{generated}/overview.adoc[]
include::{generated}/paths.adoc[]
include::{generated}/security.adoc[]
include::{generated}/definitions.adoc[]

最後,咱們再次執行mvn package -Dmaven.test.skip=true

將獲得如下文件:

clipboard.png

其中html文件夾,爲生成的html格式的API文檔。pdf文件夾中爲生成的pdf文檔。咱們進行html文件夾,更能夠瀏覽生成的html文檔了。

clipboard.png

關聯swagger與Spring rest docs

咱們swagger的HTML文件也有了,spring rest docs的測試文件也有了,那麼如何進行關聯呢?
很簡單,咱們只須要爲控制器的相應方法與測試時生成的片斷名稱起想同的名字就能夠了。

好比:

@PostMapping("/register")
    @ApiOperation(value = "註冊新單位", nickname = "DanWei_register")
    public void save(@RequestBody DanWei danWei) {
        danWeiService.save(danWei);
    }

測試文件:

@Test
    public void registerTest() throws Exception {
        String url = "/DanWei/register";
        this.mockMvc.perform(MockMvcRequestBuilders
                .post(url)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content("{}"))
                .andExpect(MockMvcResultMatchers.status().isOk())
        .andDo(MockMvcRestDocumentation.document("DanWei_register"));
    }

執行mvn package後,相關的測試片斷,則自動加入到了相應的位置上。

其實了除了起一個相同的之外,還取於這個配置:<swagger.snippetOutput.dir>${project.build.directory}/generated-snippets</swagger.snippetOutput.dir>,是它告訴了Swagger:spring rest docs生成的測試代碼片斷在的位置。

自定義HTML內容

咱們能夠修改src/main/asciidoc/index.adoc來達到更改生成的html內容的目的。好比,咱們加入一些測試的說明。

include::{generated}/overview.adoc[]
== 說明
當前版本:1.0

=== 開發環境
java1.8 + maven3.3

=== 測試用戶
用戶名: user1, 密碼: user1

include::{generated}/paths.adoc[]
include::{generated}/security.adoc[]
include::{generated}/definitions.adoc[]

則從新mvn package後,將生成以下html:

clipboard.png

總結

在本節中,咱們主要使用了一個插件進行了文檔的自動生成。插件大概替咱們作了以下的事情:

  1. 經過swagger.json來生成.adoc
  2. 自動加載測試代碼片斷
  3. 利用src/main/asciidoc/index.adoc生成htmlpdf.

其實,爲了給swagger提供可用的json,咱們寫了單元測試文件。

在下一節中,咱們將闡述如何使用自動測試機器人結合github,實現自動發佈API文檔。

參考非官方教程:

https://leongfeng.github.io/2...
相關文章
相關標籤/搜索