我們是要再微信端出示付款二維碼(自己做的付款二維碼),他人掃碼向我們商戶付款後.該二維碼關閉並且做出相應的業務跳轉.
廢話不多說進入正題!
那就簡單說一下HTTP協議,WebSocket協議. (如果對於這些協議和網絡傳輸過程比較模糊的話,請看下這篇文章 http://blog.csdn.net/gordohu/article/details/54097841 )
一、websocket與http
WebSocket是HTML5出的(協議)可以理解爲HTTP的加強版.( 推薦文章: http://blog.csdn.net/frank_good/article/details/50856585 )
HTTP:鏈接分爲短鏈接,長鏈接,短鏈接是每次請求都要三次握手才能發送自己的信息。即每一個request對應一個response。長鏈接是在一定的期限內保持鏈接。保持TCP連接不斷開。客戶端與服務器通信,必須要有客戶端發起然後服務器返回結果。客戶端是主動的,服務器是被動的。WenSocket:建立了WenSocket之後服務器不必在瀏覽器發送request請求之後才能發送信息到瀏覽器。這時的服務器已有主動權想什麼時候發就可以發送信息到服務器。而且信息當中不必在帶有head的部分信息了與http的長鏈接通信來說,這種方式,不僅能降低服務器的壓力。而且信息當中也減少了部分多餘的信息。
websocket特點:
(1)建立在 TCP 協議之上,服務器端的實現比較容易。
(2)與 HTTP 協議有着良好的兼容性。默認端口也是80和443,並且握手階段採用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理服務器。
(3)數據格式比較輕量,性能開銷小,通信高效。
(4)可以發送文本,也可以發送二進制數據。
(5)沒有同源限制,客戶端可以與任意服務器通信。
(6)協議標識符是ws
(如果加密,則爲wss
),服務器網址就是 URL。
二、上代碼Demo
Servlet配置的基類.
package websocket; import org.apache.catalina.websocket.StreamInbound; import org.apache.catalina.websocket.WebSocketServlet; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; @WebServlet(urlPatterns = { "/zy" }) //註解簡化 public class SocketService extends WebSocketServlet { private static final long serialVersionUID = 1L; public String getId(HttpServletRequest request){ String webSocketId = request.getParameter("webSocketId"); System.out.println("@@建立連接webSocketId="+webSocketId); return webSocketId; } @Override protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest request) { return new SocketServiceInbound(this.getId(request)); } }
配備強大的油條!!!!!
package websocket; import java.nio.CharBuffer; import java.util.HashMap; import java.util.Map; import java.util.Set; public class SocketServiceUtil { // 保存連接的MAP容器 private static final Map<String, SocketServiceInbound> connections = new HashMap<String, SocketServiceInbound>(); /** * 向連接池中添加連接 * @param inbound */ public static void addMessageInbound(SocketServiceInbound inbound) { System.out.println("id : " + inbound.getId() + " join.."); connections.put(inbound.getId(), inbound); } /** * 移除連接池中的連接 * @param id 用戶名 */ public static void removeMessageInbound(String id) { System.out.println("id : " + id + " exit.."); connections.remove(id); } /** * 獲取所有的在線用戶 * @return */ public static Set<String> getOnlineId() { return connections.keySet(); } /** * 向指定的用戶發送消息 * @param id 用戶名 * @param message 消息 */ public static void sendMessageToUser(String id, String message) { try { // 向特定的用戶發送數據 System.out.println("send message to id : " + id + " ,message content : " + message); SocketServiceInbound inbound = connections.get(id); if (inbound != null) { inbound.getWsOutbound().writeTextMessage( CharBuffer.wrap(message)); } } catch (Exception e) { e.printStackTrace(); } } /** * 向所有的用戶發送消息 * @param message 消息 */ public static void sendMessageToAll(String message) { try { Set<String> keySet = connections.keySet(); for (String key : keySet) { SocketServiceInbound inbound = connections.get(key); if (inbound != null) { System.out.println("send message to user : " + key + " ,message content : " + message); inbound.getWsOutbound().writeTextMessage( CharBuffer.wrap(message)); } } } catch (Exception e) { e.printStackTrace(); } } }
靜態常量Map<String,SocketServiceInbound > connections 用於保證每個id 對應一個連接.
鏈接消息綁定.繼承MessageInbound 自定義String id ,與Util中參數數據結構一致.
package websocket; import org.apache.catalina.websocket.MessageInbound; import org.apache.catalina.websocket.WsOutbound; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; public class SocketServiceInbound extends MessageInbound { // 當前連接的用戶名稱 private final String id; public SocketServiceInbound(String id) { this.id = id; } public String getId() { return this.id; } @Override protected void onOpen(WsOutbound outbound) { // TODO Auto-generated method stub //向連接池添加當前的連接對象 SocketServiceUtil.addMessageInbound(this); //向當前連接發送當前在線用戶的列表 //SocketServiceUtil.sendMessageToUser(this.user, "uuuuuuuuuu"); } @Override protected void onClose(int status) { // TODO Auto-generated method stub // 觸發關閉事件,在連接池中移除連接 SocketServiceUtil.removeMessageInbound(this.id); } @Override protected void onTextMessage(CharBuffer message) throws IOException { // TODO Auto-generated method stub SocketServiceUtil.sendMessageToUser(this.id, message.toString()); } @Override protected void onBinaryMessage(ByteBuffer arg0) throws IOException { // TODO Auto-generated method stub throw new UnsupportedOperationException("Binary message not supported."); } }
繼承後的方法的重寫 可直接在頁面中調用.eg:如下
<%@ page contentType="text/html;charset=UTF-8" %> <html> <head> <title></title> </head> <body> <H2>WebSocket Demo</H2> <button id="toAll" onclick="sendToAll()">sendToAll</button> <button id="tohujunbao" value="hujunbao" onclick="sendToHu()">sendTohujunbao</button> <div id="helloDiv"></div> <script src="../js/jquery-1.8.3.min.js"></script> </body> <script> /**************************************************WebSocket********************************************/ var websocket = null; var id = null function sendToHu() { $.post("../Testsicket/sendMessageTo",{"id":$("#tohujunbao").val(),"mesg":"testMessageToJunBao"},function (data) { }) } function sendToAll() { $.post("../Testsicket/sendMessageTo",{"id":id,"mesg":"testMessageToAll"},function (data) { }) } // 判斷當前瀏覽器是否支持WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://192.168.31.104:80/zyDoctor/zy?webSocketId=hujunbao"); } else { alert('當前瀏覽器 Not support websocket3') } // 連接發生錯誤的回調方法 websocket.onerror = function() { alert("連接錯誤"); }; // 連接成功建立的回調方法 websocket.onopen = function() { alert("鏈接成功"); }; // 接收到消息的回調方法 websocket.onmessage = function(event) { //alert(event.data); $("#helloDiv").append(event.data); $("#helloDiv").append("<br>------------------</br>"); }; // 連接關閉的回調方法 websocket.onclose = function() { //setMessageInnerHTML("WebSocket連接關閉"); }; // 監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function() { closeWebSocket(); }; // 關閉WebSocket連接 function closeWebSocket() { websocket.close(); } // 發送消息 function send(message) { websocket.send(message); } </script> </html>
webSocket的四種狀態:
在上一個推薦的文章裏都有說明.包括上文中的回調函數.
- CONNECTING:值爲0,表示正在連接。
- OPEN:值爲1,表示連接成功,可以通信了。
- CLOSING:值爲2,表示連接正在關閉。
- CLOSED:值爲3,表示連接已經關閉,或者打開連接失敗。