动态实体
目标
在原有数据基础上动态增加数据(删除).
应用场景: 在权限项目中可用来根据不同的设置来创建新的实体作为返回.
方法
通过 json工具库(fastjson,jackjson,gson...) 将查询出来的实体转换成 map 对象,将不允许显示的属性从 map 对象中移除. 通过 CGLIB 转换成新的实体即可
依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.2.4</version>
</dependency>
编码
import com.fasterxml.jackson.databind.ObjectMapper;
import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.BeanMap;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
//import org.springframework.cglib.beans.BeanGenerator;
//import org.springframework.cglib.beans.BeanMap;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.Map;
public class ReflectUtil {
public static Object getTarget(Object source, Map<String, Object> addProperties) {
// 获取原始数据的value
PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(source);
Map<String, Class> propertyMap = new HashMap<>();
for (PropertyDescriptor d : descriptors) {
if (!"class".equalsIgnoreCase(d.getName())) {
propertyMap.put(d.getName(), d.getPropertyType());
}
}
// 增加数据的值
addProperties.forEach((k, v) -> propertyMap.put(k, v.getClass()));
// 创建原始数据的实体对象
DynamicBean dynamicBean = new DynamicBean(source.getClass(), propertyMap);
// 老数据
propertyMap.forEach((k, v) -> {
try {
if (!addProperties.containsKey(k)) {
dynamicBean.setValue(k, propertyUtilsBean.getNestedProperty(source, k));
}
} catch (Exception e) {
e.printStackTrace();
}
});
// 添加新数据
addProperties.forEach((k, v) -> {
try {
dynamicBean.setValue(k, v);
} catch (Exception e) {
e.printStackTrace();
}
});
Object target = dynamicBean.getTarget();
return target;
}
public static void main(String[] args) throws Exception {
BaseBase entity = new BaseBase();
Map<String, Object> addProperties = new HashMap() {{
put("username", "username");
put("pwd", "pwd");
put("hcName", "hcName");
put("hcName1", "hcName");
put("hcName2", "hcName");
}};
Object target = getTarget(entity, addProperties);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(target);
System.out.println(json);
StuFat stuFat = new StuFat();
BeanUtils.copyProperties(stuFat, target);
System.out.println();
}
/**
* 动态bean
*/
public static class DynamicBean {
/**
* 目标对象
*/
private Object target;
/**
* 属性集合
*/
private BeanMap beanMap;
public DynamicBean(Class superclass, Map<String, Class> propertyMap) {
this.target = generateBean(superclass, propertyMap);
this.beanMap = BeanMap.create(this.target);
}
/**
* bean 添加属性和值
*
*/
public void setValue(String property, Object value) {
beanMap.put(property, value);
}
/**
* 获取属性值
*
*/
public Object getValue(String property) {
return beanMap.get(property);
}
/**
* 获取对象
*
*/
public Object getTarget() {
return this.target;
}
/**
* 根据属性生成对象
*
*/
private Object generateBean(Class superclass, Map<String, Class> propertyMap) {
BeanGenerator generator = new BeanGenerator();
if (null != superclass) {
generator.setSuperclass(superclass);
}
BeanGenerator.addProperties(generator, propertyMap);
return generator.create();
}
}
}
- 空属性对象,通过一个空属性对象来放最后真正显示的数据
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class BaseBase {
}
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class StuFat {
private String username;
private String pwd;
private String hcName;
}
ReflectUtil.getTarget
和 JSON.parseObject
对比
- 两者都可以通过 Map 的删除 key 来得到一个新的实体对象,但是两者存在差异,通过
JSON.parseObject
创建的对象属性值名称会被暴露但是值会变成空,ReflectUtil.getTarget
就直接没有多余字段
JSON.parseObject
结果如下
{
"hcName": "zs",
"pwd": "zs",
"username": ""
}
ReflectUtil.getTarget
结果如下
{
"hcName": "zs",
"pwd": "zs"
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
@RequestMapping("/hhh")
public class CController {
@GetMapping("/dc")
public Object json() {
// 假设stuFat是查询出来的
StuFat stuFat = new StuFat();
stuFat.setUsername("zs");
stuFat.setPwd("zs");
stuFat.setHcName("zs");
HashMap mapType = changeAttr(stuFat);
// basebase 是没有字段的对象直接一个实体
//{
// "hcName": "zs",
// "pwd": "zs"
//}
BaseBase entity = new BaseBase();
Object target = ReflectUtil.getTarget(entity, mapType);
return target;
}
/**
* 修改实体返回一个HashMap
* @return
*/
private HashMap changeAttr(Object stuFat) {
// 转换成map 对象,
String jsonString = JSONObject.toJSONString(stuFat);
HashMap mapType = JSON.parseObject(jsonString, HashMap.class);
System.out.println(mapType);
// 删除一个属性: 从map中删除
mapType.remove("username");
return mapType;
}
@GetMapping("/db")
public Object jsonDB() {
// 假设stuFat是查询出来的
StuFat stuFat = new StuFat();
stuFat.setUsername("zs");
stuFat.setPwd("zs");
stuFat.setHcName("zs");
HashMap mapType = changeAttr(stuFat);
// 通过 json实现 直接构建: 问题删除的对象会变成null,"" 等表示空的符号
//{
// "hcName": "zs",
// "pwd": "zs",
// "username": ""
//}
String jsonString1 = JSONObject.toJSONString(mapType);
StuFat stuFat1 = JSON.parseObject(jsonString1, StuFat.class);
return stuFat1;
}
}