微服务与中间件系列——GateWay整合Swagger3增强Knife4j
创始人
2024-02-02 05:00:34

微服务与中间件系列——GateWay整合Swagger3增强Knife4j

  • GateWay整合Swagger3增强Knife4j(easy模式)
    • 目的
    • 服务端
      • 1.导入依赖
      • 2.编写配置类
      • 3.yaml配置
    • GateWay网关
      • 1.文档枚举
      • 2.SwaggerProvider
      • 3.yaml配置
    • 结果
  • 增强版
    • 服务端
      • 1.增加配置参数类
      • 2.修改配置类
      • 3.修改yaml配置
    • GateWay网关
      • 1.增加全局认证过滤器

GateWay整合Swagger3增强Knife4j(easy模式)

目的

统一进行文档管理,查看,避免swagger文档在微服务中使用繁琐的问题
本案例使用nacos作为服务的注册中心

服务端

1.导入依赖

        io.springfoxspringfox-boot-starter3.0.0com.github.xiaoyminknife4j-spring-boot-starter3.0.3com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discovery

2.编写配置类

package cn.fly.client.config;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;/*** @author Syf200208161018* @date 2022/11/19 15:44* @ClassName:SwaggerConfig* @Effect:SwaggerConfig is used for*/
@Configuration
@EnableOpenApi
@Data
@ConfigurationProperties(prefix = "swagger")
public class SwaggerConfig {/*** 是否开启swagger,生产环境一般关闭,所以这里定义一个变量*/private Boolean enable;/*** 项目应用名*/private String applicationName;/*** 项目版本信息*/private String applicationVersion;/*** 项目描述信息*/private String applicationDescription;@Beanpublic Docket docket() {return new Docket(DocumentationType.OAS_30).pathMapping("/")// 定义是否开启swagger,false为关闭,可以通过变量控制,线上关闭.enable(enable)//配置api文档元信息.apiInfo(apiInfo())// 选择哪些接口作为swagger的doc发布.select()//apis() 控制哪些接口暴露给swagger,// RequestHandlerSelectors.any() 所有都暴露// RequestHandlerSelectors.basePackage("net.xdclass.*")  指定包位置// withMethodAnnotation(ApiOperation.class)标记有这个注解 ApiOperation.apis(RequestHandlerSelectors.basePackage("cn.fly.client.controller.common")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title(applicationName).description(applicationDescription).contact(new Contact("syf", "syf20020816@outlook.com", "syf20020816@outlook.com")).version(applicationVersion).build();}
}

3.yaml配置

  1. 配置服务名称
  2. 配置mvc路径策略
  3. 配置nacos路径
  4. 配置swagger(自定义非官方,看配置类就知道了)
spring:application:name: Eprop-clientmvc:pathmatch:matching-strategy: ant_path_matchercloud:nacos:
#      server-addr: 192.168.31.149:8848server-addr: 172.16.216.47:8848
swagger:enable: trueapplication-name: Eprop-clientapplication-version: 1.0.0application-description: client

GateWay网关

1.文档枚举

package cn.fly.gateway.swagger;import io.netty.channel.nio.AbstractNioByteChannel;/*** @author Syf200208161018* @date 2022/11/19 19:12* @ClassName:DocEnum* @Effect:DocEnum is used for*/
public enum DocEnum {/*** 路由信息*/EPROP_COMMON("Eprop-client","eprop-API模块");private String routeId;private String swaggerInfo;DocEnum(String routeId, String swaggerInfo) {this.routeId = routeId;this.swaggerInfo = swaggerInfo;}public String getRouteId() {return routeId;}public void setRouteId(String routeId) {this.routeId = routeId;}public String getSwaggerInfo() {return swaggerInfo;}public void setSwaggerInfo(String swaggerInfo) {this.swaggerInfo = swaggerInfo;}public static String getSwaggerInfoByRouteId(String routeId){for (DocEnum value : DocEnum.values()) {if (value.getRouteId().equals(routeId)){return value.getSwaggerInfo();}}return null;}}

2.SwaggerProvider

实现SwaggerResourcesProvider对资源进行修改

package cn.fly.gateway.swagger;import com.alibaba.cloud.commons.lang.StringUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
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;/*** @author Syf200208161018* @date 2022/11/19 16:55* @ClassName:SwaggerProvider* @Effect:SwaggerProvider is used for*/
/*** 聚合系统接口* @author ROCKY*/
@Component
@Primarypublic class SwaggerProvider implements SwaggerResourcesProvider {public static final String API_URI = "/v3/api-docs";private final RouteLocator routeLocator;private final GatewayProperties gatewayProperties;public SwaggerProvider(RouteLocator routeLocator, GatewayProperties gatewayProperties) {this.routeLocator = routeLocator;this.gatewayProperties = gatewayProperties;}@Overridepublic List get() {List resources = new ArrayList<>();List routes = new ArrayList<>();// 取出gateway的routerouteLocator.getRoutes().subscribe(route -> routes.add(route.getId()));// 结合配置的route-路径(Path),和route过滤,只获取在枚举中说明的route节点gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(routeDefinition -> routeDefinition.getPredicates().stream()// 目前只处理Path断言  Header或其他路由需要另行扩展.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())).forEach(predicateDefinition -> {String routeId = routeDefinition.getId();String swaggerInfo = DocEnum.getSwaggerInfoByRouteId(routeId);if (StringUtils.isNotEmpty(swaggerInfo)) {resources.add(swaggerResource(swaggerInfo, predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", API_URI)));}}));return resources;}private SwaggerResource swaggerResource(String name, String location) {SwaggerResource swaggerResource = new SwaggerResource();swaggerResource.setName(name);swaggerResource.setLocation(location);swaggerResource.setSwaggerVersion("3.0");return swaggerResource;}
}

3.yaml配置

