Instant Vert.xを読みながらサンプルコードを試してみる。
今回はHttpServerとHttpClient(Flickr)。
まずはクライアント側のコード
public class ClientVerticle extends Verticle {
HttpClient client;
public void start() {
container.logger().info("ClientVerticle deployed.");
client = vertx.createHttpClient();
client.setHost("ycpi-api.flickr.com").setPort(80);
vertx.eventBus().registerHandler("webclient_address", this::handleClientEvent);
}
void handleClientEvent(Message<String> msg) {
container.logger().info(Rythm.render("Recieved tag:@tag", msg));
client.getNow(
Rythm.render("/services/feeds/photos_public.gne?tags=@message&format=json", msg.body()),
(HttpClientResponse res) -> {
container.logger().info(Rythm.render("Got response. status_code=[@status].", res.statusCode()));
res.bodyHandler((Buffer body) -> {
String json = body.toString();
// かっこに囲まれた変なJSONを返すので削る。
json = json.substring(json.indexOf('(') + 1, json.length() - 1);
json = json.replaceAll("\\\\'", "'");
msg.reply(json);
});
});
}
}
EventBusの"webclient_address"というアドレスでイベントが着火するとイベントのメッセージに書かれたキーワードを使ってFlickrのAPIから画像を集めてきます。
FlickrのAPIは特別な認証が必要ないですが、JSONとしてパースするにはレスポンスをちょっと成形する必要があります。
続いてサーバー側のコード
public class ServerVerticle extends Verticle {
public void start() {
container.deployVerticle(ClientVerticle.class.getCanonicalName());
HttpServer server = vertx.createHttpServer();
RouteMatcher routeMatcher = new RouteMatcher();
routeMatcher.get("/tag/:theTag", this::handleTag);
routeMatcher.getWithRegEx(".*", this::handleOthers);
server.requestHandler(routeMatcher).listen(8080);
}
private void handleTag(HttpServerRequest req) {
String tag = req.params().get("theTag");
container.logger().info(Rythm.render("Looking for:@searchWord", tag));
vertx.eventBus().send("webclient_address", tag, (Message<String> result) -> {
String json = result.body();
JsonObject jsonObj = new JsonObject(json);
String html = Rythm.render(PAGE_TEMPLATE, tag, jsonObj.getArray("items"));
req.response().end(html);
});
}
private void handleOthers(HttpServerRequest req) {
req.response().end("ERROR: fill the tag.");
}
private static final String PAGE_TEMPLATE =
"@import org.vertx.java.core.json.JsonArray\n"
+ "@import org.vertx.java.core.json.JsonObject\n"
+ "@args String searchWord, JsonArray items\n"
+ "<html><h1>Result for @searchWord </h1>\n"
+ "@for(items) {\n"
+ "@{ JsonObject item = (JsonObject)_; }\n"
+ "<h3>@item.getString(\"title\")</h3>\n"
+ "<a href=\"@item.getString(\"link\")\">"
+ "<img src=\"@item.getObject(\"media\").getString(\"m\")\" />"
+ "</a>\n"
+ "}\n" + "</html>";
}
start()ではクライアントのVerticleをデプロイした後、RouteMatcherを使ってHTTP Serverで受け取るリクエストののルーティングを行っています。
クライアント側で書いたコードをこちらのVerticleに書いても問題なく動作しますが、プログラムの関心事毎にVerticleを作る方がよかろうとのことです。(例えば、データベースへの接続、WEBサーバー、認証、キャッシュ、など)
サーバーがレスポンスとして返却するHTMLのレンダリングにはRythmというテンプレートエンジンを使っています。
Verticleを実行した後はブラウザからhttp://localhost:8080/tag/catにアクセスすると、ClientVerticleが猫の画像を集めてきて、ServerVerticleが集めた猫の画像を並べたHTMLをブラウザに返却します。
今回のソースコードはこちらにあります。