maven+springMVC整合swagger,带注解扫描,非springBoot

maven+springMVC整合swagger,带注解扫描,非springBoot

背景

是在一个在用的项目中进行整合swagger,使用maven+springMVC,springMVC使用web.xml和spring-mvc.xml文件进行配置,带注解扫描,非springBoot项目

基本整合过程

1.pom.xml中加入相应的依赖

            <!--swagger-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>${swagger.version}</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>${swagger.version}</version>
            </dependency>
            <!--如果项目没有guava,则需要加上.swagger至少选择19.0以上的guava-->
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>19.0</version>
            </dependency>

2.编写swagger配置类

@Configuration //声明该类为配置类
@EnableSwagger2 //声明启动Swagger2
//@EnableWebMvc //这里我注释掉了也能正常使用,后面会讨论这个注解
public class SwaggerConfig {
    /**
     *  controller接口所在的包
     */
    @Value("${swagger.basePackage}")
    private String basePackage;
    /**
     * 当前文档的标题
     */
    @Value("${swagger.title}")
    private String title;
    /**
     * 当前文档的详细描述
     */
    @Value("${swagger.description}")
    private String description;
    /**
     * 当前文档的版本
     */
    @Value("${swagger.version}")
    private String version;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage(basePackage))
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))//只扫描有swagger注解的方法
                .paths(PathSelectors.any())
                .build();
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title(title)
                .description(description)
                .version(version)
                .build();
    }
}

3.properties文件增加相应内容

#swagger
swagger.basePackage=com.demo
swagger.title=swagger文档的标题
swagger.description=swagger文档的描述
swagger.version=0.0.1

4.编写spring和springMVC配置文件

留意Spring的配置文件和Spring-MVC的配置文件是否启用了注解扫描,如果没有是需要手动注册的

我这里已经开启了注解扫描,但Controller是在MVC加载的,所以swagger也要在MVC中加载才能发现Controller

Spring配置文件

<context:component-scan base-package="com.demo">
    <!-- 将Controller的注解排除掉,在spring-mvc.xml单独扫描Controller注解 -->
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
    
    <!--由于controller在spring-mvc中加载,swagger也要在mvc中加载才能扫描到controller,那在spring加载就没必要了-->
    <context:exclude-filter type="regex" expression="com.demo.config.SwaggerConfig"/>
    
</context:component-scan>

SpringMVC配置文件

<!--仅扫描Controller注解和SwaggerConfig类-->
<context:component-scan base-package="com.demo" use-default-filters="false">
		<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" />
		<context:include-filter type="regex" expression="com.demo.config.SwaggerConfig"/>
</context:component-scan>

<!--启用注解扫描-->
<mvc:annotation-driven />

<!--加载properties到MVC-->
<context:property-placeholder file-encoding="UTF-8" location="classpath:*.properties" 
        	ignore-unresolvable="true" />

6.拦截器/过滤器开放swagger页面的路径

包括

页面: /swagger-ui.html

