From cd70fb5023dca9a27a38eb3c640cf31a55023e4c Mon Sep 17 00:00:00 2001 From: durigon Date: Thu, 20 Sep 2018 09:40:39 +0900 Subject: [PATCH] Refactor String#replaceAll (#3199) If we repeatedly call String#replaceAll, we internally repeatedly call the regular expression pattern compilation every time as following: ```java public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement); } ``` The modifications are to keep the compiled pattern. Therefore, compiling a relatively expensive regular expression pattern does not have to be done every time. --- .../cloud/netflix/zuul/filters/ProxyRequestHelper.java | 9 +++++++-- .../filters/discovery/PatternServiceRouteMapper.java | 4 +++- .../netflix/zuul/filters/pre/PreDecorationFilter.java | 5 ++++- .../zuul/filters/route/SimpleHostRoutingFilter.java | 7 +++++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java index dc9c163ec..0a5fd7cdb 100644 --- a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java +++ b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java @@ -27,6 +27,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.regex.Pattern; import java.util.Set; import javax.servlet.http.HttpServletRequest; @@ -63,6 +64,10 @@ public class ProxyRequestHelper { */ public static final String IGNORED_HEADERS = "ignoredHeaders"; + public static final Pattern FORM_FEED_PATTERN = Pattern.compile("\f"); + + public static final Pattern COLON_PATTERN = Pattern.compile(":"); + private Set ignoredHeaders = new LinkedHashSet<>(); private Set sensitiveHeaders = new LinkedHashSet<>(); @@ -283,11 +288,11 @@ public class ProxyRequestHelper { // if form feed is already part of param name double // since form feed is used as the colon replacement below if (key.contains("\f")) { - key = (key.replaceAll("\f", "\f\f")); + key = (FORM_FEED_PATTERN.matcher(key).replaceAll("\f\f")); } // colon is special to UriTemplate if (key.contains(":")) { - key = key.replaceAll(":", "\f"); + key = COLON_PATTERN.matcher(key).replaceAll("\f"); } key = key + i; singles.put(key, value); diff --git a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/discovery/PatternServiceRouteMapper.java b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/discovery/PatternServiceRouteMapper.java index 1b6de7183..7e80ca5c8 100644 --- a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/discovery/PatternServiceRouteMapper.java +++ b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/discovery/PatternServiceRouteMapper.java @@ -21,6 +21,8 @@ import org.springframework.util.StringUtils; */ public class PatternServiceRouteMapper implements ServiceRouteMapper { + private static final Pattern MULTIPLE_SLASH_PATTERN = Pattern.compile("/{2,}"); + /** * A RegExp Pattern that extract needed information from a service ID. Ex : * "(?.*)-(?v.*$)" @@ -60,7 +62,7 @@ public class PatternServiceRouteMapper implements ServiceRouteMapper { * @return */ private String cleanRoute(final String route) { - String routeToClean = route.replaceAll("/{2,}", "/"); + String routeToClean = MULTIPLE_SLASH_PATTERN.matcher(route).replaceAll("/"); if (routeToClean.startsWith("/")) { routeToClean = routeToClean.substring(1); } diff --git a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java index 846535713..5ff66507f 100644 --- a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java +++ b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java @@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.zuul.filters.pre; import java.net.MalformedURLException; import java.net.URL; +import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; @@ -70,6 +71,8 @@ public class PreDecorationFilter extends ZuulFilter { @Deprecated public static final int FILTER_ORDER = PRE_DECORATION_FILTER_ORDER; + public static final Pattern DOUBLE_SLASH = Pattern.compile("//"); + private RouteLocator routeLocator; private String dispatcherServletPath; @@ -185,7 +188,7 @@ public class PreDecorationFilter extends ZuulFilter { fallBackUri = "/" + fallBackUri; } String forwardURI = fallbackPrefix + fallBackUri; - forwardURI = forwardURI.replaceAll("//", "/"); + forwardURI = DOUBLE_SLASH.matcher(forwardURI).replaceAll("/"); ctx.set(FORWARD_TO_KEY, forwardURI); } return null; diff --git a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java index 4ccc58529..161b8991e 100644 --- a/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java +++ b/spring-cloud-netflix-zuul/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java @@ -22,6 +22,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import java.util.Timer; import java.util.TimerTask; @@ -85,6 +86,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter { private static final Log log = LogFactory.getLog(SimpleHostRoutingFilter.class); + private static final Pattern MULTIPLE_SLASH_PATTERN = Pattern.compile("/{2,}"); + private final Timer connectionManagerTimer = new Timer( "SimpleHostRoutingFilter.connectionManagerTimer", true); @@ -286,7 +289,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter { requestEntity); URL host = RequestContext.getCurrentContext().getRouteHost(); HttpHost httpHost = getHttpHost(host); - uri = StringUtils.cleanPath((host.getPath() + uri).replaceAll("/{2,}", "/")); + uri = StringUtils.cleanPath(MULTIPLE_SLASH_PATTERN.matcher(host.getPath() + uri).replaceAll("/")); long contentLength = getContentLength(request); ContentType contentType = null; @@ -449,4 +452,4 @@ public class SimpleHostRoutingFilter extends ZuulFilter { } return request.getContentLength(); } -} \ No newline at end of file +}