日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java的websocket_java 实现websocket的两种方式实例详解

發(fā)布時間:2024/4/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java的websocket_java 实现websocket的两种方式实例详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、介紹

1.兩種方式,一種使用tomcat的websocket實現(xiàn),一種使用spring的websocket

2.tomcat的方式需要tomcat 7.x,JEE7的支持。

3.spring與websocket整合需要spring 4.x,并且使用了socketjs,對不支持websocket的瀏覽器可以模擬websocket使用

二、方式一:tomcat

使用這種方式無需別的任何配置,只需服務(wù)端一個處理類,

服務(wù)器端代碼

package com.Socket;

import java.io.IOException;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.*;

import javax.websocket.server.PathParam;

import javax.websocket.server.ServerEndpoint;

import net.sf.json.JSONObject;

@ServerEndpoint("/websocket/{username}")

public class WebSocket {

private static int onlineCount = 0;

private static Map clients = new ConcurrentHashMap();

private Session session;

private String username;

@OnOpen

public void onOpen(@PathParam("username") String username, Session session) throws IOException {

this.username = username;

this.session = session;

addOnlineCount();

clients.put(username, this);

System.out.println("已連接");

}

@OnClose

public void onClose() throws IOException {

clients.remove(username);

subOnlineCount();

}

@OnMessage

public void onMessage(String message) throws IOException {

JSONObject jsonTo = JSONObject.fromObject(message);

if (!jsonTo.get("To").equals("All")){

sendMessageTo("給一個人", jsonTo.get("To").toString());

}else{

sendMessageAll("給所有人");

}

}

@OnError

public void onError(Session session, Throwable error) {

error.printStackTrace();

}

public void sendMessageTo(String message, String To) throws IOException {

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

//session.getAsyncRemote().sendText(message);

for (WebSocket item : clients.values()) {

if (item.username.equals(To) )

item.session.getAsyncRemote().sendText(message);

}

}

public void sendMessageAll(String message) throws IOException {

for (WebSocket item : clients.values()) {

item.session.getAsyncRemote().sendText(message);

}

}

public static synchronized int getOnlineCount() {

return onlineCount;

}

public static synchronized void addOnlineCount() {

WebSocket.onlineCount++;

}

public static synchronized void subOnlineCount() {

WebSocket.onlineCount--;

}

public static synchronized Map getClients() {

return clients;

}

}

客戶端js

var websocket = null;

var username = localStorage.getItem("name");

//判斷當(dāng)前瀏覽器是否支持WebSocket

if ('WebSocket' in window) {

websocket = new WebSocket("ws://" + document.location.host + "/WebChat/websocket/" + username + "/"+ _img);

} else {

alert('當(dāng)前瀏覽器 Not support websocket')

}

//連接發(fā)生錯誤的回調(diào)方法

websocket.onerror = function() {

setMessageInnerHTML("WebSocket連接發(fā)生錯誤");

};

//連接成功建立的回調(diào)方法

websocket.onopen = function() {

setMessageInnerHTML("WebSocket連接成功");

}

//接收到消息的回調(diào)方法

websocket.onmessage = function(event) {

setMessageInnerHTML(event.data);

}

//連接關(guān)閉的回調(diào)方法

websocket.onclose = function() {

setMessageInnerHTML("WebSocket連接關(guān)閉");

}

//監(jiān)聽窗口關(guān)閉事件,當(dāng)窗口關(guān)閉時,主動去關(guān)閉websocket連接,防止連接還沒斷開就關(guān)閉窗口,server端會拋異常。

window.onbeforeunload = function() {

closeWebSocket();

}

//關(guān)閉WebSocket連接

function closeWebSocket() {

websocket.close();

}

發(fā)送消息只需要使用websocket.send(“發(fā)送消息”),就可以觸發(fā)服務(wù)端的onMessage()方法,當(dāng)連接時,觸發(fā)服務(wù)器端onOpen()方法,此時也可以調(diào)用發(fā)送消息的方法去發(fā)送消息。關(guān)閉websocket時,觸發(fā)服務(wù)器端onclose()方法,此時也可以發(fā)送消息,但是不能發(fā)送給自己,因為自己的已經(jīng)關(guān)閉了連接,但是可以發(fā)送給其他人。

三、方法二:spring整合

WebSocketConfig.java

這個類是配置類,所以需要在spring mvc配置文件中加入對這個類的掃描,第一個addHandler是對正常連接的配置,第二個是如果瀏覽器不支持websocket,使用socketjs模擬websocket的連接。

package com.websocket;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.socket.config.annotation.EnableWebSocket;

import org.springframework.web.socket.config.annotation.WebSocketConfigurer;

import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import org.springframework.web.socket.handler.TextWebSocketHandler;

@Configuration

@EnableWebSocket

public class WebSocketConfig implements WebSocketConfigurer {

@Override

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

registry.addHandler(chatMessageHandler(),"/webSocketServer").addInterceptors(new ChatHandshakeInterceptor());

registry.addHandler(chatMessageHandler(), "/sockjs/webSocketServer").addInterceptors(new ChatHandshakeInterceptor()).withSockJS();

}

@Bean

public TextWebSocketHandler chatMessageHandler(){

return new ChatMessageHandler();

}

}

ChatHandshakeInterceptor.java

這個類的作用就是在連接成功前和成功后增加一些額外的功能,Constants.java類是一個工具類,兩個常量。

