Spring Cloud Edgware SR3 让Zuul支持形如 /xxx和/xxx/yyy 格式的路径配置

在包路径:org.springframework.cloud.netflix.zuul.filters 下,新建类SimpleRouteLocator,取代jar包中的类。内容如下:

  1 /*
  2  * Copyright 2013-2014 the original author or authors.
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16
 17 package org.springframework.cloud.netflix.zuul.filters;
 18
 19 import java.util.ArrayList;
 20 import java.util.Collection;
 21 import java.util.LinkedHashMap;
 22 import java.util.List;
 23 import java.util.Map;
 24 import java.util.Map.Entry;
 25 import java.util.concurrent.atomic.AtomicReference;
 26 import org.apache.commons.logging.Log;
 27 import org.apache.commons.logging.LogFactory;
 28 import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
 29 import org.springframework.cloud.netflix.zuul.util.RequestUtils;
 30 import org.springframework.core.Ordered;
 31 import org.springframework.util.AntPathMatcher;
 32 import org.springframework.util.PathMatcher;
 33 import org.springframework.util.StringUtils;
 34
 35 /**
 36  * Simple {@link RouteLocator} based on configuration data held in {@link ZuulProperties}.
 37  *
 38  * @author Dave Syer
 39  */
 40 public class SimpleRouteLocator implements RouteLocator, Ordered {
 41
 42     private static final Log log = LogFactory.getLog(SimpleRouteLocator.class);
 43
 44     private static final int DEFAULT_ORDER = 0;
 45
 46     private ZuulProperties properties;
 47
 48     private PathMatcher pathMatcher = new AntPathMatcher();
 49
 50     private String dispatcherServletPath = "/";
 51     private String zuulServletPath;
 52
 53     private AtomicReference<Map<String, ZuulRoute>> routes = new AtomicReference<>();
 54     private int order = DEFAULT_ORDER;
 55
 56     public SimpleRouteLocator(String servletPath, ZuulProperties properties) {
 57         this.properties = properties;
 58         if (StringUtils.hasText(servletPath)) {
 59             this.dispatcherServletPath = servletPath;
 60         }
 61
 62         this.zuulServletPath = properties.getServletPath();
 63     }
 64
 65     @Override
 66     public List<Route> getRoutes() {
 67         List<Route> values = new ArrayList<>();
 68         for (Entry<String, ZuulRoute> entry : getRoutesMap().entrySet()) {
 69             ZuulRoute route = entry.getValue();
 70             String path = route.getPath();
 71             values.add(getRoute(route, path));
 72         }
 73         return values;
 74     }
 75
 76     @Override
 77     public Collection<String> getIgnoredPaths() {
 78         return this.properties.getIgnoredPatterns();
 79     }
 80
 81     @Override
 82     public Route getMatchingRoute(final String path) {
 83
 84         return getSimpleMatchingRoute(path);
 85
 86     }
 87
 88     protected Map<String, ZuulRoute> getRoutesMap() {
 89         if (this.routes.get() == null) {
 90             this.routes.set(locateRoutes());
 91         }
 92         return this.routes.get();
 93     }
 94
 95     protected Route getSimpleMatchingRoute(final String path) {
 96         if (log.isDebugEnabled()) {
 97             log.debug("Finding route for path: " + path);
 98         }
 99
100         // This is called for the initialization done in getRoutesMap()
101         getRoutesMap();
102
103         if (log.isDebugEnabled()) {
104             log.debug("servletPath=" + this.dispatcherServletPath);
105             log.debug("zuulServletPath=" + this.zuulServletPath);
106             log.debug("RequestUtils.isDispatcherServletRequest()="
107                     + RequestUtils.isDispatcherServletRequest());
108             log.debug("RequestUtils.isZuulServletRequest()="
109                     + RequestUtils.isZuulServletRequest());
110         }
111
112         String adjustedPath = adjustPath(path);
113
114         ZuulRoute route = getZuulRoute(adjustedPath);
115
116         return getRoute(route, adjustedPath);
117     }
118
119     protected ZuulRoute getZuulRoute(String adjustedPath) {
120         if (!matchesIgnoredPatterns(adjustedPath)) {
121             //2018年6月20日 刘宇祥:支持优先精确匹配-----start
122             Map m = (Map)this.routes.get();
123             ZuulRoute z = (ZuulRoute)m.get(adjustedPath);
124             if(z!=null){
125                 return z;
126             }
127             //2018年6月20日 刘宇祥:支持优先精确匹配-----end
128
129             for (Entry<String, ZuulRoute> entry : getRoutesMap().entrySet()) {
130                 String pattern = entry.getKey();
131                 log.debug("Matching pattern:" + pattern);
132                 if (this.pathMatcher.match(pattern, adjustedPath)) {
133                     return entry.getValue();
134                 }
135             }
136         }
137         return null;
138     }
139
140     protected Route getRoute(ZuulRoute route, String path) {
141         if (route == null) {
142             return null;
143         }
144         if (log.isDebugEnabled()) {
145             log.debug("route matched=" + route);
146         }
147         String targetPath = path;
148         String prefix = this.properties.getPrefix();
149         if(prefix.endsWith("/")) {
150             prefix = prefix.substring(0, prefix.length() - 1);
151         }
152         if (path.startsWith(prefix + "/") && this.properties.isStripPrefix()) {
153             targetPath = path.substring(prefix.length());
154         }
155
156         if (route.isStripPrefix()) {
157             int index = route.getPath().indexOf("*") - 1;
158             if (index > 0) {
159                 String routePrefix = route.getPath().substring(0, index);
160                 targetPath = targetPath.replaceFirst(routePrefix, "");
161                 prefix = prefix + routePrefix;
162             }
163
164             //2018年6月20日 刘宇祥:支持形如/xxx/bbb 而非/xxx/**的routes-----start
165             else{
166
167                 String routePath = route.getPath();
168                 targetPath = routePath.substring(routePath.lastIndexOf("/"));
169                 prefix = prefix + routePath.substring(0,routePath.lastIndexOf("/"));
170             }
171             //2018年6月20日 刘宇祥:支持形如/xxx/bbb 而非/xxx/**的routes-----end
172         }
173         Boolean retryable = this.properties.getRetryable();
174         if (route.getRetryable() != null) {
175             retryable = route.getRetryable();
176         }
177         return new Route(route.getId(), targetPath, route.getLocation(), prefix,
178                 retryable,
179                 route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null,
180                 route.isStripPrefix());
181     }
182
183     /**
184      * Calculate all the routes and set up a cache for the values. Subclasses can call
185      * this method if they need to implement {@link RefreshableRouteLocator}.
186      */
187     protected void doRefresh() {
188         this.routes.set(locateRoutes());
189     }
190
191     /**
192      * Compute a map of path pattern to route. The default is just a static map from the
193      * {@link ZuulProperties}, but subclasses can add dynamic calculations.
194      */
195     protected Map<String, ZuulRoute> locateRoutes() {
196         LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<String, ZuulRoute>();
197         for (ZuulRoute route : this.properties.getRoutes().values()) {
198             routesMap.put(route.getPath(), route);
199         }
200         return routesMap;
201     }
202
203     protected boolean matchesIgnoredPatterns(String path) {
204         for (String pattern : this.properties.getIgnoredPatterns()) {
205             log.debug("Matching ignored pattern:" + pattern);
206             if (this.pathMatcher.match(pattern, path)) {
207                 log.debug("Path " + path + " matches ignored pattern " + pattern);
208                 return true;
209             }
210         }
211         return false;
212     }
213
214     private String adjustPath(final String path) {
215         String adjustedPath = path;
216
217         if (RequestUtils.isDispatcherServletRequest()
218                 && StringUtils.hasText(this.dispatcherServletPath)) {
219             if (!this.dispatcherServletPath.equals("/")) {
220                 adjustedPath = path.substring(this.dispatcherServletPath.length());
221                 log.debug("Stripped dispatcherServletPath");
222             }
223         }
224         else if (RequestUtils.isZuulServletRequest()) {
225             if (StringUtils.hasText(this.zuulServletPath)
226                     && !this.zuulServletPath.equals("/")) {
227                 adjustedPath = path.substring(this.zuulServletPath.length());
228                 log.debug("Stripped zuulServletPath");
229             }
230         }
231         else {
232             // do nothing
233         }
234
235         log.debug("adjustedPath=" + adjustedPath);
236         return adjustedPath;
237     }
238
239     @Override
240     public int getOrder() {
241         return order;
242     }
243
244     public void setOrder(int order) {
245         this.order = order;
246     }
247
248 }

