原文:https://blog.csdn.net/ya_nuo/article/details/79612158

spring集成webSocket实现服务端向前端推送消息

 

1、前端连接websocket代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html> <head lang="en">
<meta charset="UTF-8">
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<title>webSocket-用户66</title>
<script type="text/javascript">
$(function() {
var websocket;
if('WebSocket' in window) {
console.log("此浏览器支持websocket");
websocket = new WebSocket("ws://localhost:8080/residential/websocketDemo/66");
} else if('MozWebSocket' in window) {
alert("此浏览器只支持MozWebSocket");
} else {
alert("此浏览器只支持SockJS");
}
websocket.onopen = function(evnt) {
console.log(evnt);
$("#tou").html("链接服务器成功!")
};
websocket.onmessage = function(evnt) {
$("#msg").html($("#msg").html() + "<br/>" + evnt.data);
};
websocket.onerror = function(evnt) {};
websocket.onclose = function(evnt) {
console.log("与服务器断开了链接!");
$("#tou").html("与服务器断开了链接!")
} $('#close').bind('click', function() {
websocket.close();
}); $('#send').bind('click', function() {
send();
}); function send() {
if(websocket != null) {
var message = document.getElementById('message').value;
console.log(message);
websocket.send(message);
} else {
alert('未与服务器链接.');
}
}
});
</script>
</head> <body>
<div class="page-header" id="tou">
webSocket多终端聊天测试
</div>
<div class="well" id="msg"></div>
<div class="col-lg">
<div class="input-group">
<input type="text" class="form-control" placeholder="发送信息..." id="message">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="send" >发送</button>
</span>
</div>
</div>
<div>
<button class="btn btn-default" type="button" id="close" >关闭连接</button>
</div>
</body>
</html>

2、maven中导入SpringConfiguator的包

<!-- websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>

3、服务端连接websocket代码

package org.property.component;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; 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; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.server.standard.SpringConfigurator; /**
*
* @Description: 给所用户所有终端推送消息
* @author liuqin
* @date 2018年3月19日 下午3:21:31
*
*/
//websocket连接URL地址和可被调用配置
@ServerEndpoint(value="/websocketDemo/{userId}",configurator = SpringConfigurator.class)
public class WebsocketDemo {
//日志记录
private Logger logger = LoggerFactory.getLogger(WebsocketDemo.class);
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0; //记录每个用户下多个终端的连接
private static Map<Long, Set<WebsocketDemo>> userSocket = new HashMap<>(); //需要session来对用户发送数据, 获取连接特征userId
private Session session;
private Long userId; /**
* @Title: onOpen
* @Description: websocekt连接建立时的操作
* @param @param userId 用户id
* @param @param session websocket连接的session属性
* @param @throws IOException
*/
@OnOpen
public void onOpen(@PathParam("userId") Long userId,Session session) throws IOException{
this.session = session;
this.userId = userId;
onlineCount++;
//根据该用户当前是否已经在别的终端登录进行添加操作
if (userSocket.containsKey(this.userId)) {
logger.debug("当前用户id:{}已有其他终端登录",this.userId);
userSocket.get(this.userId).add(this); //增加该用户set中的连接实例
}else {
logger.debug("当前用户id:{}第一个终端登录",this.userId);
Set<WebsocketDemo> addUserSet = new HashSet<>();
addUserSet.add(this);
userSocket.put(this.userId, addUserSet);
}
logger.info("用户{}登录的终端个数是为{}",userId,userSocket.get(this.userId).size());
logger.info("当前在线用户数为:{},所有终端个数为:{}",userSocket.size(),onlineCount);
} /**
* @Title: onClose
* @Description: 连接关闭的操作
*/
@OnClose
public void onClose(){
onlineCount--;
//移除当前用户终端登录的websocket信息,如果该用户的所有终端都下线了,则删除该用户的记录
if (userSocket.get(this.userId).size() == 0) {
userSocket.remove(this.userId);
}else{
userSocket.get(this.userId).remove(this);
}
logger.info("用户{}登录的终端个数是为{}",this.userId,userSocket.get(this.userId).size());
logger.info("当前在线用户数为:{},所有终端个数为:{}",userSocket.size(),onlineCount);
} /**
* @Title: onMessage
* @Description: 收到消息后的操作
* @param @param message 收到的消息
* @param @param session 该连接的session属性
*/
@OnMessage
public void onMessage(String message, Session session) {
logger.info("收到来自用户id为:{}的消息:{}",this.userId,message);
if(session ==null) logger.info("session null");
} /**
* @Title: onError
* @Description: 连接发生错误时候的操作
* @param @param session 该连接的session
* @param @param error 发生的错误
*/
@OnError
public void onError(Session session, Throwable error){
logger.debug("用户id为:{}的连接发送错误",this.userId);
error.printStackTrace();
} /**
* @Title: sendMessageToUser
* @Description: 发送消息给用户下的所有终端
* @param @param userId 用户id
* @param @param message 发送的消息
* @param @return 发送成功返回true,反则返回false
*/
public Boolean sendMessageToUser(Long userId,String message){
if (userSocket.containsKey(userId)) {
logger.info(" 给用户id为:{}的所有终端发送消息:{}",userId,message);
for (WebsocketDemo WS : userSocket.get(userId)) {
logger.info("sessionId为:{}",WS.session.getId());
try {
WS.session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
logger.info(" 给用户id为:{}发送消息失败",userId);
return false;
}
}
return true;
}
logger.info("发送错误:当前连接不包含id为:{}的用户",userId);
return false;
} }

