Websocket实现前后台通信,demo小测试
新需求大概如下:用户登录系统,登录成功之后建立websocket连接,实现通信
总体思路:前端不是我负责,只是简单的做个功能,先实现登录,把用户标识存入HttpSeesion,再建立websocket连接,拦截器HandshakeInterceptor拦截请求,把用户标识存入Map<String, Object> attributes,然后处理器handler处理各种操作。
/**
* @author wangqq
* @version 创建时间:2018年11月1日 下午2:59:21
* 实现WebSocketConfigure配置自己的socket链接
*/
@Configuration //用于定义配置类,可替换xml配置文件
@EnableWebSocket
@EnableWebMvc //启动Spring MVC特性
public class WebsocketConfig implements WebSocketConfigurer { @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// TODO Auto-generated method stub
registry.addHandler(handler(), "show").addInterceptors(interceptor()).setAllowedOrigins("*");
} @Bean
public WebSocketHandler handler(){
return new Hanlder();
} @Bean
public HandshakeInterceptor interceptor() {
return new HandshakeInterceptor();
} }
registry.addHandler第一个参数是处理器,自己可以写,第二个参数是前后台建立链接的路径,
addInterceptors 添加拦截,再握手之前之后,处理自己的业务
setAllowedOrigins 解决跨域,*代表不限,如果要指定域名则要http或者https开头
/**
* @author wangqq
* @version 创建时间:2018年11月1日 下午3:06:36
* 类说明
*/
public class Hanlder extends TextWebSocketHandler {
private Logger logger = Logger.getLogger(Hanlder.class);
private static final Map<Integer,WebSocketSession> hotels; static{
hotels = new HashMap<Integer, WebSocketSession>();
} @Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
// TODO Auto-generated method stub
Integer hotelid = IHelper.toInteger(session.getAttributes().get("hotelid"));
logger.info("-----------------afterConnectionEstablished-----------------");
if(null != hotelid){
logger.info(String.format("酒店连接,id:%s", hotelid));
hotels.put(hotelid, session);
JSONObject json = new JSONObject();
json.put("code","testMessage");
session.sendMessage(new TextMessage(json.toString()));
} //super.afterConnectionEstablished(session);
}
/**
* js调用websocket.send时候,会调用该方法
*/
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
// TODO Auto-generated method stub
logger.info(String.format("收到酒店(id:%s)发来消息,消息详情:%s", session.getAttributes().get("hotelid"),message.toString()));
super.handleTextMessage(session, message);
//这里可以给用户发消息
logger.info("执行Hanlder---------客户端收到请求");
} @Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus status) throws Exception {
// TODO Auto-generated method stub
Integer hotelid = IHelper.toInteger(session.getAttributes().get("hotelid"));
logger.info(String.format("用户退出,酒店id:%s", hotelid));
hotels.remove(hotelid);
super.afterConnectionClosed(session, status);
}
/**
* 给单个用户发消息
* @param hotelid
* @param message
* @throws IOException
*/
public void sendMessage(Integer hotelid,TextMessage message) throws Exception{
if(hotels.containsKey(hotelid)){
if(hotels.get(hotelid).isOpen()){
hotels.get(hotelid).sendMessage(message);
}
} }
/**
* 给所有在线用户发消息
* @param message
* @throws IOException
*/
public void sendMessage(TextMessage message) throws Exception{
for(Integer id : hotels.keySet()){
WebSocketSession session = hotels.get(id);
if(session.isOpen()){
session.sendMessage(message);
}
}
}
/**
* 多个在线用户,不同消息
* @param data
* @throws Exception
*/
public void sendMessage(Map<Integer, TextMessage> data) throws Exception{
for(Map.Entry<Integer, TextMessage> entry : data.entrySet()){
Integer hotelid = entry.getKey();
this.sendMessage(hotelid, entry.getValue());
}
}
/**
* 多个用户,同一消息
* @param hotelids
* @param message
* @throws Exception
*/
public void sendMessage(List<Integer> hotelids,TextMessage message) throws Exception{
for(Integer id : hotelids){
this.sendMessage(id, message);
}
}
}
/**
* @author wangqq
* @version 创建时间:2018年11月2日 下午1:42:00
* 类说明
*/
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { private Logger logger = Logger.getLogger(HandshakeInterceptor.class); @Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
// TODO Auto-generated method stub
logger.info("-----------beforeHandshake---------");
if(request instanceof ServletServerHttpRequest){
ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest)request;
HttpSession session = serverHttpRequest.getServletRequest().getSession();
if(null != session){
logger.info("拦截请求,存入attribute,酒店id:"+session.getAttribute("hotelid"));
if(null!=session.getAttribute("hotelid")){
attributes.put("hotelid", session.getAttribute("hotelid"));
}
}
}
return super.beforeHandshake(request, response, wsHandler, attributes);
} @Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
// TODO Auto-generated method stub
logger.info("-----------afterHandshake--------------");
super.afterHandshake(request, response, wsHandler, ex);
}
}
前端页面(简单的不能再简单,没有考虑浏览器支不支持)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<script language="JavaScript" src="jquery/jquery-1.11.3.min.js" charset="UTF-8"></script>
<script type="text/javascript">
var ws =
$(function(){
$.ajaxSettings.async=false;
$.post('<%=basePath%>/show/doSaveSession',{'hotelid':1},function(data){
console.log("执行保存session");//模拟先登录
});
$.ajaxSettings.async=true;
ws = new WebSocket("ws://localhost:7001/show"); ws.onopen = function () {
console.log("建立链接"); }
ws.onclose = function () {
console.log("onclose");
} ws.onmessage = function (msg) {
console.log("----------------");
console.log(msg.data);
}
}); </script> </head> <body>
This is my JSP page. <br> </body>
</html>
执行结果:
前台

