• Akka 学习(二)第一个入门程序



    参考文章

    文章系列

    Akka 基础篇就此结束了,Akka基础篇主要介绍Akka的基本概念与一些基本术语,使用方式
    代码:https://github.com/Eason-shu/Akka

    一 sbt 介绍

    1.1 Sbt

    • sbt 是为 Scala 和 Java 项目构建的。它是93.6%的 Scala 开发人员的首选构建工具(2019 年)。
    • sbt 可以理解为包管理工具,向maven一样来管理开发包管理工具。

    1.2 下载安装

    下载地址:
    image.png
    解压配置环境变量
    SBT_HOME
    image.png
    PATH
    image.png

    • 修改配置文件

    image.png

    -Xmx512M
    -XX:MaxPermSize=256m
    -XX:ReservedCodeCacheSize=128m
    -Dsbt.log.format=true
    -Dsbt.override.build.repos=true
    -Dconsold.encoding=UTF-8
    -Dsbt.log.format=true
    -Dsbt.ivy.home=D:\Environment\sbt\.ivy
    -Dsbt.boot.directory=D:\Environment\sbt\boot
    -Dsbt.global.base=D:\Environment\sbt\.sbt
    -Dsbt.repository.config=D:\Environment\sbt\conf\repo.properties  # 仓库镜像配置
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image.png

    • 仓库设置
    [repositories]
    local
    huaweicloud-maven: https://repo.huaweicloud.com/repository/maven/
    maven-central: https://repo1.maven.org/maven2/
    sbt-plugin-repo: https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 验证

    image.png

    1.3 sbt的特点

    • 简单项目需要很少或不需要配置
    • 基于 Scala 的构建定义,可以充分利用 Scala 代码的灵活性
    • 使用从编译器中提取的信息进行精确的增量重新编译
    • 使用 Coursier 的 图书馆管理支持
    • 持续编译和测试 触发执行
    • 支持混合的 Scala/ Java项目
    • 支持使用 ScalaCheck、specs 和 ScalaTest进行测试。JUnit 由插件支持。
    • 使用类路径上的项目类和依赖项启动 Scala REPL
    • 子项目支持模块化
    • 外部项目支持(将 git 存储库列为依赖项!)
    • 并行任务执行,包括并行测试执行

    1.4 Idea 配置Sbt开发工具

    • 插件安装

    image.png

    • SBT 软件配置

    image.png

    • 创建新项目

    image.png

    • sbt 命令窗口

    image.png
    image.png

    二 构建定义

    2.1 指定版本

    • 作为构建定义的一部分,您将指定构建使用的 sbt 版本。这允许使用不同版本的 sbt 启动器的人构建具有一致结果的相同项目。为此,创建一个project/build.properties指定 sbt 版本的文件。
    • 如果所需版本在本地不可用,sbt启动器将为您下载。如果此文件不存在,sbt启动器将选择一个任意版本,这是不鼓励的,因为它会使您的构建不可移植。

    image.png

    2.2 build.sbt 设置

    # 打包构建的版本
    ThisBuild / version := "0.1.0-SNAPSHOT"
    # scala的版本
    ThisBuild / scalaVersion := "2.11.7"
    // 依赖
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-actor" % "2.3.3",
      "com.typesafe.akka" %% "akka-testkit" % "2.3.6" % "test",
      "org.scalatest" %% "scalatest" % "2.1.6" % "test"
    )
    
    # 主入口
    lazy val root = (project in file("."))
      .settings(
        name := "ActorDemo01"
      )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    image.png

    三 代码实现

    3.1 Java版本

    • Maven依赖
    <dependency>
      <groupId>org.scala-langgroupId>
      <artifactId>scala-libraryartifactId>
      <version>${scala.version}version>
      
    dependency>
    
    
    <dependency>
      <groupId>log4jgroupId>
      <artifactId>log4jartifactId>
      <version>1.2.17version>
    dependency>
    
    <dependency>
      <groupId>com.typesafe.akkagroupId>
      <artifactId>akka-actor_2.10artifactId>
      <version>2.3.3version>
    dependency>
    
    
    
    
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.13.2version>
      <scope>testscope>
    dependency>
    
    <dependency>
      <groupId>org.testnggroupId>
      <artifactId>testngartifactId>
      <version>RELEASEversion>
      <scope>compilescope>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 编写消息实体类
    /**
     * @description:
     * @author: shu
     * @createDate: 2022/10/27 20:17
     * @version: 1.0
     */
    public class SetRequests {
        private final String key;
        private final Object value;
    
    
        public SetRequests(String key, Object value) {
            this.key = key;
            this.value = value;
        }
    
    
        public String getKey() {
            return key;
        }
    
        public Object getValue() {
            return value;
        }
    
        @Override
        public String toString() {
            return "SetRequests{" +
                    "key='" + key + '\'' +
                    ", value=" + value +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 编写消息Actor
    
    
    
    import akka.actor.AbstractActor;
    import akka.event.Logging;
    import akka.event.LoggingAdapter;
    import akka.japi.pf.ReceiveBuilder;
    import java.util.HashMap;
    import java.util.Map;
    
    
    /**
     * @description: Java-AkkaDba
     * @author: shu
     * @createDate: 2022/10/27 21:13
     * @version: 1.0
     */
    
    public class AkkaDbs extends AbstractActor {
        protected final LoggingAdapter log = Logging.getLogger(context().system(), this);
        protected final Map<String, Object> map = new HashMap<>();
        private AkkaDbs() {
            receive(ReceiveBuilder
    
                    .match(SetRequests.class, message -> {
                        System.out.printf("收到的key:%s,value:%s%n",message.getKey(),message.getValue());
                        map.put(message.getKey(), message.getValue());
                    })
    
                    .matchAny(o ->  System.out.printf("收到的消息:%s",o))
                    .build()
            );
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 测试
    import akka.actor.ActorRef;
    import akka.actor.ActorSystem;
    import akka.actor.Props;
    import akka.testkit.TestActorRef;
    import org.junit.Test;
    import static org.junit.Assert.assertEquals;
    
    public class AkkademyDbTest {
        // 获取Actor系统的引用
        ActorSystem system = ActorSystem.create();
        @Test
        public void itShouldPlaceKeyValueFromSetMessageIntoMap() {
            // 创建一个actor
            TestActorRef<AkkaDbs> actorRef = TestActorRef.create(system, Props.create(AkkaDbs.class));
            // 发送消息
            actorRef.tell(new SetRequests("key", "value"), ActorRef.noSender());
            // 我们需要检查Actor是否将值存入了map中,确认其行为是否正确
            AkkaDbs akkademyDb = actorRef.underlyingActor();
            assertEquals(akkademyDb.map.get("key"), "value");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    image.png

    3.2 Scala版本

    • sbt依赖
    ThisBuild / version := "0.1.0-SNAPSHOT"
    
    ThisBuild / scalaVersion := "2.11.7"
    
    
    // 依赖
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-actor" % "2.3.3",
      "com.typesafe.akka" %% "akka-testkit" % "2.3.6" % "test",
      "org.scalatest" %% "scalatest" % "2.1.6" % "test"
    )
    
    
    lazy val root = (project in file("."))
      .settings(
        name := "ActorDemo01"
      )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 消息实体类
    
    
    /**
     * @description: 样例类
     * @author: shu
     * @createDate: 2022/10/27 20:14
     * @version: 1.0
     */
    case class SetRequest (key:String ,value: Object);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • Actor处理中心
    import akka.actor.{AbstractActor, Actor}
    import akka.event.Logging
    import java.util
    
    
    /**
     * @description: Scala-AkkaDba
     * @author: shu
     * @createDate: 2022/10/27 20:52
     * @version: 1.0
     */
    class AkkaDba extends Actor {
      val map =new util.HashMap[String,Object]
      val log=Logging(context.system,this);
    
      // 接受消息
      override def receive: Receive = {
        // 指定的消息
        case SetRequest(key,value)=>{
          log.info("收到的key:{},value:{}",key,value)
          map.put(key,value);
        }
        // 默认消息
        case 0 =>{
          log.info("收到一个错误的消息")
        }
      }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 测试
    import akka.actor.ActorSystem
    import akka.testkit.TestActorRef
    
    import org.scalatest.{FunSpecLike, Matchers}
    
    
    class  AkkademyDbSpec extends FunSpecLike with Matchers {
      // 获取系统实例
      implicit val system = ActorSystem()
    
      describe("akkademyDb") {
    
        describe("given SetRequest") {
    
          it("should place key/value into map") {
            // 创建Actor实例
            val actorRef = TestActorRef(new AkkaDba)
            // 发送消息
            actorRef ! SetRequest("key", "123456")
            // 验证消息
            val akkademyDb = actorRef.underlyingActor
            akkademyDb.map.get("key") should equal("123456")
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    image.png

    3.3 对比

    • ActorSystem创建方式
              //Java
              ActorSystem system = ActorSystem.create();
              //Scala
              implicit val system = ActorSystem()
    
    • 1
    • 2
    • 3
    • 4
    • 创建Actor
              //Java
              TestActorRef<AkkademyDb> actorRef = TestActorRef.create(system, Props.
              create(AkkademyDb.class));
              //Scala
              val actorRef = TestActorRef(new AkkademyDb)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 发送消息
                //Java
                actorRef.tell(new SetRequest("key", "value"), ActorRef.noSender());
                //Scala
                actorRef ! SetRequest("key", "value")
    
    • 1
    • 2
    • 3
    • 4
    • 检测消息
                //Java
                AkkademyDb akkademyDb = actorRef.underlyingActor();
                assertEquals(akkademyDb.map.get("key"), "value");
                //Scala
                val akkademyDb = actorRef.underlyingActor
                akkademyDb.map.get("key") should equal(Some("value"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这样我们就完成了第一个简单的测试用例。这个基本的模式可以用于构建同步的Actor单元测试

  • 相关阅读:
    数据结构与算法--排序算法复习
    Linux高级IO
    解决:Navicat导入sql脚本时报2006
    从-99打造Sentinel高可用集群限流中间件
    【Kafka系列 06】Kafka Producer源码解析
    unity面试题(基础篇)
    Python做抓取程序代码示例
    玉米社:如何做好企业SEM竞价推广?数据分析不能少
    zookeeper/HA集群配置
    文心一言 vs gpt-4 全面横向比较
  • 原文地址:https://blog.csdn.net/weixin_44451022/article/details/128210518