创建的swagger启动器是给别的工程使用的,自己本身不能运行,可以看成一个工具包。
1. 创建swagger-spring-boot-starter启动器
1.1 创建maven工程,配置pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>org.example</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--打包时不会打包此模块-->
<optional>true</optional>
</dependency>
<!--其实打包发布时就包含这一个依赖-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
- 因为我们是要制作启动器swagger-spring-boot-starter,是留给别的工程使用的,所以里面导入的依赖越少越好。不然会很臃肿。
-
<optional>true</optional>: 自己百度这是什么含义(大致就是打包时不会将该依赖包含进去)
-
项目名:swagger-spring-boot-starter
-
组名:org.example
1.2 创建配置属性类SwaggerProperties
package com.example.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Data
@ConfigurationProperties(prefix = "swagger")
public class SwaggerProperties {
private Boolean enabled = true;
private String title = "在线文档"; //标题
private String group = "默认组"; //自定义组名
private String description = "在线文档"; //描述
private String version = "1.0"; //版本
private Contact contact = new Contact(); //联系人
private String basePackage = "com.example"; //swagger会解析的包路径
private List<String> basePath = new ArrayList<>(); //swagger会解析的url规则
private List<String> excludePath = new ArrayList<>();//在basePath基础上需要排除的url规则
private Map<String, DocketInfo> docket = new LinkedHashMap<>(); //分组文档
public String getGroup() {
if (group == null || "".equals(group)) {
return title;
}
return group;
}
@Data
public static class DocketInfo {
private String title = "在线文档"; //标题
private String group = ""; //自定义组名
private String description = "在线文档"; //描述
private String version = "1.0"; //版本
private Contact contact = new Contact(); //联系人
private String basePackage = ""; //swagger会解析的包路径
private List<String> basePath = new ArrayList<>(); //swagger会解析的url规则
private List<String> excludePath = new ArrayList<>();//在basePath基础上需要排除的url
public String getGroup() {
if (group == null || "".equals(group)) {
return title;
}
return group;
}
}
@Data
public static class Contact {
private String name = ""; //联系人
private String url = ""; //联系人url
private String email = ""; //联系人email
}
}
- 这里面的属性与配置文件中的配置属性一一对应
1.3 创建配置类SwaggerAutoConfiguration
package com.example.config;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@Configuration
@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true",
matchIfMissing = true)
@EnableSwagger2
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfiguration implements BeanFactoryAware {
@Autowired
SwaggerProperties swaggerProperties;
private BeanFactory beanFactory;
@Bean
@ConditionalOnMissingBean
public List<Docket> createRestApi(){
ConfigurableBeanFactory configurableBeanFactory =
(ConfigurableBeanFactory) beanFactory;
List<Docket> docketList = new LinkedList<>();
// 没有分组
if (swaggerProperties.getDocket().isEmpty()) {
Docket docket = createDocket(swaggerProperties);
configurableBeanFactory.registerSingleton(swaggerProperties.getTitle(),
docket);
docketList.add(docket);
return docketList;
}
// 分组创建
for (String groupName : swaggerProperties.getDocket().keySet()){
SwaggerProperties.DocketInfo docketInfo =
swaggerProperties.getDocket().get(groupName);
ApiInfo apiInfo = new ApiInfoBuilder()
//页面标题
.title(docketInfo.getTitle())
//创建人
.contact(new Contact(docketInfo.getContact().getName(),
docketInfo.getContact().getUrl(),
docketInfo.getContact().getEmail()))
//版本号
.version(docketInfo.getVersion())
//描述
.description(docketInfo.getDescription())
.build();
// base-path处理
// 当没有配置任何path的时候,解析/**
if (docketInfo.getBasePath().isEmpty()) {
docketInfo.getBasePath().add("/**");
}
List<Predicate<String>> basePath = new ArrayList<>();
for (String path : docketInfo.getBasePath()) {
basePath.add(PathSelectors.ant(path));
}
// exclude-path处理
List<Predicate<String>> excludePath = new ArrayList<>();
for (String path : docketInfo.getExcludePath()) {
excludePath.add(PathSelectors.ant(path));
}
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.groupName(docketInfo.getGroup())
.select()
//为当前包路径
.apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))
.paths(Predicates.and(Predicates.not(Predicates.or(excludePath)),Predicates.or(basePath)))
.build();
configurableBeanFactory.registerSingleton(groupName, docket);
docketList.add(docket);
}
return docketList;
}
//构建 api文档的详细信息
private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
return new ApiInfoBuilder()
//页面标题
.title(swaggerProperties.getTitle())
//创建人
.contact(new Contact(swaggerProperties.getContact().getName(),
swaggerProperties.getContact().getUrl(),
swaggerProperties.getContact().getEmail()))
//版本号
.version(swaggerProperties.getVersion())
//描述
.description(swaggerProperties.getDescription())
.build();
}
//创建接口文档对象
private Docket createDocket(SwaggerProperties swaggerProperties) {
//API 基础信息
ApiInfo apiInfo = apiInfo(swaggerProperties);
// base-path处理
// 当没有配置任何path的时候,解析/**
if (swaggerProperties.getBasePath().isEmpty()) {
swaggerProperties.getBasePath().add("/**");
}
List<Predicate<String>> basePath = new ArrayList<>();
for (String path : swaggerProperties.getBasePath()) {
basePath.add(PathSelectors.ant(path));
}
// exclude-path处理
List<Predicate<String>> excludePath = new ArrayList<>();
for (String path : swaggerProperties.getExcludePath()) {
excludePath.add(PathSelectors.ant(path));
}
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.groupName(swaggerProperties.getGroup())
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.paths(Predicates.and(Predicates.not(Predicates.or(excludePath)),Predicates.or(basePath)))
.build();
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
- @Configuration:表明这是一个配置类
- @EnableSwagger2:表明开启swagger文档
- @EnableConfigurationProperties(SwaggerProperties.class):开启属性注入
- @ConditionalOnProperty(name = "swagger.enabled", havingValue = "true",
matchIfMissing = true):只有在swagger.enabled=true时这个配置类才生效 - 配置类实现了BeanFactoryAware:则可以拿到spring容器
1.4 在resources/META-INF目录下创建spring.factories文件
文件内容如下
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.config.SwaggerAutoConfiguration
- 这样的话别的工程导入这个启动器,会自动来这个文件下找需要加载的类,生成对应的bean
1.5 打包发布到本地maven仓库
- 点击maven的install选项
至此,启动器已经完全做好了
2. 其他工程如何使用上述创建的启动器
2.1 创建一个springboot的web工程,添加以下依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
- 引入了我们刚刚创建的启动器
- 我们可以查看maven依赖,可以看到我们刚刚创建的启动器jar包很轻巧,没有将web依赖传递过来(就是因为我们配置了<optional>true</optional>)
2.2 创建一个controller
package com.example.controller;
import com.example.entity.Teacher;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/hello")
@RestController
@Api("菜单控制器")
public class HelloController {
@ApiOperation("请求hello")
@GetMapping("/hello")
public Teacher hello() {
Teacher teacher = new Teacher();
teacher.setName("张三");
return teacher;
}
}
- 因为导入了我们的启动器,所以可以直接使用这些注解了
2.3 创建配置文件application.properties,配置swagger信息
swagger.enabled=true
swagger.base-package=com.example.controller
- 这里我只配置了两个属性,其他的都用默认值即可
- 开启swagger功能
- 配置swagger所扫描的包路径(就是你的controller所在路径)
2.4 编写springboot启动类并启动
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
至此, 整合完毕,可以访问localhost:8080/doc.html查看swagger文档