diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 19ca53b1..acf3b9c7 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -245,6 +245,12 @@ ${revision} + + com.alibaba.cloud + spring-cloud-alibaba-commons + ${revision} + + com.alibaba.cloud diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml index b39b23ce..f659fb10 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml @@ -15,6 +15,11 @@ + + com.alibaba.cloud + spring-cloud-alibaba-commons + + org.springframework.boot spring-boot-starter-web diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java index c5ef1539..c80fba80 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/com/alibaba/cloud/dubbo/gateway/DubboGatewayServlet.java @@ -52,8 +52,8 @@ import org.springframework.util.StreamUtils; import org.springframework.web.servlet.HttpServletBean; import org.springframework.web.util.UriComponents; -import static org.apache.commons.lang.StringUtils.substringAfter; -import static org.apache.commons.lang.StringUtils.substringBetween; +import static com.alibaba.cloud.commons.StringUtils.substringAfter; +import static com.alibaba.cloud.commons.StringUtils.substringBetween; import static org.springframework.web.util.UriComponentsBuilder.fromUriString; @WebServlet(urlPatterns = "/dsc/*") diff --git a/spring-cloud-alibaba-starters/pom.xml b/spring-cloud-alibaba-starters/pom.xml index 1249b019..568ea018 100644 --- a/spring-cloud-alibaba-starters/pom.xml +++ b/spring-cloud-alibaba-starters/pom.xml @@ -27,6 +27,7 @@ spring-cloud-starter-alibaba-sentinel spring-cloud-alibaba-sentinel-datasource spring-cloud-alibaba-sentinel-gateway + spring-cloud-alibaba-commons diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/pom.xml new file mode 100644 index 00000000..73248d29 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/pom.xml @@ -0,0 +1,18 @@ + + + + com.alibaba.cloud + spring-cloud-alibaba-starters + ${revision} + ../pom.xml + + + 4.0.0 + + spring-cloud-alibaba-commons + Spring Cloud Alibaba Commons + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/StringUtils.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/StringUtils.java new file mode 100644 index 00000000..0bde79c9 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/StringUtils.java @@ -0,0 +1,372 @@ +/* + * Copyright 2013-2019 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 + * + * https://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 com.alibaba.cloud.commons; + +/** + * StringUtils. copy from apache common-lang3. + * + * @author theonefx + */ +public final class StringUtils { + + /** + * The empty String {@code ""}. + * + * @since 2.0 + */ + public static final String EMPTY = ""; + + /** + * Represents a failed index search. + * @since 2.1 + */ + public static final int INDEX_NOT_FOUND = -1; + + private StringUtils() { + } + + /** + *

+ * Checks if a CharSequence is empty ("") or null. + *

+ * + *
+	 * StringUtils.isEmpty(null)      = true
+	 * StringUtils.isEmpty("")        = true
+	 * StringUtils.isEmpty(" ")       = false
+	 * StringUtils.isEmpty("bob")     = false
+	 * StringUtils.isEmpty("  bob  ") = false
+	 * 
+ * + *

+ * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. + * That functionality is available in isBlank(). + *

+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is empty or null + * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) + */ + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; + } + + /** + *

+ * Checks if a CharSequence is not empty ("") and not null. + *

+ * + *
+	 * StringUtils.isNotEmpty(null)      = false
+	 * StringUtils.isNotEmpty("")        = false
+	 * StringUtils.isNotEmpty(" ")       = true
+	 * StringUtils.isNotEmpty("bob")     = true
+	 * StringUtils.isNotEmpty("  bob  ") = true
+	 * 
+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is not empty and not null + * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) + */ + public static boolean isNotEmpty(final CharSequence cs) { + return !isEmpty(cs); + } + + /** + *

+ * Checks if a CharSequence is whitespace, empty ("") or null. + *

+ * + *
+	 * StringUtils.isBlank(null)      = true
+	 * StringUtils.isBlank("")        = true
+	 * StringUtils.isBlank(" ")       = true
+	 * StringUtils.isBlank("bob")     = false
+	 * StringUtils.isBlank("  bob  ") = false
+	 * 
+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is null, empty or whitespace + */ + public static boolean isBlank(final CharSequence cs) { + if (cs == null || cs.length() == 0) { + return true; + } + int strLen = cs.length(); + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(cs.charAt(i))) { + return false; + } + } + return true; + } + + /** + *

+ * Checks if a CharSequence is not empty (""), not null and not whitespace only. + *

+ * + *

+ * Whitespace is defined by {@link Character#isWhitespace(char)}. + *

+ * + *
+	 * StringUtils.isNotBlank(null)      = false
+	 * StringUtils.isNotBlank("")        = false
+	 * StringUtils.isNotBlank(" ")       = false
+	 * StringUtils.isNotBlank("bob")     = true
+	 * StringUtils.isNotBlank("  bob  ") = true
+	 * 
+ * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is not empty and not null and not + * whitespace only + * @since 2.0 + * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) + */ + public static boolean isNotBlank(final CharSequence cs) { + return !isBlank(cs); + } + + // Trim + // ----------------------------------------------------------------------- + + /** + *

