2015年8月31日月曜日

WebSocketのサンプルコード(サーバサイド)

GlassFish 4.1 + Java 1.7で記述。
(サポート切れててゴメン。たぶん1.8でも動くよ(祈り)。)

なんか画面の表示下のコード表示が微妙にバグ踏んでるけど、まあいいや。
(勝手に<Session>を</session>で閉じなくていいんだよ......</session>消せないし...)
※102行目の</session></session>は無視おねがいします。

package websocketchatter;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

/**
 * WebSocketのURIを指定。
 * @author USER
 */
@ServerEndpoint("/MessageReceiptor")
public class MessageReceiptor {

    private static Set peers = Collections.synchronizedSet(new HashSet());
    private static File file;
    private static BufferedWriter writer;

  /* いずれかのセッションからメッセージが送信された場合のメソッド */
    @OnMessage
    public String onMessage(String message) {
       for(Session s : peers) {
      /*
             非同期に各セッションにメッセージを送る。
           */
           s.getAsyncRemote().sendText(message);
           try {
               System.out.println(message);
               writer.write(message, 0, message.length());
               writer.newLine();
               writer.flush();
           } catch (IOException ex) {
               Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
           }
           System.out.println(message);
       }
        return null;
    }
  /* セッションがクローズされた際に呼び出されるメソッド */
    @OnClose
    public void onClose(Session peer) {
        peers.remove(peer);
    }

    /* セッションがオープンされた際に呼び出されるメソッド */
    @OnOpen
    public void onOpen(Session peer) {
    /*
         この処理は非常に雑なので参考にしないで。
     永続化に際してはJPAとかを使ってRDBに書き込んだりしたほうがいいと思います。
     滅茶苦茶雑な処理です。(こんな書き方はしてはいけません。)
         修正したら正式版を別記事で挙げます。
        */
        if(file == null) {
            Date date = new Date();
            SimpleDateFormat format = new SimpleDateFormat("YYYYMMdd");
            String str = format.format(date);
            file = new File(str+".log");
            try {
                System.out.println("File Path:" + file.getCanonicalPath());
            } catch (IOException ex) {
                Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        if(writer == null) {
            try {
                writer = new BufferedWriter(new FileWriter(file));
            } catch (IOException ex) {
                Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        try {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            for(String str = reader.readLine(); str != null; str = reader.readLine()) {
                peer.getAsyncRemote().sendText(str);
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
        }       
        peers.add(peer);
    }    
}


そのうち、クライアント側処理(jQuery + Bootstrapを組み合わせた場合かな~...)
と組み合わせた時の画像か動画でも載せます。

ちな、jQueryとBootstrapの使い方として正しいのかは保証しません。

なので、今後のToDoとしては以下の通り

  1. クライアント側(ブラウザ側実装の提示)
  2. PowerPointスライド(画像)によるサーバサイド処理の内容の表示
  3. @OnOpen処理の屑さ加減の改善(JPAを使ったRDBによる永続化

0 件のコメント:

コメントを投稿