16.5.3 Actor通过网络通讯升级版
前面的案例中, Actor
通讯时使用的数据类型是字符串.
当传递的数据比较多的时候, 只用字符串不太方便.
我们可以传递自定义类型的数据.
使用样例类做传递的数据类型最为方便.
把传递的数据类型改为样例类
MessageProtocol.scala
package com.atguigu.akka.net2
/*
客户端发给服务器端的数据类型
*/
case class ClientMessage(msg: String)
/*
服务器发给客户端的数据类型
*/
case class ServerMessage(msg: String)
ServerActor.scala
package com.atguigu.akka.net2
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import com.typesafe.config.{Config, ConfigFactory}
class ServerActor extends Actor {
override def receive: Receive = {
case "start" => println("客服可以开始工作了...")
case ClientMessage(msg) => {
msg match {
case a: String if a.contains("地址") => {
sender() ! ServerMessage("北京市 昌平路 xxxx")
}
case a: String if a.contains("学费") => {
sender() ! ServerMessage("大数据学费 20098 元")
}
case a: String if a.contains("技术") => {
sender() ! ServerMessage("大数据 java 前段 python 区块链")
}
case a: String => {
sender() ! ServerMessage("你说的话小妹没有听懂, 再说一遍...")
}
}
}
}
}
object ServerActor {
def main(args: Array[String]): Unit = {
// 创建Config对象, 并监听指定的ip地址和端口
val config: Config = ConfigFactory.parseString(
s"""
|akka.actor.provider="akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname=localhost
|akka.remote.netty.tcp.port=10000
""".stripMargin)
val actorSystem: ActorSystem = ActorSystem("Server", config)
val serverActor: ActorRef = actorSystem.actorOf(Props(classOf[ServerActor]), "ServerActor")
serverActor ! "start"
}
}
ClientActor
package com.atguigu.akka.net2
import akka.actor.{Actor, ActorRef, ActorSelection, ActorSystem, Props}
import com.typesafe.config.{Config, ConfigFactory}
import scala.io.StdIn
class ClientActor(serverHost: String, serverPort: Int) extends Actor {
var serverSelection: ActorSelection = _
/**
* 当一个Actor启动的时候回调这个方法.
* 通常在这个方法内部做一些初始化的工作
*/
override def preStart(): Unit = {
println(serverHost)
serverSelection = context.actorSelection(s"akka.tcp://Server@${serverHost}:${serverPort}/user/ServerActor")
}
override def receive: Receive = {
case "start" => {
println("客户端已经开启, 可以向客服咨询问题...")
// 使用serverSelection向服务器发送信息
serverSelection ! ClientMessage(StdIn.readLine())
}
case ServerMessage(msg) => {
println("客服: " + msg)
serverSelection ! ClientMessage(StdIn.readLine()) // 收到客服的恢复之后, 继续向客服咨询问题
}
case _ => {
}
}
}
object ClientActor {
def main(args: Array[String]): Unit = {
// 客户端监听配置
val config: Config = ConfigFactory.parseString(
s"""
|akka.actor.provider="akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname=localhost
|akka.remote.netty.tcp.port=9999
""".stripMargin)
val clientSystem: ActorSystem = ActorSystem("Client", config)
val clientActor: ActorRef = clientSystem.actorOf(Props(classOf[ClientActor], "localhost", 10000), "clientActor")
clientActor ! "start"
}
}