4、Controller层发送消息方法

package org.property.controller.property;
import java.io.IOException; import javax.websocket.Session; import org.property.controller.BaseController;
import org.property.service.WSMessageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView; @Controller
@RequestMapping("/message")
public class MessageController extends BaseController{
private static final Logger logger = LoggerFactory.getLogger(MessageController.class);
//websocket服务层调用类
@Autowired
private WSMessageService wsMessageService; //请求入口
@RequestMapping(value="/TestWS",method=RequestMethod.GET)
@ResponseBody
public String TestWS(@RequestParam(value="userId",required=true) Long userId,
@RequestParam(value="message",required=true) String message){
logger.debug("收到发送请求,向用户{}的消息:{}",userId,message);
if(wsMessageService.sendToAllTerminal(userId, message)){
return "发送成功";
}else{
return "发送失败";
}
} @RequestMapping(value="/test66",method=RequestMethod.GET)
public ModelAndView test66() throws IOException{
return new ModelAndView("/test", null);
} @RequestMapping(value="/test88",method=RequestMethod.GET)
public ModelAndView test88() throws IOException{
return new ModelAndView("/test88", null);
}
}

5、service调用websocket发送消息

package org.property.service;
/**
* @Class: WebSocketMessageService
* @Description: 使用webscoket连接向用户发送信息
* @author JFPZ
* @date 2017年5月15日 上午20:17:01
*/
import java.io.IOException; import javax.websocket.Session; import org.property.component.WebsocketDemo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; @Service("webSocketMessageService")
public class WSMessageService {
private Logger logger = LoggerFactory.getLogger(WSMessageService.class);
//声明websocket连接类
private WebsocketDemo websocketDemo = new WebsocketDemo(); /**
* @Title: sendToAllTerminal
* @Description: 调用websocket类给用户下的所有终端发送消息
* @param @param userId 用户id
* @param @param message 消息
* @param @return 发送成功返回true,否则返回false
*/
public Boolean sendToAllTerminal(Long userId,String message){
logger.info("向用户{}的消息:{}",userId,message);
if(websocketDemo.sendMessageToUser(userId,message)){
return true;
}else{
return false;
}
} }

6、测试,连接发送成功。