其中的164-171行,让zuul支持了如下配置:

zuul:
  routes:
    all:
      path: /vod2/two
      serviceId: all
    one:
      path: /vod1/one
      serviceId: one

通过/vod2/two路径,可以访问到 /all/two

注意,测试时不存在名为vod2和vod1的服务

原文地址:https://www.cnblogs.com/flying607/p/9204427.html

时间: 2024-10-08 10:57:59

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 Finchley.SR1 1.1.Eureka Server ureka Server 依赖更新 升级前: <dependency> <groupId>org.springframework.cloud</groupId> <artifact

spring cloud:Edgware.RELEASE版本hystrix超时新坑

升级到Edgware.RELEASE发现,zuul中不管如何设置hystrix的超时时间均不起作用,仍然是默认的1000ms.  降回低版本后正常,但是低版本的fallback方法中,又拿不到详细异常信息,最终暂时在Edgware.RELEASE中,将hystrix的超时关掉,参考以下配置: ribbon: ReadTimeout: 5000 ConnectTimeout: 5000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 1 hystrix: c

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

前言: 最近开发了Zuul网关的实现和Spring Cloud Gateway实现,对比Spring Cloud Gateway发现后者性能好支持场景也丰富.在高并发或者复杂的分布式下,后者限流和自定义拦截也很棒. 提示: 本文主要列出本人开发的Zuul网关核心代码以及Spring Cloud Gateway核心代码实现.因为本人技术有限,主要是参照了 Spring Cloud Gateway 如有不足之处还请见谅并留言指出. 1:为什么要做网关 (1)网关层对外部和内部进行了隔离,保障了后台服

