knife4j是swagger的增强版,更契合微服务架构,ui前身是swagger-bootstrap-ui,api注解的使用方式和swagger一致。
springboot整合knife4j
依赖
<!-- 包含了ui界面 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<!-- 2.x基于springfox2.x,3.x基于springfox3.x-->
<version>3.0.2</version>
</dependency>
配置类
@Configuration
@EnableSwagger2 //2.x用 @EnableSwagger2WebMvc
public class Knife4jConfig {
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("xm商城接口文档")
.description("xm商城1.0的接口文档,仅限内部使用")
.termsOfServiceUrl("http://www.xmmall.com")
.contact(new Contact("chy", "www.chy.com", "xxxxxxx@qq.com"))
.version("1.0")
.build();
}
@Bean
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//分组名称
//.groupName("1.0版本")
.select()
//指定controller(接口)扫描的包路径
.apis(RequestHandlerSelectors.basePackage("com.chy.mall.orderserver.controller"))
.paths(PathSelectors.any())
.build();
}
}
和swagger-bootstrap-ui的访问地址一致,都是 doc.html 。
如果使用JRebel启动,会报一些错,这是jrebel、knife4j之间的兼容问题,影响不大
JRebel: ERROR Class ‘springfox.documentation.schema.CachingModelDependencyProvider’ could not be processed by org.zeroturnaround.jrebel.springfox.cbp.CachingModelDependencyProviderCBP@sun.misc.Launcher$AppClassLoader@18b4aac2: org.zeroturnaround.bundled.javassist.CannotCompileException: [source error] asMap() not found in java.util.Map
这种方式常用来写单个服务的接口文档,同事使用时逐个找接口文档不方便,所以在微服务项目中,还需要在网关处聚合各个接口文档,提供一个统一的接口文档访问入口。
springcloud zuul聚合接口文档
依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
配置类
@Component
@Primary
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
@Autowired
private RouteLocator routeLocator;
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
//这个配置影响不大
swaggerResource.setSwaggerVersion("3.0");
return swaggerResource;
}
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resourceList = new ArrayList<>();
//获取所有router
List<Route> routeList = routeLocator.getRoutes();
for (Route route:routeList) {
//排除不需要参与文档聚合的服务
if (!route.getId().equals("monitor-server")){
//第一个参数指定服务名,id是服务名 eg. order-server
//第二个参数指定该服务的文档访问接口 eg. /order-server/v2/api-docs。fullPath是该服务的路由地址 eg. /order-server/**
resourceList.add(swaggerResource(route.getId(), route.getFullPath().replace("/**", "/v2/api-docs")));
}
}
return resourceList;
}
}
/v2/api-docs
- v2是该服务文档配置类上的@EnableSwagger2的2,跟配置类、pom.xml中的swagger版本无关
- api-docs是固定的,不要在服务的接口文档配置类中配置groupName,因为本来是api-docs?groupName=xxx,配置groupName后不好维护网关中配置的地址。
各个服务的接口文档可以是knife4j,也可以是swagger。
访问地址是网关下的doc.html,如果一个SwaggerResource都没有,访问时js会提示空指针。