在包路径: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 格式的路径配置的更多相关文章

  1. 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 => ...

  2. Spring Cloud 系列之 Netflix Zuul 服务网关

    什么是 Zuul Zuul 是从设备和网站到应用程序后端的所有请求的前门.作为边缘服务应用程序,Zuul 旨在实现动态路由,监视,弹性和安全性.Zuul 包含了对请求的路由和过滤两个最主要的功能. Z ...

  3. Spring Cloud Edgware Release Notes

    Spring Cloud Edgware builds on Spring Boot 1.5.x. Renamed starters A number of starters did not foll ...

  4. spring cloud 2.x版本 Zuul路由网关教程

    前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...

  5. SPRING CLOUD服务网关之ZUUL

    服务网关是微服务架构中一个不可或缺的部分.通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由.均衡负载功能之外,它还具备了权限控制等功能.Spring Cloud Netflix中 ...

  6. Springboot整合Spring Cloud Kubernetes读取ConfigMap,支持自动刷新配置

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Docker & Kubernetes相关文章:容器技术 之前介绍了Spring Cloud Config的用法,但 ...

  7. Spring Cloud内置的Zuul过滤器详解

    Spring Cloud默认为Zuul编写并启用了一些过滤器,这些过滤器有什么作用呢?我们不妨按照@EnableZuulServer.@EnableZuulProxy两个注解进行展开,相信大家对这两个 ...

  8. 最全面的改造Zuul网关为Spring Cloud Gateway(包含Zuul核心实现和Spring Cloud Gateway核心实现)

    前言: 最近开发了Zuul网关的实现和Spring Cloud Gateway实现,对比Spring Cloud Gateway发现后者性能好支持场景也丰富.在高并发或者复杂的分布式下,后者限流和自定 ...

  9. Spring Cloud下基于OAUTH2+ZUUL认证授权的实现

    Spring Cloud下基于OAUTH2认证授权的实现 在Spring Cloud需要使用OAUTH2来实现多个微服务的统一认证授权,通过向OAUTH服务发送某个类型的grant type进行集中认 ...

随机推荐

  1. 隐马尔可夫(HMM)、前/后向算法、Viterbi算法

    HMM的模型  图1 如上图所示,白色那一行描述由一个隐藏的马尔科夫链生成不可观测的状态随机序列,蓝紫色那一行是各个状态生成可观测的随机序列 话说,上面也是个贝叶斯网络,而贝叶斯网络中有这么一种,如下 ...

  2. iOS:在tableView中通过Masonry使用autolayout在iOS7系统出现约束崩溃

    一.出现崩溃情景: 给tableView创建一个头视图,也即tableHeaderView,然后使用Masonry并切换到iOS7/7.1系统给tableHeaderView中的所有子视图添加约束,此 ...

  3. Verilog 加法器和减法器(6)

    为了减小行波进位加法器中进位传播延迟的影响,可以尝试在每一级中快速计算进位,如果能在较短时间完成计算,则可以提高加法器性能. 我们可以进行如下的推导: 设 gi=xi&yi, pi = xi ...

  4. 为什么你作为一个.NET的程序员工资那么低?(转)

    最近看到很多抱怨贴,也许有一定的道理,但是你想过没,为什么大部分.NET程序员工资相对低?我个人是这么看的: 大批半罐子水的程序员,永远被局限在.NET的原始的小圈圈里.前端不会(你放弃了一项很重要的 ...

  5. F分布

    定义:设X1服从自由度为m的χ2分布,X2服从自由度为n的χ2分布,且X1.X2相互独立,则称变量F=(X1/m)/(X2/n)所服从的分布为F分布,其中第一自由度为m,第二自由度为n.[1] F分布 ...

  6. Java-JUC(六):创建线程的4种方式

    Java创建线程的4种方式: Java使用Thread类代表线程,所有线程对象都必须是Thread类或者其子类的实例.Java可以用以下4种方式来创建线程: 1)继承Thread类创建线程: 2)实现 ...

  7. 为Subline Text 3 添加支持ini文件语法高亮

    转: http://lancelot.blog.51cto.com/393579/1783653 在Subline text 官网下载了Subline text 3 .不过发现没有对ini格式文件的语 ...

  8. (转)在NGUI使用图片文字(数字、美术字)(直接可用于UILable)

    本文永久地址:http://www.omuying.com/article/24.aspx,[文章转载请注明出处!] 在 Unity 开发过程中,我们经常会使用到美术提供的图片文字(数字)来美化我们的 ...

  9. cyml

    bin/kafka-topics.sh --create --replication-factor 1 --partitions 1 --topic mc_logger2 --zookeeper lo ...

  10. WIN10系统如何使用传统WIN7开始菜单

    安装StartlsBack 默认按WIN键就可以回到WIN7的菜单了 右击WIN可以点击属性,详细设置菜单样式