首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取IllegalArgumentException:在尝试添加包含AtomicInteger int redis缓存的数据时无法将字符串转换为AtomicInteger

获取IllegalArgumentException:在尝试添加包含AtomicInteger int redis缓存的数据时无法将字符串转换为AtomicInteger
EN

Stack Overflow用户
提问于 2021-11-27 23:26:00
回答 1查看 426关注 0票数 1

我试图将数据模型添加到redis缓存中。当我把模型取出来时,我得到了例外

代码语言:javascript
复制
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

模型是

代码语言:javascript
复制
@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;
       }

调用代码是

代码语言:javascript
复制
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可以被访问很多次。

但当电话是

代码语言:javascript
复制
option = throttleRateRepository.findById(url);

这会抛出IllegalArgumentException

这似乎是使用具有生存期和速率的redis缓存的最简单方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-28 01:22:12

引发此异常是因为Spring不知道如何在加载模型时将存储在Redis中的字节数组反序列化为AtomicInteger类型。您需要为此注册一个数据类型转换器。

下面是示例数据类型转换器:

代码语言:javascript
复制
@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:

代码语言:javascript
复制
@Bean
public RedisCustomConversions redisCustomConversions(
  BytesToAtomicIntegerConverter converter) {

  return new RedisCustomConversions(List.of(converter));
}

一旦数据转换器被注册,错误就会消失。

但是,在实现这样的解决方案时,您必须记住一些事情。这里使用AtomicInteger字段来对特定人员的请求进行计数。如果有多个服务器为请求提供服务,那么不同的服务器最终将在本地内存中存储在此字段中的不同值。由于与Redis的通信需要时间(即使仅在毫秒范围内),该值将由另一台服务器更新的可能性远不是零。如果这种偏差对于用例来说是可以的,那么这可能不是一个问题。

我还建议查看一些可以帮助实现请求节流的现有库。以下是一些例子:

  1. 用Java控制Rest
  2. 使用Bucket4j限制Spring的速率
  3. 在Java中实现节流(Spring )
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70139499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档