m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ m.put(StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1);
+ m.put(StandardCharsets.US_ASCII.name(), StandardCharsets.US_ASCII);
+ m.put(StandardCharsets.UTF_16.name(), StandardCharsets.UTF_16);
+ m.put(StandardCharsets.UTF_16BE.name(), StandardCharsets.UTF_16BE);
+ m.put(StandardCharsets.UTF_16LE.name(), StandardCharsets.UTF_16LE);
+ m.put(StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8);
+ return Collections.unmodifiableSortedMap(m);
+ }
+
+ /**
+ * Returns the given Charset or the default Charset if the given Charset is null.
+ * @param charset A charset or null.
+ * @return the given Charset or the default Charset if the given Charset is null
+ */
+ public static Charset toCharset(final Charset charset) {
+ return charset == null ? Charset.defaultCharset() : charset;
+ }
+
+ /**
+ * Returns a Charset for the named charset. If the name is null, return the default
+ * Charset.
+ * @param charset The name of the requested charset, may be null.
+ * @return a Charset for the named charset
+ * @throws java.nio.charset.UnsupportedCharsetException If the named charset is
+ * unavailable
+ */
+ public static Charset toCharset(final String charset) {
+ return charset == null ? Charset.defaultCharset() : Charset.forName(charset);
+ }
+
+ /**
+ * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
+ *
+ * Every implementation of the Java platform is required to support this character
+ * encoding.
+ *
+ *
+ * @see Standard
+ * charsets
+ * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ */
+ @Deprecated
+ public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
+
+ /**
+ *
+ * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of
+ * the Unicode character set.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character
+ * encoding.
+ *
+ *
+ * @see Standard
+ * charsets
+ * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ */
+ @Deprecated
+ public static final Charset US_ASCII = StandardCharsets.US_ASCII;
+
+ /**
+ *
+ * Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory
+ * initial byte-order mark (either order accepted on input, big-endian used on output)
+ *
+ *
+ * Every implementation of the Java platform is required to support this character
+ * encoding.
+ *
+ *
+ * @see Standard
+ * charsets
+ * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ */
+ @Deprecated
+ public static final Charset UTF_16 = StandardCharsets.UTF_16;
+
+ /**
+ *
+ * Sixteen-bit Unicode Transformation Format, big-endian byte order.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character
+ * encoding.
+ *
+ *
+ * @see Standard
+ * charsets
+ * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ */
+ @Deprecated
+ public static final Charset UTF_16BE = StandardCharsets.UTF_16BE;
+
+ /**
+ *
+ * Sixteen-bit Unicode Transformation Format, little-endian byte order.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character
+ * encoding.
+ *
+ *
+ * @see Standard
+ * charsets
+ * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ */
+ @Deprecated
+ public static final Charset UTF_16LE = StandardCharsets.UTF_16LE;
+
+ /**
+ *
+ * Eight-bit Unicode Transformation Format.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character
+ * encoding.
+ *
+ *
+ * @see Standard
+ * charsets
+ * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ */
+ @Deprecated
+ public static final Charset UTF_8 = StandardCharsets.UTF_8;
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/FileUtils.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/FileUtils.java
new file mode 100644
index 000000000..0635edce2
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/FileUtils.java
@@ -0,0 +1,113 @@
+/*
+ * 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.io;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+/**
+ * FileUtils. copy from apache commons-io.
+ *
+ * @author theonefx
+ */
+public final class FileUtils {
+
+ private FileUtils() {
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Opens a {@link java.io.FileInputStream} for the specified file, providing better
+ * error messages than simply calling new FileInputStream(file)
.
+ *
+ * At the end of the method either the stream will be successfully opened, or an
+ * exception will have been thrown.
+ *
+ * An exception is thrown if the file does not exist. An exception is thrown if the
+ * file object exists but is a directory. An exception is thrown if the file exists
+ * but cannot be read.
+ * @param file the file to open for input, must not be {@code null}
+ * @return a new {@link java.io.FileInputStream} for the specified file
+ * @throws java.io.FileNotFoundException if the file does not exist
+ * @throws IOException if the file object is a directory
+ * @throws IOException if the file cannot be read
+ * @since 1.3
+ */
+ public static FileInputStream openInputStream(final File file) throws IOException {
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ throw new IOException("File '" + file + "' exists but is a directory");
+ }
+ if (!file.canRead()) {
+ throw new IOException("File '" + file + "' cannot be read");
+ }
+ }
+ else {
+ throw new FileNotFoundException("File '" + file + "' does not exist");
+ }
+ return new FileInputStream(file);
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Reads the contents of a file into a String. The file is always closed.
+ * @param file the file to read, must not be {@code null}
+ * @param encoding the encoding to use, {@code null} means platform default
+ * @return the file contents, never {@code null}
+ * @throws IOException in case of an I/O error
+ */
+ public static String readFileToString(final File file, final Charset encoding)
+ throws IOException {
+ try (InputStream in = openInputStream(file)) {
+ return IOUtils.toString(in, Charsets.toCharset(encoding));
+ }
+ }
+
+ /**
+ * Reads the contents of a file into a String. The file is always closed.
+ * @param file the file to read, must not be {@code null}
+ * @param encoding the encoding to use, {@code null} means platform default
+ * @return the file contents, never {@code null}
+ * @throws java.io.IOException in case of an I/O error
+ * @throws java.nio.charset.UnsupportedCharsetException thrown instead of
+ * {@link java.io .UnsupportedEncodingException} in version 2.2 if the encoding is not
+ * supported.
+ */
+ public static String readFileToString(final File file, final String encoding)
+ throws IOException {
+ return readFileToString(file, Charsets.toCharset(encoding));
+ }
+
+ /**
+ * Reads the contents of a file into a String using the default encoding for the VM.
+ * The file is always closed.
+ * @param file the file to read, must not be {@code null}
+ * @return the file contents, never {@code null}
+ * @throws IOException in case of an I/O error
+ * @deprecated 2.5 use {@link #readFileToString(File, String)} instead (and specify
+ * the appropriate encoding)
+ */
+ @Deprecated
+ public static String readFileToString(final File file) throws IOException {
+ return readFileToString(file, Charset.defaultCharset());
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/IOUtils.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/IOUtils.java
new file mode 100644
index 000000000..85f61c5df
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/IOUtils.java
@@ -0,0 +1,233 @@
+/*
+ * 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.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.charset.Charset;
+
+/**
+ * The IOUtils. copy from apache commons-io.
+ *
+ * @author theonefx
+ */
+public final class IOUtils {
+
+ /**
+ * Represents the end-of-file (or stream).
+ * @since 2.5 (made public)
+ */
+ public static final int EOF = -1;
+
+ /**
+ * The default buffer size ({@value}) to use for.
+ * {@link #copyLarge(InputStream, java.io.OutputStream)} and
+ * {@link #copyLarge(Reader, Writer)}
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ private IOUtils() {
+
+ }
+
+ /**
+ * Gets the contents of an InputStream
as a String using the specified
+ * character encoding.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream
.
+ *
+ * @param input the InputStream
to read from
+ * @param encoding the encoding to use, null means platform default
+ * @return the requested String
+ * @throws NullPointerException if the input is null
+ * @throws java.io.IOException if an I/O error occurs
+ * @since 2.3
+ */
+ public static String toString(final InputStream input, final Charset encoding)
+ throws IOException {
+ try (StringBuilderWriter sw = new StringBuilderWriter()) {
+ copy(input, sw, encoding);
+ return sw.toString();
+ }
+ }
+
+ // copy from Reader
+ // -----------------------------------------------------------------------
+
+ /**
+ * Copies chars from a Reader
to a Writer
.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedReader
.
+ *
+ * Large streams (over 2GB) will return a chars copied value of -1
after
+ * the copy has completed since the correct number of chars cannot be returned as an
+ * int. For large streams use the copyLarge(Reader, Writer)
method.
+ * @param input the Reader
to read from
+ * @param output the Writer
to write to
+ * @return the number of characters copied, or -1 if > Integer.MAX_VALUE
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 1.1
+ */
+ public static int copy(final Reader input, final Writer output) throws IOException {
+ final long count = copyLarge(input, output);
+ if (count > Integer.MAX_VALUE) {
+ return -1;
+ }
+ return (int) count;
+ }
+
+ /**
+ * Copies bytes from an InputStream
to chars on a Writer
+ * using the specified character encoding.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream
.
+ *
+ * This method uses {@link java.io.InputStreamReader}.
+ * @param input the InputStream
to read from
+ * @param output the Writer
to write to
+ * @param inputEncoding the encoding to use for the input stream, null means platform
+ * default
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 2.3
+ */
+ public static void copy(final InputStream input, final Writer output,
+ final Charset inputEncoding) throws IOException {
+ final InputStreamReader in = new InputStreamReader(input,
+ Charsets.toCharset(inputEncoding));
+ copy(in, output);
+ }
+
+ /**
+ * Copies bytes from an InputStream
to an OutputStream
using
+ * an internal buffer of the given size.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream
.
+ *
+ * @param input the InputStream
to read from
+ * @param output the OutputStream
to write to
+ * @param bufferSize the bufferSize used to copy from the input to the output
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 2.5
+ */
+ public static long copy(final InputStream input, final OutputStream output,
+ final int bufferSize) throws IOException {
+ return copyLarge(input, output, new byte[bufferSize]);
+ }
+
+ /**
+ * Copies chars from a large (over 2GB) Reader
to a Writer
.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedReader
.
+ *
+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+ * @param input the Reader
to read from
+ * @param output the Writer
to write to
+ * @return the number of characters copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 1.3
+ */
+ public static long copyLarge(final Reader input, final Writer output)
+ throws IOException {
+ return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]);
+ }
+
+ /**
+ * Copies chars from a large (over 2GB) Reader
to a Writer
.
+ *
+ * This method uses the provided buffer, so there is no need to use a
+ * BufferedReader
.
+ *
+ * @param input the Reader
to read from
+ * @param output the Writer
to write to
+ * @param buffer the buffer to be used for the copy
+ * @return the number of characters copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 2.2
+ */
+ public static long copyLarge(final Reader input, final Writer output,
+ final char[] buffer) throws IOException {
+ long count = 0;
+ int n;
+ while (EOF != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * Copies bytes from a large (over 2GB) InputStream
to an
+ * OutputStream
.
+ *
+ * This method buffers the input internally, so there is no need to use a
+ * BufferedInputStream
.
+ *
+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+ * @param input the InputStream
to read from
+ * @param output the OutputStream
to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 1.3
+ */
+ public static long copyLarge(final InputStream input, final OutputStream output)
+ throws IOException {
+ return copy(input, output, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * Copies bytes from a large (over 2GB) InputStream
to an
+ * OutputStream
.
+ *
+ * This method uses the provided buffer, so there is no need to use a
+ * BufferedInputStream
.
+ *
+ * @param input the InputStream
to read from
+ * @param output the OutputStream
to write to
+ * @param buffer the buffer to use for the copy
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 2.2
+ */
+ public static long copyLarge(final InputStream input, final OutputStream output,
+ final byte[] buffer) throws IOException {
+ long count = 0;
+ int n;
+ while (EOF != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/StringBuilderWriter.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/StringBuilderWriter.java
new file mode 100644
index 000000000..9a0578162
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/io/StringBuilderWriter.java
@@ -0,0 +1,152 @@
+/*
+ * 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.io;
+
+import java.io.Serializable;
+import java.io.Writer;
+
+/**
+ * Copy from apache commons-io.
+ *
+ * @author theonefx
+ */
+public class StringBuilderWriter extends Writer implements Serializable {
+
+ private static final long serialVersionUID = -146927496096066153L;
+
+ private final StringBuilder builder;
+
+ /**
+ * Constructs a new {@link StringBuilder} instance with default capacity.
+ */
+ public StringBuilderWriter() {
+ this.builder = new StringBuilder();
+ }
+
+ /**
+ * Constructs a new {@link StringBuilder} instance with the specified capacity.
+ * @param capacity The initial capacity of the underlying {@link StringBuilder}
+ */
+ public StringBuilderWriter(final int capacity) {
+ this.builder = new StringBuilder(capacity);
+ }
+
+ /**
+ * Constructs a new instance with the specified {@link StringBuilder}.
+ *
+ *
+ * If {@code builder} is null a new instance with default capacity will be created.
+ *
+ * @param builder The String builder. May be null.
+ */
+ public StringBuilderWriter(final StringBuilder builder) {
+ this.builder = builder != null ? builder : new StringBuilder();
+ }
+
+ /**
+ * Appends a single character to this Writer.
+ * @param value The character to append
+ * @return This writer instance
+ */
+ @Override
+ public Writer append(final char value) {
+ builder.append(value);
+ return this;
+ }
+
+ /**
+ * Appends a character sequence to this Writer.
+ * @param value The character to append
+ * @return This writer instance
+ */
+ @Override
+ public Writer append(final CharSequence value) {
+ builder.append(value);
+ return this;
+ }
+
+ /**
+ * Appends a portion of a character sequence to the {@link StringBuilder}.
+ * @param value The character to append
+ * @param start The index of the first character
+ * @param end The index of the last character + 1
+ * @return This writer instance
+ */
+ @Override
+ public Writer append(final CharSequence value, final int start, final int end) {
+ builder.append(value, start, end);
+ return this;
+ }
+
+ /**
+ * Closing this writer has no effect.
+ */
+ @Override
+ public void close() {
+ // no-op
+ }
+
+ /**
+ * Flushing this writer has no effect.
+ */
+ @Override
+ public void flush() {
+ // no-op
+ }
+
+ /**
+ * Writes a String to the {@link StringBuilder}.
+ * @param value The value to write
+ */
+ @Override
+ public void write(final String value) {
+ if (value != null) {
+ builder.append(value);
+ }
+ }
+
+ /**
+ * Writes a portion of a character array to the {@link StringBuilder}.
+ * @param value The value to write
+ * @param offset The index of the first character
+ * @param length The number of characters to write
+ */
+ @Override
+ public void write(final char[] value, final int offset, final int length) {
+ if (value != null) {
+ builder.append(value, offset, length);
+ }
+ }
+
+ /**
+ * Returns the underlying builder.
+ * @return The underlying builder
+ */
+ public StringBuilder getBuilder() {
+ return builder;
+ }
+
+ /**
+ * Returns {@link StringBuilder#toString()}.
+ * @return The contents of the String builder.
+ */
+ @Override
+ public String toString() {
+ return builder.toString();
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/lang/StringUtils.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/lang/StringUtils.java
new file mode 100644
index 000000000..d9c151361
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-commons/src/main/java/com/alibaba/cloud/commons/lang/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.lang;
+
+/**
+ * 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 3316d7bd8..080a35d00 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
+
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 d9b514038..a0b85d55a 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.lang.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-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java
index 1053c3679..f985984ee 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/SentinelConverterTests.java
@@ -19,13 +19,13 @@ package com.alibaba.cloud.sentinel.datasource;
import java.io.IOException;
import java.util.List;
+import com.alibaba.cloud.commons.io.FileUtils;
import com.alibaba.cloud.sentinel.datasource.converter.JsonConverter;
import com.alibaba.cloud.sentinel.datasource.converter.XmlConverter;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
-import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.springframework.util.ResourceUtils;
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigManager.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigManager.java
index e8199832d..e27b3e06b 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigManager.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigManager.java
@@ -18,8 +18,6 @@ package com.alibaba.cloud.nacos;
import java.util.Objects;
-import javax.annotation.PreDestroy;
-
import com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureException;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
@@ -75,14 +73,6 @@ public class NacosConfigManager {
return service;
}
- @PreDestroy
- public void destroy() throws NacosException {
- if (service != null) {
- service.shutDown();
- service = null;
- }
- }
-
public NacosConfigProperties getNacosConfigProperties() {
return nacosConfigProperties;
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java
index 8ba0dd2e4..4990d94ed 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractPropertySourceLoader.java
@@ -30,8 +30,6 @@ import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
-import static com.alibaba.cloud.nacos.parser.NacosDataParserHandler.DOT;
-
/**
* Nacos-specific loader, If need to support other methods of parsing,you need to do the
* following steps:
@@ -47,6 +45,11 @@ import static com.alibaba.cloud.nacos.parser.NacosDataParserHandler.DOT;
*/
public abstract class AbstractPropertySourceLoader implements PropertySourceLoader {
+ /**
+ * symbol: dot.
+ */
+ static final String DOT = ".";
+
/**
* Prevent interference with other loaders.Nacos-specific loader, unless the reload
* changes it.
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java
index 82ad817ce..9d3c94ab8 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java
@@ -25,7 +25,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
+import com.alibaba.cloud.nacos.utils.NacosConfigUtils;
+
import org.springframework.boot.env.OriginTrackedMapPropertySource;
+import org.springframework.boot.env.PropertiesPropertySourceLoader;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;
@@ -33,25 +36,17 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
+import static com.alibaba.cloud.nacos.parser.AbstractPropertySourceLoader.DOT;
+
/**
* @author zkz
*/
public final class NacosDataParserHandler {
- /**
- * symbol: dot.
- */
- public static final String DOT = ".";
-
- /**
- * constant.
- */
- public static final String VALUE = "value";
-
/**
* default extension.
*/
- public static final String DEFAULT_EXTENSION = "properties";
+ private static final String DEFAULT_EXTENSION = "properties";
private static List propertySourceLoaders;
@@ -80,8 +75,18 @@ public final class NacosDataParserHandler {
if (!canLoadFileExtension(propertySourceLoader, extension)) {
continue;
}
- NacosByteArrayResource nacosByteArrayResource = new NacosByteArrayResource(
- configValue.getBytes(), configName);
+ NacosByteArrayResource nacosByteArrayResource;
+ if (propertySourceLoader instanceof PropertiesPropertySourceLoader) {
+ // PropertiesPropertySourceLoader internal is to use the ISO_8859_1,
+ // the Chinese will be garbled, needs to transform into unicode.
+ nacosByteArrayResource = new NacosByteArrayResource(
+ NacosConfigUtils.selectiveConvertUnicode(configValue).getBytes(),
+ configName);
+ }
+ else {
+ nacosByteArrayResource = new NacosByteArrayResource(
+ configValue.getBytes(), configName);
+ }
nacosByteArrayResource.setFilename(getFileName(configName, extension));
List> propertySourceList = propertySourceLoader
.load(configName, nacosByteArrayResource);
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java
index 6c633ddfe..ed9aa0655 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosJsonPropertySourceLoader.java
@@ -28,14 +28,16 @@ import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
-import static com.alibaba.cloud.nacos.parser.NacosDataParserHandler.DOT;
-import static com.alibaba.cloud.nacos.parser.NacosDataParserHandler.VALUE;
-
/**
* @author zkz
*/
public class NacosJsonPropertySourceLoader extends AbstractPropertySourceLoader {
+ /**
+ * constant.
+ */
+ private static final String VALUE = "value";
+
/**
* Returns the file extensions that the loader supports (excluding the '.').
* @return the file extensions
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java
index 666c64b4c..f656bed3c 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosXmlPropertySourceLoader.java
@@ -127,8 +127,7 @@ public class NacosXmlPropertySourceLoader extends AbstractPropertySourceLoader
continue;
}
- String key = StringUtils.isEmpty(parentKey) ? name
- : parentKey + NacosDataParserHandler.DOT + name;
+ String key = StringUtils.isEmpty(parentKey) ? name : parentKey + DOT + name;
NamedNodeMap nodeMap = node.getAttributes();
parseNodeAttr(nodeMap, map, key);
if (node.getNodeType() == Node.ELEMENT_NODE && node.hasChildNodes()) {
@@ -159,8 +158,8 @@ public class NacosXmlPropertySourceLoader extends AbstractPropertySourceLoader
if (StringUtils.isEmpty(node.getNodeValue())) {
continue;
}
- map.put(String.join(NacosDataParserHandler.DOT, parentKey,
- node.getNodeName()), node.getNodeValue());
+ map.put(String.join(DOT, parentKey, node.getNodeName()),
+ node.getNodeValue());
}
}
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/NacosConfigUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/NacosConfigUtils.java
new file mode 100644
index 000000000..b8a448dd7
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/utils/NacosConfigUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013-2018 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.nacos.utils;
+
+/**
+ * @author zkzlx
+ */
+public final class NacosConfigUtils {
+
+ private NacosConfigUtils() {
+ }
+
+ /**
+ * Convert Chinese characters to Unicode.
+ * @param configValue value of config
+ * @return new string
+ */
+ public static String selectiveConvertUnicode(String configValue) {
+ StringBuilder sb = new StringBuilder();
+ char[] chars = configValue.toCharArray();
+ for (char aChar : chars) {
+ if (isBaseLetter(aChar)) {
+ sb.append(aChar);
+ }
+ else {
+ sb.append(String.format("\\u%04x", (int) aChar));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * char is base latin or whitespace?
+ * @param ch a character
+ * @return true or false
+ */
+ public static boolean isBaseLetter(char ch) {
+ Character.UnicodeBlock ub = Character.UnicodeBlock.of(ch);
+ return ub == Character.UnicodeBlock.BASIC_LATIN || Character.isWhitespace(ch);
+ }
+
+ /**
+ * char is chinese?
+ * @param c a character
+ * @return true or false
+ */
+ public static boolean isChinese(char c) {
+ Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
+ return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
+ || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
+ || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
+ || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
+ || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
+ || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;
+ }
+
+}
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 1751f4fca..02a3c3e39 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/endpoint/NacosDiscoveryEndpoint.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java
index b1aea4179..ad2e762e0 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosDiscoveryEndpoint.java
@@ -24,6 +24,7 @@ import java.util.Map;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -66,6 +67,11 @@ public class NacosDiscoveryEndpoint {
try {
subscribe = namingService.getSubscribeServices();
+ for (ServiceInfo serviceInfo : subscribe) {
+ List instances = namingService.getAllInstances(
+ serviceInfo.getName(), serviceInfo.getGroupName());
+ serviceInfo.setHosts(instances);
+ }
}
catch (Exception e) {
log.error("get subscribe services from nacos fail,", e);
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 8d705b044..9873b8db3 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.lang.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.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java
index ae505058f..c13391dbd 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/feign/SeataFeignObjectWrapper.java
@@ -17,8 +17,8 @@
package com.alibaba.cloud.seata.feign;
import feign.Client;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
@@ -32,7 +32,8 @@ import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
*/
public class SeataFeignObjectWrapper {
- private static final Log LOG = LogFactory.getLog(SeataFeignObjectWrapper.class);
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SeataFeignObjectWrapper.class);
private final BeanFactory beanFactory;
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/actuate/DubboMetadataEndpointAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/actuate/DubboMetadataEndpointAutoConfiguration.java
index bfcc87c72..5640f241b 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/actuate/DubboMetadataEndpointAutoConfiguration.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/actuate/DubboMetadataEndpointAutoConfiguration.java
@@ -16,10 +16,11 @@
package com.alibaba.cloud.dubbo.actuate;
+import com.alibaba.cloud.dubbo.actuate.endpoint.DubboDiscoveryEndpoint;
+import com.alibaba.cloud.dubbo.actuate.endpoint.DubboExportedURLsEndpoint;
import com.alibaba.cloud.dubbo.actuate.endpoint.DubboRestMetadataEndpoint;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
-import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@@ -34,7 +35,7 @@ import org.springframework.context.annotation.PropertySource;
@ConditionalOnClass(
name = "org.springframework.boot.actuate.endpoint.annotation.Endpoint")
@PropertySource("classpath:/META-INF/dubbo/default/actuator-endpoints.properties")
-@ManagementContextConfiguration
+@Configuration(proxyBeanMethods = false)
public class DubboMetadataEndpointAutoConfiguration {
@Bean
@@ -44,4 +45,19 @@ public class DubboMetadataEndpointAutoConfiguration {
return new DubboRestMetadataEndpoint();
}
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnAvailableEndpoint
+ public DubboDiscoveryEndpoint dubboDiscoveryEndpoint() {
+
+ return new DubboDiscoveryEndpoint();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnAvailableEndpoint
+ public DubboExportedURLsEndpoint dubboServiceMetadataEndpoint() {
+ return new DubboExportedURLsEndpoint();
+ }
+
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/actuate/endpoint/DubboDiscoveryEndpoint.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/actuate/endpoint/DubboDiscoveryEndpoint.java
new file mode 100644
index 000000000..2333e27c5
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/actuate/endpoint/DubboDiscoveryEndpoint.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2013-2018 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.dubbo.actuate.endpoint;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.alibaba.cloud.dubbo.registry.DubboCloudRegistry;
+import com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.NotifyListener;
+import org.apache.dubbo.registry.integration.RegistryDirectory;
+import org.apache.dubbo.rpc.Invoker;
+
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+
+import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
+import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+/**
+ * Dubbo Registry Directory Metadata {@link DubboCloudRegistry}.
+ *
+ * @author Theonefx
+ */
+@Endpoint(id = "dubboRegistryDirectory")
+public class DubboDiscoveryEndpoint {
+
+ @ReadOperation(produces = APPLICATION_JSON_VALUE)
+ public Object get() {
+ DubboCloudRegistry registry = (DubboCloudRegistry) SpringCloudRegistryFactory
+ .getRegistries().stream().filter(o -> o instanceof DubboCloudRegistry)
+ .findFirst().orElse(null);
+
+ if (registry == null) {
+ return Collections.emptyMap();
+ }
+
+ Map> subscribeMap = registry.getSubscribed();
+
+ Map>> result = new HashMap<>();
+ subscribeMap.forEach((url, listeners) -> {
+ String side = url.getParameter(SIDE_KEY);
+ if (!CONSUMER_SIDE.equals(side)) {
+ return;
+ }
+
+ List