api信息: /v2/*

配置信息: /swagger-resources/*

js和CSS: /webjars/*

5.Controller和DTO增加注解

Controller

@ApiOperation(value = "接口名称", notes = "接口提示信息", httpMethod = "POST", response = StudentDTO.class)
@RequestMapping(value = "postSutdent",method = RequestMethod.POST)
public void postSutdent(@RequestBody StudentDTO studentDTO){
	System.out.println(studentDTO);
}

DTO

@ApiModel(value = "StudentDTO",description = "学生信息")
class StudentDTO{
    @ApiModelProperty(value = "学生姓名",required = true)
    private String name;
    
    @ApiModelProperty(value = "学生年龄",required = true)
    private Integer age;
    
    @ApiModelProperty(value = "考试情况",required = true)
    private List<ExamDTO> exams;
    
    //get set 方法略
}
@ApiModel(value = "ExamDTO",description = "考试情况")
class ExamDTO{
    @ApiModelProperty(value = "科目名称",required = true)
    private String name;
    
    @ApiModelProperty(value = "分数",required = true)
    private Double grade;
    
    //get set 方法略
}

6.启动并访问localhost:8080/demo/swagger-ui.html

常见问题

1.swagger出现无限递归

原因:通常是由于swagger解析时遇到循环引用,例如树形结构

方法1:在swaggerConfig中添加自定义的TypeResolver,当成Object类型处理

private TypeResolver typeResolver = new TypeResolver();
private AlternateTypeRule alternateTypeRule = new AlternateTypeRule(typeResolver.resolve(TreeNode.class),typeResolver.resolve(Object.class));

@Bean
public Docket createRestApi() {
    return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(apiInfo())
        .alternateTypeRules(alternateTypeRule)//将TreeNode当Object处理
        .select()
        .apis(RequestHandlerSelectors.basePackage(basePackage))
        .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
        .paths(PathSelectors.any())
        .build();
}

方法2:使用注解属性hidden隐藏循环引用的字段,缺点是文档会缺失这个字段

@ApiModelProperty(hidden = true)

2.swagger提示缺少 com.google.common.base.MoreObjects

原因:缺少guava依赖或者guava版本太低

方法:maven添加或者升级guava

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

3.swagger读取properties失败,显示${swagger.title}等

原因:springMVC没有读取到properties

方法:springMVC配置文件增加读取properties文件

<context:property-placeholder file-encoding="UTF-8" location="classpath:*.properties" 
        	ignore-unresolvable="true" />

4.swagger的properties中文乱码

原因:springMVC读取properties的编码不对

方法:增加file-encoding="UTF-8"

<context:property-placeholder file-encoding="UTF-8" location="classpath:*.properties" 
        	ignore-unresolvable="true" />

5.无法访问swagger-ui.html,但idea的Spring->bean工具中能看到swaggerConfig加载了

进行如下检查:

拦截器或过滤器没有拦截/swagger-ui.html?

spring-MVC正确处理了静态资源?

6.能访问swagger-ui.html但没有api列表

进行如下检查:

swaggerConfig能正常读取properties?

swaggerConfig的basePackage路径覆盖到Controller所在包?

swaggerConfig只扫描swagger注解,且Controller已有对应注解?

swaggerComfig加载时能发现Controller?(Controller一般由SpringMVC加载.如果swaggerConfig在String加载,但MVC中没有加载,那么swaggerConfig无法发现Controller)

idea的Spring->MVC工具中能看到/v2/api-docs路径?(说明swagger组件启动成功)

/v2/*路径被拦截?

web.xml配置springMVC时访问路径包含了/v2/*?

7.能访问swagger-ui.html但样式丢失

进行如下检查:

/webjars/*被拦截?

/swagger-resources/*被拦截?

8.能访问swagger-ui.html但一直弹窗提示Unable to infer base url

进行如下检查:

swaggerConfig已配置@EnableSwagger2注解?

/swagger-resources/*被拦截?

9.swagger把许多不需要的Controller都扫描出来了

方法1:缩小basePackage范围

方法2:扫描特定的类注解

方法3:扫描特定的方法注解

1.apis(RequestHandlerSelectors.basePackage("com.xx.xx.controller"))
2.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
3.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))

关于@EnableWebMvc

网上一些教程认为swaggerConfig必须增加@EnableWebMvc

@EnableWebMvc的作用是引入配置类DelegatingWebMvcConfiguration.class进行自动装配

由于我的项目已经使用xml文件配置好了SpringMVC,是否使用``@EnableWebMvc`都没有影响,估计是被xml覆盖了,没有深究下去

网上也有关于SpringBoot和@EnableWebMvc的讨论

不使用@EnableWebMvc时SpringBoot使用WebMvcAutoConfiguration.class对SpringMVC进行配置

使用@EnableWebMvc时SpringBoot使用DelegatingWebMvcConfiguration.class对SpringMVC进行配置

这是两条不一样的配置路线,后者通常配合自定义的MVCConfig使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值