swagger在線文檔和離線文檔
阿新 • • 發佈:2017-06-26
ger one 服務器 sys div als red rep dex
spring boot項目的swagger文檔。
依賴從spring boot的基礎上增加。參考pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Swagger -->
<!-- 文檔可視化--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> </dependency> <dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-mockmvc</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-staticdocs</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.8</version> </dependency>
maven插件:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <includes> <include>**/*Documentation.java</include> </includes> </configuration> </plugin> <plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>1.5.3</version> <!-- Configure generic document generation settings --> <configuration> <sourceDirectory>${project.basedir}/target/asciidoc</sourceDirectory> <sourceDocumentName>paths.adoc</sourceDocumentName> <attributes> <doctype>book</doctype> <toc>left</toc> <toclevels>3</toclevels> <numbered></numbered> <hardbreaks></hardbreaks> <sectlinks></sectlinks> <sectanchors></sectanchors> <generated>${project.build.directory}/asciidoc</generated> </attributes> </configuration> <!-- Since each execution can only handle one backend, run separate executions for each desired output type --> <executions> <execution> <id>output-html</id> <phase>test</phase> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <backend>html5</backend> <outputDirectory>${project.basedir}/docs/asciidoc/html</outputDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build>
Swagger2.java參考代碼:
import java.util.ArrayList; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.RequestMethod; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.builders.ResponseMessageBuilder; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ResponseMessage; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @ComponentScan @EnableSwagger2 public class Swagger2 { @Bean public Docket petApi() { //自定義異常信息 ArrayList<ResponseMessage> responseMessages = new ArrayList<ResponseMessage>() {{ add(new ResponseMessageBuilder().code(200).message("成功").build()); add(new ResponseMessageBuilder().code(400).message("請求參數錯誤").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(401).message("權限認證失敗").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(403).message("請求資源不可用").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(404).message("請求資源不存在").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(409).message("請求資源沖突").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(415).message("請求格式錯誤").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(423).message("請求資源被鎖定").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(500).message("服務器內部錯誤").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(501).message("請求方法不存在").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(503).message("服務暫時不可用").responseModel(new ModelRef("Error")).build()); add(new ResponseMessageBuilder().code(-1).message("未知異常").responseModel(new ModelRef("Error")).build()); }}; return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("my.product.controller"))//掃描的API包 .paths(PathSelectors.any()) .build() .useDefaultResponseMessages(false) .globalResponseMessage(RequestMethod.GET, responseMessages) .globalResponseMessage(RequestMethod.POST, responseMessages) .globalResponseMessage(RequestMethod.PUT, responseMessages) .globalResponseMessage(RequestMethod.DELETE, responseMessages); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Spring cloud 中使用Swagger2構建Restful APIs") .description("swagger項目文檔測試說明") .version("1.0").build(); } }
TestController.java參考代碼
import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @Api(value = "學生信息查詢", description = "學生基本信息操作API", tags = "StudentApi", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @RestController public class Swagger2TestController { @ApiOperation(value = "getStudent", notes = "依據學生姓名查詢學生信息") @RequestMapping(value = "student", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public Student getStudent(@RequestParam("name") String name){ System.out.println("name : "+name); Student reponse = new Student(); reponse.setId(1); reponse.setName(name); reponse.setAge(12); reponse.setCls("二年級"); reponse.setAddress("重慶市大竹林"); reponse.setSex("男"); return reponse; } @ApiOperation(value = "addStudent", notes = "添加一個學生", code = 201) @RequestMapping(value = "addStudent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) public void addStudent(@RequestBody Student student){ System.out.println("addStudent : "+student); return ; } }
student.java參考代碼
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @ApiModel(value = "Student", description = "學生信息描述") public class Student { /** * 學號 */ @ApiModelProperty("學號") private int id; /** * 姓名 */ @ApiModelProperty("姓名") private String name; /** * 年齡 */ @ApiModelProperty("年齡") private int age; /** * 性別 */ @ApiModelProperty("性別") private String sex; /** * 班級 */ @ApiModelProperty("班級") private String cls; /** * 住址 */ @ApiModelProperty("家庭住址") private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getCls() { return cls; } public void setCls(String cls) { this.cls = cls; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
測試類:
import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import com.alibaba.fastjson.JSON; import com.swagger.model.Student; import io.github.robwin.markup.builder.MarkupLanguage; import io.github.robwin.swagger2markup.GroupBy; import io.github.robwin.swagger2markup.Swagger2MarkupConverter; import springfox.documentation.staticdocs.SwaggerResultHandler; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; @AutoConfigureMockMvc @AutoConfigureRestDocs(outputDir = "target/generated-snippets") @RunWith(SpringRunner.class) @SpringBootTest public class SwaggerApplicationTests { private String snippetDir = "target/generated-snippets"; private String outputDir = "target/asciidoc"; @Autowired private MockMvc mockMvc; @After public void Test() throws Exception{ // 得到swagger.json,寫入outputDir目錄中 mockMvc.perform(get("/v2/api-docs").accept(MediaType.APPLICATION_JSON)) .andDo(SwaggerResultHandler.outputDirectory(outputDir).build()) .andExpect(status().isOk()) .andReturn(); // 讀取上一步生成的swagger.json轉成asciiDoc,寫入到outputDir // 這個outputDir必須和插件裏面<generated></generated>標簽配置一致 Swagger2MarkupConverter.from(outputDir + "/swagger.json") .withPathsGroupedBy(GroupBy.TAGS)// 按tag排序 .withMarkupLanguage(MarkupLanguage.ASCIIDOC)// 格式 .withExamples(snippetDir) .build() .intoFolder(outputDir);// 輸出 } @Test public void contextLoads() throws Exception { mockMvc.perform(get("/student").param("name", "xxx") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(MockMvcRestDocumentation.document("getStudent", preprocessResponse(prettyPrint()))); Student student = new Student(); student.setName("xxx"); student.setAge(23); student.setAddress("湖北麻城"); student.setCls("二年級"); student.setSex("男"); mockMvc.perform(post("/addStudent").contentType(MediaType.APPLICATION_JSON) .content(JSON.toJSONString(student)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().is2xxSuccessful()) .andDo(MockMvcRestDocumentation.document("addStudent", preprocessResponse(prettyPrint()))); } }
每個API都需要測試一下才有效。測試完後直接install,這離線文檔就會在${product.path}\docs\asciidoc\html下生成。
在線文檔啟動項目訪問http://localhost:[email protected]ger2 註解就行
swagger在線文檔和離線文檔