为什么使用 memcached 以后,Play Framework 的 Cache 保持失败?


在 Play Framework 中,开启 memcached 后,一些自定义类型的数据可能无法保存到 Cache 中。比如下面的 Java Bean:

public class PermissionBean {
    public Boolean allOperation = true; // 完全权限
    public Boolean readOperation; // 可读
    public Boolean additionOperation; // 可添加
    public Boolean editOperation; // 可修改
    public Boolean deletionOperation; // 可删除
}

如果将这个 Java Bean 保存到 Cache 中:

PermissionBean permission = new PermissionBean();
Cache.set("permission", permission);

将会出现以下错误:

Cannot cache a non-serializable value of type util.bean.PermissionBean

play.exceptions.CacheException: Cannot cache a non-serializable value of type util.bean.PermissionBean
    at play.cache.Cache.checkSerializable(Cache.java:259)
    at play.cache.Cache.set(Cache.java:92)
    at controllers.SecureAndReady.checkAccessAndReady(SecureAndReady.java:50)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:518)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:511)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:480)
    at play.mvc.ActionInvoker.handleBefores(ActionInvoker.java:338)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:143)
    at Invocation.HTTP Request(Play!)
Caused by: java.io.NotSerializableException: util.bean.PermissionBean
    ... 9 more

如果保存包含该 JavaBean 的集合,比如“Map<String, PermissionBean>”、“List<PermissionBean”等,则会报告另外的错误:

NullPointerException occurred : null

play.exceptions.JavaExecutionException
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:229)
    at Invocation.HTTP Request(Play!)
Caused by: java.lang.NullPointerException
    at net.spy.memcached.transcoders.SerializingTranscoder.encode(SerializingTranscoder.java:166)
    at net.spy.memcached.MemcachedClient.asyncStore(MemcachedClient.java:304)
    at net.spy.memcached.MemcachedClient.set(MemcachedClient.java:892)
    at play.cache.MemcachedImpl.set(MemcachedImpl.java:229)
    at play.cache.Cache.set(Cache.java:93)
    at util.service.UserService.getPermissions(UserService.java:207)
    at controllers.SecureAndReady.checkAccessAndReady(SecureAndReady.java:101)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:518)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:511)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:480)
    at play.mvc.ActionInvoker.handleBefores(ActionInvoker.java:338)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:143)
    ... 1 more

使用 Serializable 进行序列化可解决这类问题:

import java.io.Serializable;

public class PermissionBean implements Serializable {
    public Boolean allOperation = true; // 完全权限
    public Boolean readOperation; // 可读
    public Boolean additionOperation; // 可添加
    public Boolean editOperation; // 可修改
    public Boolean deletionOperation; // 可删除
}

前一篇:
后一篇:

发表评论