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的服务

  • 相关阅读:
    Linux之nginx服务
    设计模式-总结
    linux rabbitmq 远程登录
    swagger常用注解
    nginx总结
    mysql-sql
    dubbo-文档
    JVM总结-Java语法糖与Java编译器
    JVM总结-synchronized
    JVM总结-java内存模型
  • 原文地址:https://www.cnblogs.com/flying607/p/9204427.html
Copyright © 2011-2022 走看看