这里是引用
swagger
- springboot 分包的时候直接集成swagger 会不能实现该有的功能
- 先导入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
- 不能集成swagger太高的版本,不然进入swagger的时候会出现类型装换错误
下面说两个springboot 集成 swagger 的方式
1,单体没有分包 SwaggerConfiguration
@Configuration
@EnableSwagger2
public class SwaggerConfiguration implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//这里一定要标注你控制器的位置(使用了 ApiOperation 注解就能可以被springboot 扫描到)
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("TEST")
.description("哈哈API文档")
.termsOfServiceUrl("https://angegit.gitee.io/myblog/")
.contact(new Contact("zhangsan","https://ange111git.gitee.io/myblog/","9171212121057580@qq.com"))
.version("1.0")
.build();
}
2,分包
- 需要配置映射,类似于反射的形式去拦截
1, 配置SwaggerConfig
/**
* swagger 配置
* @author hanyue
*/
@Configuration
@EnableSwagger2
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
@ConditionalOnProperty(prefix = "apiDoc", name = "show", havingValue = "true")
public class SwaggerConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 解决静态资源无法访问
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
// 解决swagger无法访问
registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
// 解决swagger的js文件无法访问
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean(name = "createRestApi")
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
// 是否启用Swagger
.enable(true)
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描所有有注解的api,用这种方式更灵活
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// .apis(RequestHandlerSelectors.any())
// 扫描指定包中的swagger注解
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("TEST")
.description("哈哈API文档")
.termsOfServiceUrl("https://angegit.gitee.io/myblog/")
.contact(new Contact("zhangsan","https://angegit.gitee.io/myblog/","917057580@qq.com"))
.version("1.0")
.build();
}
}
2,配置SwaggerEnum
/**
* swagger 枚举类型处理字段描述
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SwaggerEnum {
/**
* 枚举名称
* 枚举描述内容
* @return
*/
String enumName() default "";
/**
* 枚举值字段名称 (即接口传递的值)
* @return
*/
String valueName() default "name";
/**
* 枚举描述字段名称 (接口使用值对于文字描述)
* @return
*/
String descName() default "desc";
}
3,配置SwaggerEnumPropertyPlugin
@Component
public class SwaggerEnumPropertyPlugin implements ModelPropertyBuilderPlugin {
@Override
public void apply(ModelPropertyContext context) {
Optional<ApiModelProperty> annotation = Optional.absent();
if (context.getAnnotatedElement().isPresent()) {
annotation = annotation.or(ApiModelProperties.findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
}
if (context.getBeanPropertyDefinition().isPresent()) {
annotation = annotation.or(Annotations.findPropertyAnnotation(
context.getBeanPropertyDefinition().get(),
ApiModelProperty.class));
}
Class<?> filedType = context.getBeanPropertyDefinition().get().getField().getRawType();
//如果该属性没有 ApiModelProperty 注解则跳过
if (!annotation.isPresent()) {
return;
}
//获取 ApiModelProperty 标注的枚举类型
Class<?> enumClass = context.getBeanPropertyDefinition().get().getField().getRawType();
//如果 ApiModelProperty 标注属性不是枚举类型则跳过
if (!EnumUtil.isEnum(enumClass)) {
return;
}
SwaggerEnum swaggerEnum = enumClass.getAnnotation(SwaggerEnum.class);
String valueName = "name";
String descName = "desc";
String enumName = "";
//自定义枚举生成信息
if (swaggerEnum != null) {
valueName = swaggerEnum.valueName();
descName = swaggerEnum.descName();
enumName = swaggerEnum.enumName();
}
List<Object> desces = EnumUtil.getFieldValues((Class<? extends Enum<?>>) enumClass, descName);
List<Object> types = EnumUtil.getFieldValues((Class<? extends Enum<?>>) enumClass, valueName);
if (desces == null || types == null) {
return;
}
int ds = desces.size();
int ts = types.size();
if (ds != ts || ds == 0) {
return;
}
StringBuilder sb = new StringBuilder(enumName + " ");
int counter = 0;
for (int i = 0; i < ds; i++) {
if (counter++ != 0) {
sb.append(", ");
}
sb.append(String.valueOf(types.get(i)))
.append(": ")
.append(String.valueOf(desces.get(i)));
}
sb.append(" ");
final ResolvedType resolvedType = context.getResolver().resolve(filedType);
context.getBuilder().description(sb.toString()).type(resolvedType);
}
@Override
public boolean supports(DocumentationType documentationType) {
return true;
}
}
- 最后给启动类上加上注解 @EnableSwagger2 ,就可以正常访问
分包打包依赖
- 加入有,ABCD,其中 A 主依赖,BCD 是 A 的子,D 依赖 B,C。,所以规律就是,D里面放打包的依赖,ADCD 里面都不能放打包依赖,因为我用的maven打包,依赖----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
<finalName>hanyue</finalName>
</build>