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 ...
随机推荐
- sql server 数据库 日期格式转换
日期时间转字符串:Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AM Select CONVERT(varchar(100), ...
- Android 自定义View (五)——实践
前言: 前面已经介绍了<Android 自定义 view(四)-- onMeasure 方法理解>,那么这次我们就来小实践下吧 任务: 公司现有两个任务需要我完成 (1)监测液化天然气液压 ...
- Java中关于先有鸡还是先有蛋的问题----Class&Object
在Java中,我们常常会看到一个类型:Class.并且在类似Person.class,cache.getClass()等代码中见到它的身影. 众所周知,Class是用来描述一个类的类型,而Object ...
- android 设计
引用:http://my.eoe.cn/blue_rain/archive/3631.html 1.一些概念 模式的定义: 每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案 ...
- Rational Rose
Rational Rose简明实用教程 http://furzoom.com/rational-rose-course/ Unidirectional Association 单向关联 general ...
- ClientScript.RegisterStartupScript 不起作用
asp.net webform 使用 ClientScript.RegisterStartupScript 不起作用 form 加上 runat="server",ok
- python opencv 实现Reinhard颜色迁移算法
Reinhard颜色迁移算法的过程很简单,流程如下,细节部分见原文,题目为color transfer between images: 将参考图片和目标图片转换到LAB空间下 得到参考图片和目标图片的 ...
- Linux下的Hello world
总算正式开始学习Linux了. 先从Hello world入手. 1. 查看当前目录 lenovo@ubuntu:~$ pwd /home/lenovo 2. 新建test目录 lenovo@ubun ...
- Java连接MySQL数据库——含步骤和代码
工具:eclipse MySQL5.6 MySQL连接驱动:mysql-connector-java-5.1.27.jar 加载驱动: 1. 在工程目录中创建lib文件夹,将下载好的JDBC放到该文件 ...
- discuz!
1. discuz! 安装包下载 http://www.discuz.net/thread-3570835-1-1.html