Spring项目中使用webservice实现h5的websocket通信

一、在项目中建立一个webservice来做后台操作。

package org.calonlan.soulpower.websocket;import java.text.SimpleDateFormat;
import java.util.Date;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;/*** 这里使用注释的方式来向系统指明,我的这个WebSocketTest是一个webservice。 同时指定了路径为/websocket/{uCode}* 其中的{uCode}是一个变化的参数,在网页端动态的输入。这样我就可以通过@PathParam("uCode")这个注释在参数中获得用户的信息等等了。* * */
@ServerEndpoint("/websocket/{uCode}")
public class WebSocketTest {/*** @param message*            这里是客户端传来的消息,我这里只是简单的测试文本消息,消息的种类可以有很多种。* @param uCode*            这就是{uCode}中传来的路径参数,可以用来传递用户的信息。例如帐号。* @throws Exception*             偷懒的人总是抛出一个EXCEPTION*/@OnMessage// 当有消息传来的时候进行处理的方法public void onMessage(String message, @PathParam("uCode") String uCode)throws Exception {System.out.println("revived:" + message);// 输出一下接收到的消息String tem[] = message.split("##to##");// 消息的格式是// tousername##to##message,分隔以后第一个就是要发送的用户名,第二个就是消息了if (SessionUtils.hasConnection(tem[0])) {// 从sessionUtils中判断一下是否要发送的用户名是否已经登录,登录的话做以下操作/* 弄个时间开始 */SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String x = sdf.format(new Date());/* 弄个时间结束 *//** 消息的发送,可以选择AsyncRemote也可以选择* BasicRemote,区别在于AsyncRemote是不会阻塞的,系统不会去管消息是否发送完成直接占用通道去发* 。使用它的话要用户自己去实现控制,所以我选择BasicRemote,*/SessionUtils.get(tem[0]).getBasicRemote().sendText(uCode + "##to##" + x + ":" + tem[1]);} else {// 没有登录的话做以下操作SessionUtils.get(uCode).getBasicRemote().sendText("用户不在线");}}/*** @param uCode*            同上* @param session*            这个是用户建立的session信息,用来唯一标识这个用户的通信* @throws Exception*             你懂得*/@OnOpen// 用户建立链接的时候执行的方法public void onOpen(@PathParam("uCode") String uCode, Session session)throws Exception {if (SessionUtils.hasConnection(uCode)) {// 判断缓存中是否有uCode,如果有执行括号内的方法SessionUtils.get(uCode).close();// 因为已经登录了,那么将已经登录的下线SessionUtils.remove(uCode);// 移除掉缓存中的<uCode,Session>SessionUtils.put(uCode, session);// 添加新的<uCode,Session>System.out.println(uCode + "has join server");} else {System.out.println(uCode + "has join server");/* 如果没有缓存相关的<uCode,Session>,那么直接添加 */SessionUtils.put(uCode, session);}}@OnClose//客户端断开链接时执行的方法public void onClose(@PathParam("uCode") String uCode) {System.out.println(uCode + "has left server");SessionUtils.remove(uCode);//直接移除就好了,session已经关闭了System.out.println("left deal was finished");}@OnError//客户端出错误的时候执行的方法public void onError(Throwable e, Session session) {if (SessionUtils.clients.containsValue(session)) {//移除出错的sessionSessionUtils.remove(session);}}}

二、实现用来管理session的uti类。

package org.calonlan.soulpower.websocket;import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;import javax.websocket.Session;public class SessionUtils {/*<uCode,Session>的缓存*/public static Map<String, Session> clients = new ConcurrentHashMap<String, Session>();public static void put(String uCode, Session session) {//添加clients.put(uCode, session);}public static Session get(String uCode) {//根据uCode来获取return clients.get(uCode);}public static void remove(String uCode) {//根据uCode来移除clients.remove(uCode);}public static void remove(Session session) {//根据session来移除Iterator<java.util.Map.Entry<String, Session>> ito = clients.entrySet().iterator();while (ito.hasNext()) {java.util.Map.Entry<String, Session> entry = ito.next();if (entry.getKey().equals(session))remove(entry.getKey());}}public static boolean hasConnection(String uCode) {//根据uCode来判断是否包含对应用户名的<uCode,Session>return clients.containsKey(uCode);}
}

三、html页面实现

<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html> <head> <title>WebSoket Demo</title> <script type="text/JavaScript"> //验证浏览器是否支持WebSocket协议if (!window.WebSocket) { alert("WebSocket not supported by this browser!"); } var ws;function display() { //创建webSocket,后面的${id}与{uCode}相对应ws=new WebSocket("ws://localhost:8080/newback/websocket/${id}"); //监听消息ws.onmessage = function(event) { log(event.data);}; //绑定关闭事件 ws.onclose = function(event) {/*这段代码的作用是,如果同一个id在其他的页面登录,那么就强制当前的页面下线,关闭。在服务器端我们在同一个id登录时关闭了以前的socket,所以这里在关闭事件中进行操作*/var opened=window.open('about:blank','_self'); opened.opener=null; opened.close();}; //建立websocket的事件,可以用来做一些初始化操作;比如如果用户不在线其他人发送了消息我可以放在数据库里,用户一上线就调用查询方法ws.onopen = function(event) { }; //出现错误的时候的方法ws.onerror =function(event){};} var log = function(s) {//打印消息的方法if (document.readyState !== "complete") {  log.buffer.push(s);  } else {  document.getElementById("contentId").innerHTML += (s + "\n");  }  }function sendMsg(){//这里是发送消息,我制做了c1、c2之间的通话var msg=document.getElementById("messageId");var client='${id}';if(client=='c1')ws.send("c2##to##"+msg.value);//发送消息elsews.send("c1##to##"+msg.value);}</script> </head> <body οnlοad="display();"> <div id="valueLabel"></div> <textarea rows="20" cols="30" id="contentId"></textarea><br/><input name="message" id="messageId"/><button id="sendButton" onClick="javascript:sendMsg()" >Send</button></body> 
</html> 

四、测试。

1.登录c1



服务器端显示



2.登录c2



服务器端显示



登录完成,就可以互相发送消息了。

c1发送给c2


c2发送给c1同样的道理。


这里还看到了很多不是发送的消息,这是我在后台设置的定时任务。服务器可以定时的给客户端发送一些消息。

五、定时任务

这里我遍历sessionutils中的map,给所有用户都发送

package org.calonlan.soulpower.timertask;import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;import javax.websocket.Session;import org.calonlan.soulpower.util.ComputerUtil;
import org.calonlan.soulpower.websocket.SessionUtils;
import org.hyperic.sigar.SigarException;public class TimerTask {public void printTimeStamp() throws SigarException {Map<String, Session> map = SessionUtils.clients;Iterator<Entry<String, Session>> ito = map.entrySet().iterator();while (ito.hasNext()) {Entry<String, Session> entry = ito.next();try {if (entry.getValue().isOpen()) {entry.getValue().getBasicRemote().sendText(ComputerUtil.getMemory());entry.getValue().getBasicRemote().sendText(ComputerUtil.getCPU());entry.getValue().getBasicRemote().sendText(ComputerUtil.getDisk());} else {map.remove(entry.getKey());}} catch (Exception e) {System.out.println("错误");e.printStackTrace();map.remove(entry.getKey());}}}public TimerTask() {}public void doTask() throws SigarException {this.printTimeStamp();}}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/569270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[连载型] Neutron 系列 (15): OpenStack 是如何实现 Neutron 网络 和 Nova虚机 防火墙的...

问题导读&#xff1a;1.Nova安全组是什么&#xff1f;2.Nova的是如何配置的?3.FWaas是什么&#xff1f;1. Nova 安全组1.1 配置 节点配置文件配置项说明controller/etc/nova/nova.confsecurity_group_api nova是的 nova secgroup* 命令使用的是 nova 安全组的 API/etc/neutro…

LeetCode题解

题目是这样的&#xff1a;一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为“Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为“Finish”&#xff09;。问总共有多少条不同的路径&a…

java获得指定的开始时间与结束时间之间的所有日期

import java.text.SimpleDateFormat; import java.util.Calendar;public class TimerTest {public static void main(String[] args) throws Exception {String beginDate "2016-07-16";//开始时间String endDate "2016-07-25";//结束时间SimpleDateForm…

linux中umask的使用

在linux创建文件、文件夹的时候会给它们赋予默认的权限&#xff0c;这个默认权限的赋予就是和umask相关的。总结如下&#xff1a; 1&#xff1a;x 执行 2&#xff1a;w 写入 4&#xff1a;r 读取 文件创建的时候的权限为 666与umask的每一位对应相减&#xff1b;如 umask 为…

spring boot 与redis 整合

创建项目时需要导入的包 在application.yml 配置文件中配置需要的 spring:datasource:url: jdbc:mysql://localhost:3306/数据库名?useSSLfalse&serverTimezoneAsia/Shanghaiusername: 用户名password: 密码jpa:show-sql: truehibernate:ddl-auto: none #redis 可以不配,默…

Http长连接的例子_亲测可用哦

一、什么事Http长连接&#xff1a;在网上有很多很多关于Http长连接的文章&#xff0c;但是我看了很多都看不懂。自己总结的所谓的http长连接就是在一请求一个页面后&#xff0c;在服务器端不断开http连接&#xff0c;而是通过response一直在定时的往页面客户端刷新数据。 二、s…

不同操作系统上DNS客户端操作区别汇总

结论&#xff1a;windows有DNS缓存&#xff0c;Linux默认无DNS缓存&#xff0c;只能依赖于安装其他软件。 一、不同操作系统的客户端的DNS缓存差别 1、windows 系统中dns 解析器会使用系统的dns缓存来提高dns域名解析效率。 例如&#xff1a; 查看当前的dns cache内容&#xff…

SLAM学习心得——建图

1.建图 我们所谓的地图&#xff0c;即所有路标点的集合。一旦我们确定了路标点的位置&#xff0c;那就可以说我们完成了建图。 地图的作用&#xff1a;&#xff08;1&#xff09;定位 &#xff1b;&#xff08;2&#xff09;导航&#xff1b; &#xff08;3&#xff09;避障&am…

spark2

特点 通用 批处理 迭代式计算 交互查询 流处理 组件 spark core:任务调度 内存管理 容错机制 内部定义了RDDs 提供了很多API &#xff0c;为其他组件提供底层的服务 spark sql&#xff1a;报表统计 streaming :从kafka接收数据做实时统计 mlib&#xff1a;mll 支持横向扩展&am…

spark 监控--WebUi、Metrics System(转载)

转载自&#xff1a;https://www.cnblogs.com/barrenlake/p/4364644.html Spark 监控相关的部分有WebUi 及 Metrics System; WebUi用于展示Spark 资源状态、Metrics System 整合的指标信息。 Ui相关流程 Spark集群启动之后&#xff0c;我们可以通过Web观察集群状态等信息&#x…

Hadoop64位版本安装后遇到的警告处理

在使用hadoop的过程中&#xff0c;会遇到一个警告&#xff0c;内容如下&#xff1a; WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 对于这个问题网上很多说法是由于系统位数和所下载…

ueditor跨域上传图片文件(基于jsp框架、tomcat)

额&#xff0c;好久没有用到ueditor了&#xff0c;因为现在的相关工作很少涉及到富文本编辑&#xff1b;最近临时带了一个项目&#xff0c;里面要用到富文本编辑器&#xff0c;而且文件要统一上传到文件服务器上保存&#xff1b;应为以前用过ueditor就试着在网上着一些跨域保存…

精选Pycharm里6大神器插件

http://www.sohu.com/a/306693644_752099 上次写了一篇关于Sublime的精品插件推荐&#xff0c;有小伙伴提议再来一篇Pycharm的主题。相比Sublime&#xff0c;Pycharm要强大许多&#xff0c;而且是专为python设计的集成开发环境&#xff0c;所以无论是自身功能、环境配置还是使用…

数字信号处理实验(一)——DTFT

一、离散序列傅里叶变化——DTFT 1、DTFT公式 2、Matlab算法实现 function[X]dtft(x,n,w,flag)%计算离散时间付里叶变换 %[X]dtft(x,n,w) %X在w频率点上的DTFT数组 %xn点有限长度序列 %n样本位置向量 %w频率点位置向量X x * (exp(-j).^(n * w));3、DTFT一些画图代码 function …

修改hadoop中yarn的webui中显示的任务时间为中国时间

在${HADOOP_HOME}\share\hadoop\yarn目录下找到hadoop-yarn-common-x.x.x.jar&#xff0c;然后用winRAR打开&#xff1b; 打开以后结构如下&#xff1a; 进入webapps/static/目录&#xff0c;然后修改yarn.dt.plugins.js&#xff1b;做出如下修改&#xff1a; &#xff08;1&a…

Trident API 概览

Trident API 概览 在网上看到了很多有TRIDENT相关API的翻译&#xff0c;看来看去&#xff0c;总觉得没有说清楚很多东西&#xff0c;所以自己结合使用的经验翻译了一篇出来&#xff1b;翻译完以后&#xff0c;也发现 在自己的翻译中也有很多地方是表达不清楚的不过多少感觉有些…

Trident State译文

Trident State 译文 Trident针对状态化的数据源的读写进行了一流的分装。State可以包含在拓扑中-例如&#xff0c;保存在内存中&#xff0c;有HDFS提供备份-也可以保存在一个外部的数据库中&#xff0c;像Memcached和Cassandra。针对以上的所有情况&#xff0c;Trident的API都…

软件之道:软件开发争议问题剖析

软件之道&#xff1a;软件开发争议问题剖析 基本信息 原书名&#xff1a; Making Software 原出版社&#xff1a; OReilly 作者&#xff1a; (美)Andy Oram Greg Wilson 译者&#xff1a; 鲍央舟 张玳 沈欢星丛书名&#xff1a; 图灵程序设计丛书出版社&#xff1a;人民邮…

Java 多线程-生产者、消费者

一、整体代码 ThreadDemo.java public class ThreadDemo { public static void main(String[] args) { Godown godown new Godown(0); Consumer c1 new Consumer(50, godown); Consumer c2 new Consumer(20, godown); Consumer c3 new Consumer(30, godown); Producer p1 …

HGOI20190707 题解

Problem A 钢铁侠的诞生 现在有$n$个数字$a_i \leq 10^9 $&#xff0c;然后取出$m$个数字&#xff0c;保证合法。 从小到大输出剩余的$n-m$个数字。 对于100%的数据$m\leq n \leq 3\times 10^5$ Sol : 直接map映射然后用iterator来遍历整个map输出答案即可。 复杂度大概是$O(n…