From 1f554b775913fe9f36a9d5edda620b69a4ec3dba Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 23 Sep 2022 23:45:59 +0800 Subject: [PATCH] fix cod --- .../cn/hutool/core/lang/func/LambdaInfo.java | 129 +++++++++++++----- .../cn/hutool/core/lang/func/LambdaUtil.java | 43 +++--- .../hutool/core/lang/func/SerBiConsumer.java | 8 +- .../cn/hutool/core/lang/func/SerFunction.java | 4 +- .../cn/hutool/core/lang/func/SerSupplier.java | 7 +- .../main/java/cn/hutool/core/map/Dict.java | 15 ++ .../java/cn/hutool/core/lang/DictTest.java | 16 ++- .../extra/template/AbstractTemplate.java | 36 ----- .../cn/hutool/extra/template/Template.java | 37 +++-- .../template/engine/beetl/BeetlTemplate.java | 4 +- .../template/engine/enjoy/EnjoyTemplate.java | 6 +- .../engine/freemarker/FreemarkerTemplate.java | 4 +- .../engine/jetbrick/JetbrickTemplate.java | 4 +- .../template/engine/rythm/RythmTemplate.java | 6 +- .../engine/thymeleaf/ThymeleafTemplate.java | 6 +- .../engine/velocity/VelocityTemplate.java | 6 +- .../template/engine/wit/WitTemplate.java | 3 +- .../main/java/cn/hutool/json/JSONObject.java | 33 +++++ .../java/cn/hutool/setting/AbsSetting.java | 16 +++ .../main/java/cn/hutool/setting/Setting.java | 19 +++ .../java/cn/hutool/setting/dialect/Props.java | 36 ++++- .../java/cn/hutool/setting/PropsTest.java | 10 +- 22 files changed, 314 insertions(+), 134 deletions(-) delete mode 100644 hutool-extra/src/main/java/cn/hutool/extra/template/AbstractTemplate.java diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java index bd62c2b22..43bb0ed90 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaInfo.java @@ -1,5 +1,6 @@ package cn.hutool.core.lang.func; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.classloader.ClassLoaderUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.StrPool; @@ -11,28 +12,42 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; /** - * 存放lambda信息 + * 存放lambda信息
+ * 此类是{@link SerializedLambda}信息的扩充和补充类,包括: + * * * @author VampireAchao */ public class LambdaInfo { private static final Type[] EMPTY_TYPE = new Type[0]; + // 实例对象的方法参数类型 private final Type[] instantiatedMethodParameterTypes; + // 方法或构造的参数类型 private final Type[] parameterTypes; private final Type returnType; + // 方法名或构造名称 private final String name; private final Executable executable; private final Class clazz; private final SerializedLambda lambda; + /** + * 构造 + * + * @param executable 构造对象{@link Constructor}或方法对象{@link Method} + * @param lambda 实现了序列化接口的lambda表达式 + */ public LambdaInfo(final Executable executable, final SerializedLambda lambda) { + Assert.notNull(executable, "executable must be not null!"); // return type final boolean isMethod = executable instanceof Method; final boolean isConstructor = executable instanceof Constructor; Assert.isTrue(isMethod || isConstructor, "Unsupported executable type: " + executable.getClass()); this.returnType = isMethod ? - ((Method)executable).getGenericReturnType() : ((Constructor)executable).getDeclaringClass(); + ((Method) executable).getGenericReturnType() : ((Constructor) executable).getDeclaringClass(); // lambda info this.parameterTypes = executable.getGenericParameterTypes(); @@ -42,15 +57,89 @@ public class LambdaInfo { this.lambda = lambda; // types - final int index = lambda.getInstantiatedMethodType().indexOf(";)"); - this.instantiatedMethodParameterTypes = (index > -1) ? getInstantiatedMethodParamTypes(lambda, index) : EMPTY_TYPE; + final String instantiatedMethodType = lambda.getInstantiatedMethodType(); + final int index = instantiatedMethodType.indexOf(";)"); + this.instantiatedMethodParameterTypes = (index > -1) ? + getInstantiatedMethodParamTypes(instantiatedMethodType.substring(1, index + 1)) : EMPTY_TYPE; + } + + /** + * 实例方法参数类型 + * + * @return 实例方法参数类型 + */ + public Type[] getInstantiatedMethodParameterTypes() { + return instantiatedMethodParameterTypes; + } + + /** + * 获得构造或方法参数类型列表 + * + * @return 参数类型列表 + */ + public Type[] getParameterTypes() { + return parameterTypes; + } + + /** + * 获取返回值类型(方法引用) + * + * @return 返回值类型 + */ + public Type getReturnType() { + return returnType; + } + + /** + * 方法或构造名称 + * + * @return 方法或构造名称 + */ + public String getName() { + return name; + } + + /** + * 字段名称,主要用于方法名称截取,方法名称必须为getXXX、isXXX、setXXX + * + * @return getter或setter对应的字段名称 + */ + public String getFieldName() { + return BeanUtil.getFieldName(getName()); + } + + /** + * 方法或构造对象 + * + * @return 方法或构造对象 + */ + public Executable getExecutable() { + return executable; + } + + /** + * 方法或构造所在类 + * + * @return 方法或构造所在类 + */ + public Class getClazz() { + return clazz; + } + + + /** + * 获得Lambda表达式对象 + * + * @return 获得Lambda表达式对象 + */ + public SerializedLambda getLambda() { + return lambda; } /** * 根据lambda对象的方法签名信息,解析获得实际的参数类型 */ - private Type[] getInstantiatedMethodParamTypes(SerializedLambda lambda, int index) { - final String className = lambda.getInstantiatedMethodType().substring(1, index + 1); + private static Type[] getInstantiatedMethodParamTypes(final String className) { final String[] instantiatedTypeNames = className.split(";"); final Type[] types = new Type[instantiatedTypeNames.length]; for (int i = 0; i < instantiatedTypeNames.length; i++) { @@ -72,32 +161,4 @@ public class LambdaInfo { } return types; } - - public Type[] getInstantiatedMethodParameterTypes() { - return instantiatedMethodParameterTypes; - } - - public Type[] getParameterTypes() { - return parameterTypes; - } - - public Type getReturnType() { - return returnType; - } - - public String getName() { - return name; - } - - public Executable getExecutable() { - return executable; - } - - public Class getClazz() { - return clazz; - } - - public SerializedLambda getLambda() { - return lambda; - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java index 4790332b1..239f845f0 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/LambdaUtil.java @@ -28,27 +28,29 @@ public class LambdaUtil { * 通过对象的方法或类的静态方法引用,获取lambda实现类 * 传入lambda无参数但含有返回值的情况能够匹配到此方法: * * 在以下场景无法获取到正确类型 *
{@code
-	 * // 枚举测试,只能获取到枚举类型
-	 * Class> enumSupplierClass = LambdaUtil.getRealClass(LambdaUtil.LambdaKindEnum.REF_NONE::ordinal);
-	 * Assert.assertEquals(Enum.class, enumSupplierClass);
-	 * // 调用父类方法,只能获取到父类类型
-	 * Class> superSupplierClass = LambdaUtil.getRealClass(myTeacher::getId);
-	 * Assert.assertEquals(Entity.class, superSupplierClass);
-	 * // 引用父类静态带参方法,只能获取到父类类型
-	 * Class> staticSuperFunctionClass = LambdaUtil.getRealClass(MyTeacher::takeId);
-	 * Assert.assertEquals(Entity.class, staticSuperFunctionClass);
+	 * 		// 枚举测试,只能获取到枚举类型
+	 * 		Class> enumSupplierClass = LambdaUtil.getRealClass(LambdaUtil.LambdaKindEnum.REF_NONE::ordinal);
+	 * 		Assert.assertEquals(Enum.class, enumSupplierClass);
+	 * 		// 调用父类方法,只能获取到父类类型
+	 * 		Class> superSupplierClass = LambdaUtil.getRealClass(myTeacher::getId);
+	 * 		Assert.assertEquals(Entity.class, superSupplierClass);
+	 * 		// 引用父类静态带参方法,只能获取到父类类型
+	 * 		Class> staticSuperFunctionClass = LambdaUtil.getRealClass(MyTeacher::takeId);
+	 * 		Assert.assertEquals(Entity.class, staticSuperFunctionClass);
 	 * }
* * @param func lambda @@ -60,7 +62,10 @@ public class LambdaUtil { @SuppressWarnings("unchecked") public static Class getRealClass(final T func) { final LambdaInfo lambdaInfo = resolve(func); - return (Class) Opt.of(lambdaInfo).map(LambdaInfo::getInstantiatedMethodParameterTypes).filter(types -> types.length != 0).map(types -> types[types.length - 1]).orElseGet(lambdaInfo::getClazz); + return (Class) Opt.of(lambdaInfo) + .map(LambdaInfo::getInstantiatedMethodParameterTypes) + .filter(types -> types.length != 0).map(types -> types[types.length - 1]) + .orElseGet(lambdaInfo::getClazz); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java index 6186c7d90..8fad78920 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java @@ -10,6 +10,8 @@ import java.util.stream.Stream; /** * SerBiConsumer * + * @param 第一个参数类型 + * @param 第二个参数类型 * @author VampireAchao */ @FunctionalInterface @@ -24,7 +26,8 @@ public interface SerBiConsumer extends BiConsumer, Serializable { */ @SafeVarargs static SerBiConsumer multi(final SerBiConsumer... consumers) { - return Stream.of(consumers).reduce(SerBiConsumer::andThen).orElseGet(() -> (o, q) -> {}); + return Stream.of(consumers).reduce(SerBiConsumer::andThen).orElseGet(() -> (o, q) -> { + }); } /** @@ -79,6 +82,7 @@ public interface SerBiConsumer extends BiConsumer, Serializable { * @return 什么也不做 */ static SerBiConsumer nothing() { - return (l, r) -> {}; + return (l, r) -> { + }; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java index 2e2c5b395..66af05eba 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java @@ -30,10 +30,10 @@ public interface SerFunction extends Function, Serializable { * @return the function result */ @Override - default R apply(T t) { + default R apply(final T t) { try { return applying(t); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java index 94d156b8b..7ea302bfb 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java @@ -11,9 +11,10 @@ import java.util.stream.Stream; * * @author VampireAchao * @see Supplier + * @param 返回值类型 */ @FunctionalInterface -public interface SerSupplier extends Supplier, Serializable { +public interface SerSupplier extends Supplier, Serializable { /** * Gets a result. @@ -21,7 +22,7 @@ public interface SerSupplier extends Supplier, Serializable { * @return a result * @throws Exception wrapped checked exceptions */ - T getting() throws Exception; + R getting() throws Exception; /** * Gets a result. @@ -29,7 +30,7 @@ public interface SerSupplier extends Supplier, Serializable { * @return a result */ @Override - default T get() { + default R get() { try { return getting(); } catch (final Exception e) { diff --git a/hutool-core/src/main/java/cn/hutool/core/map/Dict.java b/hutool-core/src/main/java/cn/hutool/core/map/Dict.java index f75b6aa62..4883c6e31 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/Dict.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/Dict.java @@ -7,7 +7,9 @@ import cn.hutool.core.collection.SetUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.exceptions.CloneRuntimeException; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.func.LambdaInfo; import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.lang.func.SerFunction; import cn.hutool.core.lang.func.SerSupplier; import cn.hutool.core.lang.getter.TypeGetter; @@ -352,6 +354,19 @@ public class Dict extends CustomKeyMap implements TypeGetter 参数类型 + * @param 返回值类型 + * @return 获取表达式对应属性和返回的对象 + */ + public T get(final SerFunction func) { + final LambdaInfo lambdaInfo = LambdaUtil.resolve(func); + return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType()); + } + /** * 获得特定类型值 * diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/DictTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/DictTest.java index b4ba070f5..8bfcbcb43 100755 --- a/hutool-core/src/test/java/cn/hutool/core/lang/DictTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/DictTest.java @@ -3,14 +3,15 @@ package cn.hutool.core.lang; import cn.hutool.core.builder.GenericBuilder; import cn.hutool.core.date.DateTime; import cn.hutool.core.map.Dict; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import org.junit.Assert; import org.junit.Test; import java.util.HashMap; import java.util.Map; -import static cn.hutool.core.lang.OptTest.User; - public class DictTest { @Test public void dictTest(){ @@ -70,5 +71,16 @@ public class DictTest { dict.setFields(user::getNickname, user::getUsername); Assert.assertEquals("hutool", dict.get("username")); Assert.assertNull(dict.get("nickname")); + + // get by lambda + Assert.assertEquals("hutool", dict.get(User::getUsername)); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + static class User { + private String username; + private String nickname; } } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/AbstractTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/AbstractTemplate.java deleted file mode 100644 index bbb32b5f7..000000000 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/AbstractTemplate.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.hutool.extra.template; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.StringWriter; -import java.util.Map; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IoUtil; - -/** - * 抽象模板,提供将模板融合后写出到文件、返回字符串等方法 - * - * @author looly - * - */ -public abstract class AbstractTemplate implements Template{ - - @Override - public void render(final Map bindingMap, final File file) { - BufferedOutputStream out = null; - try { - out = FileUtil.getOutputStream(file); - this.render(bindingMap, out); - } finally { - IoUtil.close(out); - } - } - - @Override - public String render(final Map bindingMap) { - final StringWriter writer = new StringWriter(); - render(bindingMap, writer); - return writer.toString(); - } -} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java b/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java index e9b92a034..feb6dca32 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/Template.java @@ -1,46 +1,63 @@ package cn.hutool.extra.template; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; + +import java.io.BufferedOutputStream; import java.io.File; import java.io.OutputStream; +import java.io.StringWriter; import java.io.Writer; import java.util.Map; /** * 抽象模板接口 - * - * @author looly * + * @author looly */ public interface Template { /** * 将模板与绑定参数融合后输出到Writer - * + * * @param bindingMap 绑定的参数,此Map中的参数会替换模板中的变量 - * @param writer 输出 + * @param writer 输出 */ void render(Map bindingMap, Writer writer); /** * 将模板与绑定参数融合后输出到流 - * + * * @param bindingMap 绑定的参数,此Map中的参数会替换模板中的变量 - * @param out 输出 + * @param out 输出 */ void render(Map bindingMap, OutputStream out); /** * 写出到文件 + * * @param bindingMap 绑定的参数,此Map中的参数会替换模板中的变量 - * @param file 输出到的文件 + * @param file 输出到的文件 */ - void render(Map bindingMap, File file); + default void render(final Map bindingMap, final File file) { + BufferedOutputStream out = null; + try { + out = FileUtil.getOutputStream(file); + this.render(bindingMap, out); + } finally { + IoUtil.close(out); + } + } /** * 将模板与绑定参数融合后返回为字符串 - * + * * @param bindingMap 绑定的参数,此Map中的参数会替换模板中的变量 * @return 融合后的内容 */ - String render(Map bindingMap); + default String render(final Map bindingMap) { + final StringWriter writer = new StringWriter(); + render(bindingMap, writer); + return writer.toString(); + } } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/beetl/BeetlTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/beetl/BeetlTemplate.java index 9b43150b0..0dfb472a8 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/beetl/BeetlTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/beetl/BeetlTemplate.java @@ -1,6 +1,6 @@ package cn.hutool.extra.template.engine.beetl; -import cn.hutool.extra.template.AbstractTemplate; +import cn.hutool.extra.template.Template; import java.io.OutputStream; import java.io.Serializable; @@ -12,7 +12,7 @@ import java.util.Map; * * @author looly */ -public class BeetlTemplate extends AbstractTemplate implements Serializable{ +public class BeetlTemplate implements Template, Serializable{ private static final long serialVersionUID = -8157926902932567280L; private final org.beetl.core.Template rawTemplate; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyTemplate.java index 02448d9fa..97c31d623 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/enjoy/EnjoyTemplate.java @@ -1,6 +1,6 @@ package cn.hutool.extra.template.engine.enjoy; -import cn.hutool.extra.template.AbstractTemplate; +import cn.hutool.extra.template.Template; import java.io.OutputStream; import java.io.Serializable; @@ -13,7 +13,7 @@ import java.util.Map; * @author looly * @since 4.1.9 */ -public class EnjoyTemplate extends AbstractTemplate implements Serializable { +public class EnjoyTemplate implements Template, Serializable { private static final long serialVersionUID = 1L; private final com.jfinal.template.Template rawTemplate; @@ -22,7 +22,7 @@ public class EnjoyTemplate extends AbstractTemplate implements Serializable { * 包装Enjoy模板 * * @param EnjoyTemplate Enjoy的模板对象 {@link com.jfinal.template.Template} - * @return {@link EnjoyTemplate} + * @return {@code EnjoyTemplate} */ public static EnjoyTemplate wrap(final com.jfinal.template.Template EnjoyTemplate) { return (null == EnjoyTemplate) ? null : new EnjoyTemplate(EnjoyTemplate); diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerTemplate.java index c1efec5dc..0540ff76b 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/freemarker/FreemarkerTemplate.java @@ -2,7 +2,7 @@ package cn.hutool.extra.template.engine.freemarker; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; -import cn.hutool.extra.template.AbstractTemplate; +import cn.hutool.extra.template.Template; import cn.hutool.extra.template.TemplateException; import java.io.IOException; @@ -17,7 +17,7 @@ import java.util.Map; * * @author looly */ -public class FreemarkerTemplate extends AbstractTemplate implements Serializable{ +public class FreemarkerTemplate implements Template, Serializable{ private static final long serialVersionUID = -8157926902932567280L; freemarker.template.Template rawTemplate; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java index 47157c6bb..31ee80a07 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/jetbrick/JetbrickTemplate.java @@ -2,7 +2,7 @@ package cn.hutool.extra.template.engine.jetbrick; import cn.hutool.core.convert.Convert; import cn.hutool.core.reflect.TypeReference; -import cn.hutool.extra.template.AbstractTemplate; +import cn.hutool.extra.template.Template; import jetbrick.template.JetTemplate; import java.io.OutputStream; @@ -17,7 +17,7 @@ import java.util.Map; * @author looly * @since 5.7.21 */ -public class JetbrickTemplate extends AbstractTemplate implements Serializable{ +public class JetbrickTemplate implements Template, Serializable{ private static final long serialVersionUID = 1L; private final JetTemplate rawTemplate; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/rythm/RythmTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/rythm/RythmTemplate.java index 324ab54c2..b746ea3f2 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/rythm/RythmTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/rythm/RythmTemplate.java @@ -2,7 +2,7 @@ package cn.hutool.extra.template.engine.rythm; import cn.hutool.core.convert.Convert; import cn.hutool.core.reflect.TypeReference; -import cn.hutool.extra.template.AbstractTemplate; +import cn.hutool.extra.template.Template; import java.io.OutputStream; import java.io.Serializable; @@ -15,7 +15,7 @@ import java.util.Map; * @author looly * */ -public class RythmTemplate extends AbstractTemplate implements Serializable { +public class RythmTemplate implements Template, Serializable { private static final long serialVersionUID = -132774960373894911L; private final org.rythmengine.template.ITemplate rawTemplate; @@ -24,7 +24,7 @@ public class RythmTemplate extends AbstractTemplate implements Serializable { * 包装Rythm模板 * * @param template Rythm的模板对象 {@link org.rythmengine.template.ITemplate} - * @return {@link RythmTemplate} + * @return {@code RythmTemplate} */ public static RythmTemplate wrap(final org.rythmengine.template.ITemplate template) { return (null == template) ? null : new RythmTemplate(template); diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafTemplate.java index 268af8527..3fe35f0e1 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/thymeleaf/ThymeleafTemplate.java @@ -5,7 +5,7 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.reflect.TypeReference; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.ObjUtil; -import cn.hutool.extra.template.AbstractTemplate; +import cn.hutool.extra.template.Template; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; @@ -22,7 +22,7 @@ import java.util.Map; * @author looly * @since 4.1.11 */ -public class ThymeleafTemplate extends AbstractTemplate implements Serializable { +public class ThymeleafTemplate implements Template, Serializable { private static final long serialVersionUID = 781284916568562509L; private final TemplateEngine engine; @@ -35,7 +35,7 @@ public class ThymeleafTemplate extends AbstractTemplate implements Serializable * @param engine Thymeleaf的模板引擎对象 {@link TemplateEngine} * @param template 模板路径或模板内容 * @param charset 编码 - * @return {@link ThymeleafTemplate} + * @return {@code ThymeleafTemplate} */ public static ThymeleafTemplate wrap(final TemplateEngine engine, final String template, final Charset charset) { return (null == engine) ? null : new ThymeleafTemplate(engine, template, charset); diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/velocity/VelocityTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/velocity/VelocityTemplate.java index 29110e57a..08db8f269 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/velocity/VelocityTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/velocity/VelocityTemplate.java @@ -3,9 +3,9 @@ package cn.hutool.extra.template.engine.velocity; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.IoUtil; import cn.hutool.core.reflect.TypeReference; -import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.text.StrUtil; -import cn.hutool.extra.template.AbstractTemplate; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.extra.template.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; @@ -20,7 +20,7 @@ import java.util.Map; * @author looly * */ -public class VelocityTemplate extends AbstractTemplate implements Serializable { +public class VelocityTemplate implements Template, Serializable { private static final long serialVersionUID = -132774960373894911L; private final org.apache.velocity.Template rawTemplate; diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitTemplate.java index 54c6c69f3..6f2633f62 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitTemplate.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/wit/WitTemplate.java @@ -2,7 +2,6 @@ package cn.hutool.extra.template.engine.wit; import cn.hutool.core.convert.Convert; import cn.hutool.core.reflect.TypeReference; -import cn.hutool.extra.template.AbstractTemplate; import org.febit.wit.Template; import java.io.OutputStream; @@ -15,7 +14,7 @@ import java.util.Map; * * @author looly */ -public class WitTemplate extends AbstractTemplate implements Serializable{ +public class WitTemplate implements cn.hutool.extra.template.Template, Serializable{ private static final long serialVersionUID = 1L; private final Template rawTemplate; diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java index 6179a5d1c..7b95980e4 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -1,6 +1,10 @@ package cn.hutool.json; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.func.LambdaInfo; +import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.lang.func.SerFunction; +import cn.hutool.core.lang.func.SerSupplier; import cn.hutool.core.lang.mutable.MutableEntry; import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapWrapper; @@ -12,6 +16,7 @@ import java.io.StringWriter; import java.io.Writer; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.function.Predicate; @@ -176,6 +181,18 @@ public class JSONObject extends MapWrapper implements JSON, JSON return this.getOrDefault(key, defaultValue); } + /** + * 根据lambda的方法引用,获取 + * @param func 方法引用 + * @param

参数类型 + * @param 返回值类型 + * @return 获取表达式对应属性和返回的对象 + */ + public T get(final SerFunction func){ + final LambdaInfo lambdaInfo = LambdaUtil.resolve(func); + return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType()); + } + /** * PUT 键值对到JSONObject中,在忽略null模式下,如果值为{@code null},将此键移除 * @@ -202,6 +219,22 @@ public class JSONObject extends MapWrapper implements JSON, JSON return this; } + /** + * 通过lambda批量设置值
+ * 实际使用时,可以使用getXXX的方法引用来完成键值对的赋值: + *

+	 *     User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
+	 *     (new JSONObject()).setFields(user::getNickname, user::getUsername);
+	 * 
+ * + * @param fields lambda,不能为空 + * @return this + */ + public JSONObject setFields(final SerSupplier... fields) { + Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get())); + return this; + } + /** * 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略 * diff --git a/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java b/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java index 1b35526a5..1023bd024 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/AbsSetting.java @@ -3,6 +3,9 @@ package cn.hutool.setting; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.ValueProvider; +import cn.hutool.core.lang.func.LambdaInfo; +import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.lang.func.SerFunction; import cn.hutool.core.lang.getter.GroupedTypeGetter; import cn.hutool.core.lang.getter.TypeGetter; import cn.hutool.core.reflect.ConstructorUtil; @@ -35,6 +38,19 @@ public abstract class AbsSetting implements TypeGetter, return ObjUtil.defaultIfNull(getObjByGroup(key, DEFAULT_GROUP), defaultValue); } + /** + * 根据lambda的方法引用,获取 + * + * @param func 方法引用 + * @param

参数类型 + * @param 返回值类型 + * @return 获取表达式对应属性和返回的对象 + */ + public T get(final SerFunction func) { + final LambdaInfo lambdaInfo = LambdaUtil.resolve(func); + return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType()); + } + /** * 获得字符串类型值,如果字符串为{@code null}或者""返回默认值 * diff --git a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java index d87f4e3ba..853cb86c6 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/Setting.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/Setting.java @@ -10,6 +10,8 @@ import cn.hutool.core.io.watch.SimpleWatcher; import cn.hutool.core.io.watch.WatchMonitor; import cn.hutool.core.io.watch.WatchUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.lang.func.SerSupplier; import cn.hutool.core.text.StrUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharsetUtil; @@ -21,6 +23,7 @@ import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.WatchEvent; +import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; @@ -577,6 +580,22 @@ public class Setting extends AbsSetting implements Map { return this; } + /** + * 通过lambda批量设置值
+ * 实际使用时,可以使用getXXX的方法引用来完成键值对的赋值: + *

+	 *     User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
+	 *     Setting.of().setFields(user::getNickname, user::getUsername);
+	 * 
+ * + * @param fields lambda,不能为空 + * @return this + */ + public Setting setFields(final SerSupplier... fields) { + Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get())); + return this; + } + /** * 将键值对加入到对应分组中
* 此方法用于与getXXX统一参数顺序 diff --git a/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java b/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java index 6d2e24cc7..26854fe9a 100644 --- a/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java +++ b/hutool-setting/src/main/java/cn/hutool/setting/dialect/Props.java @@ -11,6 +11,10 @@ import cn.hutool.core.io.watch.SimpleWatcher; import cn.hutool.core.io.watch.WatchMonitor; import cn.hutool.core.io.watch.WatchUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.func.LambdaInfo; +import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.lang.func.SerFunction; +import cn.hutool.core.lang.func.SerSupplier; import cn.hutool.core.lang.getter.TypeGetter; import cn.hutool.core.map.MapUtil; import cn.hutool.core.reflect.ConstructorUtil; @@ -27,6 +31,7 @@ import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.WatchEvent; +import java.util.Arrays; import java.util.Properties; /** @@ -230,6 +235,19 @@ public final class Props extends Properties implements TypeGetter return ObjUtil.defaultIfNull(getProperty(StrUtil.str(key)), defaultValue); } + /** + * 根据lambda的方法引用,获取 + * + * @param func 方法引用 + * @param

参数类型 + * @param 返回值类型 + * @return 获取表达式对应属性和返回的对象 + */ + public T get(final SerFunction func) { + final LambdaInfo lambdaInfo = LambdaUtil.resolve(func); + return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType()); + } + /** * 获取并删除键值对,当指定键对应值非空时,返回并删除这个值,后边的键对应的值不再查找 * @@ -353,10 +371,26 @@ public final class Props extends Properties implements TypeGetter * @param key 属性键 * @param value 属性值 */ - public void setProperty(final String key, final Object value) { + public void set(final String key, final Object value) { super.setProperty(key, value.toString()); } + /** + * 通过lambda批量设置值
+ * 实际使用时,可以使用getXXX的方法引用来完成键值对的赋值: + *

+	 *     User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
+	 *     Setting.of().setFields(user::getNickname, user::getUsername);
+	 * 
+ * + * @param fields lambda,不能为空 + * @return this + */ + public Props setFields(final SerSupplier... fields) { + Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get())); + return this; + } + /** * 持久化当前设置,会覆盖掉之前的设置 * diff --git a/hutool-setting/src/test/java/cn/hutool/setting/PropsTest.java b/hutool-setting/src/test/java/cn/hutool/setting/PropsTest.java index 8a7262769..0cbac36bb 100644 --- a/hutool-setting/src/test/java/cn/hutool/setting/PropsTest.java +++ b/hutool-setting/src/test/java/cn/hutool/setting/PropsTest.java @@ -67,11 +67,11 @@ public class PropsTest { public void toBeanWithNullPrefixTest(){ final Props configProp = new Props(); - configProp.setProperty("createTime", Objects.requireNonNull(DateUtil.parse("2020-01-01"))); - configProp.setProperty("isInit", true); - configProp.setProperty("stairPlan", 1); - configProp.setProperty("stageNum", 2); - configProp.setProperty("version", 3); + configProp.set("createTime", Objects.requireNonNull(DateUtil.parse("2020-01-01"))); + configProp.set("isInit", true); + configProp.set("stairPlan", 1); + configProp.set("stageNum", 2); + configProp.set("version", 3); final SystemConfig systemConfig = configProp.toBean(SystemConfig.class); Assert.assertEquals(DateUtil.parse("2020-01-01"), systemConfig.getCreateTime());