如何在 Play 的静态方法中使用 play.cache.CacheApi!框架 2.4.2

Posted

技术标签:

【中文标题】如何在 Play 的静态方法中使用 play.cache.CacheApi!框架 2.4.2【英文标题】:How to use the play.cache.CacheApi in a static method in Play! Framework 2.4.2 【发布时间】:2015-08-05 13:29:08 【问题描述】:

我有一个游戏框架应用程序,我已迁移它以在游戏框架 2.4.2 上运行。它为 javascript/html 前端提供 RESTful API。现在我在引入缓存时遇到了一些问题。

LibraryController(将 JSON/HTTP 请求转换为 JSON/HTTP 响应):

public class LibraryController extends Controller 

  public Result getBook(String isbn) 
      Book book = LibraryManager.getBook(isbn);
      BookDto bookDto = DtoMapper.book2BookDtos(book);
      return ok(Json.toJson(bookDto));
  

LibraryManager(将域模型请求转换为域模型响应):

public class LibraryManager 

@Inject CacheApi cache;

public static Book getBook(String isbn) 

    Book book = cache.get(isbn);
    // ...

我遇到的问题是我得到了

non-static variable cache cannot be referenced from a static context

我注入缓存的方式是按照Play 2.4.2 Cache API documentation。当我按照Play 2.2.x Cache API documentation 使用缓存时,我没有遇到这个问题。该版本有一个我可以调用的静态方法。

我该怎么办?我应该让 getBook 非静态应用一些单例模式吗?或者我应该以其他方式访问缓存吗?示例代码肯定会有所帮助!

【问题讨论】:

为什么你的 getBook 方法还是静态的? getBook 之所以是静态的,是因为实例化一个新对象只是为了服务请求和访问数据源(外部 Web API 等)似乎有点过分了。域模型类被实例化。推理无效吗? 在使用 Play 时,您通常不需要任何静态内容。只需在 Controller 中实例化 LibraryManager 并使 getBook 成为非静态的。 对于目前遇到这个问题的任何人,CacheApi 现在已被弃用 - @deprecated Deprecated as of 2.6.0. Use @link SyncCacheApi or @link AsyncCacheApi 【参考方案1】:

使用@Singleton 注解使Guice 知道LibraryManager,从方法中删除静态关键字并将它们拉到接口:

@ImplementedBy(LibraryManager.class)
public interface ILibraryManager 
    //


@Singleton
public class LibraryManager implements ILibraryManager 

    @Inject
    private CacheApi cache;

    @Override
    public Book getBook(String isbn) 
        Book book = cache.get(isbn);
        // ...
    


现在您可以通过接口向控制器注入LibraryManager

public class LibraryController extends Controller 

    @Inject
    private ILibraryManager libraryManager;


恭喜!您将LibraryManager 解耦并以适当的方式与Play 2.4 集成。

【讨论】:

我按照这个答案中的指南进行操作。除了上面的行,我发现我必须将routesGenerator := InjectedRoutesGenerator 添加到 build.sbt,因为我的控制器方法实际上也有 static 关键字。此外,我添加了import com.google.inject.ImplementedBy; @ImplementedBy(LibraryManager.class) public interface ILibraryManager 以配置要使用的实现。【参考方案2】:

在静态函数中获取 CacheApi.class 的实例。

    public class LibraryManager 

    public static Book getBook(String isbn) 
      CacheApi cache = Play.current().injector().instanceOf(CacheApi.class);
      Book book = cache.get(isbn);
    // ...
    

【讨论】:

我会注意到这在 2.5.x 中已被弃用,并在 2.6.x 中被删除。它还引入了耦合,这违背了使用注射器的全部要点。也可以看到answer。

以上是关于如何在 Play 的静态方法中使用 play.cache.CacheApi!框架 2.4.2的主要内容,如果未能解决你的问题,请参考以下文章

在 Play 框架 2.1.4 中将 Helpers.callAction 与没有静态方法的控制器一起使用

在 Play 中调用静态方法!框架控制器不起作用

如何从 Play 框架中的 YAML 固定装置加载(静态嵌套)枚举值?

Playframework 1.x 静态方法如何以线程安全的方式工作

如何在视图页面中使用Play框架和Scala显示图像

对上一篇静态方法进行补充