gpt4 book ai didi

java - 如何使用 kryoSerialzation 将非序列化对象存储到重新缓存中

转载 作者:可可西里 更新时间:2023-11-01 11:24:55 27 4
gpt4 key购买 nike

我在我的 spring boot 应用程序上使用了 redis 缓存,我需要将未知类型的响应对象存储到 redisTemplate 中。所以我在我的 redisTemplates 上使用 kryoSerialzation,

Exception :

org.objenesis.ObjenesisException: java.io.NotSerializableException: class sample.data.redis.model.Student not serializable
at org.objenesis.strategy.SerializingInstantiatorStrategy.newInstantiatorOf(SerializingInstantiatorStrategy.java:58)
at com.esotericsoftware.kryo.Kryo.newInstantiator(Kryo.java:1127)
at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:1136)

Note:

我无法在我的响应对象上实现 Serializable 接口(interface),因为它在我的应用程序中是动态的和未知的类型

pom.xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>4.0.1</version>
</dependency>

KryoRedisSerializer.java

    public class KryoRedisSerializer implements RedisSerializer<Object>{

private final ThreadLocal<Kryo> kryoThreadLocal = new ThreadLocal<Kryo>() {
@Override
protected Kryo initialValue() {
Kryo kryo = new Kryo();
kryo.register(Object.class);
return kryo;
}
};
public KryoRedisSerializer() {
kryoThreadLocal.get().setInstantiatorStrategy((InstantiatorStrategy) new SerializingInstantiatorStrategy());
}

@Override
public byte[] serialize(Object object) throws SerializationException {
// TODO Auto-generated method stub
if (object == null) {
return new byte[0];
}

try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
Output output = new Output(outputStream);
kryoThreadLocal.get().writeClassAndObject(output, object);
return output.toBytes();
} catch (IOException e) {
throw new SerializationException("Failed Serialization", e);
}
}

@Override
public Object deserialize(byte[] bytes) throws SerializationException {
// TODO Auto-generated method stub
if (bytes == null || bytes.length == 0) {
return null;
}
try (Input input = new Input(bytes)) {
return kryoThreadLocal.get().readClassAndObject(input);
}
}
}
}

SpringRadisConfig.java

 @Configuration
public class SpringRadisConfig {
@Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
connectionFactory.setHostName("localhost");
connectionFactory.setPort(6379);
return connectionFactory;
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {

RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory());

redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());

redisTemplate.setValueSerializer(kryoRedisSSerializer());
redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());

redisTemplate.afterPropertiesSet();

return redisTemplate;
}
@Bean
public RedisSerializer<Object> kryoRedisSSerializer() {
return new KryoRedisSSerializer();
}
}

SampleRedisApplication.java(主要方法)

@SpringBootApplication
@ComponentScan(basePackages = "sample.data.redis")
public class SampleRedisApplication implements CommandLineRunner {

@Autowired
private StringRedisTemplate template;

@Autowired
private SpringRadisConfig redisConfig;

@Override
public void run(String... args) throws Exception {/*
ValueOperations<String, String> ops = this.template.opsForValue();
String key = "spring.boot.redis.test";
if (!this.template.hasKey(key)) {
ops.set(key, "Hi Ratheesh ");
}
System.out.println("Found key " + key + ", value=" + ops.get(key));*/

RedisTemplate<String, Object> redisTemplate = redisConfig.redisTemplate();
ValueOperations<String, Object> values = redisTemplate.opsForValue();

try {
Student student = new Student(1L, "Vishal");
values.set("student", student);
Student std = (Student) values.get("student");

System.out.println(std.getId());
System.out.println(std.getName());

} catch(Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
// Close the context so it doesn't stay awake listening for redis
SpringApplication.run(SampleRedisApplication.class, args).close();
}

}

假设 student 是我从远程 API 获取的响应对象,实际上我的 API 响应应用程序中没有任何模型对象定义 (POJO),因为我的 API 响应类型是 (Type T) 即动态节点

我在 github 中找到了解决方案但这不起作用(将对象转换为数组并将其存储在 Redis 中)

最佳答案

后来我决定使用 Redisson 而不是 Jedis 客户端,这可以解决我的序列化问题

CacheManager Config for cachable/cachPut/cacheEvict注解类型实现

@Configuration
@EnableCaching
public class RedissonCacheConfiguration {


/**
* Property holder for holding the Redis cache configuration properties like
* <code>Host, Port, Session Duration</code>, etc.
*
* <p>
* Bean with name <code>redisCacheConfigProperties</code> should be populated with these
* configuration properties and then loaded in the application context.
*/
@Autowired
private RedissonConfigProperties redisCacheConfigProperties;

/**
* Sets the Redis cache configuration properties.
*
* @param redisCacheConfigProperties Property holder for holding the Redis cache configuration
* properties.
*/
public void setRedissonConfigProperties(
final RedissonConfigProperties redisCacheConfigProperties) {
this.redisCacheConfigProperties = redisCacheConfigProperties;
}

@Bean
public CacheManager cacheManager() {

CacheManager cacheManager = new RedissonSpringCacheManager(redissonClient(), getCacheConfigs());
return cacheManager;
}

@Bean
public Map<String, CacheConfig> getCacheConfigs(){
Map<String, CacheConfig> config = new HashMap<String, CacheConfig>();
// ttl = 24 mins, maxIdleTime = 12 mins
config.put("testCache", new CacheConfig(24*60*1000, 12*60*1000));
return config;
}

@Bean
public RedissonClient redissonClient() {
Config config = new Config();
SingleServerConfig singleServerConfig = config.useSingleServer();
// format as redis://127.0.0.1:7181 or rediss://127.0.0.1:7181 for SSL
String schema = redisCacheConfigProperties.isSsl() ? "rediss://" : "";
singleServerConfig.setAddress(schema + redisCacheConfigProperties.getHost() + ":" + redisCacheConfigProperties.getPort());
singleServerConfig.setDatabase(redisCacheConfigProperties.getDatabase());
if (redisCacheConfigProperties.getPassword() != null) {
singleServerConfig.setPassword(redisCacheConfigProperties.getPassword());
}
return Redisson.create(config);
}
}

可缓存注释使用

@Cacheable(cacheNames = "#cacheProperies.cacheName", key = "#cacheProperies.cacheKey", unless = "#result==null")
public Object fetchData( final CacheProperties cacheProperies) {
// If there is no cached data by the given key, then we will return NULL.
return doTheOperation();
}

@CacheEvict(cacheNames = "#cacheProperies.cacheName", key = "#cacheProperies.cacheKey")
public void removeData(final CacheProperties cacheProperies) {
// Deletes the Cached CartInfo.
}

@CachePut(cacheNames = "#cacheProperies.cacheName", key = "#cacheProperies.cacheKey", unless = "#result==null")
public Object cacheData(final Object object, final CacheProperties cacheProperies ) {
// Returns the same object which is received as parameter,
// so that this object will be cached by key '... reference'.
return doTheOperation();
}

关于java - 如何使用 kryoSerialzation 将非序列化对象存储到重新缓存中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48247824/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com