You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Akka Typed项目类型不匹配求助:UserActor发送消息报错

Akka Typed聊天应用类型不匹配问题解决

错误原因分析

  1. 核心类型不匹配:在SendMessageToRoom分支中,你错误地向user.userActor(类型为ActorRef[UserCommand])发送了RoomActor.BroadcastMessage(属于RoomCommand类型)。Akka Typed的Actor只能接收其自身定义的命令类型,因此触发类型不匹配报错。
  2. 参数类型不匹配:RoomActor.BroadcastMessage的第三个参数定义为room: String,但你传入的是room: ActorRef[RoomCommand],参数类型不兼容。
  3. 状态更新失效: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
      }
    }
}

关键修正点说明

  1. 命令发送目标修正:将消息发送目标从用户自身Actor改为聊天室Actor,符合业务逻辑(广播消息应该由聊天室处理),同时解决类型不匹配问题。
  2. 参数类型对齐:通过room.path.name获取聊天室名称(String类型),匹配BroadcastMessage的参数定义,解决参数类型不兼容问题。
  3. Actor状态更新:CreateUser分支返回userBehavior(users + (userId -> newUser)),确保Actor用新的用户Map更新自身状态,后续能正确查询到已创建的用户。

内容的提问来源于stack exchange,提问作者Ch1rae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 09:15:20