[关闭]
@javazjm 2017-10-30T02:42:35.000000Z 字数 8390 阅读 2224

SpringBoot系列学习十二:API文档生成

Springboot swagger JApiDocs


swagger

官网

1. 在线文档

1.1 引入依赖

  1. <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
  2. <dependency>
  3. <groupId>io.springfox</groupId>
  4. <artifactId>springfox-swagger2</artifactId>
  5. <version>2.7.0</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
  8. <dependency>
  9. <groupId>io.springfox</groupId>
  10. <artifactId>springfox-swagger-ui</artifactId>
  11. <version>2.7.0</version>
  12. </dependency>

1.2 创建Swagger2配置类

在Application.java同级创建Swagger2的配置类

  1. @Configuration // 让Spring来加载该类配置
  2. @EnableSwagger2 // 启用Swagger2
  3. public class Swagger2Config {
  4. /**
  5. * 通用配置 生成离线文档不可缺
  6. * @return
  7. */
  8. @Bean
  9. public Docket configSpringfoxDocket_all() {
  10. return new Docket(DocumentationType.SWAGGER_2)
  11. .produces(Sets.newHashSet("application/json"))
  12. .consumes(Sets.newHashSet("application/json"))
  13. .protocols(Sets.newHashSet("http", "https"))
  14. .apiInfo(apiInfo())
  15. .forCodeGeneration(true)
  16. .select()
  17. .paths(regex("/api.*"))
  18. .build();
  19. }
  20. /**
  21. * 针对user的配置
  22. * @return
  23. */
  24. @Bean
  25. public Docket createUserRestApi() {
  26. return new Docket(DocumentationType.SWAGGER_2)
  27. .groupName("user")
  28. .produces(Sets.newHashSet("application/json"))
  29. .consumes(Sets.newHashSet("application/json"))
  30. .protocols(Sets.newHashSet("http", "https"))
  31. .apiInfo(apiInfo())
  32. .select()
  33. .apis(RequestHandlerSelectors.basePackage("com.jimzhang.web")) //扫描指定包下的Controller,并生成文档 (除了被@ApiIgnore指定的请求)
  34. .paths(regex("/api/users.*"))
  35. // .paths(PathSelectors.any())
  36. .build();
  37. }
  38. /**
  39. * 创建基本信息,会展示在文档首页
  40. * @return
  41. */
  42. private ApiInfo apiInfo(){
  43. return new ApiInfoBuilder()
  44. .title("Spring Boot中使用Swagger2构建RESTful APIs")
  45. .description("欢迎关注我的博客:http://www.jianshu.com/u/450bfbaff4e3")
  46. .termsOfServiceUrl("http://www.jianshu.com/u/450bfbaff4e3")
  47. .contact(new Contact("Spring官网 ", "https://spring.io/projects", "1539745948@qq.com"))
  48. .version("1.0").build();
  49. }
  50. }

1.3 添加文档内容

  1. @Api(tags = "用户操作")
  2. @RestController
  3. @RequestMapping(value="/users") // 通过这里配置使下面的映射都在/users下,可去除
  4. public class UserController {
  5. static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());
  6. @ApiOperation(value="获取用户列表", notes="")
  7. @RequestMapping(value={""}, method= RequestMethod.GET)
  8. public List<User> getUserList() {
  9. List<User> r = new ArrayList<User>(users.values());
  10. return r;
  11. }
  12. @ApiOperation(value="创建用户", notes="根据User对象创建用户")
  13. @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
  14. @RequestMapping(value="", method= RequestMethod.POST)
  15. public String postUser(@RequestBody User user) {
  16. users.put(user.getId(), user);
  17. return "success";
  18. }
  19. @ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息")
  20. @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
  21. @RequestMapping(value="/{id}", method= RequestMethod.GET)
  22. public User getUser(@PathVariable Long id) {
  23. return users.get(id);
  24. }
  25. @ApiOperation(value="更新用户详细信息", notes="根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
  26. @ApiImplicitParams({
  27. @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"),
  28. @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
  29. })
  30. @RequestMapping(value="/{id}", method= RequestMethod.PUT)
  31. public String putUser(@PathVariable Long id, @RequestBody User user) {
  32. User u = users.get(id);
  33. u.setName(user.getName());
  34. u.setAge(user.getAge());
  35. users.put(id, u);
  36. return "success";
  37. }
  38. @ApiOperation(value="删除用户", notes="根据url的id来指定删除对象")
  39. @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
  40. @RequestMapping(value="/{id}", method= RequestMethod.DELETE)
  41. public String deleteUser(@PathVariable Long id) {
  42. users.remove(id);
  43. return "success";
  44. }
  45. }

