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 ...
随机推荐
- smarty 模板几个例子
一.assign和display方法的使用以及几个变量调节器 header("content-type:text/html;charset=utf-8");//加载Smarty引擎 ...
- spring Date JPA的主要编程接口
Repository:最顶层的接口,是一个空接口,主要目的是为了同一所有Repository的类型,并且让组件扫描的时候自动识别. CrudRepository:是Repository的子接口,提供增 ...
- C#压缩库SharpZipLib的应用
SharpZipLib是一个开源的C#压缩解压库,应用非常广泛.就像用ADO.NET操作数据库要打开连接.执行命令.关闭连接等多个步骤一样,用SharpZipLib进行压缩和解压也需要多个步骤. ...
- CI(持续集成)CD(持续交付)
持续集成实践: 1.保持单一代码仓库 2.自动化构建项目 3.使项目拥有自测试的能力 4.成员每天上传代码 5.每次上传需要在集成机上构建主线项目 6.立即修复出错的构想流程 7.保证构建效率 8.将 ...
- C语言初学者代码中的常见错误与瑕疵(23)
见:C语言初学者代码中的常见错误与瑕疵(23)
- QT 网络编程
#include "networkinformation.h" #include "ui_networkinformation.h" networkinform ...
- Linux_常用命令1
来自:http://www.weixuehao.com/archives/25 Linux简介及Ubuntu安装 Linux,免费开源,多用户多任务系统.基于Linux有多个版本的衍生.RedHat. ...
- AC6102 DDR2测试工程
AC6102 DDR2测试工程 本文档介绍AC6102上DDR2存储器基于Verilog代码的测试过程.AC6102上使用了2片16bit的DDR2存储器组成了32bit的硬件总线.虽然是32bit硬 ...
- libtool: line 990: g++: command not found的解决
yum -y install gcc+ gcc-c++
- Android的学习第六章(布局一TableLayout)
今天我们来简单的说一下Android不居中的TableLayout布局(表格布局) 表格布局的意思就是将我们的布局看做为一个表格,主要用于对控件进行整齐排列 我们看一个简单的案例 <TableL ...