实现的版本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详细配置的更多相关文章

  1. nginx 详细配置

    Nginx全局变量 Nginx中有很多的全局变量,可以通过$变量名来使用.下面列举一些常用的全局变量: 变量 说明 boxClass 需要执行动画的元素的 变量 说明 $args 请求中的参数,如ww ...

  2. Nginx详细配置

    #运行用户#user  nobody; #启动进程,通常设置成和cpu的数量相等或者2倍于cpu的个数(具体结合cpu和内存).默认为1worker_processes  1; #全局的错误日志和日志 ...

  3. 170817、Nginx详细配置

    Nginx能做什么 nginx主要是做转发,当然也可以做静态资源文件缓存,做转发的时候,比如你有几个url,可以统一通过走nginx,然后通过nginx转发到不同的url上 1.反向代理 反向代理应该 ...

  4. CentOS+Nginx+PHP+MySQL详细配置(图解)

    原文地址: http://www.jb51.net/article/26597.htm CentOS+Nginx+PHP+MySQL详细配置(带有图解),需要的朋友可以参考下.   一.安装MySQL ...

  5. Nginx keepalived实现高可用负载均衡详细配置步骤

    Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层.第4层和第7层交换机的功能.主要提供loadbalancing(负载均衡) ...

  6. Nginx location配置详细解释

    nginx location配置详细解释 语法规则: location [=|~|~*|^~] /uri/ { - } = 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 ur ...

  7. Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G

    code&monkey   Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...

  8. wordpress nginx详细环境配置安装命令和相关问题解决

    很详细的有关WordPress和nginx的环境配置安装操作步骤 指南,适合新手一步步按照命令操作安装WordPress并运行在生产环境中. 操作步骤转载自: Heap Stack blog(ping ...

  9. [转帖]nginx location配置详细解释

    nginx location配置详细解释 http://outofmemory.cn/code-snippet/742/nginx-location-configuration-xiangxi-exp ...

随机推荐

  1. smarty 模板几个例子

    一.assign和display方法的使用以及几个变量调节器 header("content-type:text/html;charset=utf-8");//加载Smarty引擎 ...

  2. spring Date JPA的主要编程接口

    Repository:最顶层的接口,是一个空接口,主要目的是为了同一所有Repository的类型,并且让组件扫描的时候自动识别. CrudRepository:是Repository的子接口,提供增 ...

  3. C#压缩库SharpZipLib的应用

       SharpZipLib是一个开源的C#压缩解压库,应用非常广泛.就像用ADO.NET操作数据库要打开连接.执行命令.关闭连接等多个步骤一样,用SharpZipLib进行压缩和解压也需要多个步骤. ...

  4. CI(持续集成)CD(持续交付)

    持续集成实践: 1.保持单一代码仓库 2.自动化构建项目 3.使项目拥有自测试的能力 4.成员每天上传代码 5.每次上传需要在集成机上构建主线项目 6.立即修复出错的构想流程 7.保证构建效率 8.将 ...

  5. C语言初学者代码中的常见错误与瑕疵(23)

    见:C语言初学者代码中的常见错误与瑕疵(23)

  6. QT 网络编程

    #include "networkinformation.h" #include "ui_networkinformation.h" networkinform ...

  7. Linux_常用命令1

    来自:http://www.weixuehao.com/archives/25 Linux简介及Ubuntu安装 Linux,免费开源,多用户多任务系统.基于Linux有多个版本的衍生.RedHat. ...

  8. AC6102 DDR2测试工程

    AC6102 DDR2测试工程 本文档介绍AC6102上DDR2存储器基于Verilog代码的测试过程.AC6102上使用了2片16bit的DDR2存储器组成了32bit的硬件总线.虽然是32bit硬 ...

  9. libtool: line 990: g++: command not found的解决

    yum -y install gcc+ gcc-c++

  10. Android的学习第六章(布局一TableLayout)

    今天我们来简单的说一下Android不居中的TableLayout布局(表格布局) 表格布局的意思就是将我们的布局看做为一个表格,主要用于对控件进行整齐排列 我们看一个简单的案例 <TableL ...