1.4 访问

http://localhost:8080/swagger-ui.html

API注解说明

  1. swagger2使用说明:
  2. @Api:用在类上,说明该类的作用
  3. @ApiOperation:用在方法上,说明方法的作用
  4. @ApiIgnore:使用该注解忽略这个API
  5. @ApiImplicitParams:用在方法上包含一组参数说明
  6. @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
  7. paramType:参数放在哪个地方
  8. header-->请求参数的获取:@RequestHeader
  9. query-->请求参数的获取:@RequestParam
  10. path(用于restful接口)-->请求参数的获取:@PathVariable
  11. body(不常用)
  12. form(不常用)
  13. name:参数名
  14. dataType:参数类型
  15. required:参数是否必须传
  16. value:参数的意思
  17. defaultValue:参数的默认值
  18. @ApiResponses:用于表示一组响应
  19. @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
  20. code:数字,例如400
  21. message:信息,例如"请求参数没填好"
  22. response:抛出异常的类
  23. @ApiModel:描述一个Model的信息(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候)
  24. @ApiModelProperty:描述一个model的属性

2. 离线文档

2.1 引入依赖

  1. <!-- 离线文档依赖 -->
  2. <dependency>
  3. <groupId>org.springframework.restdocs</groupId>
  4. <artifactId>spring-restdocs-mockmvc</artifactId>
  5. <version>1.1.2.RELEASE</version>
  6. <scope>test</scope>
  7. </dependency>
  8. <dependency>
  9. <groupId>io.springfox</groupId>
  10. <artifactId>springfox-staticdocs</artifactId>
  11. <version>2.6.1</version>
  12. </dependency>

2.2 Maven插件

asciidoctor-maven-plugin插件是用来把Asciidoc格式转成HTML5格式

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-maven-plugin</artifactId>
  6. </plugin>
  7. <!--Asciidoctor Maven 插件是一种官方支持的方式,它可以在 Apache Maven 构建过程中使用 Asciidoctor 转化你的 AsciiDoc 文档。-->
  8. <!--https://github.com/asciidoctor/asciidoctor-maven-plugin/blob/master/README_zh-CN.adoc-->
  9. <plugin>
  10. <groupId>org.asciidoctor</groupId>
  11. <artifactId>asciidoctor-maven-plugin</artifactId>
  12. <configuration>
  13. <!--配置index.adoc的获取路径-->
  14. <!--<sourceDirectory>${asciidoctor.input.directory}</sourceDirectory>-->
  15. <outputDirectory>${asciidoctor.html.output.directory}</outputDirectory>
  16. <sourceDocumentName>index.adoc</sourceDocumentName>
  17. <attributes>
  18. <doctype>book</doctype>
  19. <toc>left</toc>
  20. <toclevels>3</toclevels>
  21. <generated>${generated.asciidoc.directory}</generated>
  22. </attributes>
  23. </configuration>
  24. <executions>
  25. <execution>
  26. <id>output-html</id>
  27. <phase>test</phase>
  28. <goals>
  29. <goal>process-asciidoc</goal>
  30. </goals>
  31. <configuration>
  32. <backend>html</backend>
  33. <attributes>
  34. <snippets>${project.build.directory}/generated-snippets</snippets>
  35. </attributes>
  36. </configuration>
  37. </execution>
  38. </executions>
  39. </plugin>
  40. </plugins>
  41. </build>

2.3 配置文件

