Skip to content

Commit 447382d

Browse files
authored
Merge pull request #1 from SpringForAll/master
pull
2 parents 3f72fce + 9392471 commit 447382d

File tree

8 files changed

+187
-25
lines changed

8 files changed

+187
-25
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@
2020

2121
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2222
hs_err_pid*
23+
.idea/
24+
spring-boot-starter-swagger.iml
25+
target/

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
language: java
2+
3+
jdk:
4+
- oraclejdk8
5+
6+
install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true

README.md

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# 简介
22

3+
[![Build Status](https://travis-ci.org/dyc87112/spring-boot-starter-swagger.svg?branch=master)](https://travis-ci.org/dyc87112/spring-boot-starter-swagger)
4+
35
该项目主要利用Spring Boot的自动化配置特性来实现快速的将swagger2引入spring boot应用来生成API文档,简化原生使用swagger2的整合代码。
46

57
- 源码地址
@@ -26,7 +28,7 @@
2628
<dependency>
2729
<groupId>com.didispace</groupId>
2830
<artifactId>spring-boot-starter-swagger</artifactId>
29-
<version>1.3.0.RELEASE</version>
31+
<version>1.4.1.RELEASE</version>
3032
</dependency>
3133
```
3234

@@ -53,9 +55,11 @@ public class Bootstrap {
5355
## 配置示例
5456

5557
```properties
58+
swagger.enabled=true
59+
5660
swagger.title=spring-boot-starter-swagger
5761
swagger.description=Starter for swagger 2.x
58-
swagger.version=1.3.0.RELEASE
62+
swagger.version=1.4.0.RELEASE
5963
swagger.license=Apache License, Version 2.0
6064
swagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.html
6165
swagger.termsOfServiceUrl=https://github.com/dyc87112/spring-boot-starter-swagger
@@ -65,13 +69,25 @@ swagger.contact.email=dyc87112@qq.com
6569
swagger.base-package=com.didispace
6670
swagger.base-path=/**
6771
swagger.exclude-path=/error, /ops/**
72+
73+
swagger.globalOperationParameters[0].name=name one
74+
swagger.globalOperationParameters[0].description=some description one
75+
swagger.globalOperationParameters[0].modelRef=string
76+
swagger.globalOperationParameters[0].parameterType=header
77+
swagger.globalOperationParameters[0].required=true
78+
swagger.globalOperationParameters[1].name=name two
79+
swagger.globalOperationParameters[1].description=some description two
80+
swagger.globalOperationParameters[1].modelRef=string
81+
swagger.globalOperationParameters[1].parameterType=body
82+
swagger.globalOperationParameters[1].required=false
6883
```
6984

7085
## 配置说明
7186

7287
### 默认配置
7388

7489
```
90+
- swagger.enabled=是否启用swagger,默认:true
7591
- swagger.title=标题
7692
- swagger.description=描述
7793
- swagger.version=版本
@@ -85,9 +101,19 @@ swagger.exclude-path=/error, /ops/**
85101
- swagger.base-path=需要处理的基础URL规则,默认:/**
86102
- swagger.exclude-path=需要排除的URL规则,默认:空
87103
- swagger.host=文档的host信息,默认:空
104+
- swagger.globalOperationParameters[0].name=参数名
105+
- swagger.globalOperationParameters[0].description=描述信息
106+
- swagger.globalOperationParameters[0].modelRef=指定参数类型
107+
- swagger.globalOperationParameters[0].parameterType=指定参数存放位置,可选header,query,path,body.form
108+
- swagger.globalOperationParameters[0].required=指定参数是否必传,true,false
88109
```
89110

90-
> host属性从1.3.0.RELEASE开始支持
111+
112+
> `1.3.0.RELEASE`新增:`swagger.host`属性,同时也支持指定docket的配置
113+
>
114+
> `1.4.0.RELEASE`新增:
115+
> - `swagger.enabled`:用于开关swagger的配置
116+
> - `swagger.globalOperationParameters`:用于设置全局的参数,比如:header部分的accessToken等。该参数支持指定docket的配置。
91117
92118
### Path规则说明
93119

@@ -129,10 +155,19 @@ swagger.exclude-path=/ops/**, /error
129155
- swagger.docket.<name>.base-package=swagger扫描的基础包,默认:全扫描
130156
- swagger.docket.<name>.base-path=需要处理的基础URL规则,默认:/**
131157
- swagger.docket.<name>.exclude-path=需要排除的URL规则,默认:空
158+
- swagger.docket.<name>.name=参数名
159+
- swagger.docket.<name>.modelRef=指定参数类型
160+
- swagger.docket.<name>.parameterType=指定参数存放位置,可选header,query,path,body.form
161+
- swagger.docket.<name>.required=true=指定参数是否必传,true,false
162+
- swagger.docket.<name>.globalOperationParameters[0].name=参数名
163+
- swagger.docket.<name>.globalOperationParameters[0].description=描述信息
164+
- swagger.docket.<name>.globalOperationParameters[0].modelRef=指定参数存放位置,可选header,query,path,body.form
165+
- swagger.docket.<name>.globalOperationParameters[0].parameterType=指定参数是否必传,true,false
132166
```
133167

134168
说明:`<name>`为swagger文档的分组名称,同一个项目中可以配置多个分组,用来划分不同的API文档。
135169

170+
136171
**分组配置示例**
137172

138173
```properties
@@ -144,12 +179,16 @@ swagger.docket.aaa.contact.name=zhaiyongchao
144179
swagger.docket.aaa.contact.url=http://spring4all.com/
145180
swagger.docket.aaa.contact.email=didi@potatomato.club
146181
swagger.docket.aaa.excludePath=/ops/**
182+
swagger.docket.aaa.globalOperationParameters[0].name=name three
183+
swagger.docket.aaa.globalOperationParameters[0].description=some description three override
184+
swagger.docket.aaa.globalOperationParameters[0].modelRef=string
185+
swagger.docket.aaa.globalOperationParameters[0].parameterType=header
147186

148187
swagger.docket.bbb.title=group-bbb
149188
swagger.docket.bbb.basePackage=com.yonghui
150189
```
151190

152-
说明:默认配置与分组配置可以一起使用。在分组配置中没有配置的内容将使用默认配置替代,所以默认配置可以作为分组配置公共部分属性的配置。
191+
说明:默认配置与分组配置可以一起使用。在分组配置中没有配置的内容将使用默认配置替代,所以默认配置可以作为分组配置公共部分属性的配置。`swagger.docket.aaa.globalOperationParameters[0].name`会覆盖同名的全局配置。
153192

154193
### JSR-303校验注解支持
155194

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.didispace</groupId>
88
<artifactId>spring-boot-starter-swagger</artifactId>
9-
<version>1.3.0.RELEASE</version>
9+
<version>1.4.1.RELEASE</version>
1010

1111
<name>spring-boot-starter-swagger</name>
1212
<url>https://github.com/dyc87112/spring-boot-starter-swagger</url>
@@ -113,4 +113,4 @@
113113
</plugin>
114114
</plugins>
115115
</build>
116-
</project>
116+
</project>

src/main/java/com/didispace/swagger/EnableSwagger2Doc.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.didispace.swagger;
22

33
import org.springframework.context.annotation.Import;
4-
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
5-
import springfox.documentation.swagger2.annotations.EnableSwagger2;
64

75
import java.lang.annotation.*;
86

@@ -15,8 +13,7 @@
1513
@Retention(RetentionPolicy.RUNTIME)
1614
@Documented
1715
@Inherited
18-
@EnableSwagger2
19-
@Import({SwaggerAutoConfiguration.class, BeanValidatorPluginsConfiguration.class})
16+
@Import({SwaggerAutoConfiguration.class})
2017
public @interface EnableSwagger2Doc {
2118

2219

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.didispace.swagger;
2+
3+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.context.annotation.Import;
6+
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
7+
import springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration;
8+
9+
/**
10+
* @author 翟永超
11+
* Create Date: 2017/9/7.
12+
* My blog: http://blog.didispace.com
13+
*/
14+
@Configuration
15+
@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
16+
@Import({
17+
Swagger2DocumentationConfiguration.class,
18+
BeanValidatorPluginsConfiguration.class
19+
})
20+
public class Swagger2Configuration {
21+
}

src/main/java/com/didispace/swagger/SwaggerAutoConfiguration.java

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,39 @@
22

33
import com.google.common.base.Predicate;
44
import com.google.common.base.Predicates;
5+
import com.google.common.collect.Lists;
56
import org.springframework.beans.BeansException;
67
import org.springframework.beans.factory.BeanFactory;
78
import org.springframework.beans.factory.BeanFactoryAware;
89
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
910
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
11+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
1012
import org.springframework.context.annotation.Bean;
1113
import org.springframework.context.annotation.Configuration;
14+
import org.springframework.context.annotation.Import;
1215
import springfox.documentation.builders.ApiInfoBuilder;
16+
import springfox.documentation.builders.ParameterBuilder;
1317
import springfox.documentation.builders.PathSelectors;
1418
import springfox.documentation.builders.RequestHandlerSelectors;
19+
import springfox.documentation.schema.ModelRef;
1520
import springfox.documentation.service.ApiInfo;
1621
import springfox.documentation.service.Contact;
22+
import springfox.documentation.service.Parameter;
1723
import springfox.documentation.spi.DocumentationType;
1824
import springfox.documentation.spring.web.plugins.Docket;
1925

20-
import java.util.ArrayList;
21-
import java.util.LinkedList;
22-
import java.util.List;
26+
import java.util.*;
27+
import java.util.stream.Collectors;
2328

2429
/**
2530
* @author 翟永超
26-
* Create date :2017/8/7.
31+
* Create date:2017/8/7.
2732
* My blog: http://blog.didispace.com
2833
*/
2934
@Configuration
35+
@Import({
36+
Swagger2Configuration.class
37+
})
3038
public class SwaggerAutoConfiguration implements BeanFactoryAware {
3139

3240
private BeanFactory beanFactory;
@@ -39,11 +47,12 @@ public SwaggerProperties swaggerProperties() {
3947

4048
@Bean
4149
@ConditionalOnMissingBean
50+
@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
4251
public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
4352
ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
4453

4554
// 没有分组
46-
if(swaggerProperties.getDocket().size() == 0) {
55+
if (swaggerProperties.getDocket().size() == 0) {
4756
ApiInfo apiInfo = new ApiInfoBuilder()
4857
.title(swaggerProperties.getTitle())
4958
.description(swaggerProperties.getDescription())
@@ -58,23 +67,26 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
5867

5968
// base-path处理
6069
// 当没有配置任何path的时候,解析/**
61-
if(swaggerProperties.getBasePath().isEmpty()) {
70+
if (swaggerProperties.getBasePath().isEmpty()) {
6271
swaggerProperties.getBasePath().add("/**");
6372
}
6473
List<Predicate<String>> basePath = new ArrayList();
65-
for(String path : swaggerProperties.getBasePath()) {
74+
for (String path : swaggerProperties.getBasePath()) {
6675
basePath.add(PathSelectors.ant(path));
6776
}
6877

6978
// exclude-path处理
7079
List<Predicate<String>> excludePath = new ArrayList();
71-
for(String path : swaggerProperties.getExcludePath()) {
80+
for (String path : swaggerProperties.getExcludePath()) {
7281
excludePath.add(PathSelectors.ant(path));
7382
}
7483

84+
7585
Docket docket = new Docket(DocumentationType.SWAGGER_2)
7686
.host(swaggerProperties.getHost())
7787
.apiInfo(apiInfo)
88+
.globalOperationParameters(buildGlobalOperationParametersFromSwaggerProperties(
89+
swaggerProperties.getGlobalOperationParameters()))
7890
.select()
7991
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
8092
.paths(
@@ -91,7 +103,7 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
91103

92104
// 分组创建
93105
List<Docket> docketList = new LinkedList<>();
94-
for(String groupName : swaggerProperties.getDocket().keySet()) {
106+
for (String groupName : swaggerProperties.getDocket().keySet()) {
95107
SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName);
96108

97109
ApiInfo apiInfo = new ApiInfoBuilder()
@@ -102,33 +114,35 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
102114
.licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerProperties.getLicenseUrl() : docketInfo.getLicenseUrl())
103115
.contact(
104116
new Contact(
105-
docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(),
106-
docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(),
107-
docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail()
117+
docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(),
118+
docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(),
119+
docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail()
108120
)
109121
)
110122
.termsOfServiceUrl(docketInfo.getTermsOfServiceUrl().isEmpty() ? swaggerProperties.getTermsOfServiceUrl() : docketInfo.getTermsOfServiceUrl())
111123
.build();
112124

113125
// base-path处理
114126
// 当没有配置任何path的时候,解析/**
115-
if(docketInfo.getBasePath().isEmpty()) {
127+
if (docketInfo.getBasePath().isEmpty()) {
116128
docketInfo.getBasePath().add("/**");
117129
}
118130
List<Predicate<String>> basePath = new ArrayList();
119-
for(String path : docketInfo.getBasePath()) {
131+
for (String path : docketInfo.getBasePath()) {
120132
basePath.add(PathSelectors.ant(path));
121133
}
122134

123135
// exclude-path处理
124136
List<Predicate<String>> excludePath = new ArrayList();
125-
for(String path : docketInfo.getExcludePath()) {
137+
for (String path : docketInfo.getExcludePath()) {
126138
excludePath.add(PathSelectors.ant(path));
127139
}
128140

129141
Docket docket = new Docket(DocumentationType.SWAGGER_2)
130142
.host(swaggerProperties.getHost())
131143
.apiInfo(apiInfo)
144+
.globalOperationParameters(assemblyGlobalOperationParameters(swaggerProperties.getGlobalOperationParameters(),
145+
docketInfo.getGlobalOperationParameters()))
132146
.groupName(groupName)
133147
.select()
134148
.apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))
@@ -150,4 +164,56 @@ public List<Docket> createRestApi(SwaggerProperties swaggerProperties) {
150164
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
151165
this.beanFactory = beanFactory;
152166
}
167+
168+
private List<Parameter> buildGlobalOperationParametersFromSwaggerProperties(
169+
List<SwaggerProperties.GlobalOperationParameter> globalOperationParameters) {
170+
List<Parameter> parameters = Lists.newArrayList();
171+
172+
if (Objects.isNull(globalOperationParameters)) {
173+
return parameters;
174+
}
175+
for (SwaggerProperties.GlobalOperationParameter globalOperationParameter : globalOperationParameters) {
176+
parameters.add(new ParameterBuilder()
177+
.name(globalOperationParameter.getName())
178+
.description(globalOperationParameter.getDescription())
179+
.modelRef(new ModelRef(globalOperationParameter.getModelRef()))
180+
.parameterType(globalOperationParameter.getParameterType())
181+
.required(Boolean.parseBoolean(globalOperationParameter.getRequired()))
182+
.build());
183+
}
184+
return parameters;
185+
}
186+
187+
/**
188+
* 局部参数按照name覆盖局部参数
189+
*
190+
* @param globalOperationParameters
191+
* @param docketOperationParameters
192+
* @return
193+
*/
194+
private List<Parameter> assemblyGlobalOperationParameters(
195+
List<SwaggerProperties.GlobalOperationParameter> globalOperationParameters,
196+
List<SwaggerProperties.GlobalOperationParameter> docketOperationParameters) {
197+
198+
if (Objects.isNull(docketOperationParameters) || docketOperationParameters.isEmpty()) {
199+
return buildGlobalOperationParametersFromSwaggerProperties(globalOperationParameters);
200+
}
201+
202+
Set<String> docketNames = docketOperationParameters.stream()
203+
.map(SwaggerProperties.GlobalOperationParameter::getName)
204+
.collect(Collectors.toSet());
205+
206+
List<SwaggerProperties.GlobalOperationParameter> resultOperationParameters = Lists.newArrayList();
207+
208+
if (Objects.nonNull(globalOperationParameters)) {
209+
for (SwaggerProperties.GlobalOperationParameter parameter : globalOperationParameters) {
210+
if (!docketNames.contains(parameter.getName())) {
211+
resultOperationParameters.add(parameter);
212+
}
213+
}
214+
}
215+
216+
resultOperationParameters.addAll(docketOperationParameters);
217+
return buildGlobalOperationParametersFromSwaggerProperties(resultOperationParameters);
218+
}
153219
}

0 commit comments

Comments
 (0)