LINE BOTをJavaのServletを利用してお手軽に作る方法を紹介します
紹介したソースコード一式は https://github.com/riversun/line-bot-servlet-examples.git にあります
LINE BOTをつくる準備
Messaging APIを使える状態になっている前提でかきます。
登録方法などは別の記事に委ねます。
登録はこちらから
https://business.line.me/ja/services/bot
ServletでLINE BOTを作る
HttpServletでLINE BOTを作ります。
LINE公式Github(https://github.com/line/line-bot-sdk-java)ではSpring Bootを利用した例が紹介されています(※)。
今回はSpring Bootではなくて、スッピンのHttpServletでLINE BOTを作りたいと思います。
ご存知のとおりSpring Bootを使うとかなりお手軽にLINE BOTをつくれますが、
HttpServletでもSpring Bootの例と同じくらいのお手軽感をめざします。
そのために、ヘルパーライブラリを用意しました。ライブラリといっても、内部で https://github.com/line/line-bot-sdk-java を利用している薄いラッパーですのでソースを自分のServletにとりこんで利用しても良いとおもいます。メソッド名もSpring Bootの例を参考にしました。
ヘルパーライブラリのソースはこちら
https://github.com/riversun/line-bot-helper
※公式SDK(現時点でv1.6.0)にもline-bot-servletというものがあり、
中身をみるとHttpServlet用の簡易ヘルパークラス(署名検証など)は準備してくれているようですが
SpringBootのようなevent mappingはしてくれない模様。
メッセージへのお返事BOT をつくる
ユーザーがBOTにむかってテキストメッセージを送ると、BOTがテキストでお返事する、というサンプルです。
コードは以下のようになります。
@SuppressWarnings("serial")
public class LineBotExample01Servlet extends LineBotServlet {
// CHANNEL_SECRETとCHANNEL_ACCESS_TOKENはそのまま文字列で指定可能
private static final String CHANNEL_SECRET ="取得したものをいれる" ;
private static final String CHANNEL_ACCESS_TOKEN ="取得したものをいれる";
@Override
protected ReplyMessage handleTextMessageEvent(MessageEvent<TextMessageContent> event) throws IOException {
// ユーザーがBOTに送信したメッセージ
TextMessageContent userMessage = event.getMessage();
// ユーザーのProfileを取得する
UserProfileResponse userProfile = getUserProfile(event.getSource().getUserId());
// BOTからの返信メッセージ
String botResponseText = userProfile.getDisplayName() + "さん、"
+ "「" + userMessage.getText() + "」って言いましたね";
TextMessage textMessage = new TextMessage(botResponseText);
return new ReplyMessage(event.getReplyToken(), Arrays.asList(textMessage));
}
@Override
protected ReplyMessage handleDefaultMessageEvent(Event event) {
// overrideしていないメッセージを受信した場合は何もしない(nullを返す)
return null;
}
@Override
public String getChannelSecret() {
return CHANNEL_SECRET;
}
@Override
public String getChannelAccessToken() {
return CHANNEL_ACCESS_TOKEN;
}
動作イメージ
解説
ユーザーからのテキストメッセージを受信すると、
ReplyMessage handleTextMessageEvent(MessageEvent<TextMessageContent> event)
がコールされますので、このメソッドの中で必要な処理を行います。
この例ではユーザーの発言(テキスト)を取得して、少し加工して返事をします。
以下のよう ReplyMessage を返すと、ユーザー側に返信がおくられます。
return new ReplyMessage(event.getReplyToken(), Arrays.asList(textMessage));
ここを
return null;
にすると、返信はしません。
ちなみに、
Arrays.asList(textMessage)
としている理由は、メッセージは同時に複数返すことができるためです。
たとえば、画像とテキストを同時に返したい場合には、
Arrays.asList(imageMessage,textMessage)
のようにします。
今回の例では、handleTextMessageEventをオーバーライドしましたが、他にも以下のメソッドをオーバーライドすれば、各イベントを受信することができます。
protected ReplyMessage handleImageMessageEvent(MessageEvent<ImageMessageContent> event)
protected ReplyMessage handleLocationMessageEvent(MessageEvent<LocationMessageContent> event)
protected ReplyMessage handleStickerMessageEvent(MessageEvent<StickerMessageContent> event)
protected ReplyMessage handleAudioMessageEvent(MessageEvent<AudioMessageContent> event)
protected ReplyMessage handleVideoMessageEvent(MessageEvent<VideoMessageContent> event)
protected void handleUnfollowEvent(UnfollowEvent event)
protected ReplyMessage handleFollowEvent(FollowEvent event)
protected ReplyMessage handleJoinEvent(JoinEvent event)
protected void handleLeaveEvent(LeaveEvent event)
protected ReplyMessage handlePostbackEvent(PostbackEvent event)
protected ReplyMessage handleBeaconEvent(BeaconEvent event)
最後に、
@Override
protected ReplyMessage handleDefaultMessageEvent(Event event) {
// overrideしていないメッセージを受信した場合は何もしない(nullを返す)
return null;
}
ですが、オーバーライドしていないイベントを受信した場合にコールされます。
上記LineBotServletが含まれているヘルパーライブラリを取り込むために、Gradle/Mavenでは以下のように指定します。
Gradle
compile 'org.riversun:line-bot-helper:1.0.0'
Maven
<dependency>
<groupId>org.riversun</groupId>
<artifactId>line-bot-helper</artifactId>
<version>1.0.0</version>
</dependency>
ローカルPCでお手軽に試す
Servletをつくるところまでがこの記事の目的ですがおまけで、ローカルPCで試す方法についても書いておきます。
Servletをつくるところまではだいぶお手軽になりましたが、すぐ試せる、というところだとまだ弱いですね。
わざわざTomcat等立ち上げDeployするのはめんどうですので、servletをお手軽にためせるコンテナJettyを利用しましょう。
Jettyの利用はとっても簡単です。
まずGradle/Mavenに以下を追加します。
Gradle
compile 'org.eclipse.jetty:jetty-server:9.4.0.v20161208'
compile 'org.eclipse.jetty:jetty-webapp:9.4.0.v20161208'
Maven
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.0.v20161208</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.0.v20161208</version>
</dependency>
Jettyを起動して、servletにアクセスする
Gradle/Mavenに記述したら、以下のようにコードを書いて実行しましょう。
public class AppMain {
public static void main(String[] args) throws Exception {
ServletHandler handler = new ServletHandler();
handler.addServletWithMapping(LineBotExample01Servlet.class, "/callback");
// loclahost:3000でJettyを起動
Server jetty = new Server(3000);
jetty.setHandler(handler);
jetty.start();
jetty.join();
}
}
handler.addServletWithMapping(LineBotExample01Servlet.class, "/callback");
にあるとおり、先ほど作成したLineBotExample01Servletを**/callback**というパスで受け付けます。
ローカルPCで実行すれば http://127.0.0.1:3000/callback でLINE BOT Servletにアクセスすることができるようになります。
つくったLINE BOT Servletに外部からアクセスできるようにする
せっかくローカルで立ち上げても、LINE BOTとして振舞うには、サーバーにDeployして外部に公開する必要があります。
テスト用途でお手軽にためすため、さきほどJettyをつかってつくったサーバーを外部からアクセスできるようにしましょう。
ここでは、こうした用途にぴったりな ngrok というサービスを使います。
以下から ngrok をダウンロードしておきます
https://ngrok.com/download
コマンドラインで
ngrok http -region=ap 127.0.0.1:3000
とすると、ngrokが開始して以下のような画面が表示されます
たったこれだけで、
https://xxxxx.ap.ngrok.io というurlが https://127.0.0.1:3000 にマップされました!
(xxxxxの部分はngrokを起動するたびにランダムに変わります。sign upすれば固定することも可能です)
LINE BOTのweb hook urlにはhttpsが求められますのでこれは便利ですね。
ここまでくれば、あとは、以下のurlをWeb Hook URLに登録するだけです。
https://xxxxx.ap.ngrok.io/callback
ngrokのTIPS
-region=apと指定するとAsia Pacificリージョンが選択されますので
日本からアクセスする場合はデフォルトのUSリージョンよりもレイテンシーの面で有利です。
実行します
うまくいきました
まとめ
- 今回は、シンプルなLINE BOTをHttpServletで作る例を紹介しました。
- ServletをJettyでホストして、ngrokをつかって外部からアクセス可能にしたことで、実際にスマホのLINEアプリからBOTにメッセージを送るテストができました
- 紹介したソースコード一式は https://github.com/riversun/line-bot-servlet-examples.git にあります
次回は、画像の送受信など、もうすこしハンドリングする素材をふやす例を試したいとおもいます。