需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。

方案一:将方法参数存成JSON字符串,然后JSON反序列化成对象,然后反射调用

目标方法时这样的:

CommandResp sendXXX(BaseCommandApiDTO<XXX> baseCommandApiDTO);

方式一:FastJson

Class mainBody = Class.forName(entity.getMainBodyType());
ParameterizedTypeImpl parameterizedType = new ParameterizedTypeImpl(new Type[]{mainBody}, null, BaseCommandApiDTO.class);
Object obj = JSON.parseObject(entity.getMsgText(), parameterizedType);

CommandResp resp = ReflectUtil.invoke(serviceObj, methodName, obj);

方式二:Jackson

public class ObjectMapperHolder {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    public static ObjectMapper getObjectMapper() {
        objectMapper.registerModule(new Jdk8Module());
        objectMapper.registerModule(new JavaTimeModule());
        return objectMapper;
    }
}


ObjectMapper mapper = ObjectMapperHolder.getObjectMapper();
JavaType javaType = mapper.getTypeFactory().constructParametricType(BaseCommandApiDTO.class, mainBody);
Object obj = mapper.readValue(entity.getMsgText(), javaType);

CommandResp resp = ReflectUtil.invoke(serviceObj, methodName, obj);

实践中发现,这两种方式容易导致OOM

方案二:直接将参数对象存到数据库中

数据库对应字段设置BLOB类型(这里设置的是MEDIUMBLOB) ,对应的java字段类型是byte[]

//  写入对象
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(baseCommandApiDTO);
oos.flush();
byte[] data = bos.toByteArray();

//  读取对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(entity.getMsgObj()));
Object obj = ois.readObject();

最后的最后,优化建议:

1、尽量不要在数据库中存json字符串,如果非要存,建议字段类型设置为json,这样可以节省空间。因为你无法控制json字符串的长度,所以长度设置是个问题,另外json反序列化比较占内存。

2、长度很大的字段(比如blob类型的)建议单独存一张关联表

标签: none

添加新评论