如何使用Scala-cache API将对象集合存储至Memcache?
使用Scala-cache + Memcached存储自定义Person对象集合的完整实现
首先先确认你已经配置的依赖是没问题的:
libraryDependencies += "com.github.cb372" %% "scalacache-memcached" % "0.24.0"
你已经尝试为Person类实现Codec,但看起来只写了部分encode方法。要顺利存储和读取自定义对象(包括集合),我们需要完整实现Codec的encode和decode逻辑,或者直接用现成的序列化库来简化操作。下面给你两种可行的方案:
方案一:手动实现基于分隔符的Codec(简单直观)
这种方式适合字段内容不会包含特殊分隔符的场景,实现起来很直接:
1. 完善Person类的Codec实现
import scalacache.Codec final case class Person(id: Int, name: String, company: String) // 为单个Person实例实现Codec implicit val personCodec: Codec[Person] = new Codec[Person] { // 把Person的字段用|拼接成字符串,再转成字节数组 override def encode(value: Person): Array[Byte] = { s"${value.id}|${value.name}|${value.company}".getBytes("UTF-8") } // 把字节数组转成字符串,拆分后还原成Person对象 override def decode(bytes: Array[Byte]): Person = { // 用split("\\|", 3)确保company字段里如果有|也不会被拆分 val parts = new String(bytes, "UTF-8").split("\\|", 3) Person(parts(0).toInt, parts(1), parts(2)) } }
2. 实现List[Person]的Codec
要存储集合,我们需要为List[Person]也实现Codec,基于上面的单个Person的Codec来扩展:
implicit val personListCodec: Codec[List[Person]] = new Codec[List[Person]] { // 选一个不会出现在Person字段里的分隔符,比如;;; private val itemSeparator = ";;;" override def encode(value: List[Person]): Array[Byte] = { // 先把每个Person转成字节数组再转成字符串,然后用分隔符拼接 value.map(personCodec.encode) .map(new String(_, "UTF-8")) .mkString(itemSeparator) .getBytes("UTF-8") } override def decode(bytes: Array[Byte]): List[Person] = { new String(bytes, "UTF-8") .split(itemSeparator) .filter(_.nonEmpty) // 过滤空字符串,避免解析出错 .map(str => personCodec.decode(str.getBytes("UTF-8"))) .toList } }
3. 完整的存储/读取示例
import scalacache.memcached.MemcachedCache import scalacache.modes.sync._ // 初始化本地Memcached缓存(假设你的Memcached运行在11211端口) val cache = MemcachedCache("localhost:11211") // 准备要存储的Person集合 val engineeringTeam = List( Person(1, "Alice", "Tech Corp"), Person(2, "Bob", "Design Studio"), Person(3, "Charlie", "Startup Inc") ) // 存入缓存,设置过期时间(可选,比如1小时) cache.put("engineering-team", ttl = Some(scalacache.ttl.Hours(1)))(engineeringTeam) // 从缓存读取 val retrievedTeam = cache.get("engineering-team") retrievedTeam.foreach(team => println(s"从缓存获取到团队:$team"))
方案二:用Jackson实现JSON序列化(更健壮)
如果你的Person字段可能包含特殊字符,或者需要更通用的序列化方式,推荐用Scala-cache提供的Jackson集成,这样不需要手动写Codec:
1. 添加Jackson依赖
libraryDependencies += "com.github.cb372" %% "scalacache-jackson" % "0.24.0"
2. 自动生成Codec
Jackson会自动为case class生成序列化/反序列化逻辑,集合类型也能自动支持:
import scalacache.Codec import scalacache.jackson.JacksonCodec final case class Person(id: Int, name: String, company: String) // 自动生成Person的Codec implicit val personCodec: Codec[Person] = JacksonCodec[Person] // 自动生成List[Person]的Codec implicit val personListCodec: Codec[List[Person]] = JacksonCodec[List[Person]]
3. 存储/读取示例和方案一完全一样
直接用上面的缓存初始化、存取值代码即可,这种方式更省心,也能处理复杂字段的情况。
内容的提问来源于stack exchange,提问作者Puneeth Reddy V
相关产品推荐
相关产品推荐

