本代码使用语言是scala,首先需要说明一下Actor的运行原理(图中只是说明了一个Actor对象给自己发消息,多个Actor发消息的原理相同):
这是一个Actor的运行机理,Actor的本质是自己给自己发消息。
1.首先创建一个class对象继承Actor,里面必须重写receive方法,receive方法是一个偏函数,所以需要用case捕获
2.创建一个object对象,利用ActorSystem创建一个工厂(这个工厂是用来创建该Actor对象的代理,注意一个Actor对象可以有多个代理)。
3.创建出Actor对象的代理,利用代理发消息到1,然后1再发给自己的2中,2再把消息发送给Actor对象。Actor对象的receive方法接收消息并处理。1,2,我们不需要关注,因为被封装在包里,我们直接调用就可以。
下面贴上代码:
package day04
import akka.actor.{Actor, ActorSystem, Props}
//HelloActor是一个Actor类
class HelloActor extends Actor{
// 接受消息的
override def receive: Receive = {
// 接受消息并处理
case "你好帅" => println("竟说实话,我喜欢你这种人!")
case "丑" => println("滚犊子 !")
case "stop" => {
context.stop(self) // 停止自己的actorRef
context.system.terminate() // 关闭ActorSystem
}
}
}
object HelloActor {
private val nBFactory = ActorSystem("NBFactory")// 工厂
private val helloActorRef = nBFactory.actorOf(Props[HelloActor], "helloActor")
def main(args: Array[String]): Unit = {
// 给自己发送消息
helloActorRef ! "你好帅"
helloActorRef ! "丑"
helloActorRef ! "stop"
}
}
下面以一个项目为例:
服务端(两段代码在一个文件中,只不过为了便于做笔记,分两个图片截图):
客户端:
代码如下:
服务端代码:
package cn.sheep.robot
import akka.actor.{Actor, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
class Edu360Server extends Actor{
// 用来接受客户端发送过来的问题的
override def receive: Receive = {
case "start" => println("老娘已就绪 !")
case ClientMessage(msg) => {
println(s"收到客户端消息:$msg")
msg match {
case "你叫啥" => sender() ! ServerMessage("铁扇公主")
case "你是男是女" => sender() ! ServerMessage("老娘是男的")
case "你有男票吗" => sender() ! ServerMessage("没有")
case _ => sender() ! ServerMessage("What you say ?") //sender()发送端的代理对象, 发送到客户端的mailbox中 -> 客户端的receive
}
}
}
}
object Edu360Server {
def main(args: Array[String]): Unit = {
val host = "127.0.0.1"
val port = 8088
//设置一个配置
val config = ConfigFactory.parseString(
s"""
|akka.actor.provider="akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname=$host
|akka.remote.netty.tcp.port=$port
""".stripMargin)
// 将上面设置的配置作为参数传入,指定IP 和 端口,
val actorSystem = ActorSystem("Server", config)
val serverActorRef = actorSystem.actorOf(Props[Edu360Server], "shanshan")
serverActorRef ! "start" // 到自己的mailbox -》 receive方法
}
}
客户端代码:
package cn.sheep.robot
import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
import scala.io.StdIn
class ClientActor(host: String, port: Int) extends Actor{
var serverActorRef: ActorSelection = _ // 服务端的代理对象
// 在receive方法之前调用
override def preStart(): Unit = {
// akka.tcp://[email protected]:8088
serverActorRef = context.actorSelection(s"akka.tcp://Server@${host}:${port}/user/shanshan")
}
// mailbox ->receive
override def receive: Receive = { // shit
case "start" => println("牛魔王系列已启动...")
case msg: String => { // shit
serverActorRef ! ClientMessage(msg) // 把客户端输入的内容发送给 服务端(actorRef)--》服务端的mailbox中 -> 服务端的receive
}
case ServerMessage(msg) => println(s"收到服务端消息:$msg")
}
}
object ClientActor {
def main(args: Array[String]): Unit = {
val host = "127.0.0.1"
val port = 8089
val serverHost = "127.0.0.1"
val serverPort = 8088
val config = ConfigFactory.parseString(
s"""
|akka.actor.provider="akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname=$host
|akka.remote.netty.tcp.port=$port
""".stripMargin)
val clientSystem = ActorSystem("client", config)
// 创建dispatch | mailbox
val actorRef = clientSystem.actorOf(Props(new ClientActor(serverHost, serverPort.toInt)), "NMW-002")
actorRef ! "start" // 自己给自己发送了一条消息 到自己的mailbox => receive
while (true) {
val question = StdIn.readLine() // 同步阻塞的, shit
actorRef ! question // mailbox -> receive
}
}
}
样例类代码:
package cn.sheep.robot
// 服务端发送给客户端的消息格式
case class ServerMessage(msg: String)
// 客户端发送给服务器端的消息格式
case class ClientMessage(msg: String)