SpringBoot实战:SpringBoot之Swagger集成

Swagger 的优势有哪些

  1. 支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便,可以节约写文档的时间去学习新技术。
  2. 提供 Web 页面在线测试 API:光有文档还不够,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。

SpringBoot集成Swagger很方便,接下来将演示如何集成

首先pom.xml引入相关依赖

<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>

创建Swagger配置类

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;

/**
* @author wusy
* Company: xxxxxx科技有限公司
* Createtime : 2018年9月3日 下午1:47:48
* Description : 
*/
@EnableSwagger2
@Configuration
public class SwaggerConfigurer {

	@Bean
	public Docket createRestApi() {
		return new Docket(DocumentationType.SWAGGER_2)
				.apiInfo(apiInfo())
				.select().apis(RequestHandlerSelectors.basePackage("com.wusy.demo"))
				.paths(PathSelectors.any())
				.build();
	}

	private ApiInfo apiInfo() {
		ApiInfoBuilder builder = new ApiInfoBuilder();
		builder.title("spring-boot-wusy-demo");
		builder.description("spring-boot-wusy-demo rest full api文档");
		builder.version("1.0");
		return builder.build();
	}
}

这里记住@EnableSwagger2这个注解是必不可少的,最后编写Rest Full接口

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author wusy
 * Company: xxxxxx科技有限公司
 * Createtime : 2020/3/4 23:22
 * Description :
 */
@Api(tags = {"Swagger集成演示相关接口"})
@RestController
@RequestMapping("/api/swagger")
public class SwaggerDemoController {

    @ApiOperation("Swagger集成示例")
    @RequestMapping(value = "/demo", method = RequestMethod.GET)
    public String demo(@ApiParam(required = true , name = "param") String param) {
        return param;
    }
}

到这里集成Swagger完成,接下来我们启动项目然后在浏览器中输入http://127.0.0.1:8787/swagger-ui.html,观察结果

提示出错了,这里提示base url被拦截了,通过观察网络请求发现

通过分析原来是之前在配置自定义方法接口的时候把swapper接口也给拦截了,所以要原来的改造下

/**
 * @author wusy
 * Company: xxxxxx科技有限公司
 * Createtime : 2020/2/28 22:04
 * Description : rest full 全局统一返回封装
 */
@RestControllerAdvice
public class GlobalControllerAdvice implements ResponseBodyAdvice<Object> {

    private Logger logger = LoggerFactory.getLogger(GlobalControllerAdvice.class);

    /**
     * 需要忽略的地址
     */
    private static String[] ignores = new String[]{
            //过滤swagger相关的请求的接口,不然swagger会提示base-url被拦截
            "/swagger-resources",
            "/v2/api-docs"
    };

    /**
     * 判断哪些需要拦截
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    /**
     * 判断url是否需要拦截
     * @param uri
     * @return
     */
    private boolean ignoring(String uri) {
        for (String string : ignores) {
            if (uri.contains(string)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //判断url是否需要拦截
        if (this.ignoring(request.getURI().toString())) {
            return body;
        }
        //如果返回的数据是ResultObjectModel、Byte类型则不进行封装
        if( body instanceof ResultObjectModel || body instanceof Byte || body instanceof String) {
            return body;
        }
        return this.getWrapperResponse(request , body);
    }
  
    /**
     * 返回正常的信息
     * @param request
     * @param data
     * @return
     */
    private ResultObjectModel<Object> getWrapperResponse(ServerHttpRequest request, Object data) {
        return new ResultObjectModel<>(true, "请求成功" , data);
    }
}

重启应用,这里要重启浏览器后访问http://127.0.0.1:8787/swagger-ui.html,观察结果

至此Swagger集成成功。

集成Swagger的时候要注意以下几点:

1、@EnableSwagger2注解一定要添加

2、自定义接口ResponseBodyAdvice中是否对swagger的相关接口做了处理,本次演示中就是因为这个问题导致出现问题

3、过滤器是否对swagger的相关接口做了处理

4、集成security时如果swagger不需要登陆就能访问的话应该要对swagger的相关进行不拦截

@Override
public void configure(WebSecurity web) {
    //swagger相关的页面和接口不拦截
	web.ignoring().antMatchers("/swagger-ui.html")
			      .antMatchers("/webjars/springfox-swagger-ui/**")
				  .antMatchers("/swagger-resources/**" )
				  .antMatchers("/v2/api-docs/**");
}