Skip to content

Commit f3f18a0

Browse files
authored
Merge pull request SpringForAll#217 from llin6025/master
feat: 适配 springfox 3.0.0
2 parents cee22cd + 8a490d1 commit f3f18a0

File tree

4 files changed

+238
-95
lines changed

4 files changed

+238
-95
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.spring4all.swagger;
2+
3+
import org.springframework.beans.BeansException;
4+
import org.springframework.beans.factory.BeanFactory;
5+
import org.springframework.beans.factory.BeanFactoryAware;
6+
import org.springframework.beans.factory.config.BeanDefinition;
7+
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
8+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
9+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
10+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
11+
import org.springframework.stereotype.Component;
12+
13+
/**
14+
* Used to change the initialization order of the starter
15+
*
16+
* @since 2.0.0
17+
* @author llin6025
18+
* @Create 2021/8/13
19+
*/
20+
@Component
21+
@ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
22+
public class DocketBeanFactoryPostProcessor implements BeanFactoryPostProcessor, BeanFactoryAware {
23+
private BeanFactory beanFactory;
24+
25+
@Override
26+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
27+
this.beanFactory = beanFactory;
28+
}
29+
30+
@Override
31+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
32+
BeanDefinitionRegistry beanRegistry = (BeanDefinitionRegistry)beanFactory;
33+
34+
// 获取 documentationPluginRegistry Bean,强制依赖 swagger-spring-boot-starter 配置 Bean 初始化
35+
String beanName = "documentationPluginRegistry";
36+
if (beanRegistry.containsBeanDefinition(beanName)) {
37+
BeanDefinition documentationPluginRegistryBeanDefinition = beanRegistry.getBeanDefinition(beanName);
38+
documentationPluginRegistryBeanDefinition.setDependsOn("createSpringFoxRestApi");
39+
}
40+
}
41+
}
Lines changed: 131 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
11
package com.spring4all.swagger;
22

3-
import com.google.common.base.Predicates;
4-
import lombok.RequiredArgsConstructor;
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.function.Predicate;
7+
import java.util.stream.Collectors;
8+
9+
import org.springframework.beans.BeansException;
10+
import org.springframework.beans.factory.BeanFactory;
11+
import org.springframework.beans.factory.BeanFactoryAware;
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.beans.factory.config.BeanDefinition;
14+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
15+
import org.springframework.beans.factory.support.GenericBeanDefinition;
16+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
517
import org.springframework.context.annotation.Bean;
618
import org.springframework.context.annotation.Configuration;
19+
20+
import com.google.common.base.Predicates;
21+
722
import springfox.documentation.builders.ApiInfoBuilder;
823
import springfox.documentation.builders.RequestHandlerSelectors;
924
import springfox.documentation.builders.RequestParameterBuilder;
@@ -14,134 +29,165 @@
1429
import springfox.documentation.spi.DocumentationType;
1530
import springfox.documentation.spring.web.plugins.Docket;
1631

