WebSocket 作为一种浏览器与服务器的核心通信技术,被嵌入到了浏览器的内核中。WebSocket 的出现使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道。以前的服务器消息推送大部分采用的都是“轮询”和“长连接”技术,这两中技术都会对服务器产生相当大的开销,而且实时性不是特别高。WebSocket技术对只会产生很小的开销,并且实时性特别高。
服务器端(server):
我是JMS是接收数据源,数据处理后,发送onmessage给客户端
package com.ship; import java.io.IOException; import java.util.Properties; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import javax.annotation.PostConstruct; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.Session; import javax.jms.TextMessage; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.server.ServerEndpoint; import org.apache.activemq.ActiveMQConnectionFactory; import org.springframework.stereotype.Controller; import com.common.utils.PropertyLoader; @Controller @ServerEndpoint(value = "/ws") public class WSserver implements MessageListener { private static WSserver instance = null; private javax.websocket.Session wssession; private static final Set<WSserver> connections = new CopyOnWriteArraySet<WSserver>(); public WSserver() { instance = this; } public WSserver getInstance() { return instance; } //感知接收数据源 @Override public void onMessage(Message message) { if (message instanceof TextMessage) { TextMessage txtMsg = (TextMessage) message; try { String content = txtMsg.getText(); // System.out.println("感知数据是: " + content); String[] arrcontent = content.split(" "); for (int i = 0; i < arrcontent.length; i++) { String[] shipinfo = arrcontent[i].split(","); String shipname=shipinfo[0]; String mess=shipname; //服务器发送数据 onMessage(mess); } } catch (Exception e) { e.printStackTrace(); } } } @PostConstruct public void init() { try { buildJmsCon(); } catch (Exception e) { e.printStackTrace(); } } public void buildJmsCon() { // 消费者的主要流程 Connection connection = null; Properties properties = PropertyLoader.getPropertiesFromClassPath( "activemq.properties", "UTF-8"); String topic = properties.getProperty("topic"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); String ipaddress = properties.getProperty("ipaddress"); String port = properties.getProperty("port"); String brokerURL = "failover://tcp://" + ipaddress + ":" + port; try { // 1.初始化connection工厂 ConnectionFactory connectionFactory = new ActiveMQConnectionFactory( username, password, brokerURL); // 2.创建Connection connection = connectionFactory.createConnection(); // 3.打开连接 connection.start(); System.out.println("连接成功.................."); // 4.创建session Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 5.创建消息目标 Destination destination = session.createTopic(topic); // 6.创建消费者 MessageConsumer consumer = session.createConsumer(destination); // 7.配置监听 consumer.setMessageListener(getInstance()); } catch (JMSException e) { e.printStackTrace(); } } @OnOpen public void onOpen(javax.websocket.Session session) { this.wssession = session; connections.add(this); } @OnClose public void onClose() { connections.remove(this); String message = "onClose"; WSserver.broadCast(message); } @OnMessage public void onMessage(String message) { WSserver.broadCast(message); } @OnError public void onError(Throwable throwable) { System.out.println(throwable.getMessage()); } private static void broadCast(String message) { for (WSserver ws : connections) { try { synchronized (ws) { ws.wssession.getBasicRemote().sendText(message); } } catch (IOException e) { connections.remove(ws); try { ws.wssession.close(); } catch (IOException e1) { } WSserver.broadCast("error"); } } } }
客户端(client):
package bjs; import java.net.URI; import java.net.URISyntaxException; import java.util.Scanner; import org.java_websocket.client.WebSocketClient; import org.java_websocket.drafts.Draft_17; import org.java_websocket.handshake.ServerHandshake; public class WSClient { public static WebSocketClient initWs() throws URISyntaxException{ //ws:开头 项目路径+服务器的值 @ServerEndpoint(value = "/ws") String url = "ws://192.168.1.252:8080/ganzhi/ws"; WebSocketClient wc = new WebSocketClient(new URI(url), new Draft_17()) { @Override public void onClose(int arg0, String arg1, boolean arg2) { // TODO Auto-generated method stub } @Override public void onError(Exception arg0) { // TODO Auto-generated method stub System.out.println("error client"); } @Override public void onMessage(String arg0) { // TODO Auto-generated method stub System.out.println("server message: "+arg0); } @Override public void onOpen(ServerHandshake arg0) { // TODO Auto-generated method stub System.out.println("client open: "+arg0.getHttpStatusMessage()); } }; wc.connect(); return wc; } public static void receiveWs(WebSocketClient wc) throws URISyntaxException { Scanner scanner = new Scanner(System.in); while (true) { String message = scanner.nextLine(); if (message.equals("q")) { System.out.println("if blank"); wc.close(); continue; }else { System.out.println("else blank"); wc.send(message); } } } public static void main(String[] args) throws URISyntaxException { WebSocketClient wc=initWs(); receiveWs(wc); } }
客户端测试:
client open: Switching Protocols
server message: 浙越城货0585
server message: 通达148
server message: 鲁济宁货4588
server message: 皖华瑞696
HTML:
var webSocket = null; var tryTime = 0; $(document).ready(function() { var token = $("#token").val(); var map = new BMap.Map("divmap");// 创建地图实例 map.enableScrollWheelZoom(); map.centerAndZoom("嘉兴", 12); /* * map.addControl(new BMap.NavigationControl()); map.addControl(new * BMap.ScaleControl()); */ if (token == null || token == 'null' || token == '') { window.location.href = "/jiaxingport"; } else { loaddata(map); } $("#searchbtn").click(function() { searchship(map); }); /* * window.setInterval(function() { loaddata(map); }, 30000); */ initSocket(map); window.onbeforeunload = function() { // 离开页面时的其他操作 }; }); function loaddata(map) { map.clearOverlays(); // 清除覆盖物 $.ajax({ "url" : "queryshipaisnumpc", "data" : { 'token' : $("#token").val() }, "type" : "post", "datatype" : "json", "success" : function(resp) { var shiplist = resp.baseResult.map.shiplist; var starttime = resp.baseResult.map.starttime; var endtime = resp.baseResult.map.endtime; $("#starttime").val(starttime); $("#endtime").val(endtime); $("#showtimetxt").val("船舶数据最后有效时间:" + starttime); showships(shiplist, map); } }); } function searchship(map) { var starttime = $("#starttime").val(); var content = $("#content").val(); if (content == null || content == '请输入船名') { alert("请输入正确的船名!"); return false; } map.clearOverlays(); // 清除覆盖物 $.ajax({ "url" : "searchshipbyname", "data" : { 'token' : $("#token").val(), 'starttime' : starttime, 'content' : content }, "type" : "post", "datatype" : "json", "success" : function(resp) { var shiplist = resp.baseResult.map.shiplist; // 地点标船 if (shiplist != null && shiplist.length > 0) { $("#showtimetxt").val("船舶数据最后有效时间:" + starttime); showships(shiplist, map); } else { alert("未找到相应船舶"); window.location.reload(); } } }); } function showships(shiplist, map) { if (shiplist != null && shiplist.length > 0) { for (var i = 0; i < shiplist.length; i++) { drawMarker(shiplist[i], map); } } } function drawMarker(shipinfo, map) { var html = "船名:<label>" + shipinfo.shipname + "</label><br>ais:<label>" + shipinfo.ais + "</label><br>最后航行时间:<label>" + shipinfo.shipdate.substr(11, 16) + "</label><br><a style='color:red' onclick='showshipdetail("" + shipinfo.shipname + "")'>船舶详情</a>"; var point = new BMap.Point(shipinfo.longitude, shipinfo.latitude);// 创建点坐标 var label = new BMap.Label(shipinfo.shipname, { offset : new BMap.Size(20, -10) }); var myIcon = null if (shipinfo.shiptype == 1) { myIcon = new BMap.Icon("/jiaxingport/image/main/ds.png", new BMap.Size( 20, 20)); } else { myIcon = new BMap.Icon("/jiaxingport/image/main/uds.png", new BMap.Size(20, 20)); } var marker = new BMap.Marker(point, { icon : myIcon }); // 创建标注 label.setStyle({ display : "none" // 给label设置样式,任意的CSS都是可以的 }); marker.setLabel(label); map.addOverlay(marker); // 将标注添加到地图中 var infoWindow = new BMap.InfoWindow(html); marker.infoWindow = infoWindow;// 多点添加文字信息 marker.addEventListener("click", function(e) { this.openInfoWindow(e.target.infoWindow); }); } function showshipdetail(shipname) { window.location.href = "/jiaxingport/page/ais/shipinfo.jsp?name=" + shipname; } /** * 初始化websocket,建立连接 */ function initSocket(map) { if (!window.WebSocket) { alert("您的浏览器不支持websocket!"); return false; } //项目名+ServerEndpoint名 webSocket = new WebSocket("ws://localhost:8080/ganzhi/ws"); // 收到服务端消息 webSocket.onmessage = function(msg) { var mess = msg.data; var arr = {}; arr = mess.split(","); var shipname = arr[0]; var shipinfo = { "shipname" : shipname, "longitude" : arr[1], "latitude" : arr[2], "ais" : arr[3], "shipdate" : arr[4], "shiptype" : arr[5] }; var allOverlay = map.getOverlays(); for (var i = 0; i < allOverlay.length - 1; i++) { if (allOverlay[i].toString() == "[object Marker]" && allOverlay[i].getLabel().content == shipname) { //移除marker map.removeOverlay(allOverlay[i]); break; } } //画marker drawMarker(shipinfo, map); }; // 异常 webSocket.onerror = function(event) { console.log(event); }; // 建立连接 webSocket.onopen = function(event) { console.log(event); }; // 断线重连 webSocket.onclose = function() { // 重试10次,每次之间间隔10秒 if (tryTime < 10) { setTimeout(function() { webSocket = null; tryTime++; initSocket(); }, 500); } else { tryTime = 0; } }; }