最近在搞微服务项目需要提供API,但是单个服务访问不太友好,想做一个聚合,所以使用了Knife4j 。网上好多整合Knife4j 的文档,尝试了一下大部分都是失败的状态(可能是楼主整合的不对),所以自己整合完后记录一下。
提供一下Knife4j官网:Knife4j · 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j
全局配合springboot只需要引入一个依赖就可以了,无论是网关,还是其他的子服务,都需要引入如下的依赖:
com.github.xiaoymin
knife4j-spring-boot-starter
3.0.3
这里面使用了3.0.3版本,因为楼主在尝试其他版本的时候发现会有很多问题,如404,资源找不到的问题
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.List;
/**
* SwaggerProvider:
* 获取nacos当中注册的服务名称,以服务名称拼接接口文档路径,组成完成的接口文档访问路径
*/
@Slf4j
@Component
@Primary
@AllArgsConstructor
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
@Override
public List get() {
List resources = new ArrayList<>();
List routes = new ArrayList<>();
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {
route.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("**", "v2/api-docs"))));
});
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
log.info("name:{},location:{}", name, location);
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;
import java.util.Optional;
/**
* SwaggerHandler:获取接口文档
*/
@RestController
public class SwaggerHandler {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/swagger-resources/configuration/security")
public Mono> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources/configuration/ui")
public Mono> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources")
public Mono swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}
gateway:
discovery:
locator:
lower-case-service-id: true
routes:
- id: system
uri: lb://xxxx-system-xxxxx
predicates:
- Path=/system/**
filters:
- StripPrefix= 1 #截取去掉/system/ 这个要配置正确
依赖已经抽取了公共,此处就不引入了。
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.EnableSwagger2WebMvc;
@Configuration
@EnableSwagger2WebMvc
public class SwaggerConfiguration {
@Bean
public Docket getDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(getApiInfoBuilder())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.xx.xx.xxxx.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo getApiInfoBuilder() {
return new ApiInfoBuilder()
.title("Knife4j-mic-order文档")
.description("swagger-bootstrap-ui-demo RESTful APIs")
.termsOfServiceUrl("服务url")
.contact(new Contact("xxx", "url", "[email protected]"))
.version("1.0")
.build();
}
}
使用网关的地址访问:http://127.0.0.1:9090/doc.html