Mapion マピオンラボ Java Jetty7でWebSocket開発
Follow @honjo2











WebSocketとは
Web Sockets APIのこと。
クライアントとサーバの双方向通信を実現するAPI。
wsというhttpを拡張したプロトコルでコネクションを張りっ放しにしてやりとりする。
利点
Ajaxと違って、無駄なトラフィックが発生しない。
Cometと違って、シンプル。(開発しやすい)
Cometと違って、HTTPヘッダが少なくて済む。
Cometと違って、ブラウザからでもサーバからでも同じメッセージフォーマットを使える。
欠点
現時点で、WebSocketを実装したブラウザがほとんどない。
サンプル
Chrome4.0.249.0以上でみてください。
適当な場所でささやくことができます。
ささやきは、接続された全てのクライアントにリアルタイムで送信されます。
データを永続化していないので、その場限りです。
繋がっている人しか、ささやきを聞くことはできません。
「最新の20件」というところは、ブラウザを閉じると消えてしまいます。
一人で試す場合は、複数タブ(若しくはウィンドウ)を開いてささやいてみてください。
開発
クライアント側の開発環境は、Chromeさえあればいいので簡単なんですが、
サーバ側の開発環境を準備するのは意外と面倒です。
方法としては、
・Apacheにpywebsocketを入れてpythonで開発する
・Go言語にはwebsocketパッケージがあるので、それを使う。
・Jetty7がWebSocketに対応したので、それを使う
などがありますが、ここではJetty7を使った開発方法を書きます。
ただ、Jetty7用のEclipseプラグインがまだないので、以下の2つの方法を考えました。
1.自動デプロイバッチスクリプトを作って開発する。
2.Jetty6用Eclipseプラグインを改造して開発する。
前提
・Maven2がインストールされていること
・Eclipseがインストールされていること(m2eclipseプラグインも)
・Jetty7がインストールされていること
1の手順
1-1. eclipseでmavenプロジェクトを作成する




1-2. pom.xmlを修正する
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jp.co.mapion.honjo</groupId>
<artifactId>aaa</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>aaa Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>7.0.1.v20091125</version>
</dependency>
</dependencies>
<build>
<finalName>aaa</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<defaultGoal>validate</defaultGoal>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>source-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
1-3. 以下フォルダを作成する
src/main/java
src/test
src/test/resources

1-4. プロジェクトファイルを更新する
コマンドプロンプトでpom.xmlのある場所に移動して
>mvn eclipse:eclipse
とする
1-5. プロジェクトを更新する
プロジェクト名右クリック > refresh
1-6. WhisperServletを作成する
public class WhisperServlet extends WebSocketServlet {
private static final long serialVersionUID = 1L;
private final Set<WhisperWebSocket> clients = new CopyOnWriteArraySet<WhisperWebSocket>();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws javax.servlet.ServletException ,IOException {
getServletContext().getNamedDispatcher("default").forward(request, response);
};
@Override
protected WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
return new WhisperWebSocket();
}
class WhisperWebSocket implements WebSocket {
Outbound outbound;
@Override
public void onConnect(Outbound outbound) {
this.outbound = outbound;
clients.add(this);
onMessage((byte) 0, "WebSocket is success!!!");
}
@Override
public void onMessage(byte frame, byte[] data,int offset, int length) {
}
@Override
public void onMessage(byte frame, String data) {
for (WhisperWebSocket client : clients) {
try {
client.outbound.sendMessage(frame, data);
} catch (IOException e) {
Log.warn(e);
}
}
}
@Override
public void onDisconnect() {
clients.remove(this);
}
}
}
1-7. web.xmlに追記する
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>Whisper</servlet-name>
<servlet-class>jp.co.mapion.honjo.aaa.WhisperServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Whisper</servlet-name>
<url-pattern>/whisper/</url-pattern>
</servlet-mapping>
</web-app>
1-8. %JETTY_HOME%/contexts/aaa.xmlを作成する
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Set name="contextPath">/aaa</Set> <Set name="war"><SystemProperty name="jetty.home"/>/webapps/aaa.war</Set> <Set name="extractWAR">true</Set> <Set name="copyWebDir">false</Set> </Configure>
1-9. start.batを作ってプロジェクト直下に置く
@echo off ::プロジェクト名 SET PROJECT_NAME=aaa cd .\workspace\%PROJECT_NAME% call mvn package copy /Y .\target\%PROJECT_NAME%.war %JETTY_HOME%\webapps\%PROJECT_NAME%.war cd %JETTY_HOME% java -DSTOP.PORT=8079 -DSTOP.KEY=jetkey -jar start.jar --stop java -DSTOP.PORT=8079 -DSTOP.KEY=jetkey -jar start.jar
※プロジェクト名やパスは適宜変更してください
1-10. start.batを実行する
Eclipse上からダブルクリックでOK

処理の流れ
プロジェクトをパッケージングする
↓
Jettyにデプロイする
↓
Jettyを停止する(起動していたら)
↓
Jettyを起動する
1-11. 確認する
コマンドプロンプトで、
>telnet localhost 8080
GET /aaa/whisper/ HTTP/1.1
Origin: http://localhost/
Upgrade: WebSocket
Connection: Upgrade
Host: localhost
として
WebSocket is success!!!
と表示されれば、成功です。

1-12. 開発サイクル
ソース修正 > start.bat実行 > 確認 > ソース修正
2の手順
2-1. Jetty6用Eclipseプラグインをインストールする
アップデートサイト
http://www.webtide.com/eclipse
2-2. プラグインを改造する
%ECLIPSE_HOME%\plugins\org.mortbay.jetty.serveradaptor_1.0.4\servers\jetty.serverdefを以下のように修正する(2箇所)
<mainClass>org.mortbay.start.Main</mainClass>
↓
<mainClass>org.eclipse.jetty.start.Main</mainClass>
%ECLIPSE_HOME%\plugins\org.mortbay.jetty.serveradaptor_1.0.4\buildfiles\template.xmlを以下のようにする
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Set name="contextPath">@CONTEXT_PATH@</Set> <Set name="war">@MODULE_WAR@</Set> <Set name="extractWAR">true</Set> <Set name="copyWebDir">false</Set> </Configure>
2-3. Eclipseを再起動する
2-4. EclipseにJettyサーバを追加する
Window > Preferences > Server > Runtime Environmentsより追加する

2-5. 上記1-1~1-7まで実施する
2-6. プロジェクトをサーバに追加する


2-7. サーバを起動する

2-8. 確認する
上記1-11と同じです。
2-9. 開発サイクル
ソース修正 > サーバ再起動(ソース修正すればオートデプロイされる) > 確認 > ソース修正

-
>amさん
web.xmlと合っていればどこでもよいです。
サンプルではjp.co.mapion.honjo.aaaパッケージに置いています。honjo:2010.8.02 13:44
ちょっと時間が立っているのと、Jettyのバージョンが7.22なんですが、2の手順で、Add and Removeのところで、追加することができません。
2の手順でも、1-9のバッチファイル内のcall mvn package相当の操作が必要に思いますが。
もし、おわかりになりましたら、ご教示いただければ幸いです。pm:2011.1.12 13:59

-
この記事のトラックバックURLhttp://labs.mapion.co.jp/mtos/mt-tb.cgi/34






初歩的な質問で申し訳ありません、WhisperServlet.javaはどこに置いたら良いのでしょうか?
am:2010.7.30 05:35