spring4+websocket+nginx详细配置
实现的版本jdk1.7.0_25, tomcat7.0.47.0, Tengine/2.1.1 (nginx/1.6.2), servlet3.0, spring4.2.2
使用maven导入版本3.0+的servlet包:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
然后配置web.xml将版本的xsi配置在3.0以上:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
导入spring web socket包:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>
在spirng的DispatcherServlet的配置文件配置spring websocket handler,配置了建立连接的路径并通过allowed-origins参数来允许跨域访问:
<websocket:handlers allowed-origins="*">
<websocket:mapping path="/outer/notice/listen" handler="noticeMessageHandler"/>
<websocket:handshake-interceptors>
<bean class="com.j.socket.notice.NoticeMessageInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers> <websocket:handlers allowed-origins="*">
<websocket:mapping path="/outer/notice/sockjs/listen" handler="noticeMessageHandler"/>
<websocket:handshake-interceptors>
<bean class="com.j.socket.notice.NoticeMessageInterceptor"/>
</websocket:handshake-interceptors>
<websocket:sockjs/>
</websocket:handlers>
配置handler class:
package com.j.socket.notice.NoticeMessageHandler; // import packages
@Component
public class NoticeMessageHandler implements WebSocketHandler { //存储当前所有的在线用户socket
//目前以userId为key,所以一个用户打开多个socket页面时只会在最新的页面推送消息
private static final Map<String, WebSocketSession> users = new HashMap<>(); //socket 连接常见时该方法被调用
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
//在socket Interceptor中设置的参数
String userId = webSocketSession.getAttributes().get("SOCKET_USER");
users.put(userId, webSocketSession);
} @Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
//前端发送消息时调用该方法
} //连接出错时
@Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
if (webSocketSession.isOpen()) {
webSocketSession.close();
}
String userId = webSocketSession.getAttributes().get("SOCKET_USER");
users.remove(userId);
} //连接关闭时
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
String userId = webSocketSession.getAttributes().get("SOCKET_USER");
users.remove(userId);
} @Override
public boolean supportsPartialMessages() {
return false;
} //向某个用户发送消息
public void sendMessage(TextMessage message, String userId) {
WebSocketSession user = users.get(userId);
if (null != user && user.isOpen()) {
try {
user.sendMessage(message);
} catch (Exception e) {
}
}
} //批量向所有用户发送消息
public void sendMessage(TextMessage message) {
for (WebSocketSession user : users.values()) {
if (user.isOpen()) {
try {
user.sendMessage(message);
} catch (Exception e) {
}
}
}
}
}
配置拦截器,在websocket链接时从请求中获取用户数据,并存储起来。
public class NoticeMessageInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
if (serverHttpRequest instanceof ServletServerHttpRequest) {
ServletServerHttpRequest request = (ServletServerHttpRequest) serverHttpRequest;
String userId = request.getServletRequest().getParameter("userId");
if (StringUtils.isNotBlank(userId)) {
map.put(Constants.SOCKET_USER, userId);
return true;
}
}
return false;
}
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
}
}
前端js代码,如果浏览器不支持socket时将使用sockJS 所以需要根据情况导入sockJS文件
var websocket;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://yoururl.com/outer/notice/listen?userId="+ getUserId());
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://yoururl.com/outer/notice/listen?userId="+getUserId());
} else {
websocket = new SockJS("http://yoururl.com/outer/notice/sockjs/listen?userId="+getUserId());
}
websocket.onopen = function (evnt) {
};
var length = 0 ;
websocket.onmessage = function (evnt) {
console.log(length+=evnt.data.length);
};
websocket.onerror = function (evnt) {
console.log(evnt);
};
websocket.onclose = function (evnt) {
}
nginx相应配置
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location ~* /(outer/notice)|(outer/sockjs/notice)/ {
proxy_pass http://127.0.0.1:8084;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
spring4+websocket+nginx详细配置的更多相关文章
- nginx 详细配置
Nginx全局变量 Nginx中有很多的全局变量,可以通过$变量名来使用.下面列举一些常用的全局变量: 变量 说明 boxClass 需要执行动画的元素的 变量 说明 $args 请求中的参数,如ww ...
- Nginx详细配置
#运行用户#user nobody; #启动进程,通常设置成和cpu的数量相等或者2倍于cpu的个数(具体结合cpu和内存).默认为1worker_processes 1; #全局的错误日志和日志 ...
- 170817、Nginx详细配置
Nginx能做什么 nginx主要是做转发,当然也可以做静态资源文件缓存,做转发的时候,比如你有几个url,可以统一通过走nginx,然后通过nginx转发到不同的url上 1.反向代理 反向代理应该 ...
- CentOS+Nginx+PHP+MySQL详细配置(图解)
原文地址: http://www.jb51.net/article/26597.htm CentOS+Nginx+PHP+MySQL详细配置(带有图解),需要的朋友可以参考下. 一.安装MySQL ...
- Nginx keepalived实现高可用负载均衡详细配置步骤
Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层.第4层和第7层交换机的功能.主要提供loadbalancing(负载均衡) ...
- Nginx location配置详细解释
nginx location配置详细解释 语法规则: location [=|~|~*|^~] /uri/ { - } = 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 ur ...
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
- wordpress nginx详细环境配置安装命令和相关问题解决
很详细的有关WordPress和nginx的环境配置安装操作步骤 指南,适合新手一步步按照命令操作安装WordPress并运行在生产环境中. 操作步骤转载自: Heap Stack blog(ping ...
- [转帖]nginx location配置详细解释
nginx location配置详细解释 http://outofmemory.cn/code-snippet/742/nginx-location-configuration-xiangxi-exp ...
随机推荐
- svg学习(九)path
<path> 标签用来定义路径. 下面的命令可用于路径数据: M = moveto L = lineto H = horizontal lineto V = vertical lineto ...
- RabbitMq中的交换机
Rabbitmq的核心概念(如下图所示):有虚拟主机.交换机.队列.绑定: 交换机可以理解成具有路由表的路由程序,仅此而已.每个消息都有一个称为路由键 ...
- a biped was detected but cannot be configured properly (Bipe导入Unity 无法正确识别)
OP stated "I export the biped with 'animation' and 'bake animation' ticked and the correct fram ...
- poj 2376 Cleaning Shifts
http://poj.org/problem?id=2376 Cleaning Shifts Time Limit: 1000MS Memory Limit: 65536K Total Submi ...
- Android 自定义 view(三)—— onDraw 方法理解
前言: 上一篇已经介绍了用自己定义的属性怎么简单定义一个view<Android 自定义view(二) -- attr 使用>,那么接下来我们继续深究自定义view,下一步将要去简单理解自 ...
- android nfc中Ndef格式的读写
1. 在onCreate()中获取NfcAdapter对象: NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 2.在onNewI ...
- Windows Phone 十三、吐司通知
弹出通知对话框 <Grid> <Button Content="弹出通知" Click="Button_Click"/> </Gr ...
- jqGrid设置指定行的背景色
1.在页面中加样式 <style type="text/css"> .SelectBG{ background-color:#AAAAAA; } </style& ...
- CI(持续集成)CD(持续交付)
持续集成实践: 1.保持单一代码仓库 2.自动化构建项目 3.使项目拥有自测试的能力 4.成员每天上传代码 5.每次上传需要在集成机上构建主线项目 6.立即修复出错的构想流程 7.保证构建效率 8.将 ...
- C语言回顾-结构体、枚举和文件
1.构造类型 根据已经定义的一个或多个数据类型用构造的方法来定义. 分为:数组.结构体和共用体 2.结构体 struct 结构体名{ 成员列表: }; 1)结构体定义完成以后,计算机不会给结构体分配存 ...