目录

SpringMVC+Swagger配置使用踩坑

背景

接口写完之后手写接口文档太痛苦了,于是搜索一番自动生成api文档的工具,最后get到了神器Swagger和它的图形化工具Swagger-UI

从Android前端到Java后端的话语言方面没什么问题,框架使用的是SpringMVC,依赖注入和控制反转有点类似Android的Dagger2项目,但是在配置方面有一些坑还是踩了一遍,归根结底是自己对SpringMVC的框架体系没有理解,且是赶鸭子上架临时上手一梭子。老项目,如果是新开项目可以使用官方推荐的SpringBoot框架,配置使用更加简单舒爽。

那么先来波文档回味一下什么是SpringMVC:

了解完毕之后我们通过SpringFox来添加配置Swagger。

若干大神写文章讲Swagger配置文档的使用,我也来讲讲自己使用过程中踩的坑吧,此文仅为踩坑记录,如有谬误请指出。

最终配置及踩坑过程

  1. maven库导入。注意:我使用的是springfox 2.9.2最新版本,添加springfox自身即可,如果启动项目时出现com/fasterxml/jackson/databind/ObjectMapper类找不到,请额外添加Jackson的依赖。(有教程说2.7.0版本的springfox有bug不建议使用,我未进行验证)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    <version.jackson>2.9.6</version.jackson>
    
    <!-- jackson用于将springfox返回的文档对象转换成JSON字符串 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${version.jackson}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${version.jackson}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${version.jackson}</version>
    </dependency>
    
    <!-- ========swagger2 api自动生成工具 start======== -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
    <!-- ========swagger2 api自动生成工具 end======== -->
    
  2. swagger java配置文件,注意两个类注解的添加

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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;
    
    /**
    * Swagger配置文件。
    * [Springfox官方集成文档](http://springfox.github.io/springfox/docs/current/)
    * [Swagger注解官方文档](https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X)
    * <p>
    * 配置注意事项:
    * 1. swagger及swagger-ui的添加,注意版本
    * 2. 该config文件的注解添加,@Configuration与@EnableSwagger2为必须添加
    * 3. 配置servlet-mapping为"/",因为会生成静态文件,因此需要注意路径穿透
    *
    * @author sanchi
    */
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
    
        /**
        * 根据配置读取是否开启swagger文档,针对测试与生产环境采用不同的配置
        */
        @Value("${swagger.enable}")
        private boolean isSwaggerEnable;
    
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .groupName("sanchi")
                    .enable(isSwaggerEnable)
                    .apiInfo(apiInfo()).select()
                    // 对所有该包下的Api进行监控,如果想要监控所有的话可以改成any()
                    .apis(RequestHandlerSelectors.basePackage("com.sanchi.test"))
                    // 对所有路径进行扫描
                    .paths(PathSelectors.any())
                    .build();
        }
    
        /**
        * @return 生成文档说明信息
        */
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("Sanchi test API文档")
                    .description("接口文档")
                    .termsOfServiceUrl("http://sanchips.github.io")
                    .version("1.0.0").build();
        }
    }
    
  3. 检查dispatcherServlet的mapping映射规则,是否为转发所有的请求。也是我本次配置最坑的地方,因为是个老项目,映射处只配置了对.php.do的转发,没有配置为/,导致swagger-ui.html根本访问不到,访问对应路径时循环弹窗提示url路径不对。打开页面浏览器控制台时发现有报错:swagger-resources/configuration/ui 404 (not found),对于这个十分困惑,检索了好多文字都没有找到答案,直到找到这篇文章对于servlet静态资源穿透的说明才恍然大悟,老手们应该不会犯这么低级的错误吧😂

    1
    2
    3
    4
    5
    
    <!-- servlet处理所有请求,配合<mvc:default-servlet-handler />进行静态资源转发 -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    其他一些配置内容,这部分内容:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    <!-- 静态资源请求转发 -->
    <mvc:default-servlet-handler/>
    <!-- 启动注解 -->
    <mvc:annotation-driven/>
    <!-- 自动注入,使系统能够识别相应的注解,使用<context:component-scan/>手动扫描后可以省略该配置 -->
    <context:annotation-config/>
    <!-- 配置全局使用的k-v文件路径,添加控制参数,区分测试与正式环境觉得是否启用swagger api文档 -->
    <context:property-placeholder location="classpath*:context-sanchi.properties" file-encoding="UTF-8"/>
    
    <!-- 添加Swagger2的java config作为SpringMVC的bean -->
    <bean class="com.sanchi.test.config.SwaggerConfig"/>
    

    context-sanchi.properties文件中添加控制参数:

    1
    2
    
    # ======swagger是否启用配置字段======
    swagger.enable=true
    
  4. 上面也提到了区分测试与正式环境觉得是否启用swagger api文档,有人提到了根据正式或者测试环境是否引用<bean class="com.sanchi.test.config.SwaggerConfig"/>,觉得这种方式不太友好,找到这篇文章,发现swagger在配置的时候有提供一个enable的方法,于是使用properties参数配置的方式,见上面内容☝

至此,运行项目,打开swagger-ui页面,熟悉的界面出现,列出了所有controller下的接口信息,按照步骤添加api注解注释即可。配置结束,前期的坑也踩完了。

PS:发现一个彩蛋,SwaggerConfig文件添加@EnableWebMvc注解之后打开的ui界面跟不加不同,暂未做深究😛

/images/doge.gif