Akka/play(activator)2.5.3 创建工程
2016-5-20
5. 引入actor,编写一个复杂的逻辑
5.1 代码以及相关的类
接下来,我们引入一个akka中的actor处理具体的逻辑。
基本逻辑是,controller将收到的参数,组织成一个ArrayList,actor在onReceive中收到后,完成具体的业务逻辑。
app/ controllers/MyController.java文件内容修改如下:
packagecontrollers;
importjava.util.*;
importjava.util.concurrent.CompletionStage;
importplay.Logger;
importplay.mvc.*;
importscala.compat.java8.FutureConverters;
importscala.concurrent.Future;
importakka.pattern.Patterns;
importactors.AkkaSystem;
publicclass MyController extends Controller {
/**
*Example: curl -X PUT http://localhost:9000/my1/my2
*@return
*/
publicCompletionStage<Result> myFunc(String str1, String str2) {
List<String>messages = new ArrayList<String>();
messages.add(str1);
messages.add(str2);
Future<Object>future = Patterns.ask(AkkaSystem.getMyActorPoolActorRef(), messages,1000); // using 1000ms timeout
returnFutureConverters.toJava( future ).thenApply(msg -> (Result)msg);
//returnFutureConverters.toJava(
// Patterns.ask(AkkaSystem.getMyActorPoolActorRef(), messages,1000)
// ).thenApply(msg -> (Result)msg);
}
}
添加app/actors/MyActorPool.java文件,内容如下,这个文件包含了两个类,内部类MyActor才是业务类。
packageactors;
importjava.util.*;
importplay.Logger;
importplay.mvc.*;
importakka.actor.*;
importakka.routing.RoundRobinPool;
publicclass MyActorPool {
privateActorRef myActorPool = null;
publicMyActorPool(ActorSystem actorSystem) {
myActorPool= actorSystem.actorOf(
newRoundRobinPool(2).props(Props.create(MyActor.class)),
"myActorPool");
}
publicActorRef get() {
returnmyActorPool;
}
}
classMyActor extends UntypedActor {
@Override
publicvoid onReceive(Object message) throws Exception {
if(message instanceof Iterable<?>) {
Resultresult = null;
Iterator<?>iter = ((Iterable<?>) message).iterator();
while(iter.hasNext()) {
Objectres = iter.next();
if(res instanceof String) {
System.out.println("copied:\t"+ (String) res);
result= Results.status(200, "echo:" + (String) res);
}
}
getSender().tell(result,getSelf());
}
}
}
添加app/actors/AkkaSystem.java文件,内容如下,这个类是个工厂,接受系统配置。
packageactors;
importjavax.inject.*;
importakka.actor.*;
importactors.MyActorPool;
@Singleton
publicclass AkkaSystem {
privateActorSystem actorSystem;
privatestatic ActorRef myActorPoolActorRef = null;
@Inject
publicAkkaSystem(ActorSystem actorSystem) {
this.actorSystem= actorSystem;
myActorPoolActorRef= new MyActorPool(actorSystem).get();
}
publicstatic ActorRef getMyActorPoolActorRef() {
returnmyActorPoolActorRef;
}
}
与AkkaSystem高度相关的是app目录下的Module类,在public voidconfigure() 方法中添加如下一行,用于注入:
bind(actors.AkkaSystem.class).asEagerSingleton();
5.2 执行与输出
打开一个新的终端,执行,输入如下:
[root@xuyongshimytest]# curl -X PUT http://localhost:9000/my1/my2
echo:my2[root@xuyongshimytest]#
执行服务的终端中,输出类似如下:
[info]application - Class: [myController], Method: [myFunc], Message:[para1: my1, para2: my2]
copied: my1
copied: my2
5.3 主要的方法
相关的重要方法,已经高亮。