package com.websocket;

import java.util.Map;

import org.apache.shiro.SecurityUtils;

import org.springframework.http.server.ServerHttpRequest;

import org.springframework.http.server.ServerHttpResponse;

import org.springframework.web.socket.WebSocketHandler;

import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

public class ChatHandshakeInterceptor extends HttpSessionHandshakeInterceptor {

@Override

public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,

Map attributes) throws Exception {

System.out.println("Before Handshake");

/*

* if (request instanceof ServletServerHttpRequest) {

* ServletServerHttpRequest servletRequest = (ServletServerHttpRequest)

* request; HttpSession session =

* servletRequest.getServletRequest().getSession(false); if (session !=

* null) { //使用userName區(qū)分WebSocketHandler,以便定向發(fā)送消息 String userName =

* (String) session.getAttribute(Constants.SESSION_USERNAME); if

* (userName==null) { userName="default-system"; }

* attributes.put(Constants.WEBSOCKET_USERNAME,userName);

*

* } }

*/

//使用userName區(qū)分WebSocketHandler,以便定向發(fā)送消息(使用shiro獲取session,或是使用上面的方式)

String userName = (String) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USERNAME);

if (userName == null) {

userName = "default-system";

}

attributes.put(Constants.WEBSOCKET_USERNAME, userName);

return super.beforeHandshake(request, response, wsHandler, attributes);

}

@Override

public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,

Exception ex) {

System.out.println("After Handshake");

super.afterHandshake(request, response, wsHandler, ex);

}

}

ChatMessageHandler.java

這個類是對消息的一些處理,比如是發(fā)給一個人,還是發(fā)給所有人,并且前端連接時觸發(fā)的一些動作

package com.websocket;

import java.io.IOException;

import java.util.ArrayList;

import org.apache.log4j.Logger;

import org.springframework.web.socket.CloseStatus;

import org.springframework.web.socket.TextMessage;

import org.springframework.web.socket.WebSocketSession;

import org.springframework.web.socket.handler.TextWebSocketHandler;

public class ChatMessageHandler extends TextWebSocketHandler {

private static final ArrayList users;// 這個會出現(xiàn)性能問題,最好用Map來存儲,key用userid

private static Logger logger = Logger.getLogger(ChatMessageHandler.class);

static {

users = new ArrayList();

}

/**

* 連接成功時候,會觸發(fā)UI上onopen方法

*/

@Override

public void afterConnectionEstablished(WebSocketSession session) throws Exception {

System.out.println("connect to the websocket success......");

users.add(session);

// 這塊會實現(xiàn)自己業(yè)務(wù),比如,當(dāng)用戶登錄后,會把離線消息推送給用戶

// TextMessage returnMessage = new TextMessage("你將收到的離線");

// session.sendMessage(returnMessage);

}

/**

* 在UI在用js調(diào)用websocket.send()時候,會調(diào)用該方法

*/

@Override

protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

sendMessageToUsers(message);

//super.handleTextMessage(session, message);

}

/**

* 給某個用戶發(fā)送消息

*

* @param userName

* @param message

*/

public void sendMessageToUser(String userName, TextMessage message) {

for (WebSocketSession user : users) {

if (user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)) {

try {

if (user.isOpen()) {

user.sendMessage(message);

}

} catch (IOException e) {

e.printStackTrace();

}

break;

}

}

}

/**

* 給所有在線用戶發(fā)送消息

*

* @param message

*/

public void sendMessageToUsers(TextMessage message) {

for (WebSocketSession user : users) {

try {

if (user.isOpen()) {

user.sendMessage(message);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

@Override

public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

if (session.isOpen()) {

session.close();

}

logger.debug("websocket connection closed......");

users.remove(session);

}

@Override

public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {

logger.debug("websocket connection closed......");

users.remove(session);

}

@Override

public boolean supportsPartialMessages() {

return false;

}

}

spring-mvc.xml

正常的配置文件,同時需要增加對WebSocketConfig.java類的掃描,并且增加

xmlns:websocket="http://www.springframework.org/schema/websocket"

http://www.springframework.org/schema/websocket

http://www.springframework.org/schema/websocket/spring-websocket-4.1.xsd

客戶端

var websocket;

if ('WebSocket' in window) {

websocket = new WebSocket("ws://" + document.location.host + "/Bank/webSocketServer");

} else if ('MozWebSocket' in window) {

websocket = new MozWebSocket("ws://" + document.location.host + "/Bank/webSocketServer");

} else {

websocket = new SockJS("http://" + document.location.host + "/Bank/sockjs/webSocketServer");

}

websocket.onopen = function(evnt) {};

websocket.onmessage = function(evnt) {

$("#test").html("(" + evnt.data + ")")

};

websocket.onerror = function(evnt) {};

websocket.onclose = function(evnt) {}

$('#btn').on('click', function() {

if (websocket.readyState == websocket.OPEN) {

var msg = $('#id').val();

//調(diào)用后臺handleTextMessage方法

websocket.send(msg);

} else {

alert("連接失敗!");

}

});

注意導(dǎo)入socketjs時要使用地址全稱,并且連接使用的是http而不是websocket的ws

總結(jié)

以上所述是小編給大家介紹的java 實現(xiàn)websocket的兩種方式實例詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

總結(jié)

以上是生活随笔為你收集整理的java的websocket_java 实现websocket的两种方式实例详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。