我试图将数据模型添加到redis缓存中。当我把模型取出来时,我得到了例外
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [byte[]] to type [java.util.concurrent.atomic.AtomicInteger] for value '{53}'; nested exception is java.lang.IllegalArgumentException: Cannot convert String [5] to target class [java.util.concurrent.atomic.AtomicInteger]] with root cause模型是
@RedisHash(value = "ThottleRate", timeToLive = 5)
public class ThottleRate implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String url;
private AtomicInteger rate;
public ThottleRate(String url, int rate) {
super();
this.url = url;
this.rate = new AtomicInteger(rate);
}
public boolean isAllowed(){
if(this.rate.decrementAndGet() <= 0) {
return false;
}
return true;
}调用代码是
try {
option = throttleRateRepository.findById(url);
ThottleRate rate = option.get();
allow = rate.isAllowed();
} catch(NoSuchElementException e) {
throttleRateRepository.save(new ThottleRate(url, 5));
allow = true;
}我想要做的是使用redis缓存来控制功能。它有生存的时间,在此范围内一个url可以被访问很多次。
但当电话是
option = throttleRateRepository.findById(url);这会抛出IllegalArgumentException
这似乎是使用具有生存期和速率的redis缓存的最简单方法。
发布于 2021-11-28 01:22:12
引发此异常是因为Spring不知道如何在加载模型时将存储在Redis中的字节数组反序列化为AtomicInteger类型。您需要为此注册一个数据类型转换器。
下面是示例数据类型转换器:
@Component
@ReadingConverter
public class BytesToAtomicIntegerConverter implements Converter<byte[], AtomicInteger> {
@Override
public AtomicInteger convert(byte[] source) {
if (ObjectUtils.isEmpty(source)) {
return null;
}
int n = NumberUtils.parseNumber(
new String(source, StandardCharsets.UTF_8), Integer.class);
return new AtomicInteger(n);
}
}通过将此bean添加到SpringBoot配置中,可以将其注册到SpringBoot:
@Bean
public RedisCustomConversions redisCustomConversions(
BytesToAtomicIntegerConverter converter) {
return new RedisCustomConversions(List.of(converter));
}一旦数据转换器被注册,错误就会消失。
但是,在实现这样的解决方案时,您必须记住一些事情。这里使用AtomicInteger字段来对特定人员的请求进行计数。如果有多个服务器为请求提供服务,那么不同的服务器最终将在本地内存中存储在此字段中的不同值。由于与Redis的通信需要时间(即使仅在毫秒范围内),该值将由另一台服务器更新的可能性远不是零。如果这种偏差对于用例来说是可以的,那么这可能不是一个问题。
我还建议查看一些可以帮助实现请求节流的现有库。以下是一些例子:
https://stackoverflow.com/questions/70139499
复制相似问题