zoukankan      html  css  js  c++  java
  • Swagger2在SpringBoot环境下的应用

    Swagger2在SpringBoot环境下的应用

    1. 集成Swagger

    1.1 添加依赖

    <!--swagger2 start-->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.6.1</version>
    </dependency>
    <!--引入swagger-ui包-->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.6.1</version>
    </dependency>
     

    1.2 配置类

    package com.inn.demo.config;
     
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
     
    @Configuration
    @EnableSwagger2
    public class SwaggerConfiguration extends WebMvcConfigurerAdapter {
    //生产关闭swagger
    @Value("${swagger.enable}")
    private boolean enableSwagger;
     
    // /**
    // * 访问swagger ui 出现404时可以把注释去掉试试
    // * 解决资源系统资源目录与swagger ui资源目录冲突问题
    // * 这个地方要重新注入一下资源文件,不然不会注入资源的,也没有注入requestHandlerMappping,相当于xml配置的swagger资源配置
    // * <mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"/>
    // * <mvc:resources location="classpath:/META-INF/resources/webjars/" mapping="/webjars/**"/>
    // * @param registry
    // */
    // @Override
    // public void addResourceHandlers(ResourceHandlerRegistry registry) {
    // registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    // registry.addResourceHandler("swagger-ui.html")
    // .addResourceLocations("classpath:/META-INF/resources/");
    // registry.addResourceHandler("/webjars/**")
    // .addResourceLocations("classpath:/META-INF/resources/webjars/");
    // super.addResourceHandlers(registry);
    // }
     
    // /**
    // * 支持分组 groupName
    // */
    // @Bean(value = "solrRestApi")
    // public Docket createSolrRestApi() {
    // return new Docket(DocumentationType.SWAGGER_2)
    // .apiInfo(apiInfo()).groupName("Solr Demo模块")
    // .enable(enableSwagger)
    // .select()
    // .apis(RequestHandlerSelectors.basePackage("com.inn.demo.modules.solr.web"))
    // .paths(PathSelectors.any())
    // .build();
    // }
     
    @Bean(value = "userRestApi")
    public Docket createUserRestApi() {
    return new Docket(DocumentationType.SWAGGER_2)
    .apiInfo(apiInfo())
    //.groupName("用户管理")
    .enable(enableSwagger)
    .globalOperationParameters(createCommonParams())//公共参数
    .select()
    .apis(RequestHandlerSelectors.basePackage("com.inn.demo.modules.user.web"))
    .paths(PathSelectors.any())
    .build();
    }
     
    private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
    .title("Demo APIs")
    .description("应用实例")
    //.termsOfServiceUrl("http://www.demo.com/";)
    //.contact(new Contact("开发者1", "", "xxx@163.com"))
    .version("1.0")
    .build();
    }
    /**
    * 创建公共参数
    * @return
    */
    private List<Parameter> createCommonParams() {
    //添加head参数start
    List<Parameter> pars = new ArrayList<Parameter>();

    ParameterBuilder tokenPar = new ParameterBuilder();
    tokenPar.name("x-access-token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();

    pars.add(tokenPar.build());

    return pars;
    //添加head参数end
    }
    }
     

    1.3 注解使用

    作用范围
    API
    使用位置
    对象属性
    @ApiModelProperty
    用在出入参数对象的字段上
    协议集描述
    @Api
    用于controller类上
    协议描述
    @ApiOperation
    用在controller的方法上
    Response集
    @ApiResponses
    用在controller的方法上
    Response
    @ApiResponse
    用在 @ApiResponses里边
    非对象参数集
    @ApiImplicitParams
    用在controller的方法上
    非对象参数描述
    @ApiImplicitParam
    用在@ApiImplicitParams的方法里边
    描述返回对象的意义
    @ApiModel
    用在返回对象类上
    ApiImplicitParam的相关属性
    属性
    取值
    作用
    paramType
    path
    query
    body
    header
    form
    参数放在哪个地方:必须要有这个属性
    header:header中提交:@RequestHeader获取
    query :key=value提交:@RequestParam获取
    path  :地址中提交:@PathVariable获取
    body  :json流提交 :@RequestBody获取(限POST)
    form  :表单提交:@RequestParam获取(限POST)
    dataType
    Long
    String
    参数的数据类型 只作为标志说明,并没有实际验证
    name
     
    接收参数名
    value
     
    接收参数的意义描述
    required
     
    参数是否必填
     
    TRUE
    必填
     
    FALSE
    非必填
    defaultValue
     
    默认值
    ApiImplicitParam 与 ApiParam 的区别
    ApiImplicitParam: 
    • 对Servlets或者非 JAX-RS的环境,只能使用 ApiImplicitParam。
    • 在使用上,ApiImplicitParam比ApiParam具有更少的代码侵入性,只要写在方法上就可以了,但是需要提供具体的属性才能配合swagger ui解析使用。
    • ApiParam只需要较少的属性,与swagger ui配合更好。
     
    代码实例:
    @RestController
    @RequestMapping(value = "/user")
    @Api(value = "/user", description = "人员基本信息 ")
    public class UserController {
     
    static Map<String, User> users = Collections.synchronizedMap(new HashMap<String, User>());
     
    @ApiOperation(value = "获取用户列表", notes = "")
    @RequestMapping(value = {"/list"}, method = RequestMethod.GET)
    public List<User> getUserList() {
    List<User> r = new ArrayList<User>(users.values());
    return r;
    }
     
    @ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
    @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
    @RequestMapping(value = "add", method = RequestMethod.POST)
    public String postUser(@RequestBody User user) {
    users.put(user.getId(), user);
    return "success";
    }
     
    @ApiOperation(value = "获取用户详细信息", notes = "根据url的id来获取用户详细信息")
    @ApiParam(name = "id", value = "用户ID", required = true)
    @RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
    public User getUser(@PathVariable(value = "id") String id) {
    return users.get(id);
    }
     
    @ApiOperation(value = "更新用户详细信息", notes = "根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
    @RequestMapping(value = "/update/{id}", method = RequestMethod.PUT)
    public String putUser(@PathVariable @ApiParam(name = "id", value = "用户ID", required = true) String id,
    @RequestBody @ApiParam(name = "user", value = "用户详细实体user", required = true) User user) {
    User u = users.get(id);
    u.setName(user.getName());
    u.setAge(user.getAge());
    users.put(id, u);
    return "success";
    }
     
    @ApiOperation(value = "更新用户名称和年龄", notes = "更新用户名称和年龄")
    @ApiImplicitParams({
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "String",paramType = "path"),
    @ApiImplicitParam(name = "name", value = "用户名", required = true, dataType = "String",paramType = "query"),
    @ApiImplicitParam(name = "age", value = "年龄", required = true, dataType = "Integer",paramType = "query"),
    @ApiImplicitParam(name = "user", value = "用户信息", required = true, dataType = "User",paramType = "body"),
    @ApiImplicitParam(name = "headerName", value = "Header信息", required = true, dataType = "String",paramType = "header")
    })
    @RequestMapping(value = "/update/info/{id}", method = RequestMethod.POST)
    public String updateUserNameAndAge(@PathVariable(value = "id") String id,
    @RequestParam(value = "name") String name,
    @RequestParam(value = "age") Integer age,
    @RequestHeader(value = "headerName") String headerName,
    @RequestBody User user) {
    User u = users.get(id);
    u.setName(name);
    u.setAge(age);
    users.put(id, u);
    return "success";
    }
     
    @ApiOperation(value = "删除用户", notes = "根据url的id来指定删除对象")
    @ApiParam(name = "id", value = "用户ID", required = true)
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    public String deleteUser(@PathVariable String id) {
    users.remove(id);
    return "success";
    }
     
    @ApiOperation(value="删除用户-传递数组", notes="删除对象,传递数组")
    @RequestMapping(value="/users/deleteByIds", method = RequestMethod.DELETE)
    public void deleteUsers(@ApiParam("用户ID数组"@RequestParam Integer[] ids) {
    for (int id:ids){
    users.remove(id);
    }
    }
    }
    User实体类:
     
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties({"handler""hibernateLazyInitializer"})
    @ApiModel(value = "User")
    public class User {
    @ApiModelProperty(value = "ID")
    private String id;
     
    @ApiModelProperty(value = "姓名", required = true)
    private String name;
     
    @ApiModelProperty(value = "年龄")
    private Integer age;
     
    public String getId() {
    return id;
    }
     
    public void setId(String id) {
    this.id = id;
    }
     
    public String getName() {
    return name;
    }
     
    public void setName(String name) {
    this.name = name;
    }
     
    public Integer getAge() {
    return age;
    }
     
    public void setAge(Integer age) {
    this.age = age;
    }
    }
     

    1.4 访问控制台

     
    按以下步骤配置,项目启动后访问:

    1.5 可选配置

    在application.properties中加入以下配置,用于设置测试请求的host,默认在swagger ui上做请求测试时都是以/users/1为路径发送请求。
    如果需要改变请求的根路径,就需要配置这个参数:
    该Host也是swagger-ui发送测试请求的Host, 通常我们会将将接口文档部署在测试服务器,这样就需要设置Host,
    否则请求都是通过localhost发送,请求不到测试服务器的接口。
    springfox.documentation.swagger.v2.host = yourapp.abc.com
    配置获取api docs json数据的请求路径 ,默认为/v2/api-docs:
    springfox.documentation.swagger.v2.path = /api
     

    2. 生成静态API文档pdf

    2.1 Maven 配置

    ======属性配置=======
    <snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
    <asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
    <generated.asciidoc.directory>${project.build.directory}/asciidoc</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>
     
    =====依赖配置============
    <!--离线文档-->
    <dependency>
    <groupId>org.springframework.restdocs</groupId>
    <artifactId>spring-restdocs-mockmvc</artifactId>
    <version>1.1.2.RELEASE</version>
    <scope>test</scope>
    </dependency>
    <!--springfox-staticdocs 生成静态文档-->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-staticdocs</artifactId>
    <version>2.6.1</version>
    </dependency>
    <!--swagger2 end-->
     
    ============插件配置==========
    <!--通过Asciidoctor使得asciidoc生成其他的文档格式,例如:PDF 或者HTML5-->
    <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.14</version>
    </dependency>
    <!-- Comment this section to use the default jruby artifact provided by the plugin -->
    <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>
    <!--因为每次执行只能处理一个后端,所以对于每个想要的输出类型,都是独立分开执行-->
    <executions>
    <!--html5-->
    <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>
     
     

    2.2 创建index.adoc文件

    路径:项目名/docs/asciidoc/index.adoc
    内容:
    1. include::{generated}/overview.adoc[]  
    2. include::{generated}/definitions.adoc[]  
    3. include::{generated}/paths.adoc[]  
     

    2.3 创建生成pdf、html的测试类

    package com.inn.demo;
     
    import io.github.robwin.markup.builder.MarkupLanguage;
    import io.github.robwin.swagger2markup.GroupBy;
    import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
    import org.junit.Before;
    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.test.context.junit4.SpringRunner;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    import org.springframework.web.context.WebApplicationContext;
    import springfox.documentation.staticdocs.SwaggerResultHandler;
     
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
     
    @AutoConfigureMockMvc
    @AutoConfigureRestDocs(outputDir = "target/generated-snippets")
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class Swagger2MarkupTest {
    private String snippetDir "target/generated-snippets";
    private String outputDir "target/asciidoc";
     
    @Autowired
    private WebApplicationContext context;
     
    private MockMvc mockMvc;
     
    @Before
    public void setUp() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
    }
     
    /**
    * 生成api html、pdf
    @throws Exception
    */
    @Test
    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);// 输出
    }
    }
     
    运行测试类即可生成pdf、html
    1. 生成的PDF和HTML文件:target/asciidoc/html and target/asciidoc/pdf  

    3. Swagger-UI 汉化

    3.1 添加自定义首页和译文

    在resourece目录下创建META-INF esourece目录,然后创建一个名称为"swagger-ui.html" 的HTML文件
    html内容:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Swagger UI</title>
    <link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-32x32.png" sizes="32x32"/>
    <link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-16x16.png" sizes="16x16"/>
    <link href='webjars/springfox-swagger-ui/css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
    <link href='webjars/springfox-swagger-ui/css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
    <link href='webjars/springfox-swagger-ui/css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
    <link href='webjars/springfox-swagger-ui/css/reset.css' media='print' rel='stylesheet' type='text/css'/>
    <link href='webjars/springfox-swagger-ui/css/print.css' media='print' rel='stylesheet' type='text/css'/>
    <script src='webjars/springfox-swagger-ui/lib/object-assign-pollyfill.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/jquery-1.8.0.min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/jquery.slideto.min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/jquery.wiggle.min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/handlebars-4.0.5.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/lodash.min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/backbone-min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/swagger-ui.min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/highlight.9.1.0.pack.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/highlight.9.1.0.pack_extended.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/jsoneditor.min.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/marked.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lib/swagger-oauth.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/springfox.js' type='text/javascript'></script<!--国际化操作:选择中文版 -->
    <script src='webjars/springfox-swagger-ui/lang/translator.js' type='text/javascript'></script>
    <script src='webjars/springfox-swagger-ui/lang/zh-cn.js' type='text/javascript'></script>
    </head>
    <body class="swagger-section">
    <div id='header'>
    <div class="swagger-ui-wrap">
    <id="logo" href="javascript:void(0)">
    <img class="logo__img" alt="swagger" height="30" width="30" src="webjars/springfox-swagger-ui/images/logo_small.png" />
    <span class="logo__title">在线API</span>
    </a>
    <form id='api_selector'>
    <div class='input'>
    <select id="select_baseUrl" name="select_baseUrl"></select>
    </div>
    <div class='input'>
    <input placeholder="http://example.com/api"id="input_baseUrl" name="baseUrl" type="text"/>
    </div>
    <div id='auth_container'></div>
    <div class='input'><id="explore" class="header__btn" href="#" data-sw-translate>Explore</a></div>
    </form>
    </div>
    </div>
    <div id="message-bar" class="swagger-ui-wrap" data-sw-translate></div>
    <div id="swagger-ui-container" class="swagger-ui-wrap"></div>
    </body>
    </html>
    大功告成 我们访问 http://localhost:8080/swagger-ui.html 看看显示效果:

    3.2 更详细的汉化

    如果想进一步调整译文,可以在META-INF esourceswebjarsspringfox-swagger-uilang 目录下添加zh-cn.js文件.
     
    然后在译文(zh-cn.js )内容,如下
    'use strict';
     
    /* jshint quotmark: double */
    window.SwaggerTranslator.learn({
    "Warning: Deprecated":"警告:已过时",
    "Implementation Notes":"实现备注",
    "Response Class":"响应类",
    "Status":"状态",
    "Parameters":"参数",
    "Parameter":"参数",
    "Value":"值",
    "Description":"描述",
    "Parameter Type":"参数类型",
    "Data Type":"数据类型",
    "Response Messages":"响应消息",
    "HTTP Status Code":"HTTP状态码",
    "Reason":"原因",
    "Response Model":"响应模型",
    "Request URL":"请求URL",
    "Response Body":"响应体",
    "Response Code":"响应码",
    "Response Headers":"响应头",
    "Hide Response":"隐藏响应",
    "Headers":"头",
    "Try it out!":"试一下!",
    "Show/Hide":"显示/隐藏",
    "List Operations":"显示操作",
    "Expand Operations":"展开操作",
    "Raw":"原始",
    "can't parse JSON. Raw result":"无法解析JSON. 原始结果",
    "Example Value":"示例",
    "Click to set as parameter value":"点击设置参数",
    "Model Schema":"模型架构",
    "Model":"模型",
    "apply":"应用",
    "Username":"用户名",
    "Password":"密码",
    "Terms of service":"服务条款",
    "Created by":"创建者",
    "See more at":"查看更多:",
    "Contact the developer":"联系开发者",
    "api version":"api版本",
    "Response Content Type":"响应Content Type",
    "Parameter content type:":"参数类型:",
    "fetching resource":"正在获取资源",
    "fetching resource list":"正在获取资源列表",
    "Explore":"浏览",
    "Show Swagger Petstore Example Apis":"显示 Swagger Petstore 示例 Apis",
    "Can't read from server. It may not have the appropriate access-control-origin settings.":"无法从服务器读取。可能没有正确设置access-control-origin。",
    "Please specify the protocol for":"请指定协议:",
    "Can't read swagger JSON from":"无法读取swagger JSON于",
    "Finished Loading Resource Information. Rendering Swagger UI":"已加载资源信息。正在渲染Swagger UI",
    "Unable to read api":"无法读取api",
    "from path":"从路径",
    "server returned":"服务器返回"
    });
    大功告成!
  • 相关阅读:
    Oracle基础 (十二)数学函数
    Oracle基础 (十一)字符串函数
    Oracle基础(十) DML数据操作
    Oracle 常用命令大全
    Oracle 常用的SQL语法和数据对象
    Server.MapPath()
    登陆sharepoint的主页,提示:文件存在(异常来自 HRESULT:0x80070050)
    如何查看电脑的开机时间
    SQL 2008登录的域账户与数据库服务器不再同一个域的 处理方法
    发布MVC项目到服务器上时候遇到的 模块 DirectoryListingModule 通知 ExecuteRequestHandler 处理程序 StaticFile 错误代码 0x00000000
  • 原文地址:https://www.cnblogs.com/innchina/p/8779514.html
Copyright © 2011-2022 走看看