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进行集中认 ...
随机推荐
- [Link]Hive资料整理
Hive SQL的编译过程 Hive学习分享 IBM Hive
- vim去除行显示;vim全部复制命令
行显示和隐藏: set nu set nu! 直接上命令: ggVG*y 解释一下上面的命令: ggVG ——全选 *y —— 复制到剪贴板 gg 是光标定位到文件首行 V 是进入可视模式 G ...
- Gas Station leetcode java
题目: There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. ...
- JavaScript中textRange对象使用方法总结
TextRange对象是动态HTML(DHTML)的高级特性,使用它可以实现很多和文本有关的任务,例如搜索和选择文本.文本范围让您可以选择性的将字符.单词和句子从文档中挑选出来.TextRange对象 ...
- VB.NET,C#.NET调用Web Service,利用visual studio 的实现方法
下面是一篇文章比较详细,其实具体操作很简单,把Web Service服务地址,利用工具(VS2010),通过添加引用的形式,添加到项目中来就可以应用了. 大家如果这个地方不会操场的话,可以问问我QQ: ...
- Android studio安装配置常见问题及其解决方案
Android studio 是目前android公司主推的一款开发工具,相比较以前eclipse,它自己内部就集成了SDK等,方便开发.这几天我也尝试从官网下载了一个android studio进行 ...
- Laravel学习笔记之Session源码解析(上)
说明:本文主要通过学习Laravel的session源码学习Laravel是如何设计session的,将自己的学习心得分享出来,希望对别人有所帮助.Laravel在web middleware中定义了 ...
- Android -- ADT变化&aar&Lint
Switch Case switch case 常用的使用方法: switch(v.getId()){ case R.id.btn1: doClick1(); break; } 在ADT中的改变 在正 ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二十七):kafka manager安装
一.kafka-manager简介 为了简化开发者和服务工程师维护Kafka集群的工作,yahoo构建了一个叫做Kafka管理器的基于Web工具,叫做 Kafka Manager.这个管理工具可以很容 ...
- FPS游戏服务器设计的问题 【转】
一.追溯 去gameloft笔试,有一个题目是说: 叫你去设计一个FPS(第一人称射击游戏),你是要用TCP呢还是要用UDP,说明理由 . 二.学习 这是两篇网上找到的文章,写非常不错. 当时笔试的时 ...