注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

love3400wind的blog

like

 
 
 

日志

 
 
 
 

springmvc + angularjs + websocket (nginx)整合  

2016-11-10 16:10:38|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
介绍:
项目用的是SSM(springMVC+spring+MyBatis)框,前端angularjs 使用nginx代理tomcat
步骤:
step1: maven 的pom.xml中添加spring websocket依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
本来项目中的spring用的是4.1.0.RELEASE,奈何websocket相关依赖仓库中没有,下载不下来,改用了4.1.1.RELEASE. 其它的还有fastjson的jackson-core与jackson-databind依赖.
step2: spring配置文件中添加websocket的namespace.xsd

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
</beans>
step3:创建websocket的HandShake


import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;


public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {

@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("Before Handshake");
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpServletRequest httpServletRequest = servletRequest.getServletRequest();
HttpSession session = httpServletRequest.getSession(true);
if (session != null) {

session.setAttribute("WS_USER_ID_PROPERTY", "用户信息");
}
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}

@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("After Handshake");
super.afterHandshake(request, response, wsHandler, ex);
}
}
用户信息可以从shiro中获取,或者其它方式都可以
step4:创建websocket的Handler

import com.common.AppUser;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


public class TestWebsocketHandler extends TextWebSocketHandler {

/**
* 用户与session关系
* 分布式部署可以使用memcached
*/
private static final ConcurrentHashMap<String, WebSocketSession> userSessoinMap = new ConcurrentHashMap();

/**
* socket 接入
* @param session
* @throws Exception
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.printf("afterConnectionEstablished --> " );
//put(userId, session)
AppUser currentUser = (AppUser) session.getAttributes().get("WS_USER_ID_PROPERTY");
if(currentUser != null){
if(userSessoinMap.get(currentUser.getId()) != null){//在另一个窗口连接了
userSessoinMap.get(currentUser.getId()).close(CloseStatus.NORMAL);
}
userSessoinMap.put(currentUser.getId(), session);
}

super.afterConnectionEstablished(session);
}

/**
* 直接处理请求
* @param session
* @param message
* @throws Exception
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
TextMessage returnMessage = new TextMessage(message.getPayload()+" MatterApplyWebsocketHandler received at server");
session.sendMessage(returnMessage);
}

/**
     * socket 断开
* @param session
     * @throws Exception
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.printf("afterConnectionClosed --> ");
AppUser currentUser = (AppUser) session.getAttributes().get("WS_USER_ID_PROPERTY");
if(currentUser != null){
userSessoinMap.remove(currentUser.getId());
}
super.afterConnectionClosed(session, status);
}

/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(String message) {
for(Map.Entry<String, WebSocketSession> entry : userSessoinMap.entrySet()){
try {
entry.getValue().sendMessage(new TextMessage(message));
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 给某个用户发送消息
*
* @param userId
* @param message
*/
public void sendMessageToUser(String userId, String message) {
WebSocketSession session= userSessoinMap.get(userId);
if(session != null){
try {
session.sendMessage(new TextMessage(message));
} catch (IOException e) {
e.printStackTrace();
}
}
}


}
AppUser 就是HandShake中的用户对象类,可以有id,name...
step5: spring配置文件中配置Handler与HandShake
<bean id="testWebsocketHandler" class="com.common.ws.TestWebsocketHandler"/>
<websocket:handlers>
<websocket:mapping path="/webSocket/testWebSocket" handler="testWebsocketHandler"/>
<websocket:handshake-interceptors>
<bean class="com.common.ws.HandshakeInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>

step6: 前端angularjs中使用websocket
首先在angular的controller 中添加connect, disconnect, testSocket方法
 

/*----Spring WebSocket开始----*/
var ws = null;
var url = "ws://test.com:8000/socket-web/webSocket/testWebSocket";

var transports = [];
$scope.connect = function(entity) {

this.setConnected = function(connected) {

console.log(connected);
};

// 连接服务
ws = new WebSocket(url); // 可以使用socketJS
ws.onopen = function() {
$scope.setConnected(true);
console.log("连接成功");
};
ws.onmessage = function(event) {
console.log("接收到服务端消息,刷新列表");
};
ws.onclose = function(event) {
$scope.setConnected(false);
console.log("断开成功");
console.log("断开" + event);
var code = event.code;
if (code != undefined && code == 1006) {
$scope.connect();
}
};
ws.onerror = function(event) {
console.log("Web Socket error." + event);
};

// 设置按钮失效
}

$scope.disconnect = function(entity) {
// 断开服务
// 设置按钮失效,设置连接按钮有效
if (ws != null) {
ws.close();
ws = null;
}
// setConnected(false);
}
/*----Spring WebSocket结束----*/


$scope.testSocket = function () {
entityService.testSocket({"id":"299", "message":"我是一个中国人"});
}

在entityService中添加testSocket方法,即发送post
  

testSocket: function(params) {
return $http({
url: '/socket-web/sendMessageToUser',
method: 'post',
data: params
});
}

在html页面中添加按钮:

<div class="form-group mb10 mr10">
<a class="btn btn-default" ng-click="connect()"><i class="glyphicon glyphicon-th-list"></i> 连接</a>
</div>
<div class="form-group mb10 mr10">
<a class="btn btn-default" ng-click="disconnect()"><i class="glyphicon glyphicon-th-list"></i> 断开</a>
</div>
<div class="form-group mb10 mr10">
<a class="btn btn-default" ng-click="testSocket()"><i class="glyphicon glyphicon-th-list"></i> 发送数据</a>
</div>

在spring controller 中注入Handler(因为测试方法sendMessageToUser写在Handler中),并添加测试方法


@Autowired
private TestWebsocketHandler testWebsocketHandler;


@RequestMapping(value = "sendMessageToUser", method = RequestMethod.POST)
@ResponseBody
public ModelResult sendMessageToUser(HttpServletRequest request) {

String userId = request.getParameter("id");
String message = request.getParameter("message");

ModelResult modelResult = new ModelResult(ModelResult.CODE_200);
testWebsocketHandler.sendMessageToUser(userId, message);
modelResult.setMessage("操作成功");
return modelResult;
}
step7: nginx配置

location /socket-web {

proxy_pass http://127.0.0.1:9999;

# 下面是关键

    proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

}


好了,开始你的websocket之旅吧...




  评论这张
 
阅读(25)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017