后台:

ps:2018-11-19 更新,后来测试一下,不用提前登陆,直接在前端连socket的路径上面加参数,而后在拦截器的
beforeHandshake中就可把连接的用户存入map
Websocket实现前后台通信,demo小测试的更多相关文章
- 通信服务器群集——跨服务器通信Demo(源码)
对于一些基于TCP Socket的大型C/S应用来说,能进行跨服务器通信可能是一个绕不开的功能性需求.出现这种需求的场景类似于下面描述的这种情况. 假设,我们一台TCP应用服务器能同时承载10000人 ...
- 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)
在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...
- Cad 二次开发关于SelectCrossingPolygon和SelectFence返回结果Status为error的小测试
CAD2008的二次开发,有个很奇怪的现象,只要你选择的点集不在当前视图上SelectCrossingPolygon和SelectFence返回结果Status就会为error,所以要获取正确的结果, ...
- 客户端程序通过TCP通信传送"小文件"到服务器
客户端程序通过TCP通信传送"小文件"到服务器 [c#源码分享]客户端程序通过TCP通信传送"小文件"到服务器 源码 (不包含通信框架源码,通信框架源码请另行 ...
- VC++ 6.0 C8051F340 USB PC侧通信 Demo
// HelloWorld.cpp : Defines the entry point for the console application. // /*********************** ...
- JAVASE02-Unit011: TCP通信(小程序)
TCP通信(小程序) server端: package chat; import java.io.BufferedReader; import java.io.IOException; import ...
- 基于NIOS II的双端口CAN通信回环测试
基于NIOS II的双端口CAN通信回环测试 小梅哥编写,未经授权,严禁用于任何商业用途 说明:本稿件为初稿,如果大家在使用的过程中有什么疑问或者补充,或者需要本文中所述工程源文件,欢迎以邮件形式发送 ...
- python 程序小测试
python 程序小测试 对之前写的程序做简单的小测试 ... # -*- encoding:utf-8 -*- ''' 对所写程序做简单的测试 @author: bpf ''' def GameOv ...
- 一个基于cocos2d-x 3.0和Box2d的demo小程序
p图demo小应用.想怎么p就怎么p 本文參考于http://blog.csdn.net/xiaominghimi/article/details/6776096和http://www.cnblogs ...
随机推荐
- Memcached 之PHP实现服务器集群一致性hash算法
/** * memcached 一致性hash,分布式算法 * Class MemcacheCluster */ class MemcacheCluster { protected $nodes = ...
- 微信小程序video
1.video是原生组件原生组件的层级是最高的,想要覆盖在video上,只能用cover-view 和 cover-image 组件,这2个可以无限嵌套.适用场景:给视频加标题: 2.检测video播 ...
- CentOS7下安装ELK三件套
ELK用于分布式收集,然后elasticsearch用于分析数据,在Kibana中可以查看数据.报表. 目前公司日志数据量暂时不使用elasticsearch集群,只是用的elasticsearch单 ...
- hdu2017 字符串统计【C++】
字符串统计 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- Android第三方开源图片裁剪截取:cropper
Android第三方开源图片裁剪截取:cropper 很多app都需要裁剪截取图片作为头像.logo之类,而cropper是github上的一个针对Android平台的.第三方开源图片裁剪截取项 ...
- RSA算法求明文
#注:gmpy2 的安装请参考 http://www.cnblogs.com/gwind/p/8000570.html# -*- coding: utf-8 -*- import gmpy2 prin ...
- python编码小记
Python编码小记 标签(空格分隔): 编程 python 1.list类型remove()操作 列表对象执行remove()函数后,会自动退出循环,所以如果想利用一个单独的for循环删除列表中多个 ...
- Linux I/O scheduler for solid-state drives
An I/O scheduler and a method for scheduling I/O requests to a solid-state drive (SSD) is disclosed. ...
- JavaScript中的call()和apply()方法,借此实现继承
1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...
- [bzoj3747][POI2015]Kinoman_线段树
Kinoman bzoj-3747 POI-2015 题目大意:有m部电影,第i部电影的好看值为w[i].现在放了n天电影,请你选择一段区间l~r使得l到r之间的好看值总和最大.特别地,如果同一种电影 ...