微服务网关 swagger+spingSecurity+gateway 聚合实例
swagger文章目录swagger1什么是swagger2 springboot集成swagger2.1 构建springboot工程2.2 导入依赖2.3 编制配置类2.4 测试2.5 参照源码基础配置2.6 swagger 配置扫描接口2.7 配置是否启动swagger2.8 在dev或者test环境中使用swagger,生产环境中不使用swagger3swagger聚合的方式+spring
·
swagger
文章目录
1 什么是swagger
- 号称世界上最流行的API框架
- restful api 文档在线自动生成工具,api文档与api定义同步更新
- 直接运行,可以在线测试
- 支持多语言
2 springboot集成swagger
2.1 构建springboot工程
2.2 导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud-efk</artifactId>
<groupId>com.liu</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>efk-swagger-demo</artifactId>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
2.3 编制配置类
package com.liu.efk.config;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Created by shi860715@126.com
* Date 2021/8/19 10:16
* Description
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
}
2.4 测试
http://localhost:9005/swagger-ui.html
2.5 参照源码基础配置
package com.liu.efk.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.EnableSwagger2;
import java.util.ArrayList;
/**
* Created by shi860715@126.com
* Date 2021/8/19 10:16
* Description
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo());
}
@Bean
ApiInfo apiInfo(){
final Contact contact = new Contact("刘必君", "https://blog.csdn.net/shi860715", "shi860715@126.com");
return new ApiInfo("生兴基本机构封装",
"Api 文档",
"1.0",
"https://blog.csdn.net/shi860715",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
2.6 swagger 配置扫描接口
package com.liu.efk.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.EnableSwagger2;
import java.util.ArrayList;
/**
* Created by shi860715@126.com
* Date 2021/8/19 10:16
* Description
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// RequestHandlerSelectors 配置扫描接口的方式
// basePackage 指定扫描的包
// any 全部扫描
// none 不扫描
// withClassAnnotation 扫描类上的注解
// withMethodAnnotation 扫描方法上的注解
//
.apis(RequestHandlerSelectors.basePackage("com.liu"))
// 过滤路径 扫描包,且访问路径在/admin下的所有接口
// .paths(PathSelectors.ant("/admin/**"))
.build();
}
@Bean
ApiInfo apiInfo() {
final Contact contact = new Contact("刘必君", "https://blog.csdn.net/shi860715", "shi860715@126.com");
return new ApiInfo("生兴基本机构封装",
"Api 文档",
"1.0",
"https://blog.csdn.net/shi860715",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
2.7 配置是否启动swagger
通过.enable(boolean)
,来控制swagger是否开启,如果为false ,则swagger不能再浏览器中访问
package com.liu.efk.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.EnableSwagger2;
import java.util.ArrayList;
/**
* Created by shi860715@126.com
* Date 2021/8/19 10:16
* Description
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(false)
.select()
// RequestHandlerSelectors 配置扫描接口的方式
// basePackage 指定扫描的包
// any 全部扫描
// none 不扫描
// withClassAnnotation 扫描类上的注解
// withMethodAnnotation 扫描方法上的注解
//
.apis(RequestHandlerSelectors.basePackage("com.liu"))
// 过滤路径 扫描包,且访问路径在/admin下的所有接口
// .paths(PathSelectors.ant("/admin/**"))
.build();
}
@Bean
ApiInfo apiInfo() {
final Contact contact = new Contact("刘必君", "https://blog.csdn.net/shi860715", "shi860715@126.com");
return new ApiInfo("生兴基本机构封装",
"Api 文档",
"1.0",
"https://blog.csdn.net/shi860715",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
2.8 在dev或者test环境中使用swagger,生产环境中不使用swagger
// ** 在开发环境中,或者测试环境中开启swagger
Profiles profiles =Profiles.of(“dev”,“test”);
// 通过预定义的 条件返回项目在运行的环境结果
final boolean flag = environment.acceptsProfiles(profiles);**
package com.liu.efk.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
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.EnableSwagger2;
import java.util.ArrayList;
/**
* Created by shi860715@126.com
* Date 2021/8/19 10:16
* Description
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket(Environment environment) {
// 在开发环境中,或者测试环境中开启swagger
Profiles profiles =Profiles.of("dev","test");
// 通过预定义的 条件返回项目在运行的环境结果
final boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag)
.select()
// RequestHandlerSelectors 配置扫描接口的方式
// basePackage 指定扫描的包
// any 全部扫描
// none 不扫描
// withClassAnnotation 扫描类上的注解
// withMethodAnnotation 扫描方法上的注解
//
.apis(RequestHandlerSelectors.basePackage("com.liu"))
// 过滤路径 扫描包,且访问路径在/admin下的所有接口
// .paths(PathSelectors.ant("/admin/**"))
.build();
}
@Bean
ApiInfo apiInfo() {
final Contact contact = new Contact("刘必君", "https://blog.csdn.net/shi860715", "shi860715@126.com");
return new ApiInfo("生兴基本机构封装",
"Api 文档",
"1.0",
"https://blog.csdn.net/shi860715",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
3 swagger聚合的方式+springSecurity认证
当个工程完成swagger的配置很简单,学完上面的配置就差不多了。
什么是聚合swagger,当我们的微服务模块很多的时候,我们不可能每次访问不同的swagger端口来解决问题,这样我们就需要将所有的微服务提供的swagger文档聚合到一起,这就称为聚合;
3.1 导入依赖
<springfox.version>2.8.0</springfox.version>
<!--swgger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
3.2 文档聚合工具
package com.liu.sxcy.gateway.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import javax.annotation.Resource;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by shi860715@126.com
* Date 2021/8/19 14:27
* Description
*/
@Component
@Primary
@Slf4j
public class SwaggerProvider implements SwaggerResourcesProvider {
/**
* swagger默认的url后缀
*/
protected static final String API_URI = "/v2/api-docs";
/**
* 网关路由 对应配置文件的spring.cloud.gateway.route的路由集合
*/
@Resource
private RouteLocator routeLocator;
/**
* 网关应用名称
*/
@Value("${spring.application.name}")
private String appName;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
// SwaggerResource gatewayResource = new SwaggerResource();
// gatewayResource.setUrl(API_URI);
// gatewayResource.setName("gateway");
// resources.add(gatewayResource);
Map<String, URI> routesMap = new HashMap<>(8);
// 获取网关中配置的路由
routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
.filter(route -> !appName.equals(route.getUri().getHost()))
.subscribe(route -> routesMap.put(route.getUri().getHost(), route.getUri()));
routesMap.forEach((name, uri) -> {
String url = "/" + uri.getHost() + API_URI;
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setUrl(url);
swaggerResource.setUrl(url);
log.info("url"+uri.getHost());
swaggerResource.setName(name);
swaggerResource.setSwaggerVersion("2.0");
resources.add(swaggerResource);
});
log.info("routesMap===============:" + routesMap.toString());
return resources;
}
}
3.3 控制层
package com.liu.sxcy.gateway.controller;
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;
/**
* Created by shi860715@126.com
* Date 2021/8/19 14:18
* 添加配置,因为gate是基于webflux,swagger的资源接口应该是基于web的,所以我们需要自己配置资源接口
*/
@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<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}
3.4 安全框架放行资源
/**
* 不需药认证的接口地址
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/**","/admin/acl/noauth",
//swagger 集成需要放行的资源
"/swagger-ui.html",
"/webjars/**",
"/swagger-resources/**",
"/*/v2/api-docs",
"/favicon.ico","/");
}
3.5 配置公用swagger配置类
package com.liu.sxcy.config;
import com.fasterxml.classmate.GenericType;
import com.fasterxml.classmate.TypeResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.async.DeferredResult;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.WildcardType;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.*;
import static springfox.documentation.schema.AlternateTypeRules.newRule;
@Configuration//配置类
@EnableSwagger2 //swagger注解
public class SwaggerConfig {
@Autowired
private TypeResolver typeResolver;
@Bean
public Docket webApiConfig() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(true)
.apiInfo(apiInfo())
.select().apis(RequestHandlerSelectors.basePackage("com.liu.sxcy"))
.build().alternateTypeRules(
newRule(
typeResolver.resolve(
DeferredResult.class,
typeResolver.resolve(GenericType.class, WildcardType.class)
),
typeResolver.resolve(WildcardType.class)
)
)
// 支持的协议
.protocols(newHashSet("https", "http"))
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
@Bean
ApiInfo apiInfo() {
final Contact contact = new Contact("刘必君", "https://blog.csdn.net/shi860715", "shi860715@126.com");
return new ApiInfo("生兴基本机构封装",
"Api 文档",
"1.0",
"https://blog.csdn.net/shi860715",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
/**
* 设置授权信息
*/
private List<ApiKey> securitySchemes() {
// 在请求头header添加一个名为Authorization的token
return Collections.singletonList(new ApiKey(HttpHeaders.AUTHORIZATION, "token", "header"));
}
/**
* 授权信息全局应用
*/
private List<SecurityContext> securityContexts() {
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(
Collections.singletonList(new SecurityReference("Authorization",
new AuthorizationScope[]{new AuthorizationScope("global", "")}
)))
// 可通过配置正则表达式去排除一些不需要携带token访问的接口 这里不做特殊处理,全部接口访问都需要携带
// 比如.forPaths(PathSelectors.regex("^(?!auth).*$")) 对所有包含"auth"的接口不需要使用securitySchemes
.forPaths(PathSelectors.any())
.build()
);
}
@SafeVarargs
private final <T> Set<T> newHashSet(T... ts) {
if (ts.length > 0) {
return new LinkedHashSet<>(Arrays.asList(ts));
}
return null;
}
}
3.6 网关配置文件
server:
port: 9001
spring:
application:
name: sxcy-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
locater:
enabled: true
gateway:
routes:
- id: acl_router
uri: lb://sxcy-acl
predicates:
- Path=/*/acl/**,/sxcy-acl/**
3.7 效果图
认证图:统一认证token后,接口调试就能直接调试了
多微服务之间的接口统一swagger管理
更多推荐
已为社区贡献1条内容
所有评论(0)