浏览代码

add method for extra

Looly 5 年之前
父节点
当前提交
dc2460106f
共有 94 个文件被更改,包括 616 次插入68 次删除
  1. 1 0
      CHANGELOG.md
  2. 40 4
      hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java
  3. 54 0
      hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java
  4. 12 0
      hutool-extra/pom.xml
  5. 53 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinEngine.java
  6. 33 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinException.java
  7. 43 45
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinUtil.java
  8. 52 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/PinyinFactory.java
  9. 64 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/JPinyinEngine.java
  10. 20 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/package-info.java
  11. 7 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/package-info.java
  12. 92 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/Pinyin4jEngine.java
  13. 20 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/package-info.java
  14. 56 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/tinypinyin/TinyPinyinEngine.java
  15. 22 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/tinypinyin/package-info.java
  16. 1 1
      hutool-extra/src/main/java/cn/hutool/extra/template/TemplateUtil.java
  17. 23 0
      hutool-extra/src/main/java/cn/hutool/extra/template/engine/TemplateFactory.java
  18. 13 0
      hutool-extra/src/main/java/cn/hutool/extra/tokenizer/engine/TokenizerFactory.java
  19. 3 0
      hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine
  20. 5 6
      hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java
  21. 2 12
      hutool-log/src/main/java/cn/hutool/log/LogFactory.java
  22. 二进制
      hutool-script/.jython_cache/packages/access-bridge-64.pkc
  23. 二进制
      hutool-script/.jython_cache/packages/ant-1.10.7.pkc
  24. 二进制
      hutool-script/.jython_cache/packages/ant-antlr-1.10.7.pkc
  25. 二进制
      hutool-script/.jython_cache/packages/ant-junit-1.10.7.pkc
  26. 二进制
      hutool-script/.jython_cache/packages/ant-launcher-1.10.7.pkc
  27. 二进制
      hutool-script/.jython_cache/packages/apiguardian-api-1.1.0.pkc
  28. 二进制
      hutool-script/.jython_cache/packages/charsets.pkc
  29. 二进制
      hutool-script/.jython_cache/packages/cldrdata.pkc
  30. 二进制
      hutool-script/.jython_cache/packages/deploy.pkc
  31. 二进制
      hutool-script/.jython_cache/packages/dnsns.pkc
  32. 二进制
      hutool-script/.jython_cache/packages/groovy-3.0.2.pkc
  33. 二进制
      hutool-script/.jython_cache/packages/groovy-ant-3.0.2.pkc
  34. 二进制
      hutool-script/.jython_cache/packages/groovy-astbuilder-3.0.2.pkc
  35. 二进制
      hutool-script/.jython_cache/packages/groovy-cli-picocli-3.0.2.pkc
  36. 二进制
      hutool-script/.jython_cache/packages/groovy-console-3.0.2.pkc
  37. 二进制
      hutool-script/.jython_cache/packages/groovy-datetime-3.0.2.pkc
  38. 二进制
      hutool-script/.jython_cache/packages/groovy-docgenerator-3.0.2.pkc
  39. 二进制
      hutool-script/.jython_cache/packages/groovy-groovydoc-3.0.2.pkc
  40. 二进制
      hutool-script/.jython_cache/packages/groovy-groovysh-3.0.2.pkc
  41. 二进制
      hutool-script/.jython_cache/packages/groovy-jmx-3.0.2.pkc
  42. 二进制
      hutool-script/.jython_cache/packages/groovy-json-3.0.2.pkc
  43. 二进制
      hutool-script/.jython_cache/packages/groovy-jsr223-3.0.2.pkc
  44. 二进制
      hutool-script/.jython_cache/packages/groovy-macro-3.0.2.pkc
  45. 二进制
      hutool-script/.jython_cache/packages/groovy-nio-3.0.2.pkc
  46. 二进制
      hutool-script/.jython_cache/packages/groovy-servlet-3.0.2.pkc
  47. 二进制
      hutool-script/.jython_cache/packages/groovy-sql-3.0.2.pkc
  48. 二进制
      hutool-script/.jython_cache/packages/groovy-swing-3.0.2.pkc
  49. 二进制
      hutool-script/.jython_cache/packages/groovy-templates-3.0.2.pkc
  50. 二进制
      hutool-script/.jython_cache/packages/groovy-test-3.0.2.pkc
  51. 二进制
      hutool-script/.jython_cache/packages/groovy-test-junit5-3.0.2.pkc
  52. 二进制
      hutool-script/.jython_cache/packages/groovy-testng-3.0.2.pkc
  53. 二进制
      hutool-script/.jython_cache/packages/groovy-xml-3.0.2.pkc
  54. 二进制
      hutool-script/.jython_cache/packages/hamcrest-core-1.3.pkc
  55. 二进制
      hutool-script/.jython_cache/packages/idea_rt.pkc
  56. 二进制
      hutool-script/.jython_cache/packages/jaccess.pkc
  57. 二进制
      hutool-script/.jython_cache/packages/javaparser-core-3.15.13.pkc
  58. 二进制
      hutool-script/.jython_cache/packages/javaws.pkc
  59. 二进制
      hutool-script/.jython_cache/packages/jce.pkc
  60. 二进制
      hutool-script/.jython_cache/packages/jcommander-1.72.pkc
  61. 二进制
      hutool-script/.jython_cache/packages/jfr.pkc
  62. 二进制
      hutool-script/.jython_cache/packages/jfxrt.pkc
  63. 二进制
      hutool-script/.jython_cache/packages/jfxswt.pkc
  64. 二进制
      hutool-script/.jython_cache/packages/jline-2.14.6.pkc
  65. 二进制
      hutool-script/.jython_cache/packages/jsse.pkc
  66. 二进制
      hutool-script/.jython_cache/packages/junit-4.13.pkc
  67. 二进制
      hutool-script/.jython_cache/packages/junit-jupiter-api-5.6.0.pkc
  68. 二进制
      hutool-script/.jython_cache/packages/junit-jupiter-engine-5.6.0.pkc
  69. 二进制
      hutool-script/.jython_cache/packages/junit-platform-commons-1.6.0.pkc
  70. 二进制
      hutool-script/.jython_cache/packages/junit-platform-engine-1.6.0.pkc
  71. 二进制
      hutool-script/.jython_cache/packages/junit-platform-launcher-1.6.0.pkc
  72. 二进制
      hutool-script/.jython_cache/packages/junit-rt.pkc
  73. 二进制
      hutool-script/.jython_cache/packages/junit-vintage-engine-5.6.0.pkc
  74. 二进制
      hutool-script/.jython_cache/packages/junit5-rt.pkc
  75. 二进制
      hutool-script/.jython_cache/packages/jython-2.7.2.pkc
  76. 二进制
      hutool-script/.jython_cache/packages/localedata.pkc
  77. 二进制
      hutool-script/.jython_cache/packages/lombok-1.18.12.pkc
  78. 二进制
      hutool-script/.jython_cache/packages/luaj-jse-3.0.1.pkc
  79. 二进制
      hutool-script/.jython_cache/packages/management-agent.pkc
  80. 二进制
      hutool-script/.jython_cache/packages/nashorn.pkc
  81. 二进制
      hutool-script/.jython_cache/packages/opentest4j-1.2.0.pkc
  82. 二进制
      hutool-script/.jython_cache/packages/packages.idx
  83. 二进制
      hutool-script/.jython_cache/packages/picocli-4.1.4.pkc
  84. 二进制
      hutool-script/.jython_cache/packages/plugin.pkc
  85. 二进制
      hutool-script/.jython_cache/packages/qdox-1.12.1.pkc
  86. 二进制
      hutool-script/.jython_cache/packages/resources.pkc
  87. 二进制
      hutool-script/.jython_cache/packages/rt.pkc
  88. 二进制
      hutool-script/.jython_cache/packages/sunec.pkc
  89. 二进制
      hutool-script/.jython_cache/packages/sunjce_provider.pkc
  90. 二进制
      hutool-script/.jython_cache/packages/sunmscapi.pkc
  91. 二进制
      hutool-script/.jython_cache/packages/sunpkcs11.pkc
  92. 二进制
      hutool-script/.jython_cache/packages/testng-6.14.3.pkc
  93. 二进制
      hutool-script/.jython_cache/packages/tools.pkc
  94. 二进制
      hutool-script/.jython_cache/packages/zipfs.pkc

