zoukankan      html  css  js  c++  java
  • 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的服务

  • 相关阅读:
    Python for Infomatics 第14章 数据库和SQL应用四(译)
    展望2017
    bing的简单英文字典工具
    自我安慰
    Python for Infomatics 第14章 数据库和SQL应用三(译)
    Python for Infomatics 第14章 数据库和SQL应用二(译)
    Python for Infomatics 第14章 数据库和SQL应用一(译)
    希望父亲早日恢复
    Python for Infomatics 第13章 网页服务四(译)
    Python for Infomatics 第13章 网页服务三(译)
  • 原文地址:https://www.cnblogs.com/flying607/p/9204427.html
Copyright © 2011-2022 走看看