mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix cod
This commit is contained in:
parent
62c80a2184
commit
1f554b7759
@ -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信息<br>
|
||||
* 此类是{@link SerializedLambda}信息的扩充和补充类,包括:
|
||||
* <ul>
|
||||
* <li>实例化后的对象方法参数类型,一般用于方法引用</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
@ -28,27 +28,29 @@ public class LambdaUtil {
|
||||
* 通过对象的方法或类的静态方法引用,获取lambda实现类
|
||||
* 传入lambda无参数但含有返回值的情况能够匹配到此方法:
|
||||
* <ul>
|
||||
* <li>引用特定对象的实例方法:<pre>{@code
|
||||
* MyTeacher myTeacher = new MyTeacher();
|
||||
* Class<MyTeacher> supplierClass = LambdaUtil.getRealClass(myTeacher::getAge);
|
||||
* Assert.assertEquals(MyTeacher.class, supplierClass);
|
||||
* }</pre></li>
|
||||
* <li>引用静态无参方法:<pre>{@code
|
||||
* Class<MyTeacher> staticSupplierClass = LambdaUtil.getRealClass(MyTeacher::takeAge);
|
||||
* Assert.assertEquals(MyTeacher.class, staticSupplierClass);
|
||||
* }</pre></li>
|
||||
* <li>引用特定对象的实例方法:<pre>{@code
|
||||
* MyTeacher myTeacher = new MyTeacher();
|
||||
* Class<MyTeacher> supplierClass = LambdaUtil.getRealClass(myTeacher::getAge);
|
||||
* Assert.assertEquals(MyTeacher.class, supplierClass);
|
||||
* }</pre>
|
||||
* </li>
|
||||
* <li>引用静态无参方法:<pre>{@code
|
||||
* Class<MyTeacher> staticSupplierClass = LambdaUtil.getRealClass(MyTeacher::takeAge);
|
||||
* Assert.assertEquals(MyTeacher.class, staticSupplierClass);
|
||||
* }</pre>
|
||||
* </li>
|
||||
* </ul>
|
||||
* 在以下场景无法获取到正确类型
|
||||
* <pre>{@code
|
||||
* // 枚举测试,只能获取到枚举类型
|
||||
* Class<Enum<?>> enumSupplierClass = LambdaUtil.getRealClass(LambdaUtil.LambdaKindEnum.REF_NONE::ordinal);
|
||||
* Assert.assertEquals(Enum.class, enumSupplierClass);
|
||||
* // 调用父类方法,只能获取到父类类型
|
||||
* Class<Entity<?>> superSupplierClass = LambdaUtil.getRealClass(myTeacher::getId);
|
||||
* Assert.assertEquals(Entity.class, superSupplierClass);
|
||||
* // 引用父类静态带参方法,只能获取到父类类型
|
||||
* Class<Entity<?>> staticSuperFunctionClass = LambdaUtil.getRealClass(MyTeacher::takeId);
|
||||
* Assert.assertEquals(Entity.class, staticSuperFunctionClass);
|
||||
* // 枚举测试,只能获取到枚举类型
|
||||
* Class<Enum<?>> enumSupplierClass = LambdaUtil.getRealClass(LambdaUtil.LambdaKindEnum.REF_NONE::ordinal);
|
||||
* Assert.assertEquals(Enum.class, enumSupplierClass);
|
||||
* // 调用父类方法,只能获取到父类类型
|
||||
* Class<Entity<?>> superSupplierClass = LambdaUtil.getRealClass(myTeacher::getId);
|
||||
* Assert.assertEquals(Entity.class, superSupplierClass);
|
||||
* // 引用父类静态带参方法,只能获取到父类类型
|
||||
* Class<Entity<?>> staticSuperFunctionClass = LambdaUtil.getRealClass(MyTeacher::takeId);
|
||||
* Assert.assertEquals(Entity.class, staticSuperFunctionClass);
|
||||
* }</pre>
|
||||
*
|
||||
* @param func lambda
|
||||
@ -60,7 +62,10 @@ public class LambdaUtil {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <R, T extends Serializable> Class<R> getRealClass(final T func) {
|
||||
final LambdaInfo lambdaInfo = resolve(func);
|
||||
return (Class<R>) Opt.of(lambdaInfo).map(LambdaInfo::getInstantiatedMethodParameterTypes).filter(types -> types.length != 0).map(types -> types[types.length - 1]).orElseGet(lambdaInfo::getClazz);
|
||||
return (Class<R>) Opt.of(lambdaInfo)
|
||||
.map(LambdaInfo::getInstantiatedMethodParameterTypes)
|
||||
.filter(types -> types.length != 0).map(types -> types[types.length - 1])
|
||||
.orElseGet(lambdaInfo::getClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,6 +10,8 @@ import java.util.stream.Stream;
|
||||
/**
|
||||
* SerBiConsumer
|
||||
*
|
||||
* @param <T> 第一个参数类型
|
||||
* @param <U> 第二个参数类型
|
||||
* @author VampireAchao
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@ -24,7 +26,8 @@ public interface SerBiConsumer<T, U> extends BiConsumer<T, U>, Serializable {
|
||||
*/
|
||||
@SafeVarargs
|
||||
static <T, U> SerBiConsumer<T, U> multi(final SerBiConsumer<T, U>... 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<T, U> extends BiConsumer<T, U>, Serializable {
|
||||
* @return 什么也不做
|
||||
*/
|
||||
static <T, U> SerBiConsumer<T, U> nothing() {
|
||||
return (l, r) -> {};
|
||||
return (l, r) -> {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ public interface SerFunction<T, R> extends Function<T, R>, 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);
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@ import java.util.stream.Stream;
|
||||
*
|
||||
* @author VampireAchao
|
||||
* @see Supplier
|
||||
* @param <R> 返回值类型
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SerSupplier<T> extends Supplier<T>, Serializable {
|
||||
public interface SerSupplier<R> extends Supplier<R>, Serializable {
|
||||
|
||||
/**
|
||||
* Gets a result.
|
||||
@ -21,7 +22,7 @@ public interface SerSupplier<T> extends Supplier<T>, 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<T> extends Supplier<T>, Serializable {
|
||||
* @return a result
|
||||
*/
|
||||
@Override
|
||||
default T get() {
|
||||
default R get() {
|
||||
try {
|
||||
return getting();
|
||||
} catch (final Exception e) {
|
||||
|
@ -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<String, Object> implements TypeGetter<Str
|
||||
return getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据lambda的方法引用,获取
|
||||
*
|
||||
* @param func 方法引用
|
||||
* @param <P> 参数类型
|
||||
* @param <T> 返回值类型
|
||||
* @return 获取表达式对应属性和返回的对象
|
||||
*/
|
||||
public <P, T> T get(final SerFunction<P, T> func) {
|
||||
final LambdaInfo lambdaInfo = LambdaUtil.resolve(func);
|
||||
return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -1,7 +1,12 @@
|
||||
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;
|
||||
|
||||
@ -9,7 +14,6 @@ import java.util.Map;
|
||||
* 抽象模板接口
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public interface Template {
|
||||
|
||||
@ -17,7 +21,7 @@ public interface Template {
|
||||
* 将模板与绑定参数融合后输出到Writer
|
||||
*
|
||||
* @param bindingMap 绑定的参数,此Map中的参数会替换模板中的变量
|
||||
* @param writer 输出
|
||||
* @param writer 输出
|
||||
*/
|
||||
void render(Map<?, ?> bindingMap, Writer writer);
|
||||
|
||||
@ -25,16 +29,25 @@ public interface Template {
|
||||
* 将模板与绑定参数融合后输出到流
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将模板与绑定参数融合后返回为字符串
|
||||
@ -42,5 +55,9 @@ public interface Template {
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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<String, Object> implements JSON, JSON
|
||||
return this.getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据lambda的方法引用,获取
|
||||
* @param func 方法引用
|
||||
* @param <P> 参数类型
|
||||
* @param <T> 返回值类型
|
||||
* @return 获取表达式对应属性和返回的对象
|
||||
*/
|
||||
public <P, T> T get(final SerFunction<P, T> 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<String, Object> implements JSON, JSON
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过lambda批量设置值<br>
|
||||
* 实际使用时,可以使用getXXX的方法引用来完成键值对的赋值:
|
||||
* <pre>
|
||||
* User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
|
||||
* (new JSONObject()).setFields(user::getNickname, user::getUsername);
|
||||
* </pre>
|
||||
*
|
||||
* @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值,忽略
|
||||
*
|
||||
|
@ -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<CharSequence>,
|
||||
return ObjUtil.defaultIfNull(getObjByGroup(key, DEFAULT_GROUP), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据lambda的方法引用,获取
|
||||
*
|
||||
* @param func 方法引用
|
||||
* @param <P> 参数类型
|
||||
* @param <T> 返回值类型
|
||||
* @return 获取表达式对应属性和返回的对象
|
||||
*/
|
||||
public <P, T> T get(final SerFunction<P, T> func) {
|
||||
final LambdaInfo lambdaInfo = LambdaUtil.resolve(func);
|
||||
return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得字符串类型值,如果字符串为{@code null}或者""返回默认值
|
||||
*
|
||||
|
@ -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<String, String> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过lambda批量设置值<br>
|
||||
* 实际使用时,可以使用getXXX的方法引用来完成键值对的赋值:
|
||||
* <pre>
|
||||
* User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
|
||||
* Setting.of().setFields(user::getNickname, user::getUsername);
|
||||
* </pre>
|
||||
*
|
||||
* @param fields lambda,不能为空
|
||||
* @return this
|
||||
*/
|
||||
public Setting setFields(final SerSupplier<String>... fields) {
|
||||
Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将键值对加入到对应分组中<br>
|
||||
* 此方法用于与getXXX统一参数顺序
|
||||
|
@ -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<CharSequence>
|
||||
return ObjUtil.defaultIfNull(getProperty(StrUtil.str(key)), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据lambda的方法引用,获取
|
||||
*
|
||||
* @param func 方法引用
|
||||
* @param <P> 参数类型
|
||||
* @param <T> 返回值类型
|
||||
* @return 获取表达式对应属性和返回的对象
|
||||
*/
|
||||
public <P, T> T get(final SerFunction<P, T> 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<CharSequence>
|
||||
* @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批量设置值<br>
|
||||
* 实际使用时,可以使用getXXX的方法引用来完成键值对的赋值:
|
||||
* <pre>
|
||||
* User user = GenericBuilder.of(User::new).with(User::setUsername, "hutool").build();
|
||||
* Setting.of().setFields(user::getNickname, user::getUsername);
|
||||
* </pre>
|
||||
*
|
||||
* @param fields lambda,不能为空
|
||||
* @return this
|
||||
*/
|
||||
public Props setFields(final SerSupplier<?>... fields) {
|
||||
Arrays.stream(fields).forEach(f -> set(LambdaUtil.getFieldName(f), f.get()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 持久化当前设置,会覆盖掉之前的设置
|
||||
*
|
||||
|
@ -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());
|
||||
|
Loading…
x
Reference in New Issue
Block a user