在Swagger2Config类中新增入下配置:

  1. /**
  2. * 通用配置 生成离线文档不可缺
  3. * @return
  4. */
  5. @Bean
  6. public Docket configSpringfoxDocket_all() {
  7. return new Docket(DocumentationType.SWAGGER_2)
  8. .produces(Sets.newHashSet("application/json"))
  9. .consumes(Sets.newHashSet("application/json"))
  10. .protocols(Sets.newHashSet("http", "https"))
  11. .apiInfo(apiInfo())
  12. .forCodeGeneration(true)
  13. .select()
  14. .paths(regex("/api.*"))
  15. .build();
  16. }

2.4 添加单元测试文件

  1. @AutoConfigureMockMvc
  2. @AutoConfigureRestDocs(outputDir = "target/generated-snippets")
  3. @RunWith(SpringRunner.class)
  4. @SpringBootTest
  5. public class DocumentationBuild {
  6. private String snippetDir = "target/asciidoc/generated-snippets";
  7. private String outputDir = "target/asciidoc";
  8. @Autowired
  9. private MockMvc mockMvc;
  10. @After
  11. public void Test() throws Exception {
  12. // 得到swagger.json,写入outputDir目录中
  13. mockMvc.perform(get("/v2/api-docs").accept(MediaType.APPLICATION_JSON))
  14. .andDo(SwaggerResultHandler.outputDirectory(outputDir).build())
  15. .andExpect(status().isOk())
  16. .andReturn();
  17. // 读取上一步生成的swagger.json转成asciiDoc,写入到outputDir
  18. // 这个outputDir必须和插件里面<generated></generated>标签配置一致
  19. Swagger2MarkupConverter.from(outputDir + "/swagger.json")
  20. .withPathsGroupedBy(GroupBy.TAGS)// 按tag排序
  21. .withMarkupLanguage(MarkupLanguage.ASCIIDOC)// 格式
  22. .withExamples(snippetDir)
  23. .build()
  24. .intoFolder(outputDir);// 输出
  25. }
  26. @Test
  27. public void TestApi() throws Exception {
  28. mockMvc.perform(get("/api/users/1")
  29. .accept(MediaType.APPLICATION_JSON))
  30. .andExpect(status().isOk())
  31. .andDo(MockMvcRestDocumentation.document("查询用户", preprocessResponse(prettyPrint()))); // '查询用户' 名字要与index.adoc 中的一致,否则 生成的文档有误
  32. User userInfo = new User();
  33. userInfo.setId(1L);
  34. userInfo.setName("lisi");
  35. userInfo.setAge(23);
  36. mockMvc.perform(post("/api/users").contentType(MediaType.APPLICATION_JSON)
  37. .content(JSON.toJSONString(userInfo))
  38. .accept(MediaType.APPLICATION_JSON))
  39. .andExpect(status().is2xxSuccessful())
  40. .andDo(MockMvcRestDocumentation.document("创建用户", preprocessResponse(prettyPrint())));
  41. mockMvc.perform(get("/api/users")
  42. .accept(MediaType.APPLICATION_JSON))
  43. .andExpect(status().isOk())
  44. .andDo(MockMvcRestDocumentation.document("获取用户列表", preprocessResponse(prettyPrint())));
  45. User user = new User();
  46. user.setId(1L);
  47. user.setName("张晋苗");
  48. user.setAge(27);
  49. mockMvc.perform(post("/api/users/1").contentType(MediaType.APPLICATION_JSON)
  50. .content(JSON.toJSONString(userInfo))
  51. .accept(MediaType.APPLICATION_JSON))
  52. .andExpect(status().is2xxSuccessful())
  53. .andDo(MockMvcRestDocumentation.document("更新用户详细信息", preprocessResponse(prettyPrint())));
  54. mockMvc.perform(post("/api/users/delete/1")
  55. .accept(MediaType.APPLICATION_JSON))
  56. .andExpect(status().isOk())
  57. .andDo(MockMvcRestDocumentation.document("删除用户", preprocessResponse(prettyPrint())));
  58. }
  59. }

2.5 运行

运行单元测试文件,会生成*.adoc和swagger.json文档,均不为空
然后进行打包,在target/asciidoc/html 会生成index.html 就是API文档

直接查看index.html即可。

JApiDocs

github地址:https://github.com/YeDaxia/JApiDocs

参考:
didi
小柒
https://my.oschina.net/dlam/blog/808315

离线文档:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注