diff --git a/.gitignore b/.gitignore
index 6143e53..9ff7aa7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,6 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+.idea/
+spring-boot-starter-swagger.iml
+target/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..a322442
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,6 @@
+language: java
+
+jdk:
+ - oraclejdk8
+
+install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true
diff --git a/README.md b/README.md
index ac3eded..9f96805 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@
com.didispace
spring-boot-starter-swagger
- 1.3.0.RELEASE
+ 1.4.0.RELEASE
```
@@ -53,9 +53,11 @@ public class Bootstrap {
## 配置示例
```properties
+swagger.enabled=true
+
swagger.title=spring-boot-starter-swagger
swagger.description=Starter for swagger 2.x
-swagger.version=1.3.0.RELEASE
+swagger.version=1.4.0.RELEASE
swagger.license=Apache License, Version 2.0
swagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.html
swagger.termsOfServiceUrl=https://github.com/dyc87112/spring-boot-starter-swagger
@@ -65,6 +67,17 @@ swagger.contact.email=dyc87112@qq.com
swagger.base-package=com.didispace
swagger.base-path=/**
swagger.exclude-path=/error, /ops/**
+
+swagger.globalOperationParameters[0].name=name one
+swagger.globalOperationParameters[0].description=some description one
+swagger.globalOperationParameters[0].modelRef=string
+swagger.globalOperationParameters[0].parameterType=header
+swagger.globalOperationParameters[0].required=true
+swagger.globalOperationParameters[1].name=name two
+swagger.globalOperationParameters[1].description=some description two
+swagger.globalOperationParameters[1].modelRef=string
+swagger.globalOperationParameters[1].parameterType=body
+swagger.globalOperationParameters[1].required=false
```
## 配置说明
@@ -72,6 +85,7 @@ swagger.exclude-path=/error, /ops/**
### 默认配置
```
+- swagger.enabled=是否启用swagger,默认:true
- swagger.title=标题
- swagger.description=描述
- swagger.version=版本
@@ -85,9 +99,19 @@ swagger.exclude-path=/error, /ops/**
- swagger.base-path=需要处理的基础URL规则,默认:/**
- swagger.exclude-path=需要排除的URL规则,默认:空
- swagger.host=文档的host信息,默认:空
+- swagger.globalOperationParameters[0].name=参数名
+- swagger.globalOperationParameters[0].description=描述信息
+- swagger.globalOperationParameters[0].modelRef=指定参数类型
+- swagger.globalOperationParameters[0].parameterType=指定参数存放位置,可选header,query,path,body.form
+- swagger.globalOperationParameters[0].required=指定参数是否必传,true,false
```
-> host属性从1.3.0.RELEASE开始支持
+
+> `1.3.0.RELEASE`新增:`swagger.host`属性,同时也支持指定docket的配置
+>
+> `1.4.0.RELEASE`新增:
+> - `swagger.enabled`:用于开关swagger的配置
+> - `swagger.globalOperationParameters`:用于设置全局的参数,比如:header部分的accessToken等。该参数支持指定docket的配置。
### Path规则说明
@@ -129,10 +153,19 @@ swagger.exclude-path=/ops/**, /error
- swagger.docket..base-package=swagger扫描的基础包,默认:全扫描
- swagger.docket..base-path=需要处理的基础URL规则,默认:/**
- swagger.docket..exclude-path=需要排除的URL规则,默认:空
+- swagger.docket..name=参数名
+- swagger.docket..modelRef=指定参数类型
+- swagger.docket..parameterType=指定参数存放位置,可选header,query,path,body.form
+- swagger.docket..required=true=指定参数是否必传,true,false
+- swagger.docket..globalOperationParameters[0].name=参数名
+- swagger.docket..globalOperationParameters[0].description=描述信息
+- swagger.docket..globalOperationParameters[0].modelRef=指定参数存放位置,可选header,query,path,body.form
+- swagger.docket..globalOperationParameters[0].parameterType=指定参数是否必传,true,false
```
说明:``为swagger文档的分组名称,同一个项目中可以配置多个分组,用来划分不同的API文档。
+
**分组配置示例**
```properties
@@ -144,12 +177,16 @@ swagger.docket.aaa.contact.name=zhaiyongchao
swagger.docket.aaa.contact.url=http://spring4all.com/
swagger.docket.aaa.contact.email=didi@potatomato.club
swagger.docket.aaa.excludePath=/ops/**
+swagger.docket.aaa.globalOperationParameters[0].name=name three
+swagger.docket.aaa.globalOperationParameters[0].description=some description three override
+swagger.docket.aaa.globalOperationParameters[0].modelRef=string
+swagger.docket.aaa.globalOperationParameters[0].parameterType=header
swagger.docket.bbb.title=group-bbb
swagger.docket.bbb.basePackage=com.yonghui
```
-说明:默认配置与分组配置可以一起使用。在分组配置中没有配置的内容将使用默认配置替代,所以默认配置可以作为分组配置公共部分属性的配置。
+说明:默认配置与分组配置可以一起使用。在分组配置中没有配置的内容将使用默认配置替代,所以默认配置可以作为分组配置公共部分属性的配置。`swagger.docket.aaa.globalOperationParameters[0].name`会覆盖同名的全局配置。
### JSR-303校验注解支持
diff --git a/pom.xml b/pom.xml
index e021185..680f71e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.didispace
spring-boot-starter-swagger
- 1.3.0.RELEASE
+ 1.4.0.RELEASE
spring-boot-starter-swagger
https://github.com/dyc87112/spring-boot-starter-swagger
diff --git a/src/main/java/com/didispace/swagger/EnableSwagger2Doc.java b/src/main/java/com/didispace/swagger/EnableSwagger2Doc.java
index 01b5741..0ea7844 100644
--- a/src/main/java/com/didispace/swagger/EnableSwagger2Doc.java
+++ b/src/main/java/com/didispace/swagger/EnableSwagger2Doc.java
@@ -1,8 +1,6 @@
package com.didispace.swagger;
import org.springframework.context.annotation.Import;
-import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.annotation.*;
@@ -15,8 +13,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
-@EnableSwagger2
-@Import({SwaggerAutoConfiguration.class, BeanValidatorPluginsConfiguration.class})
+@Import({SwaggerAutoConfiguration.class})
public @interface EnableSwagger2Doc {
diff --git a/src/main/java/com/didispace/swagger/Swagger2Configuration.java b/src/main/java/com/didispace/swagger/Swagger2Configuration.java
new file mode 100644
index 0000000..0703d28
--- /dev/null
+++ b/src/main/java/com/didispace/swagger/Swagger2Configuration.java
@@ -0,0 +1,21 @@
+package com.didispace.swagger;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
+import springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration;
+
+/**
+ * @author 翟永超
+ * Create Date: 2017/9/7.
+ * My blog: http://blog.didispace.com
+ */
+@Configuration
+@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
+@Import({
+ Swagger2DocumentationConfiguration.class,
+ BeanValidatorPluginsConfiguration.class
+})
+public class Swagger2Configuration {
+}
diff --git a/src/main/java/com/didispace/swagger/SwaggerAutoConfiguration.java b/src/main/java/com/didispace/swagger/SwaggerAutoConfiguration.java
index d1689be..9529c64 100644
--- a/src/main/java/com/didispace/swagger/SwaggerAutoConfiguration.java
+++ b/src/main/java/com/didispace/swagger/SwaggerAutoConfiguration.java
@@ -2,31 +2,42 @@
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
+import com.google.common.collect.Lists;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
+import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* @author 翟永超
- * Create date :2017/8/7.
+ * Create date:2017/8/7.
* My blog: http://blog.didispace.com
*/
@Configuration
+@Import({
+ Swagger2Configuration.class
+})
public class SwaggerAutoConfiguration implements BeanFactoryAware {
private BeanFactory beanFactory;
@@ -39,11 +50,12 @@ public SwaggerProperties swaggerProperties() {
@Bean
@ConditionalOnMissingBean
+ @ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
public List createRestApi(SwaggerProperties swaggerProperties) {
ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
// 没有分组
- if(swaggerProperties.getDocket().size() == 0) {
+ if (swaggerProperties.getDocket().size() == 0) {
ApiInfo apiInfo = new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
@@ -58,23 +70,26 @@ public List createRestApi(SwaggerProperties swaggerProperties) {
// base-path处理
// 当没有配置任何path的时候,解析/**
- if(swaggerProperties.getBasePath().isEmpty()) {
+ if (swaggerProperties.getBasePath().isEmpty()) {
swaggerProperties.getBasePath().add("/**");
}
List> basePath = new ArrayList();
- for(String path : swaggerProperties.getBasePath()) {
+ for (String path : swaggerProperties.getBasePath()) {
basePath.add(PathSelectors.ant(path));
}
// exclude-path处理
List> excludePath = new ArrayList();
- for(String path : swaggerProperties.getExcludePath()) {
+ for (String path : swaggerProperties.getExcludePath()) {
excludePath.add(PathSelectors.ant(path));
}
+
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.host(swaggerProperties.getHost())
.apiInfo(apiInfo)
+ .globalOperationParameters(buildGlobalOperationParametersFromSwaggerProperties(
+ swaggerProperties.getGlobalOperationParameters()))
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.paths(
@@ -91,7 +106,7 @@ public List createRestApi(SwaggerProperties swaggerProperties) {
// 分组创建
List docketList = new LinkedList<>();
- for(String groupName : swaggerProperties.getDocket().keySet()) {
+ for (String groupName : swaggerProperties.getDocket().keySet()) {
SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName);
ApiInfo apiInfo = new ApiInfoBuilder()
@@ -102,9 +117,9 @@ public List createRestApi(SwaggerProperties swaggerProperties) {
.licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerProperties.getLicenseUrl() : docketInfo.getLicenseUrl())
.contact(
new Contact(
- docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(),
- docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(),
- docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail()
+ docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(),
+ docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(),
+ docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail()
)
)
.termsOfServiceUrl(docketInfo.getTermsOfServiceUrl().isEmpty() ? swaggerProperties.getTermsOfServiceUrl() : docketInfo.getTermsOfServiceUrl())
@@ -112,23 +127,25 @@ public List createRestApi(SwaggerProperties swaggerProperties) {
// base-path处理
// 当没有配置任何path的时候,解析/**
- if(docketInfo.getBasePath().isEmpty()) {
+ if (docketInfo.getBasePath().isEmpty()) {
docketInfo.getBasePath().add("/**");
}
List> basePath = new ArrayList();
- for(String path : docketInfo.getBasePath()) {
+ for (String path : docketInfo.getBasePath()) {
basePath.add(PathSelectors.ant(path));
}
// exclude-path处理
List> excludePath = new ArrayList();
- for(String path : docketInfo.getExcludePath()) {
+ for (String path : docketInfo.getExcludePath()) {
excludePath.add(PathSelectors.ant(path));
}
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.host(swaggerProperties.getHost())
.apiInfo(apiInfo)
+ .globalOperationParameters(assemblyGlobalOperationParameters(swaggerProperties.getGlobalOperationParameters(),
+ docketInfo.getGlobalOperationParameters()))
.groupName(groupName)
.select()
.apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))
@@ -150,4 +167,49 @@ public List createRestApi(SwaggerProperties swaggerProperties) {
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
+
+ private List buildGlobalOperationParametersFromSwaggerProperties(
+ List globalOperationParameters) {
+ List parameters = Lists.newArrayList();
+ for (SwaggerProperties.GlobalOperationParameter globalOperationParameter : globalOperationParameters) {
+ parameters.add(new ParameterBuilder()
+ .name(globalOperationParameter.getName())
+ .description(globalOperationParameter.getDescription())
+ .modelRef(new ModelRef(globalOperationParameter.getModelRef()))
+ .parameterType(globalOperationParameter.getParameterType())
+ .required(Boolean.parseBoolean(globalOperationParameter.getRequired()))
+ .build());
+ }
+ return parameters;
+ }
+
+ /**
+ * 局部参数按照name覆盖局部参数
+ *
+ * @param globalOperationParameters
+ * @param docketOperationParameters
+ * @return
+ */
+ private List assemblyGlobalOperationParameters(
+ List globalOperationParameters,
+ List docketOperationParameters) {
+
+ if (docketOperationParameters == null || docketOperationParameters.isEmpty()) {
+ return buildGlobalOperationParametersFromSwaggerProperties(globalOperationParameters);
+ }
+
+ Set docketNames = docketOperationParameters.stream()
+ .map(SwaggerProperties.GlobalOperationParameter::getName)
+ .collect(Collectors.toSet());
+
+ List resultOperationParameters = Lists.newArrayList();
+
+ for (SwaggerProperties.GlobalOperationParameter parameter : globalOperationParameters) {
+ if (!docketNames.contains(parameter.getName())) {
+ resultOperationParameters.add(parameter);
+ }
+ }
+ resultOperationParameters.addAll(docketOperationParameters);
+ return buildGlobalOperationParametersFromSwaggerProperties(resultOperationParameters);
+ }
}
diff --git a/src/main/java/com/didispace/swagger/SwaggerProperties.java b/src/main/java/com/didispace/swagger/SwaggerProperties.java
index cafc22d..75314ff 100644
--- a/src/main/java/com/didispace/swagger/SwaggerProperties.java
+++ b/src/main/java/com/didispace/swagger/SwaggerProperties.java
@@ -3,6 +3,7 @@
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import springfox.documentation.schema.ModelRef;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -18,6 +19,9 @@
@ConfigurationProperties("swagger")
public class SwaggerProperties {
+ /**是否开启swagger**/
+ private Boolean enabled;
+
/**标题**/
private String title = "";
/**描述**/
@@ -47,6 +51,30 @@ public class SwaggerProperties {
/**host信息**/
private String host = "";
+ /**全局参数配置**/
+ private List globalOperationParameters;
+
+
+ @Data
+ @NoArgsConstructor
+ public static class GlobalOperationParameter{
+ /**参数名**/
+ private String name;
+
+ /**描述信息**/
+ private String description;
+
+ /**指定参数类型**/
+ private String modelRef;
+
+ /**参数放在哪个地方:header,query,path,body.form**/
+ private String parameterType;
+
+ /**参数是否必须传**/
+ private String required;
+
+ }
+
@Data
@NoArgsConstructor
public static class DocketInfo {
@@ -74,6 +102,8 @@ public static class DocketInfo {
/**在basePath基础上需要排除的url规则**/
private List excludePath = new ArrayList<>();
+ private List globalOperationParameters;
+
}
@Data