SpringBoot进阶详解SpringBoot中使用Swagger3。0
在上篇文章中我们介绍了Spring Boot 整合Swagger3.0的一些基础用法,这篇文章中我们来深入学习一下Swagger3.0 还有其他高级用法。
在日常的开发中,为了减少工作量,我们会遇到一种情况,就是将前端的接口与后端的接口编写到同一个代码中,这样也提高了代码的复用率,减少了重复开发代码的工作量。这个时候我们就需要将接口文档也进行拆分。分为前端接口和后端接口两个部分。
在Swagger3.0中如何进行接口分组呢?Swagger3.0 接口分组操作
通过之前的例子我们知道,我们往容器中注入一个Docket就是注入了一个文档,其中我们设置了groupName的分组名称。要想注入多个文档,意思就是需要往容器中注入多个Docket。既然是这样,我们就需要修改之前的Swagger的配置文件,将其改为如下的代码。@EnableOpenApi @Configuration @EnableConfigurationProperties(value = {SwaggerProperties.class}) public class Swagger3Config { @Autowired private SwaggerProperties swaggerProperties; @Bean public Docket frontApi(){ return new Docket(DocumentationType.OAS_30) // 是否开启,根据环境配置 .enable(swaggerProperties.getFront().getEnable()) .groupName(swaggerProperties.getFront().getGroupName()) .apiInfo(frontApiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getFront().getBasePackege())) .paths(PathSelectors.any()) .build(); } // 前台API信息 private ApiInfo frontApiInfo(){ return new ApiInfoBuilder() .title(swaggerProperties.getFront().getTitle()) .description(swaggerProperties.getFront().getDescription()) .version(swaggerProperties.getFront().getVersion()) .contact( // 添加开发者信息 new Contact( swaggerProperties.getFront().getContactName(), swaggerProperties.getFront().getContactUrl(), swaggerProperties.getFront().getContactEmail()) ).build(); } @Bean public Docket backApi(){ return new Docket(DocumentationType.OAS_30) // 是否开启,根据环境配置 .enable(swaggerProperties.getBack().getEnable()) .groupName(swaggerProperties.getBack().getGroupName()) .apiInfo(backApiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBack().getBasePackege())) .paths(PathSelectors.any()) .build(); } // 前台API信息 private ApiInfo backApiInfo(){ return new ApiInfoBuilder() .title(swaggerProperties.getBack().getTitle()) .description(swaggerProperties.getBack().getDescription()) .version(swaggerProperties.getBack().getVersion()) .contact( // 添加开发者信息 new Contact( swaggerProperties.getBack().getContactName(), swaggerProperties.getBack().getContactUrl(), swaggerProperties.getBack().getContactEmail()) ).build(); } }
我们会看到在这个配置类中注入了两个Docket,分别代表前端的接口和后端的接口,那么在配置文件中如何进行配置呢?
首先我们先来看一下其配置类,代码如下@Data @ConfigurationProperties(prefix = "spring.swagger3") public class SwaggerProperties { private SwaggerEntity front; private SwaggerEntity back; @Data public static class SwaggerEntity{ private String groupName; private String basePackege; private String title; private String description; private String contactName; private String contactEmail; private String contactUrl; private String version; private Boolean enable; } }
全局配置类spring: swagger3: front: enable: true groupName: 前端接口 basePackege: com.example.demo.controller.api title: 前端测试接口 description: 前端测试Spring Boot整合Swagger3.0 contactName: nihui contactEmail: 18202504057@163.com contactUrl: https://blog.csdn.net/nihui123 version: 0.0.1 back: enable: true groupName: 后端接口 basePackege: com.example.demo.controller.web title: 后端测试接口 description: 后端测试Spring Boot整合Swagger3.0 contactName: nihui contactEmail: 18202504057@163.com contactUrl: https://blog.csdn.net/nihui123 version: 0.0.1 mvc: pathmatch: matching-strategy: ant_path_matcher
通过上面的配置完成配置之后,就会看到在接口页面会有两个分组,一个是前端接口、一个是后端接口分组。
添加授权认证信息
在很多对外提供服务的API接口中,都会有一个授权认证的操作,否则这些接口是无法进行调用的。例如在一般的情况下,会在接口中包含一个TOKEN参数。
那么在Swagger3.0中如何对这个认证信息进行配置,这样在每次请求的时候都会带着这个参数进行请求,这样就避免了我们在测试过程中,每次都需要添加这个信息的麻烦。
要完成授权信息的添加,我们需要在Docket方法中添加如下的内容@Configuration public class BaseSwagger3Config { @Autowired private BaseSwagger3Properties properties; @Bean public Docket baseApi(){ return new Docket(DocumentationType.OAS_30) // 是否开启,根据环境配置 .enable(properties.getEnable()) .groupName(properties.getGroupName()) .apiInfo(frontApiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(properties.getBasePackege())) .paths(PathSelectors.any()) .build() .securitySchemes(securitySchemes()) .securityContexts(securityContexts()); } private List securitySchemes(){ ApiKey apiKey = new ApiKey("TOKEN","token", In.HEADER.toValue()); return Collections.singletonList(apiKey); } private List securityContexts(){ return Collections.singletonList(SecurityContext.builder(). securityReferences(Collections.singletonList( new SecurityReference("TOKEN",new AuthorizationScope[] {new AuthorizationScope("global","")}))).build()); } // 前台API信息 private ApiInfo frontApiInfo(){ return new ApiInfoBuilder() .title(properties.getTitle()) .description(properties.getDescription()) .version(properties.getVersion()) .contact( // 添加开发者信息 new Contact( properties.getContactName(), properties.getContactUrl(), properties.getContactEmail()) ).build(); } }
完成上述配置之后,会看到在接口页面上会多出一个认证的按钮。通过这个认证的按钮我们可以设置对应的参数值
添加公共参数
在不同的平台使用的时候,除了携带请求Token之外还会有一些用户进行用户分析,大数据分析的参数被传到请求中。那么如何在Swagger3.0中去定义这些公共参数呢?这个时候我们需要在配置代码中添加如下的内容。@Configuration public class BaseSwagger3Config { @Autowired private BaseSwagger3Properties properties; @Bean public Docket baseApi(){ RequestParameter requestParameter = new RequestParameterBuilder() .name("clientType") .description("客户端类型") .in(ParameterType.HEADER) .required(true) .build(); //创建一个请求参数集合 List requestParameterList = Collections.singletonList(requestParameter); return new Docket(DocumentationType.OAS_30) // 是否开启,根据环境配置 .enable(properties.getEnable()) .groupName(properties.getGroupName()) .apiInfo(frontApiInfo()) .select() .apis(RequestHandlerSelectors.basePackage(properties.getBasePackege())) .paths(PathSelectors.any()) .build() .globalRequestParameters(requestParameterList) .securitySchemes(securitySchemes()) .securityContexts(securityContexts()); } private List securitySchemes(){ ApiKey apiKey = new ApiKey("TOKEN","token", In.HEADER.toValue()); return Collections.singletonList(apiKey); } private List securityContexts(){ return Collections.singletonList(SecurityContext.builder(). securityReferences(Collections.singletonList( new SecurityReference("TOKEN",new AuthorizationScope[] {new AuthorizationScope("global","")}))).build()); } // 前台API信息 private ApiInfo frontApiInfo(){ return new ApiInfoBuilder() .title(properties.getTitle()) .description(properties.getDescription()) .version(properties.getVersion()) .contact( // 添加开发者信息 new Contact( properties.getContactName(), properties.getContactUrl(), properties.getContactEmail()) ).build(); } }
会看到上述代码中通过,RequestParameter定义了一个公共的参数,并且将其放入到了一个参数集合中,通过Docket的.globalRequestParameters(requestParameterList)方法将其添加到Swagger3.0文档中。然后运行项目会看到在接口中就会携带这对应的参数出现,并且这个参数是全局的,也就是说每个接口中都需要有这一个参数。
到这里,Swagger的相关内容就告一段落了。细心的读者会发现,在前面我们添加分组配置的时候在配置类上添加了好多的注解,但是在我们演示认证信息与全局参数的时候,配置类中只是简单的添加了一个@Configuration 注解。这是为什么呢?下面我们就来探索一下源码。OpenApiAutoConfiguration 源码
会看到在这段源码中,好像什么功能都没实现,但是它确完成了Swagger3.0大多数的配置,而对于@EnableOpenApi 注解来讲。@Configuration @EnableConfigurationProperties(SpringfoxConfigurationProperties.class) @ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true) @Import({ OpenApiDocumentationConfiguration.class, SpringDataRestConfiguration.class, BeanValidatorPluginsConfiguration.class, Swagger2DocumentationConfiguration.class, SwaggerUiWebFluxConfiguration.class, SwaggerUiWebMvcConfiguration.class }) @AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class }) public class OpenApiAutoConfiguration { } @EnableOpenApi 注解
对于@EnableOpenApi注解来讲其关键的代码就是@Import(OpenApiDocumentationConfiguration.class) 引入的还是这个类。@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) @Target(value = {java.lang.annotation.ElementType.TYPE}) @Documented @Import(OpenApiDocumentationConfiguration.class) public @interface EnableOpenApi { }
这里我们会发现为什么在没有@EnableOpenApi注解的时候也会生效呢?那就是用到了我们Spring Boot自动配置的原理了。关于自动配置的原理在后续的分析中我们来进行讲解,这里就先不做过多说明。提示大家的就是找到如下图中的代码就可以理解自动配置的原理
总结
通过上面的内容我们了解了Swagger3.0的一些扩展性的用法,当然Swagger的用法远远不止这些,但是这些内容已经可以支持在我们日常开发中的一些工作。希望大家多多关注,笔者会为大家带来更多精彩干活