From 9b4433fddf5b401edb0aace8a404ac733b122702 Mon Sep 17 00:00:00 2001
From: 田源 <tianyuan@vci-tech.com>
Date: 星期四, 03 四月 2025 14:35:02 +0800
Subject: [PATCH] 添加非密字段显示

---
 Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java | 1577 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,577 insertions(+), 0 deletions(-)

diff --git a/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java b/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java
new file mode 100644
index 0000000..31b0b0a
--- /dev/null
+++ b/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java
@@ -0,0 +1,1577 @@
+/*
+ *      Copyright (c) 2018-2028, DreamLu All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: DreamLu 鍗㈡槬姊� (596392912@qq.com)
+ */
+package org.springblade.core.tool.utils;
+
+import org.springblade.core.tool.support.StrSpliter;
+import org.springframework.lang.Nullable;
+import org.springframework.util.Assert;
+import org.springframework.util.PatternMatchUtils;
+import org.springframework.web.util.HtmlUtils;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+/**
+ * 缁ф壙鑷猄pring util鐨勫伐鍏风被锛屽噺灏慾ar渚濊禆
+ *
+ * @author L.cm
+ */
+public class StringUtil extends org.springframework.util.StringUtils {
+
+	public static final int INDEX_NOT_FOUND = -1;
+
+	/**
+	 * Check whether the given {@code CharSequence} contains actual <em>text</em>.
+	 * <p>More specifically, this method returns {@code true} if the
+	 * {@code CharSequence} is not {@code null}, its length is greater than
+	 * 0, and it contains at least one non-whitespace character.
+	 * <pre class="code">
+	 * StringUtil.isBlank(null) = true
+	 * StringUtil.isBlank("") = true
+	 * StringUtil.isBlank(" ") = true
+	 * StringUtil.isBlank("12345") = false
+	 * StringUtil.isBlank(" 12345 ") = false
+	 * </pre>
+	 *
+	 * @param cs the {@code CharSequence} to check (may be {@code null})
+	 * @return {@code true} if the {@code CharSequence} is not {@code null},
+	 * its length is greater than 0, and it does not contain whitespace only
+	 * @see Character#isWhitespace
+	 */
+	public static boolean isBlank(final CharSequence cs) {
+		return !StringUtil.hasText(cs);
+	}
+
+	/**
+	 * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
+	 * <pre>
+	 * StringUtil.isNotBlank(null)	  = false
+	 * StringUtil.isNotBlank("")		= false
+	 * StringUtil.isNotBlank(" ")	   = false
+	 * StringUtil.isNotBlank("bob")	 = true
+	 * StringUtil.isNotBlank("  bob  ") = true
+	 * </pre>
+	 *
+	 * @param cs the CharSequence to check, may be null
+	 * @return {@code true} if the CharSequence is
+	 * not empty and not null and not whitespace
+	 * @see Character#isWhitespace
+	 */
+	public static boolean isNotBlank(final CharSequence cs) {
+		return StringUtil.hasText(cs);
+	}
+
+	/**
+	 * 鏈� 浠绘剰 涓�涓� Blank
+	 *
+	 * @param css CharSequence
+	 * @return boolean
+	 */
+	public static boolean isAnyBlank(final CharSequence... css) {
+		if (ObjectUtil.isEmpty(css)) {
+			return true;
+		}
+		return Stream.of(css).anyMatch(StringUtil::isBlank);
+	}
+
+	/**
+	 * 鏄惁鍏ㄩ潪 Blank
+	 *
+	 * @param css CharSequence
+	 * @return boolean
+	 */
+	public static boolean isNoneBlank(final CharSequence... css) {
+		if (ObjectUtil.isEmpty(css)) {
+			return false;
+		}
+		return Stream.of(css).allMatch(StringUtil::isNotBlank);
+	}
+
+	/**
+	 * 鏄惁鍏ㄤ负 Blank
+	 *
+	 * @param css CharSequence
+	 * @return boolean
+	 */
+	public static boolean isAllBlank(final CharSequence... css) {
+		return Stream.of(css).allMatch(StringUtil::isBlank);
+	}
+
+	/**
+	 * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁鏄暟瀛�
+	 *
+	 * @param cs the CharSequence to check, may be null
+	 * @return {boolean}
+	 */
+	public static boolean isNumeric(final CharSequence cs) {
+		if (isBlank(cs)) {
+			return false;
+		}
+		for (int i = cs.length(); --i >= 0; ) {
+			int chr = cs.charAt(i);
+			if (chr < 48 || chr > 57) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * 灏嗗瓧绗︿覆涓壒瀹氭ā寮忕殑瀛楃杞崲鎴恗ap涓搴旂殑鍊�
+	 * <p>
+	 * use: format("my name is ${name}, and i like ${like}!", {"name":"L.cm", "like": "Java"})
+	 *
+	 * @param message 闇�瑕佽浆鎹㈢殑瀛楃涓�
+	 * @param params  杞崲鎵�闇�鐨勯敭鍊煎闆嗗悎
+	 * @return 杞崲鍚庣殑瀛楃涓�
+	 */
+	public static String format(@Nullable String message, @Nullable Map<String, ?> params) {
+		// message 涓� null 杩斿洖绌哄瓧绗︿覆
+		if (message == null) {
+			return StringPool.EMPTY;
+		}
+		// 鍙傛暟涓� null 鎴栬�呬负绌�
+		if (params == null || params.isEmpty()) {
+			return message;
+		}
+		// 鏇挎崲鍙橀噺
+		StringBuilder sb = new StringBuilder((int) (message.length() * 1.5));
+		int cursor = 0;
+		for (int start, end; (start = message.indexOf(StringPool.DOLLAR_LEFT_BRACE, cursor)) != -1 && (end = message.indexOf(StringPool.RIGHT_BRACE, start)) != -1; ) {
+			sb.append(message, cursor, start);
+			String key = message.substring(start + 2, end);
+			Object value = params.get(StringUtil.trimWhitespace(key));
+			sb.append(value == null ? StringPool.EMPTY : value);
+			cursor = end + 1;
+		}
+		sb.append(message.substring(cursor));
+		return sb.toString();
+	}
+
+	/**
+	 * 鍚� log 鏍煎紡鐨� format 瑙勫垯
+	 * <p>
+	 * use: format("my name is {}, and i like {}!", "L.cm", "Java")
+	 *
+	 * @param message   闇�瑕佽浆鎹㈢殑瀛楃涓�
+	 * @param arguments 闇�瑕佹浛鎹㈢殑鍙橀噺
+	 * @return 杞崲鍚庣殑瀛楃涓�
+	 */
+	public static String format(@Nullable String message, @Nullable Object... arguments) {
+		// message 涓� null 杩斿洖绌哄瓧绗︿覆
+		if (message == null) {
+			return StringPool.EMPTY;
+		}
+		// 鍙傛暟涓� null 鎴栬�呬负绌�
+		if (arguments == null || arguments.length == 0) {
+			return message;
+		}
+		StringBuilder sb = new StringBuilder((int) (message.length() * 1.5));
+		int cursor = 0;
+		int index = 0;
+		int argsLength = arguments.length;
+		for (int start, end; (start = message.indexOf('{', cursor)) != -1 && (end = message.indexOf('}', start)) != -1 && index < argsLength; ) {
+			sb.append(message, cursor, start);
+			sb.append(arguments[index]);
+			cursor = end + 1;
+			index++;
+		}
+		sb.append(message.substring(cursor));
+		return sb.toString();
+	}
+
+	/**
+	 * 鏍煎紡鍖栨墽琛屾椂闂达紝鍗曚綅涓� ms 鍜� s锛屼繚鐣欎笁浣嶅皬鏁�
+	 *
+	 * @param nanos 绾崇
+	 * @return 鏍煎紡鍖栧悗鐨勬椂闂�
+	 */
+	public static String format(long nanos) {
+		if (nanos < 1) {
+			return "0ms";
+		}
+		double millis = (double) nanos / (1000 * 1000);
+		// 涓嶅 1 ms锛屾渶灏忓崟浣嶄负 ms
+		if (millis > 1000) {
+			return String.format("%.3fs", millis / 1000);
+		} else {
+			return String.format("%.3fms", millis);
+		}
+	}
+
+	/**
+	 * Convert a {@code Collection} into a delimited {@code String} (e.g., CSV).
+	 * <p>Useful for {@code toString()} implementations.
+	 *
+	 * @param coll the {@code Collection} to convert
+	 * @return the delimited {@code String}
+	 */
+	public static String join(Collection<?> coll) {
+		return StringUtil.collectionToCommaDelimitedString(coll);
+	}
+
+	/**
+	 * Convert a {@code Collection} into a delimited {@code String} (e.g. CSV).
+	 * <p>Useful for {@code toString()} implementations.
+	 *
+	 * @param coll  the {@code Collection} to convert
+	 * @param delim the delimiter to use (typically a ",")
+	 * @return the delimited {@code String}
+	 */
+	public static String join(Collection<?> coll, String delim) {
+		return StringUtil.collectionToDelimitedString(coll, delim);
+	}
+
+	/**
+	 * Convert a {@code String} array into a comma delimited {@code String}
+	 * (i.e., CSV).
+	 * <p>Useful for {@code toString()} implementations.
+	 *
+	 * @param arr the array to display
+	 * @return the delimited {@code String}
+	 */
+	public static String join(Object[] arr) {
+		return StringUtil.arrayToCommaDelimitedString(arr);
+	}
+
+	/**
+	 * Convert a {@code String} array into a delimited {@code String} (e.g. CSV).
+	 * <p>Useful for {@code toString()} implementations.
+	 *
+	 * @param arr   the array to display
+	 * @param delim the delimiter to use (typically a ",")
+	 * @return the delimited {@code String}
+	 */
+	public static String join(Object[] arr, String delim) {
+		return StringUtil.arrayToDelimitedString(arr, delim);
+	}
+
+	/**
+	 * 瀛楃涓叉槸鍚︾鍚堟寚瀹氱殑 琛ㄨ揪寮�
+	 *
+	 * <p>
+	 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy"
+	 * </p>
+	 *
+	 * @param pattern 琛ㄨ揪寮�
+	 * @param str     瀛楃涓�
+	 * @return 鏄惁鍖归厤
+	 */
+	public static boolean simpleMatch(@Nullable String pattern, @Nullable String str) {
+		return PatternMatchUtils.simpleMatch(pattern, str);
+	}
+
+	/**
+	 * 瀛楃涓叉槸鍚︾鍚堟寚瀹氱殑 琛ㄨ揪寮�
+	 *
+	 * <p>
+	 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy"
+	 * </p>
+	 *
+	 * @param patterns 琛ㄨ揪寮� 鏁扮粍
+	 * @param str      瀛楃涓�
+	 * @return 鏄惁鍖归厤
+	 */
+	public static boolean simpleMatch(@Nullable String[] patterns, String str) {
+		return PatternMatchUtils.simpleMatch(patterns, str);
+	}
+
+	/**
+	 * 鐢熸垚uuid
+	 *
+	 * @return UUID
+	 */
+	public static String randomUUID() {
+		ThreadLocalRandom random = ThreadLocalRandom.current();
+		return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY);
+	}
+
+	/**
+	 * 杞箟HTML鐢ㄤ簬瀹夊叏杩囨护
+	 *
+	 * @param html html
+	 * @return {String}
+	 */
+	public static String escapeHtml(String html) {
+		return StringUtil.isBlank(html) ? StringPool.EMPTY : HtmlUtils.htmlEscape(html);
+	}
+
+	/**
+	 * 娓呯悊瀛楃涓诧紝娓呯悊鍑烘煇浜涗笉鍙瀛楃
+	 *
+	 * @param txt 瀛楃涓�
+	 * @return {String}
+	 */
+	public static String cleanChars(String txt) {
+		return txt.replaceAll("[ 銆�`路鈥拷\\f\\t\\v\\s]", "");
+	}
+
+	/**
+	 * 鐗规畩瀛楃姝e垯锛宻ql鐗规畩瀛楃鍜岀┖鐧界
+	 */
+	private final static Pattern SPECIAL_CHARS_REGEX = Pattern.compile("[`'\"|/,;()-+*%#路鈥拷銆�\\s]");
+
+	/**
+	 * 娓呯悊瀛楃涓诧紝娓呯悊鍑烘煇浜涗笉鍙瀛楃鍜屼竴浜泂ql鐗规畩瀛楃
+	 *
+	 * @param txt 鏂囨湰
+	 * @return {String}
+	 */
+	@Nullable
+	public static String cleanText(@Nullable String txt) {
+		if (txt == null) {
+			return null;
+		}
+		return SPECIAL_CHARS_REGEX.matcher(txt).replaceAll(StringPool.EMPTY);
+	}
+
+	/**
+	 * 鑾峰彇鏍囪瘑绗︼紝鐢ㄤ簬鍙傛暟娓呯悊
+	 *
+	 * @param param 鍙傛暟
+	 * @return 娓呯悊鍚庣殑鏍囪瘑绗�
+	 */
+	@Nullable
+	public static String cleanIdentifier(@Nullable String param) {
+		if (param == null) {
+			return null;
+		}
+		StringBuilder paramBuilder = new StringBuilder();
+		for (int i = 0; i < param.length(); i++) {
+			char c = param.charAt(i);
+			if (Character.isJavaIdentifierPart(c)) {
+				paramBuilder.append(c);
+			}
+		}
+		return paramBuilder.toString();
+	}
+
+	/**
+	 * 闅忔満鏁扮敓鎴�
+	 *
+	 * @param count 瀛楃闀垮害
+	 * @return 闅忔満鏁�
+	 */
+	public static String random(int count) {
+		return StringUtil.random(count, RandomType.ALL);
+	}
+
+	/**
+	 * 闅忔満鏁扮敓鎴�
+	 *
+	 * @param count      瀛楃闀垮害
+	 * @param randomType 闅忔満鏁扮被鍒�
+	 * @return 闅忔満鏁�
+	 */
+	public static String random(int count, RandomType randomType) {
+		if (count == 0) {
+			return StringPool.EMPTY;
+		}
+		Assert.isTrue(count > 0, "Requested random string length " + count + " is less than 0.");
+		final Random random = Holder.SECURE_RANDOM;
+		char[] buffer = new char[count];
+		for (int i = 0; i < count; i++) {
+			String factor = randomType.getFactor();
+			buffer[i] = factor.charAt(random.nextInt(factor.length()));
+		}
+		return new String(buffer);
+	}
+
+	/**
+	 * 鏈夊簭鐨勬牸寮忓寲鏂囨湰锛屼娇鐢▄number}鍋氫负鍗犱綅绗�<br>
+	 * 渚嬶細<br>
+	 * 閫氬父浣跨敤锛歠ormat("this is {0} for {1}", "a", "b") =銆� this is a for b<br>
+	 *
+	 * @param pattern   鏂囨湰鏍煎紡
+	 * @param arguments 鍙傛暟
+	 * @return 鏍煎紡鍖栧悗鐨勬枃鏈�
+	 */
+	public static String indexedFormat(CharSequence pattern, Object... arguments) {
+		return MessageFormat.format(pattern.toString(), arguments);
+	}
+
+	/**
+	 * 鏍煎紡鍖栨枃鏈紝浣跨敤 {varName} 鍗犱綅<br>
+	 * map = {a: "aValue", b: "bValue"} format("{a} and {b}", map) ---=銆� aValue and bValue
+	 *
+	 * @param template 鏂囨湰妯℃澘锛岃鏇挎崲鐨勯儴鍒嗙敤 {key} 琛ㄧず
+	 * @param map      鍙傛暟鍊煎
+	 * @return 鏍煎紡鍖栧悗鐨勬枃鏈�
+	 */
+	public static String format(CharSequence template, Map<?, ?> map) {
+		if (null == template) {
+			return null;
+		}
+		if (null == map || map.isEmpty()) {
+			return template.toString();
+		}
+
+		String template2 = template.toString();
+		for (Map.Entry<?, ?> entry : map.entrySet()) {
+			template2 = template2.replace("{" + entry.getKey() + "}", Func.toStr(entry.getValue()));
+		}
+		return template2;
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓诧紝涓嶅幓闄ゅ垏鍒嗗悗姣忎釜鍏冪礌涓よ竟鐨勭┖鐧界锛屼笉鍘婚櫎绌虹櫧椤�
+	 *
+	 * @param str       琚垏鍒嗙殑瀛楃涓�
+	 * @param separator 鍒嗛殧绗﹀瓧绗�
+	 * @param limit     闄愬埗鍒嗙墖鏁帮紝-1涓嶉檺鍒�
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 */
+	public static List<String> split(CharSequence str, char separator, int limit) {
+		return split(str, separator, limit, false, false);
+	}
+
+	/**
+	 * 鍒嗗壊 瀛楃涓� 鍒犻櫎甯歌 绌虹櫧绗�
+	 *
+	 * @param str       瀛楃涓�
+	 * @param delimiter 鍒嗗壊绗�
+	 * @return 瀛楃涓叉暟缁�
+	 */
+	public static String[] splitTrim(@Nullable String str, @Nullable String delimiter) {
+		return StringUtil.delimitedListToStringArray(str, delimiter, " \t\n\n\f");
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓诧紝鍘婚櫎鍒囧垎鍚庢瘡涓厓绱犱袱杈圭殑绌虹櫧绗︼紝鍘婚櫎绌虹櫧椤�
+	 *
+	 * @param str       琚垏鍒嗙殑瀛楃涓�
+	 * @param separator 鍒嗛殧绗﹀瓧绗�
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 * @since 3.1.2
+	 */
+	public static List<String> splitTrim(CharSequence str, char separator) {
+		return splitTrim(str, separator, -1);
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓诧紝鍘婚櫎鍒囧垎鍚庢瘡涓厓绱犱袱杈圭殑绌虹櫧绗︼紝鍘婚櫎绌虹櫧椤�
+	 *
+	 * @param str       琚垏鍒嗙殑瀛楃涓�
+	 * @param separator 鍒嗛殧绗﹀瓧绗�
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 * @since 3.2.0
+	 */
+	public static List<String> splitTrim(CharSequence str, CharSequence separator) {
+		return splitTrim(str, separator, -1);
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓诧紝鍘婚櫎鍒囧垎鍚庢瘡涓厓绱犱袱杈圭殑绌虹櫧绗︼紝鍘婚櫎绌虹櫧椤�
+	 *
+	 * @param str       琚垏鍒嗙殑瀛楃涓�
+	 * @param separator 鍒嗛殧绗﹀瓧绗�
+	 * @param limit     闄愬埗鍒嗙墖鏁帮紝-1涓嶉檺鍒�
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 * @since 3.1.0
+	 */
+	public static List<String> splitTrim(CharSequence str, char separator, int limit) {
+		return split(str, separator, limit, true, true);
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓诧紝鍘婚櫎鍒囧垎鍚庢瘡涓厓绱犱袱杈圭殑绌虹櫧绗︼紝鍘婚櫎绌虹櫧椤�
+	 *
+	 * @param str       琚垏鍒嗙殑瀛楃涓�
+	 * @param separator 鍒嗛殧绗﹀瓧绗�
+	 * @param limit     闄愬埗鍒嗙墖鏁帮紝-1涓嶉檺鍒�
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 * @since 3.2.0
+	 */
+	public static List<String> splitTrim(CharSequence str, CharSequence separator, int limit) {
+		return split(str, separator, limit, true, true);
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓诧紝涓嶉檺鍒跺垎鐗囨暟閲�
+	 *
+	 * @param str         琚垏鍒嗙殑瀛楃涓�
+	 * @param separator   鍒嗛殧绗﹀瓧绗�
+	 * @param isTrim      鏄惁鍘婚櫎鍒囧垎瀛楃涓插悗姣忎釜鍏冪礌涓よ竟鐨勭┖鏍�
+	 * @param ignoreEmpty 鏄惁蹇界暐绌轰覆
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 * @since 3.0.8
+	 */
+	public static List<String> split(CharSequence str, char separator, boolean isTrim, boolean ignoreEmpty) {
+		return split(str, separator, 0, isTrim, ignoreEmpty);
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓�
+	 *
+	 * @param str         琚垏鍒嗙殑瀛楃涓�
+	 * @param separator   鍒嗛殧绗﹀瓧绗�
+	 * @param limit       闄愬埗鍒嗙墖鏁帮紝-1涓嶉檺鍒�
+	 * @param isTrim      鏄惁鍘婚櫎鍒囧垎瀛楃涓插悗姣忎釜鍏冪礌涓よ竟鐨勭┖鏍�
+	 * @param ignoreEmpty 鏄惁蹇界暐绌轰覆
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 * @since 3.0.8
+	 */
+	public static List<String> split(CharSequence str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) {
+		if (null == str) {
+			return new ArrayList<>(0);
+		}
+		return StrSpliter.split(str.toString(), separator, limit, isTrim, ignoreEmpty);
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓�
+	 *
+	 * @param str         琚垏鍒嗙殑瀛楃涓�
+	 * @param separator   鍒嗛殧绗﹀瓧绗�
+	 * @param limit       闄愬埗鍒嗙墖鏁帮紝-1涓嶉檺鍒�
+	 * @param isTrim      鏄惁鍘婚櫎鍒囧垎瀛楃涓插悗姣忎釜鍏冪礌涓よ竟鐨勭┖鏍�
+	 * @param ignoreEmpty 鏄惁蹇界暐绌轰覆
+	 * @return 鍒囧垎鍚庣殑闆嗗悎
+	 * @since 3.2.0
+	 */
+	public static List<String> split(CharSequence str, CharSequence separator, int limit, boolean isTrim, boolean ignoreEmpty) {
+		if (null == str) {
+			return new ArrayList<>(0);
+		}
+		final String separatorStr = (null == separator) ? null : separator.toString();
+		return StrSpliter.split(str.toString(), separatorStr, limit, isTrim, ignoreEmpty);
+	}
+
+	/**
+	 * 鍒囧垎瀛楃涓�
+	 *
+	 * @param str       琚垏鍒嗙殑瀛楃涓�
+	 * @param separator 鍒嗛殧绗�
+	 * @return 瀛楃涓�
+	 */
+	public static String[] split(CharSequence str, CharSequence separator) {
+		if (str == null) {
+			return new String[]{};
+		}
+
+		final String separatorStr = (null == separator) ? null : separator.toString();
+		return StrSpliter.splitToArray(str.toString(), separatorStr, 0, false, false);
+	}
+
+	/**
+	 * 鏍规嵁缁欏畾闀垮害锛屽皢缁欏畾瀛楃涓叉埅鍙栦负澶氫釜閮ㄥ垎
+	 *
+	 * @param str 瀛楃涓�
+	 * @param len 姣忎竴涓皬鑺傜殑闀垮害
+	 * @return 鎴彇鍚庣殑瀛楃涓叉暟缁�
+	 * @see StrSpliter#splitByLength(String, int)
+	 */
+	public static String[] split(CharSequence str, int len) {
+		if (null == str) {
+			return new String[]{};
+		}
+		return StrSpliter.splitByLength(str.toString(), len);
+	}
+
+	/**
+	 * 鎸囧畾瀛楃鏄惁鍦ㄥ瓧绗︿覆涓嚭鐜拌繃
+	 *
+	 * @param str        瀛楃涓�
+	 * @param searchChar 琚煡鎵剧殑瀛楃
+	 * @return 鏄惁鍖呭惈
+	 * @since 3.1.2
+	 */
+	public static boolean contains(CharSequence str, char searchChar) {
+		return indexOf(str, searchChar) > -1;
+	}
+
+	/**
+	 * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆
+	 *
+	 * @param str      鎸囧畾瀛楃涓�
+	 * @param testStrs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+	 * @return 鏄惁鍖呭惈浠绘剰涓�涓瓧绗︿覆
+	 * @since 3.2.0
+	 */
+	public static boolean containsAny(CharSequence str, CharSequence... testStrs) {
+		return null != getContainsStr(str, testStrs);
+	}
+
+	/**
+	 * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆锛屽鏋滃寘鍚繑鍥炴壘鍒扮殑绗竴涓瓧绗︿覆
+	 *
+	 * @param str      鎸囧畾瀛楃涓�
+	 * @param testStrs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+	 * @return 琚寘鍚殑绗竴涓瓧绗︿覆
+	 * @since 3.2.0
+	 */
+	public static String getContainsStr(CharSequence str, CharSequence... testStrs) {
+		if (isEmpty(str) || Func.isEmpty(testStrs)) {
+			return null;
+		}
+		for (CharSequence checkStr : testStrs) {
+			if (str.toString().contains(checkStr)) {
+				return checkStr.toString();
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 鏄惁鍖呭惈鐗瑰畾瀛楃锛屽拷鐣ュぇ灏忓啓锛屽鏋滅粰瀹氫袱涓弬鏁伴兘涓�<code>null</code>锛岃繑鍥瀟rue
+	 *
+	 * @param str     琚娴嬪瓧绗︿覆
+	 * @param testStr 琚祴璇曟槸鍚﹀寘鍚殑瀛楃涓�
+	 * @return 鏄惁鍖呭惈
+	 */
+	public static boolean containsIgnoreCase(CharSequence str, CharSequence testStr) {
+		if (null == str) {
+			// 濡傛灉琚洃娴嬪瓧绗︿覆鍜�
+			return null == testStr;
+		}
+		return str.toString().toLowerCase().contains(testStr.toString().toLowerCase());
+	}
+
+	/**
+	 * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆<br>
+	 * 蹇界暐澶у皬鍐�
+	 *
+	 * @param str      鎸囧畾瀛楃涓�
+	 * @param testStrs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+	 * @return 鏄惁鍖呭惈浠绘剰涓�涓瓧绗︿覆
+	 * @since 3.2.0
+	 */
+	public static boolean containsAnyIgnoreCase(CharSequence str, CharSequence... testStrs) {
+		return null != getContainsStrIgnoreCase(str, testStrs);
+	}
+
+	/**
+	 * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆锛屽鏋滃寘鍚繑鍥炴壘鍒扮殑绗竴涓瓧绗︿覆<br>
+	 * 蹇界暐澶у皬鍐�
+	 *
+	 * @param str      鎸囧畾瀛楃涓�
+	 * @param testStrs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+	 * @return 琚寘鍚殑绗竴涓瓧绗︿覆
+	 * @since 3.2.0
+	 */
+	public static String getContainsStrIgnoreCase(CharSequence str, CharSequence... testStrs) {
+		if (isEmpty(str) || Func.isEmpty(testStrs)) {
+			return null;
+		}
+		for (CharSequence testStr : testStrs) {
+			if (containsIgnoreCase(str, testStr)) {
+				return testStr.toString();
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 鏀硅繘JDK subString<br>
+	 * index浠�0寮�濮嬭绠楋紝鏈�鍚庝竴涓瓧绗︿负-1<br>
+	 * 濡傛灉from鍜宼o浣嶇疆涓�鏍凤紝杩斿洖 "" <br>
+	 * 濡傛灉from鎴杢o涓鸿礋鏁帮紝鍒欐寜鐓ength浠庡悗鍚戝墠鏁颁綅缃紝濡傛灉缁濆鍊煎ぇ浜庡瓧绗︿覆闀垮害锛屽垯from褰掑埌0锛宼o褰掑埌length<br>
+	 * 濡傛灉缁忚繃淇鐨刬ndex涓璮rom澶т簬to锛屽垯浜掓崲from鍜宼o example: <br>
+	 * abcdefgh 2 3 =銆� c <br>
+	 * abcdefgh 2 -3 =銆� cde <br>
+	 *
+	 * @param str       String
+	 * @param fromIndex 寮�濮嬬殑index锛堝寘鎷級
+	 * @param toIndex   缁撴潫鐨刬ndex锛堜笉鍖呮嫭锛�
+	 * @return 瀛椾覆
+	 */
+	public static String sub(CharSequence str, int fromIndex, int toIndex) {
+		if (isEmpty(str)) {
+			return StringPool.EMPTY;
+		}
+		int len = str.length();
+
+		if (fromIndex < 0) {
+			fromIndex = len + fromIndex;
+			if (fromIndex < 0) {
+				fromIndex = 0;
+			}
+		} else if (fromIndex > len) {
+			fromIndex = len;
+		}
+
+		if (toIndex < 0) {
+			toIndex = len + toIndex;
+			if (toIndex < 0) {
+				toIndex = len;
+			}
+		} else if (toIndex > len) {
+			toIndex = len;
+		}
+
+		if (toIndex < fromIndex) {
+			int tmp = fromIndex;
+			fromIndex = toIndex;
+			toIndex = tmp;
+		}
+
+		if (fromIndex == toIndex) {
+			return StringPool.EMPTY;
+		}
+
+		return str.toString().substring(fromIndex, toIndex);
+	}
+
+
+	/**
+	 * 鎴彇鍒嗛殧瀛楃涓蹭箣鍓嶇殑瀛楃涓诧紝涓嶅寘鎷垎闅斿瓧绗︿覆<br>
+	 * 濡傛灉缁欏畾鐨勫瓧绗︿覆涓虹┖涓诧紙null鎴�""锛夋垨鑰呭垎闅斿瓧绗︿覆涓簄ull锛岃繑鍥炲師瀛楃涓�<br>
+	 * 濡傛灉鍒嗛殧瀛楃涓蹭负绌轰覆""锛屽垯杩斿洖绌轰覆锛屽鏋滃垎闅斿瓧绗︿覆鏈壘鍒帮紝杩斿洖鍘熷瓧绗︿覆
+	 * <p>
+	 * 鏍楀瓙锛�
+	 *
+	 * <pre>
+	 * StringUtil.subBefore(null, *)      = null
+	 * StringUtil.subBefore("", *)        = ""
+	 * StringUtil.subBefore("abc", "a")   = ""
+	 * StringUtil.subBefore("abcba", "b") = "a"
+	 * StringUtil.subBefore("abc", "c")   = "ab"
+	 * StringUtil.subBefore("abc", "d")   = "abc"
+	 * StringUtil.subBefore("abc", "")    = ""
+	 * StringUtil.subBefore("abc", null)  = "abc"
+	 * </pre>
+	 *
+	 * @param string          琚煡鎵剧殑瀛楃涓�
+	 * @param separator       鍒嗛殧瀛楃涓诧紙涓嶅寘鎷級
+	 * @param isLastSeparator 鏄惁鏌ユ壘鏈�鍚庝竴涓垎闅斿瓧绗︿覆锛堝娆″嚭鐜板垎闅斿瓧绗︿覆鏃堕�夊彇鏈�鍚庝竴涓級锛宼rue涓洪�夊彇鏈�鍚庝竴涓�
+	 * @return 鍒囧壊鍚庣殑瀛楃涓�
+	 * @since 3.1.1
+	 */
+	public static String subBefore(CharSequence string, CharSequence separator, boolean isLastSeparator) {
+		if (isEmpty(string) || separator == null) {
+			return null == string ? null : string.toString();
+		}
+
+		final String str = string.toString();
+		final String sep = separator.toString();
+		if (sep.isEmpty()) {
+			return StringPool.EMPTY;
+		}
+		final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep);
+		if (pos == INDEX_NOT_FOUND) {
+			return str;
+		}
+		return str.substring(0, pos);
+	}
+
+	/**
+	 * 鎴彇鍒嗛殧瀛楃涓蹭箣鍚庣殑瀛楃涓诧紝涓嶅寘鎷垎闅斿瓧绗︿覆<br>
+	 * 濡傛灉缁欏畾鐨勫瓧绗︿覆涓虹┖涓诧紙null鎴�""锛夛紝杩斿洖鍘熷瓧绗︿覆<br>
+	 * 濡傛灉鍒嗛殧瀛楃涓蹭负绌轰覆锛坣ull鎴�""锛夛紝鍒欒繑鍥炵┖涓诧紝濡傛灉鍒嗛殧瀛楃涓叉湭鎵惧埌锛岃繑鍥炵┖涓�
+	 * <p>
+	 * 鏍楀瓙锛�
+	 *
+	 * <pre>
+	 * StringUtil.subAfter(null, *)      = null
+	 * StringUtil.subAfter("", *)        = ""
+	 * StringUtil.subAfter(*, null)      = ""
+	 * StringUtil.subAfter("abc", "a")   = "bc"
+	 * StringUtil.subAfter("abcba", "b") = "cba"
+	 * StringUtil.subAfter("abc", "c")   = ""
+	 * StringUtil.subAfter("abc", "d")   = ""
+	 * StringUtil.subAfter("abc", "")    = "abc"
+	 * </pre>
+	 *
+	 * @param string          琚煡鎵剧殑瀛楃涓�
+	 * @param separator       鍒嗛殧瀛楃涓诧紙涓嶅寘鎷級
+	 * @param isLastSeparator 鏄惁鏌ユ壘鏈�鍚庝竴涓垎闅斿瓧绗︿覆锛堝娆″嚭鐜板垎闅斿瓧绗︿覆鏃堕�夊彇鏈�鍚庝竴涓級锛宼rue涓洪�夊彇鏈�鍚庝竴涓�
+	 * @return 鍒囧壊鍚庣殑瀛楃涓�
+	 * @since 3.1.1
+	 */
+	public static String subAfter(CharSequence string, CharSequence separator, boolean isLastSeparator) {
+		if (isEmpty(string)) {
+			return null == string ? null : string.toString();
+		}
+		if (separator == null) {
+			return StringPool.EMPTY;
+		}
+		final String str = string.toString();
+		final String sep = separator.toString();
+		final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep);
+		if (pos == INDEX_NOT_FOUND) {
+			return StringPool.EMPTY;
+		}
+		return str.substring(pos + separator.length());
+	}
+
+	/**
+	 * 鎴彇鎸囧畾瀛楃涓蹭腑闂撮儴鍒嗭紝涓嶅寘鎷爣璇嗗瓧绗︿覆<br>
+	 * <p>
+	 * 鏍楀瓙锛�
+	 *
+	 * <pre>
+	 * StringUtil.subBetween("wx[b]yz", "[", "]") = "b"
+	 * StringUtil.subBetween(null, *, *)          = null
+	 * StringUtil.subBetween(*, null, *)          = null
+	 * StringUtil.subBetween(*, *, null)          = null
+	 * StringUtil.subBetween("", "", "")          = ""
+	 * StringUtil.subBetween("", "", "]")         = null
+	 * StringUtil.subBetween("", "[", "]")        = null
+	 * StringUtil.subBetween("yabcz", "", "")     = ""
+	 * StringUtil.subBetween("yabcz", "y", "z")   = "abc"
+	 * StringUtil.subBetween("yabczyabcz", "y", "z")   = "abc"
+	 * </pre>
+	 *
+	 * @param str    琚垏鍓茬殑瀛楃涓�
+	 * @param before 鎴彇寮�濮嬬殑瀛楃涓叉爣璇�
+	 * @param after  鎴彇鍒扮殑瀛楃涓叉爣璇�
+	 * @return 鎴彇鍚庣殑瀛楃涓�
+	 * @since 3.1.1
+	 */
+	public static String subBetween(CharSequence str, CharSequence before, CharSequence after) {
+		if (str == null || before == null || after == null) {
+			return null;
+		}
+
+		final String str2 = str.toString();
+		final String before2 = before.toString();
+		final String after2 = after.toString();
+
+		final int start = str2.indexOf(before2);
+		if (start != INDEX_NOT_FOUND) {
+			final int end = str2.indexOf(after2, start + before2.length());
+			if (end != INDEX_NOT_FOUND) {
+				return str2.substring(start + before2.length(), end);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 鎴彇鎸囧畾瀛楃涓蹭腑闂撮儴鍒嗭紝涓嶅寘鎷爣璇嗗瓧绗︿覆<br>
+	 * <p>
+	 * 鏍楀瓙锛�
+	 *
+	 * <pre>
+	 * StringUtil.subBetween(null, *)            = null
+	 * StringUtil.subBetween("", "")             = ""
+	 * StringUtil.subBetween("", "tag")          = null
+	 * StringUtil.subBetween("tagabctag", null)  = null
+	 * StringUtil.subBetween("tagabctag", "")    = ""
+	 * StringUtil.subBetween("tagabctag", "tag") = "abc"
+	 * </pre>
+	 *
+	 * @param str            琚垏鍓茬殑瀛楃涓�
+	 * @param beforeAndAfter 鎴彇寮�濮嬪拰缁撴潫鐨勫瓧绗︿覆鏍囪瘑
+	 * @return 鎴彇鍚庣殑瀛楃涓�
+	 * @since 3.1.1
+	 */
+	public static String subBetween(CharSequence str, CharSequence beforeAndAfter) {
+		return subBetween(str, beforeAndAfter, beforeAndAfter);
+	}
+
+	/**
+	 * 鍘绘帀鎸囧畾鍓嶇紑
+	 *
+	 * @param str    瀛楃涓�
+	 * @param prefix 鍓嶇紑
+	 * @return 鍒囨帀鍚庣殑瀛楃涓诧紝鑻ュ墠缂�涓嶆槸 preffix锛� 杩斿洖鍘熷瓧绗︿覆
+	 */
+	public static String removePrefix(CharSequence str, CharSequence prefix) {
+		if (isEmpty(str) || isEmpty(prefix)) {
+			return StringPool.EMPTY;
+		}
+
+		final String str2 = str.toString();
+		if (str2.startsWith(prefix.toString())) {
+			return subSuf(str2, prefix.length());
+		}
+		return str2;
+	}
+
+	/**
+	 * 蹇界暐澶у皬鍐欏幓鎺夋寚瀹氬墠缂�
+	 *
+	 * @param str    瀛楃涓�
+	 * @param prefix 鍓嶇紑
+	 * @return 鍒囨帀鍚庣殑瀛楃涓诧紝鑻ュ墠缂�涓嶆槸 prefix锛� 杩斿洖鍘熷瓧绗︿覆
+	 */
+	public static String removePrefixIgnoreCase(CharSequence str, CharSequence prefix) {
+		if (isEmpty(str) || isEmpty(prefix)) {
+			return StringPool.EMPTY;
+		}
+
+		final String str2 = str.toString();
+		if (str2.toLowerCase().startsWith(prefix.toString().toLowerCase())) {
+			return subSuf(str2, prefix.length());
+		}
+		return str2;
+	}
+
+	/**
+	 * 鍘绘帀鎸囧畾鍚庣紑
+	 *
+	 * @param str    瀛楃涓�
+	 * @param suffix 鍚庣紑
+	 * @return 鍒囨帀鍚庣殑瀛楃涓诧紝鑻ュ悗缂�涓嶆槸 suffix锛� 杩斿洖鍘熷瓧绗︿覆
+	 */
+	public static String removeSuffix(CharSequence str, CharSequence suffix) {
+		if (isEmpty(str) || isEmpty(suffix)) {
+			return StringPool.EMPTY;
+		}
+
+		final String str2 = str.toString();
+		if (str2.endsWith(suffix.toString())) {
+			return subPre(str2, str2.length() - suffix.length());
+		}
+		return str2;
+	}
+
+	/**
+	 * 鍘绘帀鎸囧畾鍚庣紑锛屽苟灏忓啓棣栧瓧姣�
+	 *
+	 * @param str    瀛楃涓�
+	 * @param suffix 鍚庣紑
+	 * @return 鍒囨帀鍚庣殑瀛楃涓诧紝鑻ュ悗缂�涓嶆槸 suffix锛� 杩斿洖鍘熷瓧绗︿覆
+	 */
+	public static String removeSufAndLowerFirst(CharSequence str, CharSequence suffix) {
+		return firstCharToLower(removeSuffix(str, suffix));
+	}
+
+	/**
+	 * 蹇界暐澶у皬鍐欏幓鎺夋寚瀹氬悗缂�
+	 *
+	 * @param str    瀛楃涓�
+	 * @param suffix 鍚庣紑
+	 * @return 鍒囨帀鍚庣殑瀛楃涓诧紝鑻ュ悗缂�涓嶆槸 suffix锛� 杩斿洖鍘熷瓧绗︿覆
+	 */
+	public static String removeSuffixIgnoreCase(CharSequence str, CharSequence suffix) {
+		if (isEmpty(str) || isEmpty(suffix)) {
+			return StringPool.EMPTY;
+		}
+
+		final String str2 = str.toString();
+		if (str2.toLowerCase().endsWith(suffix.toString().toLowerCase())) {
+			return subPre(str2, str2.length() - suffix.length());
+		}
+		return str2;
+	}
+
+	/**
+	 * 棣栧瓧姣嶅彉灏忓啓
+	 *
+	 * @param str 瀛楃涓�
+	 * @return {String}
+	 */
+	public static String firstCharToLower(String str) {
+		char firstChar = str.charAt(0);
+		if (firstChar >= CharPool.UPPER_A && firstChar <= CharPool.UPPER_Z) {
+			char[] arr = str.toCharArray();
+			arr[0] += (CharPool.LOWER_A - CharPool.UPPER_A);
+			return new String(arr);
+		}
+		return str;
+	}
+
+	/**
+	 * 棣栧瓧姣嶅彉澶у啓
+	 *
+	 * @param str 瀛楃涓�
+	 * @return {String}
+	 */
+	public static String firstCharToUpper(String str) {
+		char firstChar = str.charAt(0);
+		if (firstChar >= CharPool.LOWER_A && firstChar <= CharPool.LOWER_Z) {
+			char[] arr = str.toCharArray();
+			arr[0] -= (CharPool.LOWER_A - CharPool.UPPER_A);
+			return new String(arr);
+		}
+		return str;
+	}
+
+	/**
+	 * 鍒囧壊鎸囧畾浣嶇疆涔嬪墠閮ㄥ垎鐨勫瓧绗︿覆
+	 *
+	 * @param string  瀛楃涓�
+	 * @param toIndex 鍒囧壊鍒扮殑浣嶇疆锛堜笉鍖呮嫭锛�
+	 * @return 鍒囧壊鍚庣殑鍓╀綑鐨勫墠鍗婇儴鍒嗗瓧绗︿覆
+	 */
+	public static String subPre(CharSequence string, int toIndex) {
+		return sub(string, 0, toIndex);
+	}
+
+	/**
+	 * 鍒囧壊鎸囧畾浣嶇疆涔嬪悗閮ㄥ垎鐨勫瓧绗︿覆
+	 *
+	 * @param string    瀛楃涓�
+	 * @param fromIndex 鍒囧壊寮�濮嬬殑浣嶇疆锛堝寘鎷級
+	 * @return 鍒囧壊鍚庡悗鍓╀綑鐨勫悗鍗婇儴鍒嗗瓧绗︿覆
+	 */
+	public static String subSuf(CharSequence string, int fromIndex) {
+		if (isEmpty(string)) {
+			return null;
+		}
+		return sub(string, fromIndex, string.length());
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵炬寚瀹氬瓧绗�
+	 *
+	 * @param str        瀛楃涓�
+	 * @param searchChar 琚煡鎵剧殑瀛楃
+	 * @return 浣嶇疆
+	 */
+	public static int indexOf(final CharSequence str, char searchChar) {
+		return indexOf(str, searchChar, 0);
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵炬寚瀹氬瓧绗�
+	 *
+	 * @param str        瀛楃涓�
+	 * @param searchChar 琚煡鎵剧殑瀛楃
+	 * @param start      璧峰浣嶇疆锛屽鏋滃皬浜�0锛屼粠0寮�濮嬫煡鎵�
+	 * @return 浣嶇疆
+	 */
+	public static int indexOf(final CharSequence str, char searchChar, int start) {
+		if (str instanceof String) {
+			return ((String) str).indexOf(searchChar, start);
+		} else {
+			return indexOf(str, searchChar, start, -1);
+		}
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵炬寚瀹氬瓧绗�
+	 *
+	 * @param str        瀛楃涓�
+	 * @param searchChar 琚煡鎵剧殑瀛楃
+	 * @param start      璧峰浣嶇疆锛屽鏋滃皬浜�0锛屼粠0寮�濮嬫煡鎵�
+	 * @param end        缁堟浣嶇疆锛屽鏋滆秴杩噑tr.length()鍒欓粯璁ゆ煡鎵惧埌瀛楃涓叉湯灏�
+	 * @return 浣嶇疆
+	 */
+	public static int indexOf(final CharSequence str, char searchChar, int start, int end) {
+		final int len = str.length();
+		if (start < 0 || start > len) {
+			start = 0;
+		}
+		if (end > len || end < 0) {
+			end = len;
+		}
+		for (int i = start; i < end; i++) {
+			if (str.charAt(i) == searchChar) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵惧瓧绗︿覆锛屽拷鐣ュぇ灏忓啓<br>
+	 *
+	 * <pre>
+	 * StringUtil.indexOfIgnoreCase(null, *, *)          = -1
+	 * StringUtil.indexOfIgnoreCase(*, null, *)          = -1
+	 * StringUtil.indexOfIgnoreCase("", "", 0)           = 0
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
+	 * StringUtil.indexOfIgnoreCase("abc", "", 9)        = -1
+	 * </pre>
+	 *
+	 * @param str       瀛楃涓�
+	 * @param searchStr 闇�瑕佹煡鎵句綅缃殑瀛楃涓�
+	 * @return 浣嶇疆
+	 * @since 3.2.1
+	 */
+	public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
+		return indexOfIgnoreCase(str, searchStr, 0);
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵惧瓧绗︿覆
+	 *
+	 * <pre>
+	 * StringUtil.indexOfIgnoreCase(null, *, *)          = -1
+	 * StringUtil.indexOfIgnoreCase(*, null, *)          = -1
+	 * StringUtil.indexOfIgnoreCase("", "", 0)           = 0
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
+	 * StringUtil.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
+	 * StringUtil.indexOfIgnoreCase("abc", "", 9)        = -1
+	 * </pre>
+	 *
+	 * @param str       瀛楃涓�
+	 * @param searchStr 闇�瑕佹煡鎵句綅缃殑瀛楃涓�
+	 * @param fromIndex 璧峰浣嶇疆
+	 * @return 浣嶇疆
+	 * @since 3.2.1
+	 */
+	public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) {
+		return indexOf(str, searchStr, fromIndex, true);
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呭弽鍚戞煡鎵惧瓧绗︿覆
+	 *
+	 * @param str        瀛楃涓�
+	 * @param searchStr  闇�瑕佹煡鎵句綅缃殑瀛楃涓�
+	 * @param fromIndex  璧峰浣嶇疆
+	 * @param ignoreCase 鏄惁蹇界暐澶у皬鍐�
+	 * @return 浣嶇疆
+	 * @since 3.2.1
+	 */
+	public static int indexOf(final CharSequence str, CharSequence searchStr, int fromIndex, boolean ignoreCase) {
+		if (str == null || searchStr == null) {
+			return INDEX_NOT_FOUND;
+		}
+		if (fromIndex < 0) {
+			fromIndex = 0;
+		}
+
+		final int endLimit = str.length() - searchStr.length() + 1;
+		if (fromIndex > endLimit) {
+			return INDEX_NOT_FOUND;
+		}
+		if (searchStr.length() == 0) {
+			return fromIndex;
+		}
+
+		if (false == ignoreCase) {
+			// 涓嶅拷鐣ュぇ灏忓啓璋冪敤JDK鏂规硶
+			return str.toString().indexOf(searchStr.toString(), fromIndex);
+		}
+
+		for (int i = fromIndex; i < endLimit; i++) {
+			if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) {
+				return i;
+			}
+		}
+		return INDEX_NOT_FOUND;
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵惧瓧绗︿覆锛屽拷鐣ュぇ灏忓啓<br>
+	 *
+	 * @param str       瀛楃涓�
+	 * @param searchStr 闇�瑕佹煡鎵句綅缃殑瀛楃涓�
+	 * @return 浣嶇疆
+	 * @since 3.2.1
+	 */
+	public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
+		return lastIndexOfIgnoreCase(str, searchStr, str.length());
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵惧瓧绗︿覆锛屽拷鐣ュぇ灏忓啓<br>
+	 *
+	 * @param str       瀛楃涓�
+	 * @param searchStr 闇�瑕佹煡鎵句綅缃殑瀛楃涓�
+	 * @param fromIndex 璧峰浣嶇疆锛屼粠鍚庡線鍓嶈鏁�
+	 * @return 浣嶇疆
+	 * @since 3.2.1
+	 */
+	public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) {
+		return lastIndexOf(str, searchStr, fromIndex, true);
+	}
+
+	/**
+	 * 鎸囧畾鑼冨洿鍐呮煡鎵惧瓧绗︿覆<br>
+	 *
+	 * @param str        瀛楃涓�
+	 * @param searchStr  闇�瑕佹煡鎵句綅缃殑瀛楃涓�
+	 * @param fromIndex  璧峰浣嶇疆锛屼粠鍚庡線鍓嶈鏁�
+	 * @param ignoreCase 鏄惁蹇界暐澶у皬鍐�
+	 * @return 浣嶇疆
+	 * @since 3.2.1
+	 */
+	public static int lastIndexOf(final CharSequence str, final CharSequence searchStr, int fromIndex, boolean ignoreCase) {
+		if (str == null || searchStr == null) {
+			return INDEX_NOT_FOUND;
+		}
+		if (fromIndex < 0) {
+			fromIndex = 0;
+		}
+		fromIndex = Math.min(fromIndex, str.length());
+
+		if (searchStr.length() == 0) {
+			return fromIndex;
+		}
+
+		if (false == ignoreCase) {
+			// 涓嶅拷鐣ュぇ灏忓啓璋冪敤JDK鏂规硶
+			return str.toString().lastIndexOf(searchStr.toString(), fromIndex);
+		}
+
+		for (int i = fromIndex; i > 0; i--) {
+			if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) {
+				return i;
+			}
+		}
+		return INDEX_NOT_FOUND;
+	}
+
+	/**
+	 * 杩斿洖瀛楃涓� searchStr 鍦ㄥ瓧绗︿覆 str 涓 ordinal 娆″嚭鐜扮殑浣嶇疆銆�<br>
+	 * 姝ゆ柟娉曟潵鑷細Apache-Commons-Lang
+	 * <p>
+	 * 鏍楀瓙锛�*浠h〃浠绘剰瀛楃锛夛細
+	 *
+	 * <pre>
+	 * StringUtil.ordinalIndexOf(null, *, *)          = -1
+	 * StringUtil.ordinalIndexOf(*, null, *)          = -1
+	 * StringUtil.ordinalIndexOf("", "", *)           = 0
+	 * StringUtil.ordinalIndexOf("aabaabaa", "a", 1)  = 0
+	 * StringUtil.ordinalIndexOf("aabaabaa", "a", 2)  = 1
+	 * StringUtil.ordinalIndexOf("aabaabaa", "b", 1)  = 2
+	 * StringUtil.ordinalIndexOf("aabaabaa", "b", 2)  = 5
+	 * StringUtil.ordinalIndexOf("aabaabaa", "ab", 1) = 1
+	 * StringUtil.ordinalIndexOf("aabaabaa", "ab", 2) = 4
+	 * StringUtil.ordinalIndexOf("aabaabaa", "", 1)   = 0
+	 * StringUtil.ordinalIndexOf("aabaabaa", "", 2)   = 0
+	 * </pre>
+	 *
+	 * @param str       琚鏌ョ殑瀛楃涓诧紝鍙互涓簄ull
+	 * @param searchStr 琚煡鎵剧殑瀛楃涓诧紝鍙互涓簄ull
+	 * @param ordinal   绗嚑娆″嚭鐜扮殑浣嶇疆
+	 * @return 鏌ユ壘鍒扮殑浣嶇疆
+	 * @since 3.2.3
+	 */
+	public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
+		if (str == null || searchStr == null || ordinal <= 0) {
+			return INDEX_NOT_FOUND;
+		}
+		if (searchStr.length() == 0) {
+			return 0;
+		}
+		int found = 0;
+		int index = INDEX_NOT_FOUND;
+		do {
+			index = str.indexOf(searchStr, index + 1);
+			if (index < 0) {
+				return index;
+			}
+			found++;
+		} while (found < ordinal);
+		return index;
+	}
+
+	/**
+	 * 鎴彇涓や釜瀛楃涓茬殑涓嶅悓閮ㄥ垎锛堥暱搴︿竴鑷达級锛屽垽鏂埅鍙栫殑瀛愪覆鏄惁鐩稿悓<br>
+	 * 浠绘剰涓�涓瓧绗︿覆涓簄ull杩斿洖false
+	 *
+	 * @param str1       绗竴涓瓧绗︿覆
+	 * @param start1     绗竴涓瓧绗︿覆寮�濮嬬殑浣嶇疆
+	 * @param str2       绗簩涓瓧绗︿覆
+	 * @param start2     绗簩涓瓧绗︿覆寮�濮嬬殑浣嶇疆
+	 * @param length     鎴彇闀垮害
+	 * @param ignoreCase 鏄惁蹇界暐澶у皬鍐�
+	 * @return 瀛愪覆鏄惁鐩稿悓
+	 * @since 3.2.1
+	 */
+	public static boolean isSubEquals(CharSequence str1, int start1, CharSequence str2, int start2, int length, boolean ignoreCase) {
+		if (null == str1 || null == str2) {
+			return false;
+		}
+
+		return str1.toString().regionMatches(ignoreCase, start1, str2.toString(), start2, length);
+	}
+
+	/**
+	 * 姣旇緝涓や釜瀛楃涓诧紙澶у皬鍐欐晱鎰燂級銆�
+	 *
+	 * <pre>
+	 * equalsIgnoreCase(null, null)   = true
+	 * equalsIgnoreCase(null, &quot;abc&quot;)  = false
+	 * equalsIgnoreCase(&quot;abc&quot;, null)  = false
+	 * equalsIgnoreCase(&quot;abc&quot;, &quot;abc&quot;) = true
+	 * equalsIgnoreCase(&quot;abc&quot;, &quot;ABC&quot;) = true
+	 * </pre>
+	 *
+	 * @param str1 瑕佹瘮杈冪殑瀛楃涓�1
+	 * @param str2 瑕佹瘮杈冪殑瀛楃涓�2
+	 * @return 濡傛灉涓や釜瀛楃涓茬浉鍚岋紝鎴栬�呴兘鏄�<code>null</code>锛屽垯杩斿洖<code>true</code>
+	 */
+	public static boolean equals(CharSequence str1, CharSequence str2) {
+		return equals(str1, str2, false);
+	}
+
+	/**
+	 * 姣旇緝涓や釜瀛楃涓诧紙澶у皬鍐欎笉鏁忔劅锛夈��
+	 *
+	 * <pre>
+	 * equalsIgnoreCase(null, null)   = true
+	 * equalsIgnoreCase(null, &quot;abc&quot;)  = false
+	 * equalsIgnoreCase(&quot;abc&quot;, null)  = false
+	 * equalsIgnoreCase(&quot;abc&quot;, &quot;abc&quot;) = true
+	 * equalsIgnoreCase(&quot;abc&quot;, &quot;ABC&quot;) = true
+	 * </pre>
+	 *
+	 * @param str1 瑕佹瘮杈冪殑瀛楃涓�1
+	 * @param str2 瑕佹瘮杈冪殑瀛楃涓�2
+	 * @return 濡傛灉涓や釜瀛楃涓茬浉鍚岋紝鎴栬�呴兘鏄�<code>null</code>锛屽垯杩斿洖<code>true</code>
+	 */
+	public static boolean equalsIgnoreCase(CharSequence str1, CharSequence str2) {
+		return equals(str1, str2, true);
+	}
+
+	/**
+	 * 姣旇緝涓や釜瀛楃涓叉槸鍚︾浉绛夈��
+	 *
+	 * @param str1       瑕佹瘮杈冪殑瀛楃涓�1
+	 * @param str2       瑕佹瘮杈冪殑瀛楃涓�2
+	 * @param ignoreCase 鏄惁蹇界暐澶у皬鍐�
+	 * @return 濡傛灉涓や釜瀛楃涓茬浉鍚岋紝鎴栬�呴兘鏄�<code>null</code>锛屽垯杩斿洖<code>true</code>
+	 * @since 3.2.0
+	 */
+	public static boolean equals(CharSequence str1, CharSequence str2, boolean ignoreCase) {
+		if (null == str1) {
+			// 鍙湁涓や釜閮戒负null鎵嶅垽鏂浉绛�
+			return str2 == null;
+		}
+		if (null == str2) {
+			// 瀛楃涓�2绌猴紝瀛楃涓�1闈炵┖锛岀洿鎺alse
+			return false;
+		}
+
+		if (ignoreCase) {
+			return str1.toString().equalsIgnoreCase(str2.toString());
+		} else {
+			return str1.equals(str2);
+		}
+	}
+
+	/**
+	 * 鍒涘缓StringBuilder瀵硅薄
+	 *
+	 * @return {String}Builder瀵硅薄
+	 */
+	public static StringBuilder builder() {
+		return new StringBuilder();
+	}
+
+	/**
+	 * 鍒涘缓StringBuilder瀵硅薄
+	 *
+	 * @param capacity 鍒濆澶у皬
+	 * @return {String}Builder瀵硅薄
+	 */
+	public static StringBuilder builder(int capacity) {
+		return new StringBuilder(capacity);
+	}
+
+	/**
+	 * 鍒涘缓StringBuilder瀵硅薄
+	 *
+	 * @param strs 鍒濆瀛楃涓插垪琛�
+	 * @return {String}Builder瀵硅薄
+	 */
+	public static StringBuilder builder(CharSequence... strs) {
+		final StringBuilder sb = new StringBuilder();
+		for (CharSequence str : strs) {
+			sb.append(str);
+		}
+		return sb;
+	}
+
+	/**
+	 * 鍒涘缓StringBuilder瀵硅薄
+	 *
+	 * @param sb   鍒濆StringBuilder
+	 * @param strs 鍒濆瀛楃涓插垪琛�
+	 * @return {String}Builder瀵硅薄
+	 */
+	public static StringBuilder appendBuilder(StringBuilder sb, CharSequence... strs) {
+		for (CharSequence str : strs) {
+			sb.append(str);
+		}
+		return sb;
+	}
+
+	/**
+	 * 鑾峰緱StringReader
+	 *
+	 * @param str 瀛楃涓�
+	 * @return {String}Reader
+	 */
+	public static StringReader getReader(CharSequence str) {
+		if (null == str) {
+			return null;
+		}
+		return new StringReader(str.toString());
+	}
+
+	/**
+	 * 鑾峰緱StringWriter
+	 *
+	 * @return {String}Writer
+	 */
+	public static StringWriter getWriter() {
+		return new StringWriter();
+	}
+
+	/**
+	 * 缁熻鎸囧畾鍐呭涓寘鍚寚瀹氬瓧绗︿覆鐨勬暟閲�<br>
+	 * 鍙傛暟涓� {@code null} 鎴栬�� "" 杩斿洖 {@code 0}.
+	 *
+	 * <pre>
+	 * StringUtil.count(null, *)       = 0
+	 * StringUtil.count("", *)         = 0
+	 * StringUtil.count("abba", null)  = 0
+	 * StringUtil.count("abba", "")    = 0
+	 * StringUtil.count("abba", "a")   = 2
+	 * StringUtil.count("abba", "ab")  = 1
+	 * StringUtil.count("abba", "xxx") = 0
+	 * </pre>
+	 *
+	 * @param content      琚煡鎵剧殑瀛楃涓�
+	 * @param strForSearch 闇�瑕佹煡鎵剧殑瀛楃涓�
+	 * @return 鏌ユ壘鍒扮殑涓暟
+	 */
+	public static int count(CharSequence content, CharSequence strForSearch) {
+		if (Func.hasEmpty(content, strForSearch) || strForSearch.length() > content.length()) {
+			return 0;
+		}
+
+		int count = 0;
+		int idx = 0;
+		final String content2 = content.toString();
+		final String strForSearch2 = strForSearch.toString();
+		while ((idx = content2.indexOf(strForSearch2, idx)) > -1) {
+			count++;
+			idx += strForSearch.length();
+		}
+		return count;
+	}
+
+	/**
+	 * 缁熻鎸囧畾鍐呭涓寘鍚寚瀹氬瓧绗︾殑鏁伴噺
+	 *
+	 * @param content       鍐呭
+	 * @param charForSearch 琚粺璁$殑瀛楃
+	 * @return 鍖呭惈鏁伴噺
+	 */
+	public static int count(CharSequence content, char charForSearch) {
+		int count = 0;
+		if (isEmpty(content)) {
+			return 0;
+		}
+		int contentLength = content.length();
+		for (int i = 0; i < contentLength; i++) {
+			if (charForSearch == content.charAt(i)) {
+				count++;
+			}
+		}
+		return count;
+	}
+
+	/**
+	 * 涓嬪垝绾胯浆椹煎嘲
+	 *
+	 * @param para 瀛楃涓�
+	 * @return {String}
+	 */
+	public static String underlineToHump(String para) {
+		if (isBlank(para)) {
+			return StringPool.EMPTY;
+		}
+		StringBuilder result = new StringBuilder();
+		String[] a = para.split("_");
+		for (String s : a) {
+			if (result.length() == 0) {
+				result.append(s.toLowerCase());
+			} else {
+				result.append(s.substring(0, 1).toUpperCase());
+				result.append(s.substring(1).toLowerCase());
+			}
+		}
+		return result.toString();
+	}
+
+	/**
+	 * 椹煎嘲杞笅鍒掔嚎
+	 *
+	 * @param para 瀛楃涓�
+	 * @return {String}
+	 */
+	public static String humpToUnderline(String para) {
+		if (isBlank(para)) {
+			return StringPool.EMPTY;
+		}
+		para = firstCharToLower(para);
+		StringBuilder sb = new StringBuilder(para);
+		int temp = 0;
+		for (int i = 0; i < para.length(); i++) {
+			if (Character.isUpperCase(para.charAt(i))) {
+				sb.insert(i + temp, "_");
+				temp += 1;
+			}
+		}
+		return sb.toString().toLowerCase();
+	}
+
+	/**
+	 * 妯嚎杞┘宄�
+	 *
+	 * @param para 瀛楃涓�
+	 * @return {String}
+	 */
+	public static String lineToHump(String para) {
+		if (isBlank(para)) {
+			return StringPool.EMPTY;
+		}
+		StringBuilder result = new StringBuilder();
+		String[] a = para.split("-");
+		for (String s : a) {
+			if (result.length() == 0) {
+				result.append(s.toLowerCase());
+			} else {
+				result.append(s.substring(0, 1).toUpperCase());
+				result.append(s.substring(1).toLowerCase());
+			}
+		}
+		return result.toString();
+	}
+
+	/**
+	 * 椹煎嘲杞í绾�
+	 *
+	 * @param para 瀛楃涓�
+	 * @return {String}
+	 */
+	public static String humpToLine(String para) {
+		if (isBlank(para)) {
+			return StringPool.EMPTY;
+		}
+		para = firstCharToLower(para);
+		StringBuilder sb = new StringBuilder(para);
+		int temp = 0;
+		for (int i = 0; i < para.length(); i++) {
+			if (Character.isUpperCase(para.charAt(i))) {
+				sb.insert(i + temp, "-");
+				temp += 1;
+			}
+		}
+		return sb.toString().toLowerCase();
+	}
+
+
+}
+

--
Gitblit v1.9.3