+ 1 - 0
CHANGELOG.md

@@ -17,6 +17,7 @@
 * 【core   】     增加FastStringWriter
 * 【core   】     增加NumberUtil.ceilDiv方法(pr#858@Github)
 * 【core   】     IdcardUtil增加省份校验(issue#859@Github)
+* 【extra  】     TemplateFactory和TokenizerFactory增加单例的get方法
 
 ### Bug修复
 * 【core   】     修复URLBuilder中请求参数有`&`导致的问题(issue#850@Github)

+ 40 - 4
hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java

@@ -1,5 +1,6 @@
 package cn.hutool.core.lang;
 
+import cn.hutool.core.lang.func.Func0;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ClassUtil;
 import cn.hutool.core.util.ReflectUtil;
@@ -30,11 +31,26 @@ public final class Singleton {
 	 * @param params 构造方法参数
 	 * @return 单例对象
 	 */
-	@SuppressWarnings("unchecked")
 	public static <T> T get(Class<T> clazz, Object... params) {
 		Assert.notNull(clazz, "Class must be not null !");
 		final String key = buildKey(clazz.getName(), params);
-		return (T) POOL.get(key, () -> ReflectUtil.newInstance(clazz, params));
+		return get(key, () -> ReflectUtil.newInstance(clazz, params));
+	}
+
+	/**
+	 * 获得指定类的单例对象<br>
+	 * 对象存在于池中返回,否则创建,每次调用此方法获得的对象为同一个对象<br>
+	 * 注意:单例针对的是类和对象,因此get方法第一次调用时创建的对象始终唯一,也就是说就算参数变更,返回的依旧是第一次创建的对象
+	 *
+	 * @param <T>      单例对象类型
+	 * @param key      自定义键
+	 * @param supplier 单例对象的创建函数
+	 * @return 单例对象
+	 * @since 5.3.3
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T get(String key, Func0<T> supplier) {
+		return (T) POOL.get(key, supplier::call);
 	}
 
 	/**
@@ -60,7 +76,18 @@ public final class Singleton {
 	 */
 	public static void put(Object obj) {
 		Assert.notNull(obj, "Bean object must be not null !");
-		POOL.put(obj.getClass().getName(), obj);
+		put(obj.getClass().getName(), obj);
+	}
+
+	/**
+	 * 将已有对象放入单例中,其Class做为键
+	 *
+	 * @param key 键
+	 * @param obj 对象
+	 * @since 5.3.3
+	 */
+	public static void put(String key, Object obj) {
+		POOL.put(key, obj);
 	}
 
 	/**
@@ -70,11 +97,20 @@ public final class Singleton {
 	 */
 	public static void remove(Class<?> clazz) {
 		if (null != clazz) {
-			POOL.remove(clazz.getName());
+			remove(clazz.getName());
 		}
 	}
 
 	/**
+	 * 移除指定Singleton对象
+	 *
+	 * @param key 键
+	 */
+	public static void remove(String key) {
+		POOL.remove(key);
+	}
+
+	/**
 	 * 清除所有Singleton对象
 	 */
 	public static void destroy() {

+ 54 - 0
hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java

@@ -839,6 +839,27 @@ public class ArrayUtil {
 	}
 
 	/**
+	 * 编辑数组<br>
+	 * 编辑过程通过传入的Editor实现来返回需要的元素内容,这个Editor实现可以实现以下功能:
+	 *
+	 * <pre>
+	 * 1、修改元素对象,返回集合中为修改后的对象
+	 * </pre>
+	 *
+	 * 注意:此方法会修改原数组!
+	 *
+	 * @param <T> 数组元素类型
+	 * @param array 数组
+	 * @param editor 编辑器接口
+	 * @since 5.3.3
+	 */
+	public static <T> void edit(T[] array, Editor<T> editor) {
+		for(int i = 0; i < array.length; i++){
+			array[i] = editor.edit(array[i]);
+		}
+	}
+
+	/**
 	 * 过滤<br>
 	 * 过滤过程通过传入的Filter实现来过滤返回需要的元素内容,这个Filter实现可以实现以下功能:
 	 * 
@@ -2414,6 +2435,39 @@ public class ArrayUtil {
 
 	/**
 	 * 以 conjunction 为分隔符将数组转换为字符串
+	 *
+	 * @param <T> 被处理的集合
+	 * @param array 数组
+	 * @param conjunction 分隔符
+	 * @param editor 每个元素的编辑器,null表示不编辑
+	 * @return 连接后的字符串
+	 * @since 5.3.3
+	 */
+	public static <T> String join(T[] array, CharSequence conjunction, Editor<T> editor) {
+		if (null == array) {
+			return null;
+		}
+
+		final StringBuilder sb = new StringBuilder();
+		boolean isFirst = true;
+		for (T item : array) {
+			if (isFirst) {
+				isFirst = false;
+			} else {
+				sb.append(conjunction);
+			}
+			if(null != editor){
+				item = editor.edit(item);
+			}
+			if(null != item){
+				sb.append(StrUtil.toString(item));
+			}
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 以 conjunction 为分隔符将数组转换为字符串
 	 * 
 	 * @param array 数组
 	 * @param conjunction 分隔符

+ 12 - 0
hutool-extra/pom.xml

@@ -221,6 +221,18 @@
 			<optional>true</optional>
 		</dependency>
 		<dependency>
+			<groupId>com.belerweb</groupId>
+			<artifactId>pinyin4j</artifactId>
+			<version>2.5.1</version>
+			<optional>true</optional>
+		</dependency>
+		<dependency>
+			<groupId>com.github.stuxuhai</groupId>
+			<artifactId>jpinyin</artifactId>
+			<version>1.1.8</version>
+			<optional>true</optional>
+		</dependency>
+		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-test</artifactId>
 			<version>${spring-boot.version}</version>

+ 53 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinEngine.java

@@ -0,0 +1,53 @@
+package cn.hutool.extra.pinyin;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 拼音引擎接口,具体的拼音实现通过实现此接口,完成具体实现功能
+ *
+ * @author looly
+ * @since 5.3.3
+ */
+public interface PinyinEngine {
+
+	/**
+	 * 如果c为汉字,则返回大写拼音;如果c不是汉字,则返回String.valueOf(c)
+	 *
+	 * @param c 任意字符,汉字返回拼音,非汉字原样返回
+	 * @return 汉字返回拼音,非汉字原样返回
+	 */
+	String getPinyin(char c);
+
+	/**
+	 * 获取字符串对应的完整拼音,非中文返回原字符
+	 *
+	 * @param str 字符串
+	 * @param separator 拼音之间的分隔符
+	 * @return 拼音
+	 */
+	String getPinyin(String str, String separator);
+
+	/**
+	 * 将输入字符串转为拼音首字母,其它字符原样返回
+	 *
+	 * @param c 任意字符,汉字返回拼音,非汉字原样返回
+	 * @return 汉字返回拼音,非汉字原样返回
+	 */
+	default char getFirstLetter(char c) {
+		return getPinyin(c).charAt(0);
+	}
+
+	/**
+	 * 将输入字符串转为拼音首字母,其它字符原样返回
+	 *
+	 * @param str 任意字符,汉字返回拼音,非汉字原样返回
+	 * @param separator 分隔符
+	 * @return 汉字返回拼音,非汉字原样返回
+	 */
+	default String getFirstLetter(String str, String separator) {
+		final String splitSeparator = StrUtil.isEmpty(separator) ? "#" : separator;
+		final String[] split = StrUtil.split(getPinyin(str, splitSeparator), splitSeparator);
+		return ArrayUtil.join(split, separator, (s)->String.valueOf(s.charAt(0)));
+	}
+}

+ 33 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinException.java

@@ -0,0 +1,33 @@
+package cn.hutool.extra.pinyin;
+
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 模板异常
+ * 
+ * @author xiaoleilu
+ */
+public class PinyinException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+
+	public PinyinException(Throwable e) {
+		super(ExceptionUtil.getMessage(e), e);
+	}
+
+	public PinyinException(String message) {
+		super(message);
+	}
+
+	public PinyinException(String messageTemplate, Object... params) {
+		super(StrUtil.format(messageTemplate, params));
+	}
+
+	public PinyinException(String message, Throwable throwable) {
+		super(message, throwable);
+	}
+
+	public PinyinException(Throwable throwable, String messageTemplate, Object... params) {
+		super(StrUtil.format(messageTemplate, params), throwable);
+	}
+}

+ 43 - 45
hutool-extra/src/main/java/cn/hutool/extra/pinyin/PinyinUtil.java

@@ -1,87 +1,85 @@
 package cn.hutool.extra.pinyin;
 
-import com.github.promeg.pinyinhelper.Pinyin;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.pinyin.engine.PinyinFactory;
 
 /**
- * 拼音工具类,封装了TinyPinyin
- *
- * <p>
- * TinyPinyin(https://github.com/promeG/TinyPinyin)提供者未提交Maven中央库,<br>
- * 因此使用
- * https://github.com/biezhi/TinyPinyin打包的版本
- * </p>
- *
- * <p>
- * 引入:
- * <pre>
- * &lt;dependency&gt;
- *     &lt;groupId&gt;io.github.biezhi&lt;/groupId&gt;
- *     &lt;artifactId&gt;TinyPinyin&lt;/artifactId&gt;
- *     &lt;version&gt;2.0.3.RELEASE&lt;/version&gt;
- * &lt;/dependency&gt;
- * </pre>
+ * 拼音工具类,封装了TinyPinyin、JPinyin、Pinyin4j,通过SPI自动识别。
  *
  * @author looly
  */
 public class PinyinUtil {
 
+	private static final String CHINESE_REGEX = "[\\u4e00-\\u9fa5]";
+
 	/**
-	 * 自定义拼音全局配置,例如加入自定义字典等
+	 * 获得全局单例的拼音引擎
 	 *
-	 * @param config 配置,通过Pinyin.newConfig().with(dict)添加字典
+	 * @return 全局单例的拼音引擎
 	 */
-	public static void init(Pinyin.Config config) {
-		Pinyin.init(config);
+	public static PinyinEngine getEngine(){
+		return PinyinFactory.get();
 	}
 
 	/**
 	 * 如果c为汉字,则返回大写拼音;如果c不是汉字,则返回String.valueOf(c)
 	 *
-	 * @param c             任意字符,汉字返回拼音,非汉字原样返回
-	 * @param isToUpperCase 是否转换为大写
+	 * @param c 任意字符,汉字返回拼音,非汉字原样返回
 	 * @return 汉字返回拼音,非汉字原样返回
 	 */
-	public static String getPinyin(char c, boolean isToUpperCase) {
-		final String pinyin = Pinyin.toPinyin(c);
-		return isToUpperCase ? pinyin : pinyin.toLowerCase();
+	public static String getPinyin(char c) {
+		return getEngine().getPinyin(c);
 	}
 
 	/**
 	 * 将输入字符串转为拼音,每个字之间的拼音使用空格分隔
 	 *
-	 * @param str           任意字符,汉字返回拼音,非汉字原样返回
-	 * @param isToUpperCase 是否转换为大写
+	 * @param str 任意字符,汉字返回拼音,非汉字原样返回
 	 * @return 汉字返回拼音,非汉字原样返回
 	 */
-	public static String getPinyin(String str, boolean isToUpperCase) {
-		return getPinyin(str, " ", isToUpperCase);
+	public static String getPinyin(String str) {
+		return getPinyin(str, StrUtil.SPACE);
 	}
 
 	/**
 	 * 将输入字符串转为拼音,以字符为单位插入分隔符
 	 *
-	 * @param str           任意字符,汉字返回拼音,非汉字原样返回
-	 * @param separator     每个字拼音之间的分隔符
-	 * @param isToUpperCase 是否转换为大写
+	 * @param str       任意字符,汉字返回拼音,非汉字原样返回
+	 * @param separator 每个字拼音之间的分隔符
 	 * @return 汉字返回拼音,非汉字原样返回
 	 */
-	public static String getPinyin(String str, String separator, boolean isToUpperCase) {
-		final String pinyin = Pinyin.toPinyin(str, separator);
-		return isToUpperCase ? pinyin : pinyin.toLowerCase();
+	public static String getPinyin(String str, String separator) {
+		return getEngine().getPinyin(str, separator);
 	}
 
 	/**
 	 * 将输入字符串转为拼音首字母,其它字符原样返回
 	 *
-	 * @param str           任意字符,汉字返回拼音,非汉字原样返回
-	 * @param isToUpperCase 是否转换为大写
+	 * @param c 任意字符,汉字返回拼音,非汉字原样返回
 	 * @return 汉字返回拼音,非汉字原样返回
 	 */
-	public static char[] getFirstLetter(String str, boolean isToUpperCase) {
-		final char[] result = new char[str.length()];
-		for(int i=0; i < result.length; i++){
-			result[i] = getPinyin(str.charAt(i), isToUpperCase).charAt(0);
-		}
-		return result;
+	public static char getFirstLetter(char c) {
+		return getEngine().getFirstLetter(c);
+	}
+
+	/**
+	 * 将输入字符串转为拼音首字母,其它字符原样返回
+	 *
+	 * @param str       任意字符,汉字返回拼音,非汉字原样返回
+	 * @param separator 分隔符
+	 * @return 汉字返回拼音,非汉字原样返回
+	 */
+	public static String getFirstLetter(String str, String separator) {
+		return getEngine().getFirstLetter(str, separator);
+	}
+
+	/**
+	 * 是否为中文字符
+	 *
+	 * @param c 字符
+	 * @return 是否为中文字符
+	 */
+	public static boolean isChinese(char c) {
+		return '〇' == c || String.valueOf(c).matches(CHINESE_REGEX);
 	}
 }

+ 52 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/PinyinFactory.java

@@ -0,0 +1,52 @@
+package cn.hutool.extra.pinyin.engine;
+
+import cn.hutool.core.lang.Singleton;
+import cn.hutool.core.util.ServiceLoaderUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.pinyin.PinyinEngine;
+import cn.hutool.extra.template.TemplateException;
+import cn.hutool.log.StaticLog;
+
+/**
+ * 简单拼音引擎工厂,用于根据用户引入的拼音库jar,自动创建对应的拼音引擎对象
+ *
+ * @author looly
+ */
+public class PinyinFactory {
+
+	/**
+	 * 获得单例的PinyinEngine
+	 *
+	 * @return 单例的PinyinEngine
+	 */
+	public static PinyinEngine get(){
+		return Singleton.get(PinyinEngine.class.getName(), PinyinFactory::create);
+	}
+
+	/**
+	 * 根据用户引入的拼音引擎jar,自动创建对应的拼音引擎对象<br>
+	 * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎
+	 *
+	 * @return {@link PinyinEngine}
+	 */
+	public static PinyinEngine create() {
+		final PinyinEngine engine = doCreate();
+		StaticLog.debug("Use [{}] Engine As Default.", StrUtil.removeSuffix(engine.getClass().getSimpleName(), "Engine"));
+		return engine;
+	}
+
+	/**
+	 * 根据用户引入的拼音引擎jar,自动创建对应的拼音引擎对象<br>
+	 * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎
+	 *
+	 * @return {@link PinyinEngine}
+	 */
+	private static PinyinEngine doCreate() {
+		final PinyinEngine engine = ServiceLoaderUtil.loadFirstAvailable(PinyinEngine.class);
+		if(null != engine){
+			return engine;
+		}
+
+		throw new TemplateException("No template found ! Please add one of pinyin jar to your project !");
+	}
+}

+ 64 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/JPinyinEngine.java

@@ -0,0 +1,64 @@
+package cn.hutool.extra.pinyin.engine.jpinyin;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.extra.pinyin.PinyinEngine;
+import com.github.stuxuhai.jpinyin.PinyinException;
+import com.github.stuxuhai.jpinyin.PinyinFormat;
+import com.github.stuxuhai.jpinyin.PinyinHelper;
+
+/**
+ * 封装了Jpinyin的引擎。
+ *
+ * <p>
+ * jpinyin(github库作者已删除)封装。
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;com.github.stuxuhai&lt;/groupId&gt;
+ *     &lt;artifactId&gt;jpinyin&lt;/artifactId&gt;
+ *     &lt;version&gt;1.1.8&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ */
+public class JPinyinEngine implements PinyinEngine {
+
+	//设置汉子拼音输出的格式
+	PinyinFormat format;
+
+	public JPinyinEngine(){
+		this(null);
+	}
+
+	public JPinyinEngine(PinyinFormat format){
+		init(format);
+	}
+
+	public void init(PinyinFormat format){
+		if(null == format){
+			// 不加声调
+			format = PinyinFormat.WITHOUT_TONE;
+		}
+		this.format = format;
+	}
+
+
+	@Override
+	public String getPinyin(char c) {
+		String[] results = PinyinHelper.convertToPinyinArray(c, format);
+		return ArrayUtil.isEmpty(results) ? String.valueOf(c) : results[0];
+	}
+
+	@Override
+	public String getPinyin(String str, String separator) {
+		try {
+			return PinyinHelper.convertToPinyinString(str, separator, format);
+		} catch (PinyinException e) {
+			throw new cn.hutool.extra.pinyin.PinyinException(e);
+		}
+	}
+}

+ 20 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/jpinyin/package-info.java

@@ -0,0 +1,20 @@
+/**
+ * 封装了Jpinyin的引擎。
+ *
+ * <p>
+ * jpinyin(github库作者已删除)封装。
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;com.github.stuxuhai&lt;/groupId&gt;
+ *     &lt;artifactId&gt;jpinyin&lt;/artifactId&gt;
+ *     &lt;version&gt;1.1.8&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ */
+package cn.hutool.extra.pinyin.engine.jpinyin;

+ 7 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/package-info.java

@@ -0,0 +1,7 @@
+/**
+ * 拼音具体实现
+ * 
+ * @author looly
+ *
+ */
+package cn.hutool.extra.pinyin.engine;

+ 92 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/Pinyin4jEngine.java

@@ -0,0 +1,92 @@
+package cn.hutool.extra.pinyin.engine.pinyin4j;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.extra.pinyin.PinyinEngine;
+import cn.hutool.extra.pinyin.PinyinException;
+import net.sourceforge.pinyin4j.PinyinHelper;
+import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
+import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
+import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
+import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
+import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
+
+/**
+ * 封装了Pinyin4j的引擎。
+ *
+ * <p>
+ * pinyin4j(http://sourceforge.net/projects/pinyin4j)封装。
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;com.belerweb&lt;/groupId&gt;
+ *     &lt;artifactId&gt;pinyin4j&lt;/artifactId&gt;
+ *     &lt;version&gt;2.5.1&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ */
+public class Pinyin4jEngine implements PinyinEngine {
+
+	//设置汉子拼音输出的格式
+	HanyuPinyinOutputFormat format;
+
+	/**
+	 * 构造
+	 */
+	public Pinyin4jEngine() {
+		this(null);
+	}
+
+	/**
+	 * 构造
+	 *
+	 * @param format 格式
+	 */
+	public Pinyin4jEngine(HanyuPinyinOutputFormat format) {
+		init(format);
+	}
+
+	/**
+	 * 初始化
+	 *
+	 * @param format 格式
+	 */
+	public void init(HanyuPinyinOutputFormat format) {
+		if (null == format) {
+			format = new HanyuPinyinOutputFormat();
+			// 小写
+			format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
+			// 不加声调
+			format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
+			// 'ü' 使用 "v" 代替
+			format.setVCharType(HanyuPinyinVCharType.WITH_V);
+		}
+		this.format = format;
+	}
+
+	@Override
+	public String getPinyin(char c) {
+		String result;
+		try {
+			String[] results = PinyinHelper.toHanyuPinyinStringArray(c, format);
+			result = ArrayUtil.isEmpty(results) ? String.valueOf(c) : results[0];
+		} catch (BadHanyuPinyinOutputFormatCombination e) {
+			result = String.valueOf(c);
+		}
+		return result;
+	}
+
+	@Override
+	public String getPinyin(String str, String separator) {
+		try {
+			return PinyinHelper.toHanYuPinyinString(str, format, separator, true);
+		} catch (BadHanyuPinyinOutputFormatCombination e) {
+			throw new PinyinException(e);
+		}
+	}
+
+}

+ 20 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/pinyin4j/package-info.java

@@ -0,0 +1,20 @@
+/**
+ * 封装了Pinyin4j的引擎。
+ *
+ * <p>
+ * pinyin4j(http://sourceforge.net/projects/pinyin4j)封装。
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;com.belerweb&lt;/groupId&gt;
+ *     &lt;artifactId&gt;pinyin4j&lt;/artifactId&gt;
+ *     &lt;version&gt;2.5.1&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ */
+package cn.hutool.extra.pinyin.engine.pinyin4j;

+ 56 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/tinypinyin/TinyPinyinEngine.java

@@ -0,0 +1,56 @@
+package cn.hutool.extra.pinyin.engine.tinypinyin;
+
+import cn.hutool.extra.pinyin.PinyinEngine;
+import com.github.promeg.pinyinhelper.Pinyin;
+
+/**
+ * 封装了TinyPinyin的引擎。
+ *
+ * <p>
+ * TinyPinyin(https://github.com/promeG/TinyPinyin)提供者未提交Maven中央库,<br>
+ * 因此使用
+ * https://github.com/biezhi/TinyPinyin打包的版本
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;io.github.biezhi&lt;/groupId&gt;
+ *     &lt;artifactId&gt;TinyPinyin&lt;/artifactId&gt;
+ *     &lt;version&gt;2.0.3.RELEASE&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ */
+public class TinyPinyinEngine implements PinyinEngine {
+
+	/**
+	 * 构造
+	 */
+	public TinyPinyinEngine(){
+	}
+
+	/**
+	 * 构造
+	 * @param config 配置
+	 */
+	public TinyPinyinEngine(Pinyin.Config config){
+		Pinyin.init(config);
+	}
+
+	@Override
+	public String getPinyin(char c) {
+		if(false == Pinyin.isChinese(c)){
+			return String.valueOf(c);
+		}
+		return Pinyin.toPinyin(c).toLowerCase();
+	}
+
+	@Override
+	public String getPinyin(String str, String separator) {
+		return Pinyin.toPinyin(str, separator).toLowerCase();
+	}
+
+}

+ 22 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/tinypinyin/package-info.java

@@ -0,0 +1,22 @@
+/**
+ * 封装了TinyPinyin的引擎。
+ *
+ * <p>
+ * TinyPinyin(https://github.com/promeG/TinyPinyin)提供者未提交Maven中央库,<br>
+ * 因此使用
+ * https://github.com/biezhi/TinyPinyin打包的版本
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;io.github.biezhi&lt;/groupId&gt;
+ *     &lt;artifactId&gt;TinyPinyin&lt;/artifactId&gt;
+ *     &lt;version&gt;2.0.3.RELEASE&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ */
+package cn.hutool.extra.pinyin.engine.tinypinyin;

+ 1 - 1
hutool-extra/src/main/java/cn/hutool/extra/template/TemplateUtil.java

@@ -18,7 +18,7 @@ public class TemplateUtil {
 	 * @since 4.1.11
 	 */
 	public static TemplateEngine createEngine() {
-		return createEngine(new TemplateConfig());
+		return TemplateFactory.create();
 	}
 
 	/**

+ 23 - 0
hutool-extra/src/main/java/cn/hutool/extra/template/engine/TemplateFactory.java

@@ -1,5 +1,6 @@
 package cn.hutool.extra.template.engine;
 
+import cn.hutool.core.lang.Singleton;
 import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.ServiceLoaderUtil;
 import cn.hutool.core.util.StrUtil;
@@ -14,6 +15,28 @@ import cn.hutool.log.StaticLog;
  * @author looly
  */
 public class TemplateFactory {
+
+	/**
+	 * 根据用户引入的模板引擎jar,自动创建对应的模板引擎对象<br>
+	 * 获得的是单例的TemplateEngine
+	 *
+	 * @return 单例的TemplateEngine
+	 */
+	public static TemplateEngine get(){
+		return Singleton.get(TemplateEngine.class.getName(), TemplateFactory::create);
+	}
+
+	/**
+	 * 根据用户引入的模板引擎jar,自动创建对应的模板引擎对象<br>
+	 * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎
+	 *
+	 * @return {@link TemplateEngine}
+	 * @since 5.3.3
+	 */
+	public static TemplateEngine create() {
+		return create(new TemplateConfig());
+	}
+
 	/**
 	 * 根据用户引入的模板引擎jar,自动创建对应的模板引擎对象<br>
 	 * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎

+ 13 - 0
hutool-extra/src/main/java/cn/hutool/extra/tokenizer/engine/TokenizerFactory.java

@@ -1,5 +1,6 @@
 package cn.hutool.extra.tokenizer.engine;
 
+import cn.hutool.core.lang.Singleton;
 import cn.hutool.core.util.ServiceLoaderUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.tokenizer.TokenizerEngine;
@@ -13,6 +14,18 @@ import cn.hutool.log.StaticLog;
  *
  */
 public class TokenizerFactory {
+
+	/**
+	 * 根据用户引入的模板引擎jar,自动创建对应的分词引擎对象<br>
+	 * 获得的是单例的TokenizerEngine
+	 *
+	 * @return 单例的TokenizerEngine
+	 * @since 5.3.3
+	 */
+	public static TokenizerEngine get(){
+		return Singleton.get(TokenizerEngine.class.getName(), TokenizerFactory::create);
+	}
+
 	/**
 	 * 根据用户引入的分词引擎jar,自动创建对应的分词引擎对象
 	 * 

+ 3 - 0
hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine

@@ -0,0 +1,3 @@
+cn.hutool.extra.pinyin.engine.tinypinyin.TinyPinyinEngine
+cn.hutool.extra.pinyin.engine.jpinyin.JPinyinEngine
+cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine

+ 5 - 6
hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java

@@ -1,6 +1,5 @@
 package cn.hutool.extra.pinyin;
 
-import cn.hutool.core.util.ArrayUtil;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -8,19 +7,19 @@ public class PinyinUtilTest {
 
 	@Test
 	public void getPinyinTest(){
-		final String pinyin = PinyinUtil.getPinyin("你好", false);
+		final String pinyin = PinyinUtil.getPinyin("你好", " ");
 		Assert.assertEquals("ni hao", pinyin);
 	}
 
 	@Test
 	public void getPinyinUpperCaseTest(){
-		final String pinyin = PinyinUtil.getPinyin("你好怡", true);
-		Assert.assertEquals("NI HAO YI", pinyin);
+		final String pinyin = PinyinUtil.getPinyin("你好怡", " ");
+		Assert.assertEquals("ni hao yi", pinyin);
 	}
 
 	@Test
 	public void getFirstLetterTest(){
-		final char[] result = PinyinUtil.getFirstLetter("H是第一个", false);
-		Assert.assertEquals("h, s, d, y, g", ArrayUtil.join(result, ", "));
+		final String result = PinyinUtil.getFirstLetter("H是第一个", ", ");
+		Assert.assertEquals("h, s, d, y, g", result);
 	}
 }

+ 2 - 12
hutool-log/src/main/java/cn/hutool/log/LogFactory.java

@@ -53,12 +53,7 @@ public abstract class LogFactory {
 	 * @return 日志对象
 	 */
 	public Log getLog(String name) {
-		Log log = logCache.get(name);
-		if (null == log) {
-			log = createLog(name);
-			logCache.put(name, log);
-		}
-		return log;
+		return logCache.computeIfAbsent(name, o -> createLog((String)o));
 	}
 
 	/**
@@ -68,12 +63,7 @@ public abstract class LogFactory {
 	 * @return 日志对象
 	 */
 	public Log getLog(Class<?> clazz) {
-		Log log = logCache.get(clazz);
-		if (null == log) {
-			log = createLog(clazz);
-			logCache.put(clazz, log);
-		}
-		return log;
+		return logCache.computeIfAbsent(clazz, o -> createLog((Class<?>)o));
 	}
 
 	/**

二进制
hutool-script/.jython_cache/packages/access-bridge-64.pkc


二进制
hutool-script/.jython_cache/packages/ant-1.10.7.pkc


二进制
hutool-script/.jython_cache/packages/ant-antlr-1.10.7.pkc


二进制
hutool-script/.jython_cache/packages/ant-junit-1.10.7.pkc


二进制
hutool-script/.jython_cache/packages/ant-launcher-1.10.7.pkc


二进制
hutool-script/.jython_cache/packages/apiguardian-api-1.1.0.pkc


二进制
hutool-script/.jython_cache/packages/charsets.pkc


二进制
hutool-script/.jython_cache/packages/cldrdata.pkc


二进制
hutool-script/.jython_cache/packages/deploy.pkc


二进制
hutool-script/.jython_cache/packages/dnsns.pkc


二进制
hutool-script/.jython_cache/packages/groovy-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-ant-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-astbuilder-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-cli-picocli-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-console-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-datetime-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-docgenerator-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-groovydoc-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-groovysh-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-jmx-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-json-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-jsr223-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-macro-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-nio-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-servlet-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-sql-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-swing-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-templates-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-test-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-test-junit5-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-testng-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/groovy-xml-3.0.2.pkc


二进制
hutool-script/.jython_cache/packages/hamcrest-core-1.3.pkc


二进制
hutool-script/.jython_cache/packages/idea_rt.pkc


二进制
hutool-script/.jython_cache/packages/jaccess.pkc


二进制
hutool-script/.jython_cache/packages/javaparser-core-3.15.13.pkc


二进制
hutool-script/.jython_cache/packages/javaws.pkc


二进制
hutool-script/.jython_cache/packages/jce.pkc


二进制
hutool-script/.jython_cache/packages/jcommander-1.72.pkc


二进制
hutool-script/.jython_cache/packages/jfr.pkc


二进制
hutool-script/.jython_cache/packages/jfxrt.pkc


二进制
hutool-script/.jython_cache/packages/jfxswt.pkc


二进制
hutool-script/.jython_cache/packages/jline-2.14.6.pkc


二进制
hutool-script/.jython_cache/packages/jsse.pkc


二进制
hutool-script/.jython_cache/packages/junit-4.13.pkc


二进制
hutool-script/.jython_cache/packages/junit-jupiter-api-5.6.0.pkc


二进制
hutool-script/.jython_cache/packages/junit-jupiter-engine-5.6.0.pkc


二进制
hutool-script/.jython_cache/packages/junit-platform-commons-1.6.0.pkc


二进制
hutool-script/.jython_cache/packages/junit-platform-engine-1.6.0.pkc


二进制
hutool-script/.jython_cache/packages/junit-platform-launcher-1.6.0.pkc


二进制
hutool-script/.jython_cache/packages/junit-rt.pkc


二进制
hutool-script/.jython_cache/packages/junit-vintage-engine-5.6.0.pkc


二进制
hutool-script/.jython_cache/packages/junit5-rt.pkc


二进制
hutool-script/.jython_cache/packages/jython-2.7.2.pkc


二进制
hutool-script/.jython_cache/packages/localedata.pkc


二进制
hutool-script/.jython_cache/packages/lombok-1.18.12.pkc


二进制
hutool-script/.jython_cache/packages/luaj-jse-3.0.1.pkc


二进制
hutool-script/.jython_cache/packages/management-agent.pkc


二进制
hutool-script/.jython_cache/packages/nashorn.pkc


二进制
hutool-script/.jython_cache/packages/opentest4j-1.2.0.pkc


二进制
hutool-script/.jython_cache/packages/packages.idx


二进制
hutool-script/.jython_cache/packages/picocli-4.1.4.pkc


二进制
hutool-script/.jython_cache/packages/plugin.pkc


二进制
hutool-script/.jython_cache/packages/qdox-1.12.1.pkc


二进制
hutool-script/.jython_cache/packages/resources.pkc


二进制
hutool-script/.jython_cache/packages/rt.pkc


二进制
hutool-script/.jython_cache/packages/sunec.pkc


二进制
hutool-script/.jython_cache/packages/sunjce_provider.pkc


二进制
hutool-script/.jython_cache/packages/sunmscapi.pkc


二进制
hutool-script/.jython_cache/packages/sunpkcs11.pkc


二进制
hutool-script/.jython_cache/packages/testng-6.14.3.pkc


二进制
hutool-script/.jython_cache/packages/tools.pkc


二进制
hutool-script/.jython_cache/packages/zipfs.pkc