# cloud-nacos-gateway-knife4j **Repository Path**: liuqin2014/cloud-nacos-gateway-knife4j ## Basic Information - **Project Name**: cloud-nacos-gateway-knife4j - **Description**: knife4j整合多个微服务进行文档展示 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 6 - **Created**: 2021-06-10 - **Last Updated**: 2021-06-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # spring cloud + nacos +gateway + knife4j ## 这是一个微服务聚合文档 项目文档访问地址: http://localhost:8333/doc.html ## 什么是knife4j? knife4j 就是 swagger的升级版, 除了美化了swagger的界面。而且还有其他的增强功能
## 增强功能有哪些? - tags分组标签排序、api接口排序、markdown文档下载、权限控制 ## 注意 - 聚合服务的文档需要用到gateway,所以想搭建聚合服务文档应先搭建网关 - 一个版本的 knife4j 有一种配置方法, 不可将不同版本knife4j的配置方式混在一起 - 使用排序时,需要先在文档页面进行设置: **访问文档访问地址->文档管理->个性化设置->将**“启用Knife4j提供的增强功能”**勾选即可** - 使用权限控制时, 网关不需要单独配置yml文件。但是需要权限控制的服务需要用到 yml 的文件配置 - gateway是根据配置的路由去映射文档的。 请不要忘记添加映射的路由 ## 无论是网关还是其他服务,都引用如下maven ``` com.github.xiaoymin knife4j-spring-boot-starter ``` ## 网关配置 ``` import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.stereotype.Component; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * 在集成Spring Cloud Gateway网关的时候,会出现没有basePath的情况(即定义的例如/user、/order等微服务的前缀), * * 这个情况在使用zuul网关的时候不会出现此问题,因此,在Gateway网关需要添加一个Filter实体Bean * * @author qiusn * @date 2021-03-04 */ @Component public class SwaggerProvider implements SwaggerResourcesProvider { /** * 接口地址 */ public static final String API_URI = "/v2/api-docs"; /** * 路由加载器 */ @Autowired private RouteLocator routeLocator; /** * 网关应用名称 */ @Value("${spring.application.name}") private String applicationName; @Override public List get() { //接口资源列表 List resources = new ArrayList<>(); //服务名称列表 List routeHosts = new ArrayList<>(); // 获取所有可用的应用名称 routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null) .filter(route -> !applicationName.equals(route.getUri().getHost())) .subscribe(route -> routeHosts.add(route.getUri().getHost())); // 去重,多负载服务只添加一次 Set existsServer = new HashSet<>(); routeHosts.forEach(host -> { // 拼接url String url = "/" + host + API_URI; //不存在则添加 if (!existsServer.contains(url)) { existsServer.add(url); SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setUrl(url); swaggerResource.setName(host); resources.add(swaggerResource); } }); return resources; } } ``` ``` 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.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; import springfox.documentation.swagger.web.*; import java.util.Optional; /** * swagger访问接口 * * @author qiusn * @date 2021-03-04 **/ @RestController @RequestMapping("/swagger-resources") 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("/configuration/security") public Mono> securityConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); } @GetMapping("/configuration/ui") public Mono> uiConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); } /** * 获取接口信息 */ @GetMapping("") public Mono swaggerResources() { return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); } } ``` ## 网关.yml文件 ``` server: port: 8333 spring: application: name: gateway-service cloud: gateway: discovery: locator: enabled: true # 启用自动根据服务ID生成路由 lower-case-service-id: true # 设置路由的路径为小写的服务ID routes: - id: order-service uri: lb://order-service predicates: - Path=/api/order/** - id: user-service uri: lb://user-service predicates: - Path=/api/user/** ``` ## 其他服务配置 ``` import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; import com.google.common.base.Predicates; 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.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * 配置Swagger主页信息 * * @author qiusn * @date 2021-03-05 */ @Configuration @EnableSwagger2 @EnableKnife4j public class SwaggerConfig { /** * 创建RestApi 并包扫描controller */ @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.qsn.order")) .paths(PathSelectors.any()) .paths(Predicates.not(PathSelectors.regex("/error.*"))) .build(); } /** * 创建Swagger页面 信息 * * @return */ private ApiInfo apiInfo() { return new ApiInfoBuilder(). title("订单模块"). contact("小凡"). version("1.0 version"). termsOfServiceUrl("api/order/**"). description("用户模块-这是一个 cloud+nacos+gateway+knife4j 的项目") .build(); } } ``` ## 其他服务.yml文件 ``` knife4j: # 开启Swagger的Basic认证功能,默认是false # 注:(1)默认账号/密码 admin/123321; (2)但是如果不配置密码。 即使输入对了,也始终在输入密码的地方重新循环;(3)如果用浏览器记住密码了则不用输入, swagger会直接读取进去不会再手动输入一次; basic: enable: true # Basic认证用户名 username: test # Basic认证密码 password: 1234567 ## 开启生产环境屏蔽(true看不到文档;false可以看到文档,但是密码失效) # production: false ```