  1. 注意路由的ID要对应服务的名称
    在这里插入图片描述

  2. 注意过滤器的StripPrefix=3一定要和你前面指定的断言- Path=/api/v1/eprop/**匹配上,比如我这个就是去除3个前缀,如果是/api/hello/**,就是去除2个前缀,这个一定不能错,因为这和swagger请求地址有关
    在这里插入图片描述

server:port: 21301
spring:application:name: gatewaycloud:nacos:
#      server-addr: 192.168.31.149:8848server-addr: 172.16.216.47:8848
#     server-addr: 192.168.1.103:8848gateway:routes:- id: Eprop-clienturi: lb://Eprop-clientpredicates:- Path=/api/v1/eprop/**filters:- StripPrefix=3globalcors:cors-configurations:'[/**]':allowedOrigins: # 允许哪些网站进行跨域请求- "http://localhost:8080"allowedMethods:- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" # 允许所有请求头allowCredentials: true # 是否允许携带cookiemaxAge: 360000 # 跨域监测有效期add-to-simple-url-handler-mapping: true #解决options请求拦截discovery:locator:lower-case-service-id: true

结果

启动gateway浏览器访问ip:端口/doc.html
成功如下:
在这里插入图片描述

增强版

其实也就是做了一下对于配置的处理

服务端

1.增加配置参数类

package cn.fly.client.properties;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.ArrayList;
import java.util.List;/*** @author Syf200208161018* @date 2022/11/20 0:44* @ClassName:SwaggerProperties* @Effect:SwaggerProperties is used for*/
@ConfigurationProperties(prefix = "swagger-api")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SwaggerProperties {private String title="EPROP-API文档";private String groupName = "default";private String des="default API doc";private String version="1.1.0";
//    private Contact contact = new Contact("syf","syf20020816@outlook.com","syf20020816@outlook.com");private String docMaker = "syf";private String docUrl = "syf20020816@Outlook.com";private String makerEmail="syf20020816@Outlook.com";private String basePackage="cn.fly.client.controller";//解析的url规则private List basePath = new ArrayList<>();//需要排除的urlprivate List excludePath = new ArrayList<>();/*** 是否开启swagger,生产环境一般关闭,所以这里定义一个变量*/private Boolean enable;/*** 项目应用名*/private String applicationName;/*** 项目版本信息*/private String applicationVersion;/*** 项目描述信息*/private String applicationDescription;}

2.修改配置类

package cn.fly.client.config;import cn.fly.client.properties.SwaggerProperties;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;/*** @author Syf200208161018* @date 2022/11/19 15:44* @ClassName:SwaggerConfig* @Effect:SwaggerConfig is used for*/
@Configuration
@EnableOpenApi
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerConfig {@Autowiredprivate SwaggerProperties swaggerProperties;@Beanpublic Docket docket() {return new Docket(DocumentationType.OAS_30).pathMapping("/")// 定义是否开启swagger,false为关闭,可以通过变量控制,线上关闭.enable(swaggerProperties.getEnable())//配置api文档元信息.apiInfo(apiInfo())// 选择哪些接口作为swagger的doc发布.select()//apis() 控制哪些接口暴露给swagger,// RequestHandlerSelectors.any() 所有都暴露// RequestHandlerSelectors.basePackage("net.xdclass.*")  指定包位置// withMethodAnnotation(ApiOperation.class)标记有这个注解 ApiOperation.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title(swaggerProperties.getTitle()).description(swaggerProperties.getApplicationDescription()).contact(new Contact(swaggerProperties.getDocMaker(),swaggerProperties.getDocUrl(),swaggerProperties.getMakerEmail())).version(swaggerProperties.getApplicationVersion()).build();}
}

3.修改yaml配置

swagger-api:enable: trueapplication-name: Eprop-clientapplication-version: 1.0.0application-description: Eprop API文档Swagger3版本title: EPROP-API 文档groupName: Eprop-clientdes: Eprop API文档Swagger3版本version: 1.0.0docMaker: syfdocUrl: www.eprop.fly.cnmarkerEmail: syf20020816@Outlook.combasePackage: cn.fly.client.controller

GateWay网关

1.增加全局认证过滤器

package cn.fly.gateway.filter;import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.List;/*** @author Syf200208161018* @date 2022/10/28 13:16* @ClassName:AuthorizeFilter* @Effect:AuthorizeFilter is used for filtering user* the request header must have a token-eprop and then getUserInfo*/
@Component
@Order(-1)
public class AuthorizeFilter implements GlobalFilter {@Overridepublic Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println(exchange.getRequest().getURI().getPath());if (exchange.getRequest().getURI().getPath().equals("/v3/api-docs")){return chain.filter(exchange);}else{//get request paramsfinal ServerHttpRequest request = exchange.getRequest();//get header: token-epropfinal HttpHeaders requestHeaders = request.getHeaders();final List values = requestHeaders.get("token-eprop");for (String value : values) {System.out.println(value);}final String tokenValue = values.get(0);System.out.println(tokenValue);//if tokenValue is empty or null intercept the requestif (StringUtils.isBlank(tokenValue)){return exchange.getResponse().setComplete();}return chain.filter(exchange);}}
}

其他无需更改

相关内容

热门资讯

应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...