一、介绍

1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket

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

3.spring与websocket整合需要spring 4.x,并且使用了socketjs,对不支持websocket的浏览器可以模拟websocket使用

二、方式一:tomcat

使用这种方式无需别的任何配置,只需服务端一个处理类,

服务器端代码

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");

//判断当前浏览器是否支持WebSocket

if ('WebSocket' in window) {

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

} else {

alert('当前浏览器 Not support websocket')

}

//连接发生错误的回调方法

websocket.onerror = function() {

setMessageInnerHTML("WebSocket连接发生错误");

};

//连接成功建立的回调方法

websocket.onopen = function() {

setMessageInnerHTML("WebSocket连接成功");

}

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

websocket.onmessage = function(event) {

setMessageInnerHTML(event.data);

}

//连接关闭的回调方法

websocket.onclose = function() {

setMessageInnerHTML("WebSocket连接关闭");

}

//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。

window.onbeforeunload = function() {

closeWebSocket();

}

//关闭WebSocket连接

function closeWebSocket() {

websocket.close();

}

发送消息只需要使用websocket.send(“发送消息”),就可以触发服务端的onMessage()方法,当连接时,触发服务器端onOpen()方法,此时也可以调用发送消息的方法去发送消息。关闭websocket时,触发服务器端onclose()方法,此时也可以发送消息,但是不能发送给自己,因为自己的已经关闭了连接,但是可以发送给其他人。

三、方法二: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区分WebSocketHandler,以便定向发送消息 String userName =

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

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

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

*

* } }

*/

//使用userName区分WebSocketHandler,以便定向发送消息(使用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

这个类是对消息的一些处理,比如是发给一个人,还是发给所有人,并且前端连接时触发的一些动作

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;// 这个会出现性能问题,最好用Map来存储,key用userid

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

static {

users = new ArrayList();

}

/**

* 连接成功时候,会触发UI上onopen方法

*/

@Override

public void afterConnectionEstablished(WebSocketSession session) throws Exception {

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

users.add(session);

// 这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户

// TextMessage returnMessage = new TextMessage("你将收到的离线");

// session.sendMessage(returnMessage);

}

/**

* 在UI在用js调用websocket.send()时候,会调用该方法

*/

@Override

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

sendMessageToUsers(message);

//super.handleTextMessage(session, message);

}

/**

* 给某个用户发送消息

*

* @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;

}

}

}

/**

* 给所有在线用户发送消息

*

* @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();

//调用后台handleTextMessage方法

websocket.send(msg);

} else {

alert("连接失败!");

}

});

注意导入socketjs时要使用地址全称,并且连接使用的是http而不是websocket的ws

总结

以上所述是小编给大家介绍的java 实现websocket的两种方式实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

java的websocket_java 实现websocket的两种方式实例详解相关推荐

  1. websocket java 例子_java 实现websocket的两种方式实例详解

    目录 一.介绍 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring ...

  2. python模块的导入的两种方式区别详解

    Python 有两种导入模块的方法.两种都有用,你应该知道什么时候使用哪一种方法.一种方法,import module,另一种是from module import,下面是 from module i ...

  3. php mysql 去重_mysql去重的两种方法实例详解

    这篇文章主要介绍了mysql去重的两种方法详解及实例代码的相关资料,这里对去重的两种方法进行了一一实例详解,需要的朋友可以参考下 mysql去重 方法一: 在使用MySQL时,有时需要查询出某个字段不 ...

  4. 【Vue】路由Router传参的两种方式(详解)

    本文我们来介绍一下Vue中的 路由传参 问题,首先我们来准备一个基本路由的页面,如下: <!DOCTYPE html> <html lang="en"> & ...

  5. Spring详解-------依赖注入的三种方式实例详解

    目录 1.什么是依赖注入 1.1类的关系 1.1.1 依赖关系(Dependency) 1.1.2 聚合(Aggregation) 1.2关系强度 2 为什么使用依赖注入 2.1开闭原则 2.1.1 ...

  6. python表单提交的两种方式_详解flask表单提交的两种方式

    一.通用方式 通用方式就是使用ajax或者$.post来提交. 前端html ... data Submit &nbsp 将操作绑定 $(document).ready(function() ...

  7. 权限管理实现的两种方式(详解)

  8. Java中线程的创建有两种方式

    Java中继承thread类与实现Runnable接口的区别 Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过 ...

  9. 批量插入数据库语句java_java相关:MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码)...

    java相关:MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码) 发布于 2020-7-22| 复制链接 本文通过实例代码给大家分享了MyBatis批量插入数据到Oracle数据库 ...

最新文章

  1. vc6.0绿色完整版 适用于xp win7 win8 win10
  2. 自然语言处理的发展历程
  3. python3 判断进程是否存在
  4. 树莓派 4B安装ubuntu18.04与melodic版ROS
  5. 怎样在Ubuntu系统安装可用的QQ
  6. WPF 实现ScrollViewer的垂直偏移滚动跳转
  7. LR通过SiteScope监控mysql
  8. 获取进程或线程的ID以及句柄信息
  9. Python基础学习六 操作Redis
  10. java 虚拟机内存管理_java虚拟机内存管理
  11. Java 1.2.3 文件输入与输出
  12. 为什么C语言简洁灵活方便,C语言语法简洁紧凑使用方便灵活具有丰富的运算.ppt...
  13. 代码Review那些事
  14. linux优化安装包,安装Xshell跟Linux相连并优化(付安装包)
  15. java 九九乘法表 99乘法表
  16. 开源免费截图软件ShareX如何改变文字水印和logo特效透明度
  17. 使用@Vaild或@Validated正则校验以及常用正则
  18. 2022建筑电工(建筑特殊工种)考试题目模拟考试平台操作
  19. MySQL 高级知识之 Show Profile
  20. 教育知识与能力(1)

热门文章

  1. mysql没法修改数据_MySQL学习笔记之数据的增、删、改实现方法
  2. php mongodb 别名,PHP mongo与mongodb扩展 | 码路春哥
  3. 永恒python怎么强化_永恒python加6_pythontip 挑战python (6-10)
  4. 每日算法C语言1-求某整数
  5. C语言学习之用*打印菱形
  6. Jenkins任务失败,发送邮件通知
  7. Eclipse 配置 maven 的两个 settings 文件
  8. 使用Amazon Simple Queue Service(SQS) 实现简单的消息服务
  9. enquire.js-响应css媒体查询的轻量级javascript库
  10. hdu 6200 mustedge mustedge mustedge(dfs序+树状数组+并查集)