【问题标题】:Passing a second argument to Guava Cache load() method将第二个参数传递给 Guava Cache load() 方法
【发布时间】:2018-05-22 18:03:43
【问题描述】:

我之前在这里问过一个关于如何在 Java 中实现 Guava Cache 的问题,见 here。虽然它有效,但我最近注意到 getAllProfile 方法中的一个错误。

private LoadingCache<Integer, List<Profile>> loadingCache = CacheBuilder.newBuilder()
            .refreshAfterWrite(10,TimeUnit.MINUTES)
            .maximumSize(100).build(
            new CacheLoader<Integer, List<Profile>>() {
                @Override
                public List<Profile> load(Integer integer) throws Exception {
                    Profile profile= new Profile();
                    if (integer == null) {
                        integer = 10;
                    }
                    return profileDAO.getAllProfiles(profile, integer);
                }
            }
    );

public List<Profile> getAllProfiles(Profile profile, Integer integer) throws Exception {
        return loadingCache.get(integer);
    }

在方法中,我传入了一个名为profileProfile 对象。这样一来,在服务层,用户可以使用@QueryParam 为工人的个人资料设置一个参数,以查看他们是否仍在工作:

@GET
public List<Profile> getProfiles(@QueryParam("employed") Boolean employed, @QueryParam("size") Integer integer) {
//code for service here.  the value for query param is used in a 
//new Profile object
}

此处创建的配置文件对象通过管理器层向下传递,并进入 DAO 层,其中设置的参数(如使用的布尔值)被解析为 select 语句的参数。

这里的问题是,由于我已经开始使用缓存,布尔值不再被解析。使用 System.out.println 调用该方法以评估所用字段的评估结果为 null。这是有道理的,因为我在缓存管理器中创建了一个新的 Profile 对象,除了缓存 get 方法没有在 getAllProfile 方法中获取配置文件之外,没有调用任何设置器;它只需要大小。

我想我可以通过在 load 方法中添加一个新的 Profile 参数来解决这个问题,如下所示:

private LoadingCache<Integer, List<Profile>> loadingCache = CacheBuilder.newBuilder()
                .refreshAfterWrite(10,TimeUnit.MINUTES)
                .maximumSize(100).build(
                new CacheLoader<Integer, List<Profile>>() {
                    @Override
                    public List<Profile> load(Integer integer) throws Exception {
                        @Override
                            public List<Profile> load(Integer integer, Profile profile) throws Exception {
                                if (integer == null) {
                                    integer = 10;
                                }
                                return profileDAO.getAllProfiles(profile, integer);
                    }
                }
            }
    );

然而,load() 似乎被设计为只接受一个参数,所以这会引发这个错误:

Class 'Anonymous class derived from CacheLoader' must either be declared abstract or implement abstract method 'load(K)' in 'CacheLoader'

重申一下,我需要做的就是将在服务层中创建的配置文件对象传递给管理器层并缓存。这似乎就像将第二个参数传递给 load() 一样简单,但这似乎是不可能的。

编辑:

我已经编辑了 getAllProfiles 方法以使用 Callable:

public List<Profile> getAllProfiles(Profile profile, Integer integer) throws Exception {
        return loadingCache.get(size, new Callable<Profile>() {
            @Override
            public Profile call() throws Exception {
                return profile;
            }
        });
    }

这会产生一个错误,因为我传入的是Profile 而不是List&lt;Profile&gt;。不过,我需要传入profile,以便通过DAO 中的字段解析SQL 语句。

【问题讨论】:

  • 改用Cache.get(key, callable)
  • 您能否提供一个代码示例,说明如何使用可调用函数?我将编辑我的问题以显示我是如何使用它的,但是我发现的文档和示例似乎并不是特别有用。当我尝试使用它来传递配置文件时,当它需要 List 对象时,我收到一个关于我如何传递 Profile 对象的错误。
  • 您的缓存值为List&lt;Profile&gt;,因此您需要将其返回。 profile 是通过匿名类传递的,它允许您调用上面显示的 profileDAO.searchProfile(profile) 方法。
  • 我刚刚意识到,带有搜索配置文件的第二个代码是另一个缓存。我将该类型编辑回 getAllProfiles。

标签: java caching dropwizard google-guava-cache


【解决方案1】:

这是一个例子:

public class ImageCache2 extends CaffeineCache<URL, Image> {
    ImageCache2() {
        this.cache = Caffeine.newBuilder()
                .maximumSize(300)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .refreshAfterWrite(1, TimeUnit.MINUTES)
                .build((k) -> null);
    }
}

只给 build 一个 null 返回,因为我们不使用它。

public static Image LoadImageFromURL(URL url, double w, double h) {
    URLConnection conn;
    Image returnImage;

    try {
        conn = url.openConnection();
    } catch (IOException e1) {
        e1.printStackTrace();
        return null;
    }

    conn.setRequestProperty("User-Agent", "Wget/1.13.4 (linux-gnu)");

    try (InputStream stream = conn.getInputStream()) {
        returnImage = new Image(stream, w, h, true, true);
    } catch (IOException e2) {
        e2.printStackTrace();
        return null;
    }

    return returnImage;
}

这是我真正用来获取物品的代码。

public static void useExecutors(Runnable run) {
     executorServices.execute(run);
}

public void LoadImage(URL url, double w, double h, Consumer<Image> callWhenFinish) {

        useExecutors(() ->
        {
            Image thumbImage = ImageCacheInstance.Cache().get(url, (u) -> LoadImageFromURL(url, w, h));

            Platform.runLater(() ->
            {
                callWhenFinish.accept(thumbImage);
                System.out.println("ImageLoad >> Finish -- " + this);
            });
        });
}

这里是我调用缓存获取方法的地方。 PS:useExecutors 在后台线程中运行它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 2019-07-05
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多