Akka Typed项目类型不匹配求助:UserActor发送消息报错
Akka Typed聊天应用类型不匹配问题解决
错误原因分析
- 核心类型不匹配:在
SendMessageToRoom分支中,你错误地向user.userActor(类型为ActorRef[UserCommand])发送了RoomActor.BroadcastMessage(属于RoomCommand类型)。Akka Typed的Actor只能接收其自身定义的命令类型,因此触发类型不匹配报错。 - 参数类型不匹配:
RoomActor.BroadcastMessage的第三个参数定义为room: String,但你传入的是room: ActorRef[RoomCommand],参数类型不兼容。 - 状态更新失效:
CreateUser分支中,更新用户Map后直接返回Behaviors.same,没有用新的Map更新Actor行为,导致用户数据无法持久化,后续查询不到已创建的用户。
修正后的代码
UserActor
import Chat.RoomActor.RoomCommand import akka.actor.typed.{ActorRef, Behavior} import akka.actor.typed.scaladsl.Behaviors import java.util.UUID object UserActor { sealed trait UserCommand case class CreateUser(name: String, surname: String, age: Int, userActor: ActorRef[UserCommand]) extends UserCommand case class User(name: String, surname: String, age: Int, userId: String, userActor: ActorRef[UserCommand]) case class SendMessageToRoom(room: ActorRef[RoomCommand], content: String, userName: String) extends UserCommand def apply(): Behavior[UserCommand] = userBehavior(Map.empty) private def userBehavior(users: Map[String, User]): Behavior[UserCommand] = Behaviors.receive{(context, message) => message match { case SendMessageToRoom(room, content, userName) => users.get(userName) match { case Some(user) => // 修正:向聊天室Actor发送广播消息,而非用户自身Actor val roomName = room.path.name room ! RoomActor.BroadcastMessage(user.userActor, content, roomName) case None => context.log.warn(s"未找到用户: $userName") } Behaviors.same case CreateUser(name, surname, age, userActor) => val userId = UUID.randomUUID().toString val newUser = User(name, surname, age, userId, userActor) context.log.info(s"用户 $newUser 已添加到列表") context.log.info(s"创建用户ID: $userId") // 修正:用新的用户Map更新Actor状态 userBehavior(users + (userId -> newUser)) case _ => context.log.warn("UserActor收到未知消息") Behaviors.same } } }
RoomActor
import Chat.UserActor.UserCommand import akka.actor.typed.scaladsl.Behaviors import akka.actor.typed.{ActorRef, Behavior} object RoomActor { sealed trait RoomCommand case class CreateRoom(user: ActorRef[UserCommand], roomName: String) extends RoomCommand case class LeaveRoom(user: ActorRef[UserCommand], roomName: String) extends RoomCommand case class JoinRoom(user: ActorRef[UserCommand], roomName: String) extends RoomCommand case class BroadcastMessage(user: ActorRef[UserCommand], content: String, room: String) extends RoomCommand def apply(): Behavior[RoomCommand] = roomBehavior(Map.empty) private def roomBehavior(rooms: Map[String, ActorRef[RoomCommand]]): Behavior[RoomCommand] = Behaviors.receive { (context, message) => message match { case CreateRoom(user, roomName) => val newRoomActor = context.spawn(RoomActor(), roomName) context.log.info(s"$user 创建了房间: $roomName") roomBehavior(rooms + (roomName -> newRoomActor)) case LeaveRoom(user, roomName) => context.log.info(s"$user 离开了房间: $roomName") Behaviors.same case JoinRoom(user, roomName) => context.log.info(s"$user 加入了房间: $roomName") Behaviors.same case BroadcastMessage(user, content, room) => context.log.info(s"用户 $user 在房间 $room 发送消息: $content") Behaviors.same case _ => context.log.error("RoomActor收到未知消息") Behaviors.same } } }
关键修正点说明
- 命令发送目标修正:将消息发送目标从用户自身Actor改为聊天室Actor,符合业务逻辑(广播消息应该由聊天室处理),同时解决类型不匹配问题。
- 参数类型对齐:通过
room.path.name获取聊天室名称(String类型),匹配BroadcastMessage的参数定义,解决参数类型不兼容问题。 - Actor状态更新:
CreateUser分支返回userBehavior(users + (userId -> newUser)),确保Actor用新的用户Map更新自身状态,后续能正确查询到已创建的用户。
内容的提问来源于stack exchange,提问作者Ch1rae
相关产品推荐
相关产品推荐

