我知道不能直接将函数/匿名类序列化到数据库,但有哪些替代方案?你知道有什么有用的方法吗?
介绍一下我的情况:我想根据用户的分数授予用户“徽章”。所以我有不同类型的徽章,可以通过扩展此类轻松定义:
class BadgeType(id:Long, name:String, detector:Function1[List[UserScore],Boolean])
检测器成员是一个函数,它遍历分数列表并在用户有资格获得这种类型的徽章时返回 true。
问题是每次我想添加/编辑/修改徽章类型时,我都需要编辑源代码,重新编译整个东西并重新部署服务器。如果我可以将所有 BadgeType 实例持久保存到数据库中,那将会更有用。但是该怎么做呢?
唯一想到的是将函数体作为在运行时评估的脚本(例如:Groovy)。
另一种方法(不涉及数据库)可能是将每个徽章类型放入一个 jar 中,我可以在运行时以某种方式热部署,我想这就是插件系统的工作方式。
你怎么看?
最佳答案
我非常简短的建议是,如果您希望它真正是数据驱动的,则需要实现规则 DSL 和解释器。规则是保存到数据库中的内容,解释器获取规则实例并根据某些上下文对其进行评估。
但在大多数情况下,这有点矫枉过正。最好有一小段实际的 Scala 代码来实现每个徽章的规则,给它们唯一的 ID,然后将 ID 存储在数据库中。
例如:
trait BadgeEval extends Function1[User,Boolean] {
def badgeId: Int
}
object Badge1234 extends BadgeEval {
def badgeId = 1234
def apply(user: User) = {
user.isSufficientlyAwesome // && ...
}
}
您可以拥有一个 BadgeEval 实例的大白名单:
val weDontNeedNoStinkingBadges = Map(
1234 -> Badge1234,
5678 -> Badge5678,
// ...
}
def evaluator(id: Int): Option[BadgeEval] = weDontNeedNoStinkingBadges.get(id)
def doesUserGetBadge(user: User, id: Int) = evaluator(id).map(_(user)).getOrElse(false)
...或者如果你想让它们分离,使用反射:
def badgeEvalClass(id: Int) = Class.forName("com.example.badge.Badge" + id + "$").asInstanceOf[Class[BadgeEval]]
... 如果您对运行时可插入性感兴趣,请尝试 service provider pattern .
关于scala - 将 Function1 序列化到数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8839999/