一、在项目中建立一个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();}}

Spring项目中使用webservice实现h5的websocket通信相关推荐

  1. spring 项目中集成 Protocol Buffers 示例

    http://blog.csdn.net/fangzhangsc2006/article/details/8687388 本文适用于了解spring框架,同时想在spring项目中使用Protocol ...

  2. 【SpringBoot】Spring项目中value注解,@Value不能够读取到配置文件的值,无法成功注入值的问题汇总及解决

    Spring项目中value注解,@Value不能够读取到配置文件的值,无法成功注入值的问题汇总及解决 @Value注解 常规用法示例 我们都知道通过@Value()注解可以取到我们配置文件的内容,之 ...

  3. 将MongoDB集成到您的Spring项目中

    本文展示了如何通过注释配置将MongoDB集成到您的spring项目中. 我们将从Gradle配置开始. group 'com.gkatzioura.spring' version '1.0-SNAP ...

  4. redis集成spring_将Redis集成到您的Spring项目中

    redis集成spring 本文介绍如何通过注释配置将Redis缓存集成到您的spring项目中. 我们将从Gradle配置开始. 我们将使用jedis驱动程序. group 'com.gkatzio ...

  5. 将Redis集成到您的Spring项目中

    本文展示了如何通过注释配置将Redis缓存集成到您的spring项目中. 我们将从Gradle配置开始. 我们将使用jedis驱动程序. group 'com.gkatzioura.spring' v ...

  6. 在Maven+Spring项目中使用Node.js的Gulp进行前端自动化构建

    摘要: 在Maven+Spring项目中使用Node.js的Gulp进行前端自动化构建 刚开始打算进行前后端分离开发,后来发现在使用JSP或者Freemarker做动态页面时,想发挥这些自动化构建工具 ...

  7. 在Spring项目中集成使用MongoDB

    在Spring项目中集成使用MongoDB 这里使用的是maven工程,所以依赖jar包都是pom.xml配置型式. pom.xml引入依赖 <properties><spring. ...

  8. mybatis手动切换数据库_在Spring项目中使用 Mybatis 如何实现动态切换数据源

    在Spring项目中使用 Mybatis 如何实现动态切换数据源 发布时间:2020-11-17 16:20:11 来源:亿速云 阅读:108 作者:Leah 这篇文章将为大家详细讲解有关在Sprin ...

  9. Spring项目中 注解@Aspect无法被引入的原因

    Spring项目中 注解@Aspect无法被引入的原因 解决方式 解决方式    在maven 中引入最新版本的Aspectj依赖,官网显示为 <!-- https://mvnrepositor ...

最新文章

  1. Android Studio 使用Log
  2. 【转】Net Framework,Net Core 和 Net Standard 区别
  3. 飞机是由塑料杆的飞鸽传书
  4. 给一线讲产品·8期|VPC、子网、安全组,是什么关系?
  5. 定量库存控制模型_供应链分析:关于库存管理的预测功能(1)
  6. Android 获取静态上下文(Application)
  7. VUE 项目如何快速优化?| 原力计划
  8. java算法按指定数量读取集合或数组中的值
  9. win10无法装载iso文件_win10系统打开iso格式文件的四种方法
  10. 设置8211网口方法并关闭EEE模式
  11. 垃圾工作还不如伺候一个渣男!!!
  12. 关于\x开头的字符串编码转换中文解决方法
  13. wegame显示不出区服务器,wegame无法显示网页怎么办?腾讯wegame无法显示网页的三种解决方法...
  14. 阿里现场三面+HR面
  15. java8中map的新方法--replace
  16. 一款易用的视频云是如何迅速积累客户的?
  17. 利用poi 1.6 通过模板导出复杂 Word表格,包含合单元格后垂直居中、循环生成行等
  18. 中文自然语言处理--基于 textCNN 的电影推荐系统
  19. Mac电脑使用EasyAR45的注意事项
  20. python3 运行argparse XX.py: error: the following arguments are required: N An exception has occurred,

热门文章

  1. ❤️六W字《计算机基础知识》(二)(建议收藏)❤️
  2. informix和mysql的区别_DB2与Informix区别比较
  3. 通过stream去重_Java 8 Stream.distinct() 列表去重的操作
  4. 为什么自己编写的页面总是在那里抖动_别克威朗为什么销量不佳?
  5. 数码管显示实验一 编写程序让8只数码管同时显示零
  6. Java中文乱码破碎重组_总结彻底解决Spring MVC+Mybatis中文乱码问题
  7. python基础入门(6)之列表
  8. C++ PAT 乙级 ——1002 读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。
  9. PHP在哪里执行_php文件放在哪运行
  10. 【OpenCV 例程200篇】92. 指数噪声、均匀噪声、椒盐噪声