news 2026/4/3 1:36:39

SpringCloudGateWay

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringCloudGateWay

SpringCloudGateWay进行服务化:
我们需要将我们的springCloudGatewa项目当作一个服务注册到EurekaServer中,配置如下
server:
port: 8888
spring:
application:
name: cloud-gateway-eureka
cloud:
gateway:
discovery:
locator:
enabled: true
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/
logging:
level:
org.springframework.cloud.gateway: debug
spring.cloud.gateway.discovery.locator.enable是否与服务注册于发现组件进行结合,通过注册于Eureka server的serviceId匹配转发到对应的服务实例,从而根据serviceId创建路由功能。
Logging.level.org.springframework.cloud.gateway日志级别,便于排查问题
此时可以在http://localhost:8000/上看到注册的serviceId为CLOUD-GATEWAY-EUREKA(“在EurekaServer自动转换成大写”)的服务。
通过网关访问注册在EurekaServer上的服务的语法:
http://网关地址:端口/服务中心注册 serviceId/具体的url
比如和我们的网关服务注册在同一个EurekaServer上还注册了一个serviceId为”PRODUCER”的服务, 同时我们的网关服务开启了spring.cloud.gateway.discovery.locator.enable,即spring.cloud.gateway.discovery.locator.enable:true,比如我们的网关服务器ip是192.168.10.1,端口是8080,我们的PRODUCER服务的主机IP是192.168.10.2,端口是:9999如果我们想通过网关访问我们的PRODUCER服务的say功能,我们可以键入请求:http://192.168.10.1:8080/PRODUCER/say这样请求就会被网关转发,相当于我们直接请求http://192.168.10.2:9999/say