spring集成webSocket实现服务端向前端推送消息的更多相关文章

  1. SpringBoot2.0集成WebSocket,实现后台向前端推送信息

    感谢作者,支持原创: https://blog.csdn.net/moshowgame/article/details/80275084 什么是WebSocket? WebSocket协议是基于TCP ...

  2. 服务端向客户端推送消息技术之websocket的介绍

    websocket的介绍 在讲解WebSocket前,我们先来看看下面这种场景,在HTTP协议下,怎么实现. 需求: 在网站中,要实现简单的聊天,这种情况怎么实现呢?如下图: 当发送私信的时候,如果要 ...

  3. Spring Boot 集成 WebSocket 实现服务端推送消息到客户端

    假设有这样一个场景:服务端的资源经常在更新,客户端需要尽量及时地了解到这些更新发生后展示给用户,如果是 HTTP 1.1,通常会开启 ajax 请求询问服务端是否有更新,通过定时器反复轮询服务端响应的 ...

  4. C#服务端通过Socket推送数据到Android端App中

    需求: 描述:实时在客户端上获取到哪些款需要补货. 要求: 后台需要使用c#,并且哪些需要补货的逻辑写在公司框架内,客户端采用PDA(即Android客户端 版本4.4) . 用户打开了补货通知页面时 ...

  5. Java端百度云推送消息Demo

    因为在做Java服务器有用到推送消息机制,于是到网上找了一下,就自己试着敲了一个demo.这个demo主要是简单的一个对app消息推送. jar:百度云消息推送Java端的jar. package x ...

  6. java服务端的 极光推送

    项目中用到了极光推送  下面写下笔记 首先引入jar包   下载地址https://docs.jiguang.cn/jpush/resources/(非maven项目的下载地址) <depend ...

  7. 结合实际需求,在webapi内利用WebSocket建立单向的消息推送平台,让A页面和服务端建立WebSocket连接,让其他页面可以及时给A页面推送消息

    1.需求示意图 2.需求描述 原本是为了给做unity3d客户端开发的同事提供不定时的消息推送,比如商城购买道具后服务端将道具信息推送给客户端. 本篇文章简化理解,用“相关部门开展活动,向全市人民征集 ...

  8. 使用WebSocket实现服务端和客户端的通信

    开发中经常会有这样的使用场景.如某个用户在一个数据上做了xx操作, 与该数据相关的用户在线上的话,需要实时接收到一条信息. 这种可以使用WebSocket来实现. 另外,对于消息,可以定义一个类进行固 ...

  9. springboot 服务端获取前端传过来的参数7种方式

    下面为7种服务端获取前端传过来的参数的方法  1.直接把表单的参数写在Controller相应的方法的形参中,适用于GET 和 POST请求方式 这种方式不会校验请求里是否带参数,即下面的userna ...

随机推荐

  1. 【实用】巧用For xml 生成HTML代码

    可以利用SQL的For xml直接生成HTML结构,比如我想生成如下结构: <li> <img src="..."/> <input type=&qu ...

  2. 003--MySQL 数据库事务

    什么是事务? 事务是一组原子性的 SQL 查询, 或者说是一个独立的工作单元. 在事务内的语句, 要么全部执行成功, 要么全部执行失败. 事务的 ACID 性质 数据库事务拥有以下四个特性, 即 AC ...

  3. Java飞机大战MVC版

    PlaneWar Java飞机大战MVC版 //无聊时偷的雷霆战机素材写了一个飞机大战,本意是练习mvc,但写得还是不清晰 github下载:https://github.com/dejavudwh/ ...

  4. Mybatis中的几种注解映射

    1.  普通映射 2. @Select("select * from mybatis_Student where id=#{id}") 3. public Student getS ...

  5. 转:为什么说招到合适的人比融到钱更加重要 - Hiring Great Talent is More Important Than Fund Raising

    我在猎头行业工作了 20 多年,一直在帮助创业公司招聘优秀的人才.我服务过的客户既有 VC 投资的初创企业,也有即将 IPO 的公司.我和 200 多个 VC 合作过,也见过 300 多个客户失败的案 ...

  6. Linux下文件的打包、解压缩指令——tar,gzip,bzip2

    本文是对 鸟叔的Linux私房菜(基础学习篇) 第三版 的学习笔记,原文可参考原书中文网站 鸟叔的Linux私房菜.更多详细信息可直接参考对应Linux命令的 man 帮助( 如 man tar). ...

  7. hbase Problem binding to node1/192.168.1.13:16020 : 地址已在使用

    这是hbase 从0.9.x升级到1.x后HMaster与HRegionServer端口冲突问题 在hbase升级到1.0.0版本后,默认端口做了改动.其中16020端口是hmaster服务和hreg ...

  8. ES6对数组的扩展

    ECMAScript6对数组进行了扩展,为数组Array构造函数添加了from().of()等静态方法,也为数组实例添加了find().findIndex()等方法.下面一起来看一下这些方法的用法. ...

  9. VIM字符编码基础知识

    1 字符编码基础知识 字符编码是计算机技术中最基本和最重要的知识之一.如果缺乏相关知识,请自行恶补之.这里仅做最简要的说明. 1.1 字符编码概述 所谓的字符编码,就是对人类发明的每一个文字进行数字 ...

  10. uc浏览器的用户体验

    用户界面: 我认为,uc浏览器的用户界面还是很招人喜欢的,可以很容易让用户找到自己想看的网页.简单快捷. 记住用户的选择: uc在每次用户访问完网站之后都会记住用户访问的高频网站,以便下次用户可以更好 ...