+ * Removes control characters (char <= 32) from both ends of this String, handling + * {@code null} by returning {@code null}. + *

+ * + *

+ * The String is trimmed using {@link String#trim()}. Trim removes start and end + * characters <= 32. + *

+ * + *
+	 * StringUtils.trim(null)          = null
+	 * StringUtils.trim("")            = ""
+	 * StringUtils.trim("     ")       = ""
+	 * StringUtils.trim("abc")         = "abc"
+	 * StringUtils.trim("    abc    ") = "abc"
+	 * 
+ * @param str the String to be trimmed, may be null + * @return the trimmed string, {@code null} if null String input + */ + public static String trim(final String str) { + return str == null ? null : str.trim(); + } + + // Equals + // ----------------------------------------------------------------------- + + /** + *

+ * Compares two CharSequences, returning {@code true} if they represent equal + * sequences of characters. + *

+ * + *

+ * {@code null}s are handled without exceptions. Two {@code null} references are + * considered to be equal. The comparison is case sensitive. + *

+ * + *
+	 * StringUtils.equals(null, null)   = true
+	 * StringUtils.equals(null, "abc")  = false
+	 * StringUtils.equals("abc", null)  = false
+	 * StringUtils.equals("abc", "abc") = true
+	 * StringUtils.equals("abc", "ABC") = false
+	 * 
+ * @param cs1 the first CharSequence, may be {@code null} + * @param cs2 the second CharSequence, may be {@code null} + * @return {@code true} if the CharSequences are equal (case-sensitive), or both + * {@code null} + * @see Object#equals(Object) + */ + public static boolean equals(final CharSequence cs1, final CharSequence cs2) { + if (cs1 == cs2) { + return true; + } + if (cs1 == null || cs2 == null) { + return false; + } + if (cs1 instanceof String && cs2 instanceof String) { + return cs1.equals(cs2); + } + return StringUtils.regionMatches(cs1, false, 0, cs2, 0, + Math.max(cs1.length(), cs2.length())); + } + + /** + * Green implementation of regionMatches. + * @param cs the {@code CharSequence} to be processed + * @param ignoreCase whether or not to be case insensitive + * @param thisStart the index to start on the {@code cs} CharSequence + * @param substring the {@code CharSequence} to be looked for + * @param start the index to start on the {@code substring} CharSequence + * @param length character length of the region + * @return whether the region matched + */ + public static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, + final int thisStart, final CharSequence substring, final int start, + final int length) { + if (cs instanceof String && substring instanceof String) { + return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, + start, length); + } + int index1 = thisStart; + int index2 = start; + int tmpLen = length; + + while (tmpLen-- > 0) { + final char c1 = cs.charAt(index1++); + final char c2 = substring.charAt(index2++); + + if (c1 == c2) { + continue; + } + + if (!ignoreCase) { + return false; + } + + // The same check as in String.regionMatches(): + if (Character.toUpperCase(c1) != Character.toUpperCase(c2) + && Character.toLowerCase(c1) != Character.toLowerCase(c2)) { + return false; + } + } + + return true; + } + + /** + *

+ * Gets the substring after the first occurrence of a separator. The separator is not + * returned. + *

+ * + *

+ * A null string input will return null. An empty ("") + * string input will return the empty string. A null separator will + * return the empty string if the input string is not null. + *

+ * + *

+ * If nothing is found, the empty string is returned. + *

+ * + *
+	 * StringUtils.substringAfter(null, *)      = null
+	 * StringUtils.substringAfter("", *)        = ""
+	 * StringUtils.substringAfter(*, null)      = ""
+	 * StringUtils.substringAfter("abc", "a")   = "bc"
+	 * StringUtils.substringAfter("abcba", "b") = "cba"
+	 * StringUtils.substringAfter("abc", "c")   = ""
+	 * StringUtils.substringAfter("abc", "d")   = ""
+	 * StringUtils.substringAfter("abc", "")    = "abc"
+	 * 
+ * @param str the String to get a substring from, may be null + * @param separator the String to search for, may be null + * @return the substring after the first occurrence of the separator, + * null if null String input + * @since 2.0 + */ + public static String substringAfter(String str, String separator) { + if (isEmpty(str)) { + return str; + } + if (separator == null) { + return EMPTY; + } + int pos = str.indexOf(separator); + if (pos == INDEX_NOT_FOUND) { + return EMPTY; + } + return str.substring(pos + separator.length()); + } + + // Substring between + // ----------------------------------------------------------------------- + /** + *

+ * Gets the String that is nested in between two instances of the same String. + *

+ * + *

+ * A null input String returns null. A null tag + * returns null. + *

+ * + *
+	 * StringUtils.substringBetween(null, *)            = null
+	 * StringUtils.substringBetween("", "")             = ""
+	 * StringUtils.substringBetween("", "tag")          = null
+	 * StringUtils.substringBetween("tagabctag", null)  = null
+	 * StringUtils.substringBetween("tagabctag", "")    = ""
+	 * StringUtils.substringBetween("tagabctag", "tag") = "abc"
+	 * 
+ * @param str the String containing the substring, may be null + * @param tag the String before and after the substring, may be null + * @return the substring, null if no match + * @since 2.0 + */ + public static String substringBetween(String str, String tag) { + return substringBetween(str, tag, tag); + } + + /** + *

+ * Gets the String that is nested in between two Strings. Only the first match is + * returned. + *

+ * + *

+ * A null input String returns null. A null + * open/close returns null (no match). An empty ("") open and close + * returns an empty string. + *

+ * + *
+	 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
+	 * StringUtils.substringBetween(null, *, *)          = null
+	 * StringUtils.substringBetween(*, null, *)          = null
+	 * StringUtils.substringBetween(*, *, null)          = null
+	 * StringUtils.substringBetween("", "", "")          = ""
+	 * StringUtils.substringBetween("", "", "]")         = null
+	 * StringUtils.substringBetween("", "[", "]")        = null
+	 * StringUtils.substringBetween("yabcz", "", "")     = ""
+	 * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
+	 * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
+	 * 
+ * @param str the String containing the substring, may be null + * @param open the String before the substring, may be null + * @param close the String after the substring, may be null + * @return the substring, null if no match + * @since 2.0 + */ + public static String substringBetween(String str, String open, String close) { + if (str == null || open == null || close == null) { + return null; + } + int start = str.indexOf(open); + if (start != INDEX_NOT_FOUND) { + int end = str.indexOf(close, start + open.length()); + if (end != INDEX_NOT_FOUND) { + return str.substring(start + open.length(), end); + } + } + return null; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml index 7f2550c2..080a35d0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/pom.xml @@ -15,6 +15,10 @@ Spring Cloud Alibaba Sentinel DataSource + + com.alibaba.cloud + spring-cloud-alibaba-commons + @@ -101,12 +105,6 @@ true - - org.apache.commons - commons-lang3 - true - - diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java index d9b51403..033a8769 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java @@ -16,9 +16,9 @@ package com.alibaba.cloud.sentinel.datasource.factorybean; +import com.alibaba.cloud.commons.StringUtils; import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.FactoryBean; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml index 1751f4fc..02a3c3e3 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/pom.xml @@ -14,6 +14,11 @@ + + com.alibaba.cloud + spring-cloud-alibaba-commons + + org.springframework.boot spring-boot-actuator diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java index 82cdd317..1922586e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/ribbon/NacosRule.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; +import com.alibaba.cloud.commons.StringUtils; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.nacos.api.naming.NamingService; @@ -28,7 +29,6 @@ import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.DynamicServerListLoadBalancer; import com.netflix.loadbalancer.Server; -import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory;