NetBeansやらEclipseでやってる例は簡単に見つけることが出来ましたが、IntelliJでやってる記事が見当たらない感じだったので備忘録として詳しく書いておきます。
あと、ここではjarで出力して動かすまでの手順を説明をしていきます。
環境
- MacOSX El Capitan
- IntelliJ IDEA 14.1.5 (Ultimate)
- Jetty 9.2.13
WebSocketを使う前の準備
WebSocketを使うために、Jettyを動かす必要があるのでここではJettyを動かす環境の作成について説明します。
プロジェクトの作成
まず、IntelliJを立ち上げます。
そしてプロジェクト新規作成。
以下のように"Web Application"にチェックを入れます。
ライブラリを追加
プロジェクトの生成が完了したら、ライブラリを入れるディレクトリを作成します。
ここでは"libs"とします。
ディレクトリを作成したら、以下のページから2つのjarファイルをダウンロードします。
jetty-all-9.2.13.v20150730.jar
javax.servlet-api-3.1.0.jar
ダウンロードしたら、先ほど作ったライブラリを入れるディレクトリ(今回はlibs)にファイルを入れます。
すると以下のようになります。
そして、以下のアイコンから"Project Structure"を開きます。
開いたら、左のペインから"Modules"を選択し、"Dependencies"タブを開きます。
すると、下部「+」ボタンがあるのでクリックし、"Jars or directories..."をクリックします。
そして、先ほど作成したライブラリディレクトリ(libs)を選択します。
そうすると以下の画面になると思うので、「OK」を押して完了です。
以上で、WebSocketを使う準備ができました。
プログラムを書く
前項でJettyを動かす事が出来るようになったので、次はWebSocketを使う為にプログラムを記述していきます。
今回はjarとして動かすのでmain()を作ります。
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class Main {
public static void main(String[] args){
Server server = new Server(8080);
ResourceHandler resourceHandler = new ResourceHandler();
WebSocketServletImpl wsservlet = new WebSocketServletImpl();
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.addServlet(new ServletHolder(wsservlet), "/");
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { resourceHandler, contextHandler });
server.setHandler(handlers);
try {
server.start();
System.out.println("Server Start");
} catch (InterruptedException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
public class WebSocketServletImpl extends WebSocketServlet {
private static final long serialVersionUID = 1L;
@Override
public void configure(WebSocketServletFactory factory) {
factory.register(WebSocketSample.class);
}
}
WebSocketSample.javaは、@WebSocketアノテーションを忘れずに。
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@WebSocket //付け忘れに注意
public class WebSocketSample {
private Session session;
@OnWebSocketConnect
public void onConnect(Session session) {
this.session = session;
WebSocketBroadcaster.getInstance().join(this);
}
@OnWebSocketMessage
public void onText(String message) {
WebSocketBroadcaster.getInstance().sendToAll(message);
}
@OnWebSocketClose
public void onClose(int statusCode, String reason) {
WebSocketBroadcaster.getInstance().bye(this);
}
public Session getSession(){
return this.session;
}
}
import java.util.ArrayList;
import java.util.List;
public class WebSocketBroadcaster {
private static WebSocketBroadcaster INSTANCE = new WebSocketBroadcaster();
private List<WebSocketSample> clients = new ArrayList<WebSocketSample>();
private WebSocketBroadcaster(){}
protected static WebSocketBroadcaster getInstance(){
return INSTANCE;
}
//接続時に呼ばれる
protected void join(WebSocketSample socket){
clients.add(socket);
}
//切断時に呼ばれる
protected void bye(WebSocketSample socket){
clients.remove(socket);
}
//全ソケットにmessageを送信
protected void sendToAll(String message){
for(WebSocketSample member: clients){
member.getSession().getRemote().sendStringByFuture(message);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<display-name>WebSocketSample</display-name>
<servlet-name>WebSocketSample</servlet-name>
<servlet-class>WebSocketServletImpl</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebSocketSample</servlet-name>
<url-pattern>/WebSocketSample/*</url-pattern>
</servlet-mapping>
</web-app>
おまけ(?)
Mainにサーバを立ち上げる記述があります。
server.start();
サーバが立ち上がった後に、以下のコードを実行する事で接続中の全クライアントに対してメッセージを送ることが出来ます。
WebSocketBroadcaster.getInstance().sendToAll("Hello World!");
実行
上部にある実行ボタンの横のプルダウンメニュの"Edit Configurations"を選択します。
(ここでは既にMainがありますが気にしないで下さい)
下図のように「+」をクリックして"Application"をクリックします。
名前とMainクラスを設定し、OKをクリックします。
そして、実行ボタンを押すとサーバが起動します。
WebSocket接続
サーバを動かした状態で、Chromeの拡張を入れて実際に動作を確認してみます。
Simple WebSocket Client
URLに「ws://localhost:8080/WebSocketSample」を設定してOpenすると接続できます。
接続出来たら、Requestからメッセージを送ってそのまま戻ってくると成功です。
jarを生成
"Project Structure"を開き、左のペインから"Artifacts"をクリックして「+」をクリックし、以下を参考に選択します。
Main Classを設定します。(ここではModule名などがJettyWS2になってますが気にしないで下さい。)
設定が終わったら、Buildします。
あとは、jarが生成されるのでそれを叩けばサーバが動きます。