17-
import java.util.ArrayList;
18-
import java.util.Collections;
19-
import java.util.List;
20-
import java.util.function.Predicate;
21-
import java.util.stream.Collectors;
22-
23-
import static java.util.Collections.singletonList;
24-
2532
/**
2633
* @author 翟永超
27-
* Create date:2017/8/7.
28-
* My blog: http://blog.didispace.com
34+
* @Create date:2017/8/7.
35+
* @Update date:2021/8/13
36+
* @My blog: http://blog.didispace.com
2937
*/
3038
@Configuration
31-
public class DocketConfiguration {
39+
@EnableConfigurationProperties(SwaggerProperties.class)
40+
public class DocketConfiguration implements BeanFactoryAware {
3241

42+
private BeanFactory beanFactory;
43+
44+
@Autowired
3345
private SwaggerProperties swaggerProperties;
34-
private SwaggerAuthorizationConfiguration swaggerAuthorizationConfiguration;
3546

36-
public DocketConfiguration(SwaggerProperties swaggerProperties,
37-
SwaggerAuthorizationConfiguration swaggerAuthorizationConfiguration) {
38-
this.swaggerProperties = swaggerProperties;
39-
this.swaggerAuthorizationConfiguration = swaggerAuthorizationConfiguration;
47+
private static final String BEAN_NAME = "spring-boot-starter-swagger-";
48+
49+
@Override
50+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
51+
this.beanFactory = beanFactory;
4052
}
4153

54+
/**
55+
* Create the corresponding configuration for DocumentationPluginRegistry
56+
*/
4257
@Bean
43-
public Docket createRestApi() {
44-
// 文档的基础信息配置
45-
Docket builder = new Docket(DocumentationType.SWAGGER_2)
46-
.host(swaggerProperties.getHost())
47-
.apiInfo(apiInfo(swaggerProperties));
48-
49-
// 安全相关的配置
50-
builder.securityContexts(Collections.singletonList(swaggerAuthorizationConfiguration.securityContext()));
51-
if ("BasicAuth".equalsIgnoreCase(swaggerAuthorizationConfiguration.getType())) {
52-
builder.securitySchemes(Collections.singletonList(swaggerAuthorizationConfiguration.basicAuth()));
53-
} else if (!"None".equalsIgnoreCase(swaggerAuthorizationConfiguration.getType())) {
54-
builder.securitySchemes(Collections.singletonList(swaggerAuthorizationConfiguration.apiKey()));
55-
}
56-
57-
// 要忽略的参数类型
58-
Class<?>[] array = new Class[swaggerProperties.getIgnoredParameterTypes().size()];
59-
Class<?>[] ignoredParameterTypes = swaggerProperties.getIgnoredParameterTypes().toArray(array);
60-
builder.ignoredParameterTypes(ignoredParameterTypes);
61-
62-
// 设置全局参数
63-
if (swaggerProperties.getGlobalOperationParameters() != null) {
64-
builder.globalRequestParameters(globalRequestParameters(swaggerProperties));
58+
public void createSpringFoxRestApi() {
59+
BeanDefinitionRegistry beanRegistry = (BeanDefinitionRegistry)beanFactory;
60+
61+
// 没有分组
62+
if (swaggerProperties.getDocket().size() == 0) {
63+
String beanName = BEAN_NAME + "default";
64+
BeanDefinition beanDefinition4Group = new GenericBeanDefinition();
65+
beanDefinition4Group.getConstructorArgumentValues().addIndexedArgumentValue(0, DocumentationType.OAS_30);
66+
beanDefinition4Group.setBeanClassName(Docket.class.getName());
67+
beanDefinition4Group.setRole(BeanDefinition.ROLE_SUPPORT);
68+
beanRegistry.registerBeanDefinition(beanName, beanDefinition4Group);
69+
70+
Docket docket4Group = (Docket)beanFactory.getBean(beanName);
71+
ApiInfo apiInfo = apiInfo(swaggerProperties);
72+
docket4Group.host(swaggerProperties.getHost()).apiInfo(apiInfo).select()
73+
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
74+
.paths(paths(swaggerProperties.getBasePath(), swaggerProperties.getExcludePath())).build();
75+
return;
6576
}
6677

67-
// 需要生成文档的接口目标配置
68-
Docket docket = builder.select()
69-
// 通过扫描包选择接口
70-
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
71-
// 通过路径匹配选择接口
72-
.paths(paths(swaggerProperties))
78+
for (Map.Entry<String, SwaggerProperties.DocketInfo> entry : swaggerProperties.getDocket().entrySet()) {
79+
String groupName = entry.getKey();
80+
SwaggerProperties.DocketInfo docketInfo = entry.getValue();
81+
String beanName = BEAN_NAME + groupName;
82+
83+
ApiInfo apiInfo = new ApiInfoBuilder()
84+
.title(docketInfo.getTitle().isEmpty() ? swaggerProperties.getTitle() : docketInfo.getTitle())
85+
.description(docketInfo.getDescription().isEmpty() ? swaggerProperties.getDescription()
86+
: docketInfo.getDescription())
87+
.version(docketInfo.getVersion().isEmpty() ? swaggerProperties.getVersion() : docketInfo.getVersion())
88+
.license(docketInfo.getLicense().isEmpty() ? swaggerProperties.getLicense() : docketInfo.getLicense())
89+
.licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerProperties.getLicenseUrl()
90+
: docketInfo.getLicenseUrl())
91+
.contact(new Contact(
92+
docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName()
93+
: docketInfo.getContact().getName(),
94+
docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl()
95+
: docketInfo.getContact().getUrl(),
96+
docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail()
97+
: docketInfo.getContact().getEmail()))
98+
.termsOfServiceUrl(docketInfo.getTermsOfServiceUrl().isEmpty()
99+
? swaggerProperties.getTermsOfServiceUrl() : docketInfo.getTermsOfServiceUrl())
73100
.build();
74101

75-
return docket;
102+
// base-path处理
103+
// 当没有配置任何path的时候,解析/**
104+
if (docketInfo.getBasePath().isEmpty()) {
105+
docketInfo.getBasePath().add("/**");
106+
}
107+
108+
List<Predicate<String>> basePath = new ArrayList<>();
109+
for (String path : docketInfo.getBasePath()) {
110+
basePath.add(PathSelectors.ant(path));
111+
}
112+
113+
// exclude-path处理
114+
List<Predicate<String>> excludePath = new ArrayList<>();
115+
for (String path : docketInfo.getExcludePath()) {
116+
excludePath.add(PathSelectors.ant(path));
117+
}
118+
119+
BeanDefinition beanDefinition4Group = new GenericBeanDefinition();
120+
beanDefinition4Group.getConstructorArgumentValues().addIndexedArgumentValue(0, DocumentationType.OAS_30);
121+
beanDefinition4Group.setBeanClassName(Docket.class.getName());
122+
beanDefinition4Group.setRole(BeanDefinition.ROLE_SUPPORT);
123+
beanRegistry.registerBeanDefinition(beanName, beanDefinition4Group);
124+
125+
Docket docket4Group = (Docket)beanFactory.getBean(beanName);
126+
docket4Group.groupName(groupName).host(docketInfo.getBasePackage()).apiInfo(apiInfo).select()
127+
.apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))
128+
.paths(paths(docketInfo.getBasePath(), docketInfo.getExcludePath())).build();
129+
}
76130
}
77131

78132
/**
79133
* 全局请求参数
80134
*
81-
* @param swaggerProperties {@link SwaggerProperties}
135+
* @param swaggerProperties
136+
* {@link SwaggerProperties}
82137
* @return RequestParameter {@link RequestParameter}
83138
*/
84139
private List<RequestParameter> globalRequestParameters(SwaggerProperties swaggerProperties) {
85-
return swaggerProperties.getGlobalOperationParameters().stream().map(param -> new RequestParameterBuilder()
86-
.name(param.getName())
87-
.description(param.getDescription())
88-
.in(param.getParameterType())
89-
.required(param.getRequired())
140+
return swaggerProperties.getGlobalOperationParameters().stream()
141+
.map(param -> new RequestParameterBuilder().name(param.getName()).description(param.getDescription())
142+
.in(param.getParameterType()).required(param.getRequired())
90143
.query(q -> q.defaultValue(param.getModelRef()))
91-
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
92-
.build()).collect(Collectors.toList());
144+
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING))).build())
145+
.collect(Collectors.toList());
93146
}
94147

