Spring Cloud Edgware SR3 让Zuul支持形如 /xxx和/xxx/yyy 格式的路径配置
在包路径:org.springframework.cloud.netflix.zuul.filters 下,新建类SimpleRouteLocator,取代jar包中的类。内容如下:
/*
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.cloud.netflix.zuul.filters; import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.cloud.netflix.zuul.util.RequestUtils;
import org.springframework.core.Ordered;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils; /**
* Simple {@link RouteLocator} based on configuration data held in {@link ZuulProperties}.
*
* @author Dave Syer
*/
public class SimpleRouteLocator implements RouteLocator, Ordered { private static final Log log = LogFactory.getLog(SimpleRouteLocator.class); private static final int DEFAULT_ORDER = 0; private ZuulProperties properties; private PathMatcher pathMatcher = new AntPathMatcher(); private String dispatcherServletPath = "/";
private String zuulServletPath; private AtomicReference<Map<String, ZuulRoute>> routes = new AtomicReference<>();
private int order = DEFAULT_ORDER; public SimpleRouteLocator(String servletPath, ZuulProperties properties) {
this.properties = properties;
if (StringUtils.hasText(servletPath)) {
this.dispatcherServletPath = servletPath;
} this.zuulServletPath = properties.getServletPath();
} @Override
public List<Route> getRoutes() {
List<Route> values = new ArrayList<>();
for (Entry<String, ZuulRoute> entry : getRoutesMap().entrySet()) {
ZuulRoute route = entry.getValue();
String path = route.getPath();
values.add(getRoute(route, path));
}
return values;
} @Override
public Collection<String> getIgnoredPaths() {
return this.properties.getIgnoredPatterns();
} @Override
public Route getMatchingRoute(final String path) { return getSimpleMatchingRoute(path); } protected Map<String, ZuulRoute> getRoutesMap() {
if (this.routes.get() == null) {
this.routes.set(locateRoutes());
}
return this.routes.get();
} protected Route getSimpleMatchingRoute(final String path) {
if (log.isDebugEnabled()) {
log.debug("Finding route for path: " + path);
} // This is called for the initialization done in getRoutesMap()
getRoutesMap(); if (log.isDebugEnabled()) {
log.debug("servletPath=" + this.dispatcherServletPath);
log.debug("zuulServletPath=" + this.zuulServletPath);
log.debug("RequestUtils.isDispatcherServletRequest()="
+ RequestUtils.isDispatcherServletRequest());
log.debug("RequestUtils.isZuulServletRequest()="
+ RequestUtils.isZuulServletRequest());
} String adjustedPath = adjustPath(path); ZuulRoute route = getZuulRoute(adjustedPath); return getRoute(route, adjustedPath);
} protected ZuulRoute getZuulRoute(String adjustedPath) {
if (!matchesIgnoredPatterns(adjustedPath)) {
//2018年6月20日 马赛克:支持优先精确匹配-----start
Map m = (Map)this.routes.get();
ZuulRoute z = (ZuulRoute)m.get(adjustedPath);
if(z!=null){
return z;
}
//2018年6月20日 马赛克:支持优先精确匹配-----end for (Entry<String, ZuulRoute> entry : getRoutesMap().entrySet()) {
String pattern = entry.getKey();
log.debug("Matching pattern:" + pattern);
if (this.pathMatcher.match(pattern, adjustedPath)) {
return entry.getValue();
}
}
}
return null;
} protected Route getRoute(ZuulRoute route, String path) {
if (route == null) {
return null;
}
if (log.isDebugEnabled()) {
log.debug("route matched=" + route);
}
String targetPath = path;
String prefix = this.properties.getPrefix();
if(prefix.endsWith("/")) {
prefix = prefix.substring(0, prefix.length() - 1);
}
if (path.startsWith(prefix + "/") && this.properties.isStripPrefix()) {
targetPath = path.substring(prefix.length());
} if (route.isStripPrefix()) {
int index = route.getPath().indexOf("*") - 1;
if (index > 0) {
String routePrefix = route.getPath().substring(0, index);
targetPath = targetPath.replaceFirst(routePrefix, "");
prefix = prefix + routePrefix;
} //2018年6月20日 马赛克:支持形如/xxx/bbb 而非/xxx/**的routes-----start
else{ String routePath = route.getPath();
targetPath = routePath.substring(routePath.lastIndexOf("/"));
prefix = prefix + routePath.substring(0,routePath.lastIndexOf("/"));
}
//2018年6月20日 马赛克:支持形如/xxx/bbb 而非/xxx/**的routes-----end
}
Boolean retryable = this.properties.getRetryable();
if (route.getRetryable() != null) {
retryable = route.getRetryable();
}
return new Route(route.getId(), targetPath, route.getLocation(), prefix,
retryable,
route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null,
route.isStripPrefix());
} /**
* Calculate all the routes and set up a cache for the values. Subclasses can call
* this method if they need to implement {@link RefreshableRouteLocator}.
*/
protected void doRefresh() {
this.routes.set(locateRoutes());
} /**
* Compute a map of path pattern to route. The default is just a static map from the
* {@link ZuulProperties}, but subclasses can add dynamic calculations.
*/
protected Map<String, ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<String, ZuulRoute>();
for (ZuulRoute route : this.properties.getRoutes().values()) {
routesMap.put(route.getPath(), route);
}
return routesMap;
} protected boolean matchesIgnoredPatterns(String path) {
for (String pattern : this.properties.getIgnoredPatterns()) {
log.debug("Matching ignored pattern:" + pattern);
if (this.pathMatcher.match(pattern, path)) {
log.debug("Path " + path + " matches ignored pattern " + pattern);
return true;
}
}
return false;
} private String adjustPath(final String path) {
String adjustedPath = path; if (RequestUtils.isDispatcherServletRequest()
&& StringUtils.hasText(this.dispatcherServletPath)) {
if (!this.dispatcherServletPath.equals("/")) {
adjustedPath = path.substring(this.dispatcherServletPath.length());
log.debug("Stripped dispatcherServletPath");
}
}
else if (RequestUtils.isZuulServletRequest()) {
if (StringUtils.hasText(this.zuulServletPath)
&& !this.zuulServletPath.equals("/")) {
adjustedPath = path.substring(this.zuulServletPath.length());
log.debug("Stripped zuulServletPath");
}
}
else {
// do nothing
} log.debug("adjustedPath=" + adjustedPath);
return adjustedPath;
} @Override
public int getOrder() {
return order;
} public void setOrder(int order) {
this.order = order;
} }
其中的164-171行,让zuul支持了如下配置:
zuul:
routes:
all:
path: /vod2/two
serviceId: all
one:
path: /vod1/one
serviceId: one
通过/vod2/two路径,可以访问到 /all/two
注意,测试时不存在名为vod2和vod1的服务
Spring Cloud Edgware SR3 让Zuul支持形如 /xxx和/xxx/yyy 格式的路径配置的更多相关文章
- 001-Spring Cloud Edgware.SR3 升级最新 Finchley.SR1,spring boot 1.5.9.RELEASE 升级2.0.4.RELEASE注意问题点
一.前提 升级前 => 升级后 Spring Boot 1.5.x => Spring Boot 2.0.4.RELEASE Spring Cloud Edgware SR3 => ...
- Spring Cloud 系列之 Netflix Zuul 服务网关
什么是 Zuul Zuul 是从设备和网站到应用程序后端的所有请求的前门.作为边缘服务应用程序,Zuul 旨在实现动态路由,监视,弹性和安全性.Zuul 包含了对请求的路由和过滤两个最主要的功能. Z ...
- Spring Cloud Edgware Release Notes
Spring Cloud Edgware builds on Spring Boot 1.5.x. Renamed starters A number of starters did not foll ...
- spring cloud 2.x版本 Zuul路由网关教程
前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...
- SPRING CLOUD服务网关之ZUUL
服务网关是微服务架构中一个不可或缺的部分.通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由.均衡负载功能之外,它还具备了权限控制等功能.Spring Cloud Netflix中 ...
- Springboot整合Spring Cloud Kubernetes读取ConfigMap,支持自动刷新配置
1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Docker & Kubernetes相关文章:容器技术 之前介绍了Spring Cloud Config的用法,但 ...
- Spring Cloud内置的Zuul过滤器详解
Spring Cloud默认为Zuul编写并启用了一些过滤器,这些过滤器有什么作用呢?我们不妨按照@EnableZuulServer.@EnableZuulProxy两个注解进行展开,相信大家对这两个 ...
- 最全面的改造Zuul网关为Spring Cloud Gateway(包含Zuul核心实现和Spring Cloud Gateway核心实现)
前言: 最近开发了Zuul网关的实现和Spring Cloud Gateway实现,对比Spring Cloud Gateway发现后者性能好支持场景也丰富.在高并发或者复杂的分布式下,后者限流和自定 ...
- Spring Cloud下基于OAUTH2+ZUUL认证授权的实现
Spring Cloud下基于OAUTH2认证授权的实现 在Spring Cloud需要使用OAUTH2来实现多个微服务的统一认证授权,通过向OAUTH服务发送某个类型的grant type进行集中认 ...
随机推荐
- wim2008 让FTP防火墙可用性配置
转: Win2003和Win2008防火墙导致FTP服务器不能访问的解决方法 这篇文章主要介绍了Win2003和Win2008防火墙导致FTP服务器不能访问的解决方法,需要的朋友可以参考下 由于通过远 ...
- Swift3.0:Get/Post同步和异步请求
一.介绍 Get和Post区别: Get是从服务器上获取数据,Post是向服务器发送数据. 对于Get方式,服务端用Request.QueryString获取变量的值,对于Post方式,服务端用Req ...
- Windows server 2008 r2 如何开启Win7的Aero效果 (转)
Aero 桌面体验为开放式外观提供了类似于玻璃的窗口. 它包括与众不同的直观样式,将轻型透明的窗口外观与强大的图形高级功能结合在一起.您可以享受具有视觉冲击力的效果和外观,并可从更快地访问程序中获益. ...
- solr4.7配置(ik-analyzer)
环境: windows server 2003 sp2 x86 tomcat8.0 solr-4.7.2 IK Analyzer 2012FF_hf1 ————————————华丽的分割线—————— ...
- 深入浅出Nodejs读书笔记
深入浅出Nodejs读书笔记 转:http://tw93.github.io/2015-03-01/shen-ru-qian-chu-nodejs-reading-mind-map.html cate ...
- 使用 CSS 接收用户的点击事情并对相关节点进行操作
问题背景:使用纯 CSS 方案,实现导航栏tab切换 实现 Tab 切换的难点在于如何使用 CSS 接收到用户的点击事情并对相关的节点进行操作.即是: 如何接收点击事件 如何操作相关DOM 下面看看如 ...
- pThreads线程(三) 线程同步--条件变量
条件变量(Condition Variables) 参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1 条件变量是什么? 条件变量为我们提供了另一种 ...
- 3分钟搞定Linux系统正则表达式
正则表达式是一种字符模式,用于在查找过程中匹配制定的字符. 元字符通常在Linux中分为两类:Shell元字符,由Linux Shell进行解析:正则表达式元字符,由vi/grep/sed/awk等文 ...
- (转)AssetBundle系列——共享资源打包/依赖资源打包
有人在之前的博客中问我有关共享资源打包的代码,其实这一块很简单,就两个函数: BuildPipeline.PushAssetDependencies():依赖资源压栈: BuildPipeline.P ...
- 微软BI 之SSAS 系列 - 多维数据集中度量值设计时的聚合函数 (累加性_半累加性和非累加性)
在 SSAS 系列 - 实现第一个 Cube 以及角色扮演维度,度量值格式化和计算成员的创建 中主要是通过已存在的维度和事实数据创建了一个多维数据集,并同时解释了 Role-Playing Dimen ...