mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
invoke support null type
This commit is contained in:
parent
e295779330
commit
b8adadda38
@ -9,6 +9,7 @@
|
||||
* 【core 】 NumberUtil.parseInt等支持123,2.00这类数字(issue#I23ORQ@Gitee)
|
||||
* 【core 】 增加ArrayUtil.isSub、indexOfSub、lastIndexOfSub方法(issue#I23O1K@Gitee)
|
||||
* 【extra 】 增加ValidationUtil(pr#207@Gitee)
|
||||
* 【core 】 反射调用支持传递参数的值为null(pr#1205@Github)
|
||||
|
||||
### Bug修复
|
||||
* 【core 】 修复DateUtil.current使用System.nanoTime的问题(issue#1198@Github)
|
||||
|
@ -2,19 +2,28 @@ package cn.hutool.core.bean;
|
||||
|
||||
/**
|
||||
* 为了解决反射过程中,需要传递null参数,但是会丢失参数类型而设立的包装类
|
||||
*
|
||||
* @param <T> Null值对应的类型
|
||||
* @author Lillls
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public class NullWrapperBean {
|
||||
public class NullWrapperBean<T> {
|
||||
|
||||
private final Class<?> mClasses;
|
||||
private final Class<T> clazz;
|
||||
|
||||
/**
|
||||
* @param classes null的类型
|
||||
*/
|
||||
public NullWrapperBean(Class<?> classes) {
|
||||
this.mClasses = classes;
|
||||
}
|
||||
/**
|
||||
* @param clazz null的类型
|
||||
*/
|
||||
public NullWrapperBean(Class<T> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public Class<?> getClasses() {
|
||||
return mClasses;
|
||||
}
|
||||
/**
|
||||
* 获取null值对应的类型
|
||||
*
|
||||
* @return 类型
|
||||
*/
|
||||
public Class<T> getWrappedClass() {
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
@ -140,21 +140,22 @@ public class ClassUtil {
|
||||
* @param objects 对象数组,如果数组中存在{@code null}元素,则此元素被认为是Object类型
|
||||
* @return 类数组
|
||||
*/
|
||||
public static Class<?>[] getClasses(Object... objects) {
|
||||
Class<?>[] classes = new Class<?>[objects.length];
|
||||
Object obj;
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
obj = objects[i];
|
||||
if (obj instanceof NullWrapperBean) {
|
||||
classes[i] = ((NullWrapperBean) obj).getClasses();
|
||||
} else if (null == obj) {
|
||||
classes[i] = Object.class;
|
||||
} else {
|
||||
classes[i] = obj.getClass();
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
public static Class<?>[] getClasses(Object... objects) {
|
||||
Class<?>[] classes = new Class<?>[objects.length];
|
||||
Object obj;
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
obj = objects[i];
|
||||
if (obj instanceof NullWrapperBean) {
|
||||
// 自定义null值的参数类型
|
||||
classes[i] = ((NullWrapperBean<?>) obj).getWrappedClass();
|
||||
} else if (null == obj) {
|
||||
classes[i] = Object.class;
|
||||
} else {
|
||||
classes[i] = obj.getClass();
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定类是否与给定的类名相同
|
||||
|
@ -149,7 +149,7 @@ public class ReflectUtil {
|
||||
*/
|
||||
public static Field getField(Class<?> beanClass, String name) throws SecurityException {
|
||||
final Field[] fields = getFields(beanClass);
|
||||
return ArrayUtil.firstMatch((field)->name.equals(getFieldName(field)), fields);
|
||||
return ArrayUtil.firstMatch((field) -> name.equals(getFieldName(field)), fields);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,7 +191,7 @@ public class ReflectUtil {
|
||||
* 获得一个类中所有字段列表,直接反射获取,无缓存<br>
|
||||
* 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
|
||||
*
|
||||
* @param beanClass 类
|
||||
* @param beanClass 类
|
||||
* @param withSuperClassFields 是否包括父类的字段列表
|
||||
* @return 字段列表
|
||||
* @throws SecurityException 安全检查异常
|
||||
@ -865,84 +865,84 @@ public class ReflectUtil {
|
||||
return invoke(obj, method, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行方法
|
||||
*
|
||||
* <p>
|
||||
* 对于用户传入参数会做必要检查,包括:
|
||||
*
|
||||
* <pre>
|
||||
* 1、忽略多余的参数
|
||||
* 2、参数不够补齐默认值
|
||||
* 3、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 返回对象类型
|
||||
* @param obj 对象,如果执行静态方法,此值为<code>null</code>
|
||||
* @param method 方法(对象方法或static方法都可)
|
||||
* @param args 参数对象
|
||||
* @return 结果
|
||||
* @throws UtilException 一些列异常的包装
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T invoke(Object obj, Method method, Object... args) throws UtilException {
|
||||
setAccessible(method);
|
||||
/**
|
||||
* 执行方法
|
||||
*
|
||||
* <p>
|
||||
* 对于用户传入参数会做必要检查,包括:
|
||||
*
|
||||
* <pre>
|
||||
* 1、忽略多余的参数
|
||||
* 2、参数不够补齐默认值
|
||||
* 3、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 返回对象类型
|
||||
* @param obj 对象,如果执行静态方法,此值为<code>null</code>
|
||||
* @param method 方法(对象方法或static方法都可)
|
||||
* @param args 参数对象
|
||||
* @return 结果
|
||||
* @throws UtilException 一些列异常的包装
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T invoke(Object obj, Method method, Object... args) throws UtilException {
|
||||
setAccessible(method);
|
||||
|
||||
// 检查用户传入参数:
|
||||
// 1、忽略多余的参数
|
||||
// 2、参数不够补齐默认值
|
||||
// 3、通过NullWrapperBean传递的参数,会直接赋值null
|
||||
// 4、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||
// 5、传入参数类型不对应,尝试转换类型
|
||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
final Object[] actualArgs = new Object[parameterTypes.length];
|
||||
if (null != args) {
|
||||
for (int i = 0; i < actualArgs.length; i++) {
|
||||
if (i >= args.length || null == args[i]) {
|
||||
// 越界或者空值
|
||||
actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
|
||||
} else if (args[i] instanceof NullWrapperBean) {
|
||||
//如果是通过NullWrapperBean传递的null参数,直接赋值null
|
||||
actualArgs[i] = null;
|
||||
} else if (!parameterTypes[i].isAssignableFrom(args[i].getClass())) {
|
||||
//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
|
||||
final Object targetValue = Convert.convert(parameterTypes[i], args[i]);
|
||||
if (null != targetValue) {
|
||||
actualArgs[i] = targetValue;
|
||||
}
|
||||
} else {
|
||||
actualArgs[i] = args[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
// 检查用户传入参数:
|
||||
// 1、忽略多余的参数
|
||||
// 2、参数不够补齐默认值
|
||||
// 3、通过NullWrapperBean传递的参数,会直接赋值null
|
||||
// 4、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||
// 5、传入参数类型不对应,尝试转换类型
|
||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
final Object[] actualArgs = new Object[parameterTypes.length];
|
||||
if (null != args) {
|
||||
for (int i = 0; i < actualArgs.length; i++) {
|
||||
if (i >= args.length || null == args[i]) {
|
||||
// 越界或者空值
|
||||
actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
|
||||
} else if (args[i] instanceof NullWrapperBean) {
|
||||
//如果是通过NullWrapperBean传递的null参数,直接赋值null
|
||||
actualArgs[i] = null;
|
||||
} else if (false == parameterTypes[i].isAssignableFrom(args[i].getClass())) {
|
||||
//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
|
||||
final Object targetValue = Convert.convert(parameterTypes[i], args[i]);
|
||||
if (null != targetValue) {
|
||||
actualArgs[i] = targetValue;
|
||||
}
|
||||
} else {
|
||||
actualArgs[i] = args[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs);
|
||||
} catch (Exception e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs);
|
||||
} catch (Exception e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行对象中指定方法
|
||||
* 如果需要传递的参数为null,请使用NullWrapperBean来传递,不然会丢失类型信息
|
||||
*
|
||||
* @param <T> 返回对象类型
|
||||
* @param obj 方法所在对象
|
||||
* @param methodName 方法名
|
||||
* @param args 参数列表
|
||||
* @return 执行结果
|
||||
* @throws UtilException IllegalAccessException包装
|
||||
* @see NullWrapperBean
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static <T> T invoke(Object obj, String methodName, Object... args) throws UtilException {
|
||||
final Method method = getMethodOfObj(obj, methodName, args);
|
||||
if (null == method) {
|
||||
throw new UtilException(StrUtil.format("No such method: [{}]", methodName));
|
||||
}
|
||||
return invoke(obj, method, args);
|
||||
}
|
||||
/**
|
||||
* 执行对象中指定方法
|
||||
* 如果需要传递的参数为null,请使用NullWrapperBean来传递,不然会丢失类型信息
|
||||
*
|
||||
* @param <T> 返回对象类型
|
||||
* @param obj 方法所在对象
|
||||
* @param methodName 方法名
|
||||
* @param args 参数列表
|
||||
* @return 执行结果
|
||||
* @throws UtilException IllegalAccessException包装
|
||||
* @see NullWrapperBean
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static <T> T invoke(Object obj, String methodName, Object... args) throws UtilException {
|
||||
final Method method = getMethodOfObj(obj, methodName, args);
|
||||
if (null == method) {
|
||||
throw new UtilException(StrUtil.format("No such method: [{}]", methodName));
|
||||
}
|
||||
return invoke(obj, method, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置方法为可访问(私有方法可以被外部调用)
|
||||
|
@ -7,10 +7,9 @@ import java.util.List;
|
||||
* bean 校验结果
|
||||
*
|
||||
* @author chengqiang
|
||||
* @since 5.5.0
|
||||
*/
|
||||
|
||||
public class BeanValidationResult {
|
||||
|
||||
/**
|
||||
* 校验是否成功
|
||||
*/
|
||||
@ -25,29 +24,57 @@ public class BeanValidationResult {
|
||||
*
|
||||
* @param success 是否验证成功
|
||||
*/
|
||||
public BeanValidationResult(boolean success){
|
||||
public BeanValidationResult(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否验证通过
|
||||
*
|
||||
* @return 是否验证通过
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否通过
|
||||
*
|
||||
* @param success 是否通过
|
||||
* @return this
|
||||
*/
|
||||
public BeanValidationResult setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误信息列表
|
||||
*
|
||||
* @return 错误信息列表
|
||||
*/
|
||||
public List<ErrorMessage> getErrorMessages() {
|
||||
return errorMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置错误信息列表
|
||||
*
|
||||
* @param errorMessages 错误信息列表
|
||||
* @return this
|
||||
*/
|
||||
public BeanValidationResult setErrorMessages(List<ErrorMessage> errorMessages) {
|
||||
this.errorMessages = errorMessages;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BeanValidationResult addErrorMessage(ErrorMessage errorMessage){
|
||||
/**
|
||||
* 增加错误信息
|
||||
*
|
||||
* @param errorMessage 错误信息
|
||||
* @return this
|
||||
*/
|
||||
public BeanValidationResult addErrorMessage(ErrorMessage errorMessage) {
|
||||
this.errorMessages.add(errorMessage);
|
||||
return this;
|
||||
}
|
||||
|
@ -15,15 +15,27 @@ import java.util.Set;
|
||||
* <p>注意:hibernate-validator还依赖了javax.el,需自行引入。</p>
|
||||
*
|
||||
* @author chengqiang
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public class ValidationUtil {
|
||||
|
||||
/**
|
||||
* 默认{@link Validator} 对象
|
||||
*/
|
||||
private static final Validator validator;
|
||||
|
||||
static {
|
||||
validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取原生{@link Validator} 对象
|
||||
*
|
||||
* @return {@link Validator} 对象
|
||||
*/
|
||||
public static Validator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验对象
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user