spring cloud 学习笔记--网关zuul学习

微服务是多个服务共同完成一件事情,那么"一致对外"就很有必要,就像我们去买面包,不可能先去找农民买小麦,再.... 盗图 spring cloud 引入zuul方式来实现这一功能 添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </depend

Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)

通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现>一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBalancerClient接口来获取某个服务的具体实例,并根据实例信息来发起服务接口消费请求.但是这样的做法需要我们手工的去编写服务选取.链接拼接等繁琐的工作,对于开发人员来说非常的不友好.所以接下来,我们再来看看除此之外,还支持哪些其他的服务消费方式. 使用RestTemplate 在之前的例子中,已经使用过R

Spring Cloud之搭建动态Zuul网关路由转发

传统方式将路由规则配置在配置文件中,如果路由规则发生了改变,需要重启服务器.这时候我们结合上节课内容整合SpringCloud Config分布式配置中心,实现动态路由规则. 将yml的内容粘贴到码云上: ###注册 中心 eureka: client: serviceUrl: defaultZone: http://localhost:8100/eureka/ server: ##api网关端口号 port: 80 ###网关名称 spring: ##网关服务名称 application: n

Spring Cloud微服务架构实现+Guava缓存+redis+数据库设计+微服务原理改造房产销售

Spring Cloud微服务架构实现+Guava缓存+redis+数据库设计+微服务原理改造房产销售 一.分布式服务框架的发展 1.1 第一代服务框架 代表:Dubbo(Java).Orleans(.Net)等 特点:和语言绑定紧密 1.2 第二代服务框架 代表:Spring Cloud等 现状:适合混合式开发(例如借助Steeltoe OSS可以让ASP.Net Core与Spring Cloud集成),正值当年 1.3 第三代服务框架 代表:Service Mesh(服务网格) => 例如

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

前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka-ribbon和eureka-feign的实现. 参考 eureka-server eureka-client eureka-ribbon eureka-feign 概念 Spring Cloud Gateway是Spring Cloud的一个新项目,该项目是基于Spring5.0,Sprint B

Spring cloud整体框架

研究了一段时间spring boot了准备向spirng cloud进发,公司架构和项目也全面拥抱了Spring Cloud.在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统构建的要求,使我们以非常低的成本(技术或者硬件)搭建一套高效.分布式.容错的平台,但Spring Cloud也不是没有缺点,小型独立的项目不适合使用,另外对分布式事物的支持暂时也没有. Spring Cloud是什么鬼? Spring Cloud是一个基于Spring Boot实现的云应用开发工具,