相比较于我们直接访问我们的服务,我们可以通过网关服务统一对所有调用我们任意服务的请求进行过滤路由:
这就需要我们设置路由规则:
例如下面的路由规则
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
- id: nameTree
uri: lb://spring-cloud-producer
predicates:
- Mathod=get
- Path=/poing/**
Filters:
- PrefixPath=/bing
从上面的例子我们可以看到我们需要在spring.clou.gateway.routes下配置路由规则,
包括id uri predicates filter字段,
其中id字段为路由规则id,
uri字段是在predicates断言为true时路由的地址,在id为nameTree的路由规则我们可以看到用到了lb://spring-cloud-producer而不是直接指定的新的地址,这里的lb是一种协议,gateway将使用LoadBaLancerClient把spring-cloud-producer通过Eureka解析serviceId为spring-cloud-producer对应的主机和端口进行负载均衡.
当我们的uri:使用的是http或者https时使用的是netty的HttpClient进行路由转发
当我们的uri:使用的时ws:或者wss:时使用的是Spring web socket进行路由转发,如果我们需要路由转发同时还要负载均衡话,我们可以在uri:里面同时设置使用lb:ws:serviceId这样既能实现转发也能实现负载

predicates后面跟的条件,与请求进行匹配从而断言是否满足,filter后面跟的是各种filter 是org.springframework.cloud.gateway.filter.GatewayFilter的实例
Predicate来源于java8的函数编程,Predicate接受一个入参返回的是布尔类型的参数,内部的defaulte函数支持与或非 test等的操作,详情查看api
SpringCloud内置的集中Predicate的实现


SpringCloudGateway的常见的几种Filter
StriPrefix Filter是一种请求拦截的功能的Filter我们可以使用利用这个来做请求拼接
例如 spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2

Server: Port:8080

这个的意思就是说当我们匹配到/name/时,比如我们的请求http://locahost:8080/name/a/b时StriPrefix=2就代表截取的路径的个数,这样gateway在进行路由转发时,就会生成新的转发请求:http://nameservice/b
PrefixPath Filter
PrefixPath Filter的作用和StriPrefix Filter刚好相反,实在转发URL时添加一部分前缀
例如 spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/

filters:
- PrefixPath=/mypath
Server:
Port:8080
这样当你请求为http://localhost:8080/name/a/b 这样gateway在进行转发时就会转发成新的请求http://nameservice/mypath/name/a/b

如果自定义GateWayFilterFactory可以参考SpringCloudGateWay提供的几种常见的Filter的实现方式,也就是继承抽象类AbstractNameValueGateWayFilterFactory 实现 GateWayFilter apply(C Config)方法,然后加入到容器被容器管理即可

public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {

private static final Log logger = LogFactory.getLog(AuthorizeGatewayFilterFactory.class); private static final String AUTHORIZE_TOKEN = "token"; private static final String AUTHORIZE_UID = "uid"; @Autowired private StringRedisTemplate stringRedisTemplate; public AuthorizeGatewayFilterFactory() { super(Config.class); logger.info("Loaded GatewayFilterFactory [Authorize]"); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("enabled"); } @Override public GatewayFilter apply(AuthorizeGatewayFilterFactory.Config config) { return (exchange, chain) -> { if (!config.isEnabled()) { return chain.filter(exchange); } ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); String token = headers.getFirst(AUTHORIZE_TOKEN); String uid = headers.getFirst(AUTHORIZE_UID); if (token == null) { token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN); } if (uid == null) { uid = request.getQueryParams().getFirst(AUTHORIZE_UID); } ServerHttpResponse response = exchange.getResponse(); if (StringUtils.isEmpty(token) || StringUtils.isEmpty(uid)) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } String authToken = stringRedisTemplate.opsForValue().get(uid); if (authToken == null || !authToken.equals(token)) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } return chain.filter(exchange); }; } public static class Config { // 控制是否开启认证 private boolean enabled; public Config() {} public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } }

}

如何应用呢

网关路由配置

spring:
cloud:
gateway:
routes:
- id: user-service
uri: http://localhost:8077/api/user/list
predicates:
- Path=/user/list
filters:
# 关键在下面一句,值为true则开启认证,false则不开启
# 这种配置方式和spring cloud gateway内置的GatewayFilterFactory一致
- Authorize=true

另外一种自定义GateWayFilter的方式时实现GateWayFilter 和Ordered接口
public class AuthorizeGatewayFilter implements GatewayFilter, Ordered {

private static final String AUTHORIZE_TOKEN = "token"; private static final String AUTHORIZE_UID = "uid"; @Autowired private StringRedisTemplate stringRedisTemplate; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); String token = headers.getFirst(AUTHORIZE_TOKEN); String uid = headers.getFirst(AUTHORIZE_UID); if (token == null) { token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN); } if (uid == null) { uid = request.getQueryParams().getFirst(AUTHORIZE_UID); } ServerHttpResponse response = exchange.getResponse(); if (StringUtils.isEmpty(token) || StringUtils.isEmpty(uid)) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } String authToken = stringRedisTemplate.opsForValue().get(uid); if (authToken == null || !authToken.equals(token)) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; }

}
如何使用我们的自定义的AuthorizeGateWayFilter呢,
在我们的RouteLocatorBuilder中添加,当然继承了AbstractNameValueGateWayFilterFactory的自定义filter也可以通过这种方式注册进去生效:
@SpringBootApplication
public class GatewayApplication {

public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.routes().route(r -> r.path("/user/list") .uri("http://localhost:8077/api/user/list") .filters(new AuthorizeGatewayFilter()) .id("user-service")) .build(); }

}
如果我们要定义全局的Filter从而对所有的请求都起过滤作用则需要实现GlobalFilter 和ordered接口并实现对应的方法如下:
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
private static final String AUTHORIZE_TOKEN = “token”;
private static final String AUTHORIZE_UID = “uid”;

@Autowired private StringRedisTemplate stringRedisTemplate; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); String token = headers.getFirst(AUTHORIZE_TOKEN); String uid = headers.getFirst(AUTHORIZE_UID); if (token == null) { token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN); } if (uid == null) { uid = request.getQueryParams().getFirst(AUTHORIZE_UID); } ServerHttpResponse response = exchange.getResponse(); if (StringUtils.isEmpty(token) || StringUtils.isEmpty(uid)) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } String authToken = stringRedisTemplate.opsForValue().get(uid); if (authToken == null || !authToken.equals(token)) { response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; }

}
如何让我们自定义的全局Filter起作用呢
不需要做任何额外的操作只需要对我们自定义的Filter添加@Component注解 让容器管理这样就对所有请求起到过滤作用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/30 18:52:58

如何快速配置微信增强插件:完整功能指南

如何快速配置微信增强插件&#xff1a;完整功能指南 【免费下载链接】WeChatExtension-ForMac Mac微信功能拓展/微信插件/微信小助手(A plugin for Mac WeChat) 项目地址: https://gitcode.com/gh_mirrors/we/WeChatExtension-ForMac 微信作为我们日常工作和生活中不可或…

作者头像 李华
网站建设 2026/3/28 14:17:58

HLS流媒体下载器技术解析与应用指南

HLS流媒体下载器技术解析与应用指南 【免费下载链接】hls-downloader Web Extension for sniffing and downloading HTTP Live streams (HLS) 项目地址: https://gitcode.com/gh_mirrors/hl/hls-downloader 技术架构概述 HLS Downloader是一款专为浏览器环境设计的HTTP…

作者头像 李华
网站建设 2026/3/27 20:07:15

HLS流媒体下载工具如何实现高效的视频捕获与下载?

HLS流媒体下载工具如何实现高效的视频捕获与下载&#xff1f; 【免费下载链接】hls-downloader Web Extension for sniffing and downloading HTTP Live streams (HLS) 项目地址: https://gitcode.com/gh_mirrors/hl/hls-downloader 在当今流媒体内容盛行的时代&#xf…

作者头像 李华
网站建设 2026/3/26 17:25:35

LX Music Desktop终极音乐体验指南:解锁你的免费音乐世界

LX Music Desktop终极音乐体验指南&#xff1a;解锁你的免费音乐世界 【免费下载链接】lx-music-desktop 一个基于 electron 的音乐软件 项目地址: https://gitcode.com/GitHub_Trending/lx/lx-music-desktop 在寻找一款真正免费又好用的音乐播放器&#xff1f;LX Music…

作者头像 李华
网站建设 2026/4/1 21:35:58

电视盒子改造避坑实战:从安卓TV到全能服务器的华丽转身

电视盒子改造避坑实战&#xff1a;从安卓TV到全能服务器的华丽转身 【免费下载链接】amlogic-s9xxx-armbian amlogic-s9xxx-armbian: 该项目提供了为Amlogic、Rockchip和Allwinner盒子构建的Armbian系统镜像&#xff0c;支持多种设备&#xff0c;允许用户将安卓TV系统更换为功能…

作者头像 李华
网站建设 2026/3/26 22:16:37

WPS-Zotero终极指南:3步实现Linux系统完美文献管理

WPS-Zotero终极指南&#xff1a;3步实现Linux系统完美文献管理 【免费下载链接】WPS-Zotero An add-on for WPS Writer to integrate with Zotero. 项目地址: https://gitcode.com/gh_mirrors/wp/WPS-Zotero 在学术写作和科研工作中&#xff0c;如何在Linux系统上实现WP…

作者头像 李华