项目操作常见工具类(持续更新中)
1、使用cglib高效拷贝对象属性
注意事项:
- spring-core中已经将cglib集成在其中,不需要导入其他的包,直接使用即可。类路径:
org.springframework.cglib.beans.BeanCopier
- 两个对象中如果相同字段的类型不一致,则无法复制属性值,会导致目标对象的此字段值为null,请保证字段类型保持一致。
- 针对第二点,实体对象中不要使用基础类型(int、long、boolean等),统一使用包装类型(Integer、Long、Boolean等)
对象间属性拷贝在DTO到VO或者PO到VO之间会经常使用,而这个对象属性拷贝不同的实现方案性能差异极大,为保证平台的稳定性,规范的一致性。我们建议各位采用Cglib
的BeanCopier
来实现对象属性拷贝,避免BeanUtils.copyproperties()
这种性能差的方案,核心代码为
// 动态生成用于复制的类
BeanCopier copier = BeanCopier.create(source.getClass(), target.getClass(), false);
// 执行source到target的属性复制
copier.copy(source, target, null);
- 具体示例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AppleDTO {
private String name;
private Integer price;
private String address;
private String weight;
private String createDate;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FoodDTO {
private Integer price;
private String code;
private Integer weight;
private String name;
private Date createDate;
}
AppleDTO source = new AppleDTO();
source.setPrice(new Integer(43));
FoodDTO target = new FoodDTO();
// 动态生成用于复制的类
BeanCopier copier = BeanCopier.create(source.getClass(), target.getClass(), false);
// 执行source到target的属性复制
copier.copy(source, target, null);
if(target.getPrice()==43){
System.out.println("cp success!");
}
2、动态修改注解信息
BaseRemotePush
@TBASClient(addresses = "${thinkive.tbas.push.addresses}")
public interface BaseRemotePush extends AskSenderAware {
/**
* 同步调用
* @param parameters 方法参数
* @return
*/
@Function(value = 2, timeout = 10000L, parameters = {
@Parameter(name = "account_id", value = "123")
})
ResultAdapter methodSync(Map<String, Object> parameters);
/**
* 异步调用
* @param parameters 方法参数
* @return
*/
@Function(value = 1, timeout = 10000L, parameters = {
@Parameter(name = "account_id", value = "123")
})
CompletableFuture<ResultAdapter> methodAsync(Map<String, Object> parameters);
/**
* Reactive模式调用
* @param parameters 方法参数
* @return
*/
@Function(value = 3, timeout = 10000L, parameters = {
@Parameter(name = "account_id", value = "123")
})
Mono<ResultAdapter> methodReactive(Map<String, Object> parameters);
}
DynamicRemoteValue
public class DynamicRemoteValue {
public Class<? extends BaseRemotePush> dynamicValue(Class<? extends BaseRemotePush> baseRemotePushClass, int functionId) {
Method[] declaredMethods = baseRemotePushClass.getDeclaredMethods();
for (Method item : declaredMethods) {
Function annotation = item.getAnnotation(Function.class);
InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
try {
Field f1= invocationHandler.getClass().getDeclaredField("memberValues");
f1.setAccessible(true);
Map r = null;
r = (Map) f1.get(invocationHandler);
r.put("value", functionId);
Annotation[] annotations = item.getAnnotations();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return baseRemotePushClass;
}
public static void printAnnotationInfo(Class<?> baseRemotePush) {
Method[] declaredMethods = baseRemotePush.getDeclaredMethods();
for (Method item : declaredMethods) {
Annotation[] annotations = item.getAnnotations();
for (Annotation annoitem : annotations) {
System.out.println("注解打印:"+annoitem.toString());
}
}
}
}
待研究问题
1、Springsecurity中登录为什么默认只能为键值对即key-value形式?
2、fastdfs中对防盗链的处理?
3、多数据源处理?
4、rabbitmq消息丢失的处理?rabbitmq消息持久化 消息的幂等性
5、枚举的使用
6、spirng循环依赖
7、重复提交
8、导出表格(redis限流)
9、网站的访问量(redis 位图操作)