95148
/**
96149
* API接口路径选择
97150
*
98-
* @param swaggerProperties
99-
* @return
151+
* @param basePath
152+
* basePath
153+
* @param excludePath
154+
* excludePath
155+
* @return path
100156
*/
101157

102-
private Predicate paths(SwaggerProperties swaggerProperties) {
158+
private Predicate paths(List<String> basePath, List<String> excludePath) {
103159
// base-path处理
104160
// 当没有配置任何path的时候,解析/**
105-
if (swaggerProperties.getBasePath().isEmpty()) {
106-
swaggerProperties.getBasePath().add("/**");
161+
if (basePath.isEmpty()) {
162+
basePath.add("/**");
107163
}
108-
List<com.google.common.base.Predicate<String>> basePath = new ArrayList<>();
109-
for (String path : swaggerProperties.getBasePath()) {
110-
basePath.add(PathSelectors.ant(path));
164+
List<com.google.common.base.Predicate<String>> basePathList = new ArrayList<>();
165+
for (String path : basePath) {
166+
basePathList.add(PathSelectors.ant(path));
111167
}
112168

113169
// exclude-path处理
114-
List<com.google.common.base.Predicate<String>> excludePath = new ArrayList<>();
115-
for (String path : swaggerProperties.getExcludePath()) {
116-
excludePath.add(PathSelectors.ant(path));
170+
List<com.google.common.base.Predicate<String>> excludePathList = new ArrayList<>();
171+
for (String path : excludePath) {
172+
excludePathList.add(PathSelectors.ant(path));
117173
}
118174

119-
return Predicates.and(
120-
Predicates.not(Predicates.or(excludePath)),
121-
Predicates.or(basePath)
122-
);
175+
return Predicates.and(Predicates.not(Predicates.or(excludePathList)), Predicates.or(basePathList));
123176
}
124177

125178
/**
126179
* API文档基本信息
127180
*
128181
* @param swaggerProperties
129-
* @return
182+
* swaggerProperties
183+
* @return apiInfo
130184
*/
131185
private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
132-
ApiInfo apiInfo = new ApiInfoBuilder()
133-
.title(swaggerProperties.getTitle())
134-
.description(swaggerProperties.getDescription())
135-
.version(swaggerProperties.getVersion())
136-
.license(swaggerProperties.getLicense())
137-
.licenseUrl(swaggerProperties.getLicenseUrl())
138-
.contact(new Contact(swaggerProperties.getContact().getName(),
139-
swaggerProperties.getContact().getUrl(),
140-
swaggerProperties.getContact().getEmail()))
141-
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
142-
.build();
143-
return apiInfo;
186+
return new ApiInfoBuilder().title(swaggerProperties.getTitle()).description(swaggerProperties.getDescription())
187+
.version(swaggerProperties.getVersion()).license(swaggerProperties.getLicense())
188+
.licenseUrl(swaggerProperties.getLicenseUrl())
189+
.contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(),
190+
swaggerProperties.getContact().getEmail()))
191+
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()).build();
144192
}
145-
146-
147193
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.spring4all.swagger;
22

3+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
34
import org.springframework.boot.context.properties.EnableConfigurationProperties;
45
import org.springframework.context.annotation.Configuration;
56
import org.springframework.context.annotation.Import;
@@ -11,11 +12,8 @@
1112
*/
1213
@Configuration
1314
@EnableConfigurationProperties(SwaggerProperties.class)
14-
@Import({
15-
SwaggerUiConfiguration.class,
16-
SwaggerAuthorizationConfiguration.class,
17-
DocketConfiguration.class
18-
})
15+
@ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
16+
@Import({SwaggerUiConfiguration.class, SwaggerAuthorizationConfiguration.class, DocketConfiguration.class})
1917
public class SwaggerAutoConfiguration {
2018

2119
}

0 commit comments

Comments
 (0)