JavaのWebアプリケーション開発フレームワークによる、Webサイト開発の顛末記です。

EclipseのMavenを使った、Spring-MVC、Thymeleaf、MyBatis 等のプログラミングテクニックを、
備忘録的に記録しています。実際に動くソースコードを多用して説明していますので、
これからEclipseや、Spring-MVCを始めたいと思っている人にとって、少しでも参考になれば幸いです。
WebSocket(ライン風)のサンプルです。
メッセージ:

WebSocketを使ったライン風チャットサンプルです。
複数のブラウザを同時に開いて送信しあうと、ちょっとだけ面白いかもしれません。
代表的なブラウザでは動作しますが、
Microsoft Internet Explorer は WebSocketサポートがバージョン10以降なのでIE9とかでは動きません。
あと、Safari5 for Windows は動かないようです。
Mac版Safariは未確認ですが、
iPhoneのSafariブラウザからは送信できるので、純正Mac Safariは多分いけると思います。

参考までに、環境的な問題もあるのかもしれませんが
Windows7/IE11 の組み合わせで一部WebSocketが動かないケースがありました。
ただし、このケースの場合、IE11のみでなくChrome/FireFoxで全滅なので、
ファイヤーウォール等の原因が考えられます。

運が良ければ(悪ければ?)私(ありもどき)と直接ラインできるかもです(笑)

 

■プラグイン
WebSocketを使用するためには、Springのプラグインspring-websocketが必要になります。
pom.xmlに定義しますが、これは本編「■SpringMVC の小径 1-3)pom.xmlの編集
であらかじめ定義してあるので、今回は特に意識しなくても大丈夫です。

 

■Spring定義ファイル
本編「■SpringMVC の小径 4-2)Spring-MVC設定」で説明している
applicationContext.xmlにWebSocketを使用するための定義を追加します。

WebContent/WEB-INF/applicationContext.xml

今回、WebSocketを使用するために追加した部分を赤字で表示してあります。
先頭の、spring-websocket使用宣言と、
末尾の、ハンドラマッピング定義および、ハンドラのDI宣言となります。
"/wshandle.xhtml" が ブラウザのJavaScriptでWebSocketに接続する際のURLになります。
jp.dip.arimodoki.websocket.EchoHandlerは、ブラウザから送信されたメッセージを
処理するハンドラクラスとなります

 

■WebSocketハンドラ
ブラウザから送信されたテキストメッセージを受け取るハンドラを作成します。
src/main/java/jp/dip/arimodoki/websocket/EchoHandler.java

 

■view
メッセージの送受信を行うHTMLです。
WebContent/websocket.html

 

■Apache設定ファイル
EclipseのTomcat上で動作確認を行う際は、WebSocketハンドラ呼び出しに
通常は、ws://localhost:8080/j_Labo/wshandle.xhtml のように
tomcat 8080ポートを指定して実行します。
この場合、なんの問題もなくWebSocketは接続されますが
実際の運用環境では、ApacheなどのWebサーバー経由で
ws://arimodoki.dip.jp/j_Labo/wshandle.html のように
HTTP 80ポートで接続するはずですが、このままだと
WebSocket Connectionエラーが発生します。
これは、Tomcat側のWebSocketが8080ポートで待ち受けているため
HTTPD 80番ポートでリクエストしても接続できないのが理由です。
ここで、だいぶんはまってしまったので、
解決策を伝授しておきます。
要は、Apacheに特定のURLでリクエストが来た場合は、Proxyで
Tomcat 8080ポートの特定のパスにリクエストを転送してしまう設定です。
ここからは、サーバーがLinux前提で解説します。
Apacheの設定ファイル /etc/httpd/conf/extra/httpd-proxy.conf
に少し修正を加えます。
 ※)Apacheの設定ファイルについては、環境によってファイルのパスが違うかもしれません。
   我が家のサーバー(Fedora23 httpd-2.4.18)では、上記のファイルになっています

上の設定ファイルを開いて

<Location /j_Labo/wshandle.xhtml>
 ProxyPass ws://localhost:8080/j_Labo/wshandle.xhtml
</Location>

の3行を追加します。
保存して、httpdを再起動します。
[root@ws01 extra]#systemctl restart httpd.service

以上で、ブラウザのリクエスト(HTTP80番ポート)から
ws://arimodoki.dip.jp/j_Labo/wshandle.xhtml のリクエストが通るようになります。

 

※)nginxの話 2018/Nov/02 追記
SpringFramework5.x系が出て久しい(2017 Sep)ですが、
最近どうも、WebSocketの通信が切れるようになり、しばらく悪戦苦闘していました。
まず、原因の切り分けとして、Apacheを経由せず、8080ポートで直接tomcatでアクセスすると。
問題なくWebSocketは繋がります。
次にApache proxy経由で 80番ポートを 8080番ポートに振り向けると、
WebSocket的には 1006 エラーが発生し、ブラウザには、ws.close()イベントが発生する状況。
つまり、SpringFramework(spring-websocketプラグイン)の問題というより
Tomcat(9.0.12)標準でついてくる WebSocket exsampleページで
Tomcat標準のtomcat-websocketライブラリを使っても接続エラーとなるので、
Apacheの mod_proxyとかmod_proxy_wstunnelモジュールが上手く立ち回っていない感じ。

試しに、OSもTomcatもApacheもJDKもほとんど同じ構成の予備サーバーで、
全く同じサイト立ち上げて実験してみると、こちらは何故か動く ????

なんか切り抜ける手立てがないかと、さんざんネットを漁ってみましたが
あんまり大した情報が見つからなかったので
最後の手段で、Apache httpd に見切りをつけて、nginx に切り替えてみたところ
全く問題なく、サクサクと WebSocket繋がります!

Apache httpd よ。長い付き合いじゃったが、これでさらばじゃ!!