springcloud+gateway微服务整合swagger
单一的微服务集成swagger:
maven:
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>- </dependency>
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>- </dependency>
- package fwz.cpjiang.ums.utils;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import springfox.documentation.builders.ApiInfoBuilder;
- import springfox.documentation.builders.ParameterBuilder;
- import springfox.documentation.builders.PathSelectors;
- import springfox.documentation.builders.RequestHandlerSelectors;
- import springfox.documentation.schema.ModelRef;
- import springfox.documentation.service.ApiInfo;
- import springfox.documentation.service.Parameter;
- import springfox.documentation.spi.DocumentationType;
- import springfox.documentation.spring.web.plugins.Docket;
- import springfox.documentation.swagger2.annotations.EnableSwagger2;
- import java.util.ArrayList;
- import java.util.List;
- @Configuration
- @EnableSwagger2
- public class SwaggerConfig {
- @Bean
- public Docket createRestApi(){
- ParameterBuilder tokenPar = new ParameterBuilder();
- List<Parameter> pars = new ArrayList<Parameter>();
- tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
- pars.add(tokenPar.build());
- return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
- .select()
- .apis(RequestHandlerSelectors.any())
- .paths(PathSelectors.any()).build().globalOperationParameters(pars);
- }
- private ApiInfo apiInfo(){
- return new ApiInfoBuilder()
- .title("用户管理 API Doc")
- .description("This is a restful api document of 用户管理.")
- .version("1.0")
- .build();
- }
- }
此时swagger只是存在于单一的微服务,很不方便
gateway整合swagger:
所有的微服务均按上述配置swagger
然后在gateway微服务中,添加如下配置:
- package fwz.cpjiang.gateway.utils;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import springfox.documentation.swagger.web.SecurityConfiguration;
- import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
- import springfox.documentation.swagger.web.UiConfiguration;
- import springfox.documentation.swagger.web.UiConfigurationBuilder;
- @Configuration
- public class SwaggerConfig {
- @Bean
- public SecurityConfiguration securityConfiguration() {
- return SecurityConfigurationBuilder.builder().build();
- }
- @Bean
- public UiConfiguration uiConfiguration() {
- return UiConfigurationBuilder.builder().build();
- }
- }
- package fwz.cpjiang.gateway.utils;
- 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.List;
- import java.util.Optional;
- @RestController
- @RequestMapping("/swagger-resources")
- public class SwaggerHandler {
- private final SecurityConfiguration securityConfiguration;
- private final UiConfiguration uiConfiguration;
- private final SwaggerResourcesProvider swaggerResources;
- @Autowired
- public SwaggerHandler(SwaggerResourcesProvider swaggerResources, SecurityConfiguration securityConfiguration, UiConfiguration uiConfiguration) {
- this.swaggerResources = swaggerResources;
- this.securityConfiguration = securityConfiguration;
- this.uiConfiguration = uiConfiguration;
- }
- @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<List<SwaggerResource>>> swaggerResources() {
- return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
- }
- }
- package fwz.cpjiang.gateway.utils;
- import lombok.AllArgsConstructor;
- 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;
- @Primary
- @Component
- @AllArgsConstructor
- public class SwaggerProvider implements SwaggerResourcesProvider {
- public static final String API_URI = "/v2/api-docs";
- private final RouteLocator routeLocator;
- private final GatewayProperties gatewayProperties;
- @Override
- public List<SwaggerResource> get() {
- List<SwaggerResource> resources = new ArrayList<>();
- List<String> routes = new ArrayList<>();
- routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
- gatewayProperties.getRoutes().stream()
- .filter(routeDefinition -> routes.contains(routeDefinition.getId()))
- .forEach(routeDefinition -> routeDefinition.getPredicates().stream()
- .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
- .forEach(predicateDefinition -> resources
- .add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs()
- .get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", API_URI)))));
- return resources;
- }
- private SwaggerResource swaggerResource(String name, String url) {
- SwaggerResource swaggerResource = new SwaggerResource();
- swaggerResource.setName(name);
- swaggerResource.setUrl(url);
- swaggerResource.setSwaggerVersion("2.0");
- return swaggerResource;
- }
- }
- package fwz.cpjiang.gateway.utils;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.context.annotation.Configuration;
- import java.util.List;
- @Configuration
- @ConfigurationProperties(prefix = "system")
- public class UrlConfig {
- // 配置文件使用list接收
- private List<String> whiteList;
- public List<String> getWhiteList() {
- return whiteList;
- }
- public void setWhiteList(List<String> whiteList) {
- this.whiteList = whiteList;
- }
- }
yml配置文件:
- system:
- whiteList:
- - "/swagger-ui.html"
- - "/swagger-resources/**"
- - "/v2/api-docs"
- - "/admin/login"
- routes:
- id: hbistc-ums
uri: lb://hbistc-ums
predicates:
- Path=/ums/**
filters:
- StripPrefix=1
- id: hbistc-mall
uri: lb://hbistc-mall
predicates:
- Path=/mall/**
filters:
- StripPrefix=1
- package fwz.cpjiang.gateway.utils;
- import io.jsonwebtoken.Claims;
- import io.jsonwebtoken.JwtBuilder;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.SignatureAlgorithm;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.SecretKeySpec;
- import java.util.Base64;
- import java.util.Date;
- import java.util.UUID;
- /**
- * JWT工具类
- */
- public class JwtUtils {
- //有效期为
- public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000 一个小时
- //设置秘钥明文
- public static final String JWT_KEY = "joijgisdlwejjjfeawoGdeizeffsaz";
- /**
- * 创建token
- *
- * @param id
- * @param subject
- * @param ttlMillis
- * @return
- */
- public static String createJWT(String id, String subject, Long ttlMillis) {
- SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
- long nowMillis = System.currentTimeMillis();
- Date now = new Date(nowMillis);
- if (ttlMillis == null) {
- ttlMillis = JwtUtils.JWT_TTL;
- }
- long expMillis = nowMillis + ttlMillis;
- Date expDate = new Date(expMillis);
- SecretKey secretKey = generalKey();
- JwtBuilder builder = Jwts.builder()
- .setId(id) //唯一的ID
- .setSubject(subject) // 主题 可以是JSON数据
- .setIssuer("admin") // 签发者
- .setIssuedAt(now) // 签发时间
- .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
- .setExpiration(expDate);// 设置过期时间
- return builder.compact();
- }
- /**
- * 生成加密后的秘钥 secretKey
- *
- * @return
- */
- public static SecretKey generalKey() {
- byte[] encodedKey = Base64.getDecoder().decode(JwtUtils.JWT_KEY);
- SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
- return key;
- }
- /**
- * 解析
- *
- * @param jwt
- * @return
- * @throws Exception
- */
- public static Claims parseJWT(String jwt) throws Exception {
- SecretKey secretKey = generalKey();
- return Jwts.parser()
- .setSigningKey(secretKey)
- .parseClaimsJws(jwt)
- .getBody();
- }
- public static void main(String[] args) throws Exception {
- String token = createJWT(UUID.randomUUID().toString(), "ggggggg", null);
- System.out.println(token);
- Claims c = parseJWT(token);
- String id = c.getId();
- System.out.println(id);
- }
- }
- package fwz.cpjiang.gateway.filter;
- import cn.hutool.core.util.StrUtil;
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import fwz.cpjiang.gateway.utils.JwtUtils;
- import fwz.cpjiang.gateway.utils.UrlConfig;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cloud.gateway.filter.GatewayFilterChain;
- import org.springframework.cloud.gateway.filter.GlobalFilter;
- import org.springframework.core.Ordered;
- import org.springframework.http.HttpHeaders;
- import org.springframework.http.HttpStatus;
- import org.springframework.http.server.reactive.ServerHttpRequest;
- import org.springframework.http.server.reactive.ServerHttpResponse;
- import org.springframework.stereotype.Component;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Flux;
- import reactor.core.publisher.Mono;
- import reactor.netty.ByteBufFlux;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * 鉴权过滤器 验证token
- */
- @Component
- public class AuthorizeFilter implements GlobalFilter, Ordered {
- private static final String AUTHORIZE_TOKEN = "token";
- @Autowired
- private UrlConfig urlConfig;
- @Override
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- //1. 获取请求
- ServerHttpRequest request = exchange.getRequest();
- //2. 则获取响应
- ServerHttpResponse response = exchange.getResponse();
- //3. 如果是登录请求则放行
- for (int i = 0; i <urlConfig.getWhiteList().size() ; i++) {
- if (request.getURI().getPath().contains(urlConfig.getWhiteList().get(i))) {
- return chain.filter(exchange);
- }
- }
- //4. 获取请求头
- HttpHeaders headers = request.getHeaders();
- //5. 请求头中获取令牌
- String token = headers.getFirst(AUTHORIZE_TOKEN);
- //6. 判断请求头中是否有令牌
- if (StrUtil.isEmpty(token)) {
- //7. 响应中放入返回的状态吗, 没有权限访问
- response.setStatusCode(HttpStatus.UNAUTHORIZED);
- //8. 返回
- //return response.setComplete();
- //设置响应头信息Content-Type类型
- response.getHeaders().add("Content-Type","application/json");
- //设置返回json数据
- return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(getWrapData()))));
- }
- //9. 如果请求头中有令牌则解析令牌
- try {
- JwtUtils.parseJWT(token);
- } catch (Exception e) {
- e.printStackTrace();
- //10. 解析jwt令牌出错, 说明令牌过期或者伪造等不合法情况出现
- response.setStatusCode(HttpStatus.UNAUTHORIZED);
- //11. 返回
- //设置响应头信息Content-Type类型
- response.getHeaders().add("Content-Type","application/json");
- //设置返回json数据
- return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(getWrapData()))));
- }
- //12. 放行
- return chain.filter(exchange);
- }
- @Override
- public int getOrder() {
- return 0;
- }
- private byte[] getWrapData() {
- Map<String,String> map = new HashMap<>();
- map.put("code","1");
- map.put("msg","token is empty or illegal");
- try {
- return new ObjectMapper().writeValueAsString(map).getBytes();
- } catch (JsonProcessingException e) {
- //
- }
- return "".getBytes();
- }
- }
进行白名单过滤
然后访问网关:
可以发现红框内出现了微服务切换的选项,至此整合完毕
springcloud+gateway微服务整合swagger的更多相关文章
- SpringCloud Gateway微服务网关实战与源码分析-上
概述 定义 Spring Cloud Gateway 官网地址 https://spring.io/projects/spring-cloud-gateway/ 最新版本3.1.3 Spring Cl ...
- 用SpringCloud进行微服务架构演进
在<架构师必须要知道的阿里的中台战略与微服务> 中已经阐明选择SpringCloud进行微服务架构实现中台战略,因此下面介绍SpringCloud的一些内容,SpringCloud已经出来 ...
- SpringCloud学习--微服务架构
目录 微服务架构快速指南 SOA Dubbo Spring Cloud Dubbo与SpringCloud对比 微服务(Microservice)架构快速指南 什么是软件架构? 软件架构是一个包含各种 ...
- springCloud搭建微服务集群+Zuul服务器端负载均衡
概述 最近研究了一下springCloud的微服务集群,主要用到了SpringCloud的服务发现和服务器端负载均衡,所有的项目都是用的springboot,可以和springCloud无缝对接. 技 ...
- SpringCloud与微服务Ⅲ --- SpringCloud入门概述
一. 什么是SpringCloud SpringCloud基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于NetF ...
- 一个C#开发者学习SpringCloud搭建微服务的心路历程
前言 Spring Cloud很火,很多文章都有介绍如何使用,但对于我这种初学者,我需要从创建项目开始学起,所以这些文章对于我的启蒙,帮助不大,所以只好自己写一篇文章,用于备忘. SpringClou ...
- 基于Spring-Cloud的微服务框架设计
基于Spring-Cloud的微服务框架设计 先进行大的整体的框架整理,然后在针对每一项进行具体的详细介绍
- SpringCloud与微服务系列专栏
一. 前置知识 学习SpringCloud之前需要具备和掌握如下框架和工具的使用:SpringMVC,Spring,Spring Boot,Mybatis,Maven,Git. SpringCloud ...
- springCloud进阶(微服务架构&Eureka)
springCloud进阶(微服务架构&Eureka) 1. 微服务集群 1.1 为什么要集群 为了提供并发量,有时同一个服务提供者可以部署多个(商品服务).这个客户端在调用时要根据一定的负责 ...
随机推荐
- SpringBoot 之 国际化
增加国际化i18n语言配置: # src/main/resources/i18n/login.properties login.btn=登录 # src/main/resources/i18n/log ...
- Linux上天之路(九)之文件和文件夹的权限
主要内容 linux 基本权限 linux特殊权限 linux隐藏权限 linux file ACL 权限 1. Linux的基本权限 使用ls -l filename 命令查看文件或文件夹详细权限 ...
- 第3届云原生技术实践峰会(CNBPS 2020)重磅开启,“原”力蓄势待发!
CNBPS 2020将在11月19-21日全新启动!作为国内最有影响力的云原生盛会之一,云原生技术实践峰会(CNBPS)至今已举办三届. 在2019年的CNBPS上,灵雀云CTO陈恺喊出"云 ...
- css3中transition属性详解
css3中通过transition属性可以实现一些简单的动画过渡效果~ 1.语法 transition: property duration timing-function delay; transi ...
- Vulnhub - THE PLANETS: EARTH
环境配置 从www.vulnhub.com下载靶机,在VMware中导入,自动分配IP 主机发现 通过对内网主机的扫描,VMware为目标主机 端口扫描 使用nmap对主机进行扫描 发现443端口信息 ...
- [Raspberry Pi] 入门使用
今天开始介绍Raspberry Pi(简称RPi,下同)入门的一些基础知识. 第1部分: 安装RPi 1.1 从 http://www.raspberrypi.org/downloads 下载RPi ...
- 【刷题-LeetCode】238. Product of Array Except Self
Product of Array Except Self Given an array nums of n integers where n > 1, return an array outpu ...
- netty系列之:请netty再爱UDT一次
目录 简介 netty对UDT的支持 搭建一个支持UDT的netty服务 异常来袭 TypeUDT和KindUDT 构建ChannelFactory SelectorProviderUDT 使用UDT ...
- 多线程-线程间通信-多生产者多消费者问题解决(notifyAll)
1 package multithread4; 2 3 /* 4 * 生产者,消费者. 5 * 6 * 多生产者,多消费者的问题. 7 * 8 * if判断标记,只有一次,会导致不该运行的线程运行了. ...
- spring内嵌cglib包,这里藏着一个大坑
问题发现 2022-01-21 早上 9 点,订单系统出现大面积的"系统未知错误"报错,导致部分用户无法正常下单.查询后台日志,可以看到大量的 duplicate class at ...