统一进行文档管理,查看,避免swagger文档在微服务中使用繁琐的问题
本案例使用nacos作为服务的注册中心
io.springfox springfox-boot-starter 3.0.0 com.github.xiaoymin knife4j-spring-boot-starter 3.0.3 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery
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();}
}
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
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;}}
实现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;}
}
注意路由的ID要对应服务的名称

注意过滤器的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
成功如下:

其实也就是做了一下对于配置的处理
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;}
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();}
}
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
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);}}
}
其他无需更改
上一篇:用anacnda创建虚拟环境用不用指定python版本
下一篇:如何解释肩并肩