天天看點

JAVA開發WebSocket應用開發流程,附代碼說明

WebSocket的學習以及使用

首先,舊版本的Tomcat 不能支援WebSocket, 至少需要 7.0.47 以上才可以;

其次,建立BitCoinServer類,用注解@ServerEndpoint("/ws/bitcoinServer")把它标記為一個WebSocket Server

ws/bitcoinServer 表示有通過這個位址通路該服務

OnOpen 表示有浏覽器連結過來的時候被調用

OnClose 表示浏覽器發出關閉請求的時候被調用

OnMessage 表示浏覽器發消息的時候被調用

OnError 表示有錯誤發生,比如網絡斷開了等等

sendMessage 用于向浏覽器回發消息

其中OnOpen發生的時候,即有連結過來的時候,會把目前WebSocket Server丢在ServerManager裡管理起來,這樣Tomcat才知道總共有哪些Server, 友善以後進行群發;

代碼如下:

package

com.myjava.bitcoin;

import

java.io.IOException;

import

javax.websocket.OnClose;

import

javax.websocket.OnError;

import

javax.websocket.OnMessage;

import

javax.websocket.OnOpen;

import

javax.websocket.Session;

import

javax.websocket.server.ServerEndpoint;

@ServerEndpoint

(

"/ws/bitcoinServer"

)

public

class

BitCoinServer {

//與某個用戶端的連接配接會話,需要通過它來給用戶端發送資料

private

Session session;

@OnOpen

public

void

onOpen(Session session){

this

.session = session;

ServerManager.add(

this

);    

}

public

void

sendMessage(String message) 

throws

IOException{

this

.session.getBasicRemote().sendText(message);

}

@OnClose

public

void

onClose(){

ServerManager.remove(

this

); 

}

@OnMessage

public

void

onMessage(String message, Session session) {

System.out.println(

"來自用戶端的消息:"

+ message);

}

@OnError

public

void

onError(Session session, Throwable error){

System.out.println(

"發生錯誤"

);

error.printStackTrace();

}

}

其次,建立ServerManager 類,ServerManager 中維護了一個線程安全的集合servers, 用于因為浏覽器發起連接配接請求而建立的BitCoinServer. 

broadCast 方法周遊這個集合,讓每個Server向浏覽器發消息。

package

com.myjava.bitcoin;

import

java.io.IOException;

import

java.util.ArrayList;

import

java.util.Collection;

import

java.util.Collections;

public

class

ServerManager {

private

static

Collection<BitCoinServer> servers = Collections.synchronizedCollection(

new

ArrayList<BitCoinServer>());

public

static

void

broadCast(String msg){

for

(BitCoinServer bitCoinServer : servers) {

try

{

bitCoinServer.sendMessage(msg);

catch

(IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

public

static

int

getTotal(){

return

servers.size();

}

public

static

void

add(BitCoinServer server){

System.out.println(

"有新連接配接加入! 目前總連接配接數是:"

+ servers.size());

servers.add(server);

}

public

static

void

remove(BitCoinServer server){

System.out.println(

"有連接配接退出! 目前總連接配接數是:"

+ servers.size());

servers.remove(server);

}

}

然後還需建立BitCoinDataCenter,使其繼承HttpServlet.

标記為Servlet不是為了其被通路,而是為了便于伴随Tomcat一起啟動,因為可以通過loadOnStartup一起就啟動了

這個類實作了Runnable,可以在初始化方法裡建立一個線程并調用之。

run 方法: 每個1-3秒就建立一個新價格,然後根據目前有多少人連結過來,進行調整價格,接着通過ServerManager廣播出去。 這樣浏覽器就看到如如圖所示的效果了

package

com.myjava.bitcoin;

import

java.util.Random;

import

javax.servlet.ServletConfig;

import

javax.servlet.annotation.WebServlet;

import

javax.servlet.http.HttpServlet;

@WebServlet

(name=

"BitCoinDataCenter"

,urlPatterns = 

"/BitCoinDataCenter"

,loadOnStartup=

1

//标記為Servlet不是為了其被通路,而是為了便于伴随Tomcat一起啟動

public

class

BitCoinDataCenter 

extends

HttpServlet 

implements

Runnable{

public

void

init(ServletConfig config){

startup();

}

public

void

startup(){

new

Thread(

this

).start();

}

@Override

public

void

run() {

int

bitPrice = 

100000

;

while

(

true

){

//每隔1-3秒就産生一個新價格

int

duration = 

1000

+

new

Random().nextInt(

2000

);

try

{

Thread.sleep(duration);

catch

(InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//新價格圍繞100000左右50%波動

float

random = 

1

+(

float

) (Math.random()-

0.5

);

int

newPrice = (

int

) (bitPrice*random);

//檢視的人越多,價格越高

int

total = ServerManager.getTotal();

newPrice = newPrice*total;

String messageFormat = 

"{\"price\":\"%d\",\"total\":%d}"

;

String message = String.format(messageFormat, newPrice,total);

//廣播出去

ServerManager.broadCast(message);

}

}

}

最後,建立index.jsp頁面進行測試

在WebContent下建立index.jsp

主要代碼講解:

1. 判斷浏覽器是否支援WebSocket;

     if ('WebSocket' in window) {}

2. 接受伺服器回發的消息

    websocket.onmessage = function (event) {      setMessageInnerHTML(event.data);

    }

<%@ page language="java" pageEncoding="UTF-8" %>

<!DOCTYPE html>

<

html

>

<

head

>

<

title

>用WebSocket實時獲知比特币價格</

title

>

</

head

>

<

body

>

<

div

style

=

"width:400px;margin:20px auto;border:1px solid lightgray;padding:20px;text-align:center;"

>

目前比特币價格:¥<

span

style

=

"color:#FF7519"

id

=

"price"

>10000</

span

>

<

div

style

=

"font-size:0.9em;margin-top:20px"

>檢視的人數越多,價格越高, 目前總共 <

span

id

=

"total"

>1</

span

> 個人線上</

div

>           

</

div

>

</

body

>

<

script

type

=

"text/javascript"

>

var websocket = null;

//判斷目前浏覽器是否支援WebSocket

if ('WebSocket' in window) {

websocket = new WebSocket("ws://localhost:8080/bitcoin/ws/bitcoinServer");

//連接配接成功建立的回調方法

websocket.onopen = function () {

websocket.send("用戶端連結成功");

}

//接收到消息的回調方法

websocket.onmessage = function (event) {

setMessageInnerHTML(event.data);

}

//連接配接發生錯誤的回調方法

websocket.onerror = function () {

alert("WebSocket連接配接發生錯誤");

};

//連接配接關閉的回調方法

websocket.onclose = function () {

alert("WebSocket連接配接關閉");

}

//監聽視窗關閉事件,當視窗關閉時,主動去關閉websocket連接配接,防止連接配接還沒斷開就關閉視窗,server端會抛異常。

window.onbeforeunload = function () {

closeWebSocket();

}

}

else {

alert('目前浏覽器 Not support websocket')

}

//将消息顯示在網頁上

function setMessageInnerHTML(innerHTML) {

var bitcoin = eval("("+innerHTML+")");

document.getElementById('price').innerHTML = bitcoin.price;

document.getElementById('total').innerHTML = bitcoin.total;

}

//關閉WebSocket連接配接

function closeWebSocket() {

websocket.close();

}

</

script

>

</

html

>

繼續閱讀