您的位置:首页 > 编程语言 > Java开发

Spring与WebSocket的整合

2016-01-19 22:48 483 查看

1  环境

jdk1.8
tomcat 7
spring4.0.5

2  pom.xml的配置

2.1 引入Spring相关的配置

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>

2.2 websocket相关的配置

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>


3 编写WebSocketConfig、HandshakeInterceptor与WebSocketHander

3.1 WebSocketConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

/**
* 支持websocket 的 connection
*/
registry.addHandler(new WebSocketHander(),"/websocket").addInterceptors(new HandshakeInterceptor());

/**
* 不支持websocket的connenction,采用sockjs
*/
registry.addHandler(new WebSocketHander(),"/sockjs/websocket").addInterceptors(new HandshakeInterceptor()).withSockJS();
}
}

3.2 HandshakeInterceptor

import java.util.Map;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
public class HandshakeInterceptor implements org.springframework.web.socket.server.HandshakeInterceptor {

/**
* Interceptor before hander
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
return true;
}

@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {

}
}

3.3 WebSocketHander

import java.io.IOException;
import java.util.ArrayList;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

public class WebSocketHander implements WebSocketHandler {

private static final Logger logger = org.slf4j.LoggerFactory.getLogger(WebSocketHander.class);

private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();

/**
* after connection establish
*/
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
logger.info("connect success...");
users.add(session);
}

/**
* process the received message
*/
@Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
sendMessageToUsers(new TextMessage(webSocketMessage.getPayload() + "hello"));
}

@Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
if(webSocketSession.isOpen()){
webSocketSession.close();
}
logger.info("connenction error,close the connection...");
users.remove(webSocketSession);
}

@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
logger.info("close the connenction..."+closeStatus.toString());
users.remove(webSocketSession);
}

@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
for (WebSocketSession user : users) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}}


4 页面
<span style="font-weight: normal;"><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head lang="en">
<meta charset="UTF-8">
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<!--<script type="text/javascript" src="js/jquery-1.7.2.js"></script>-->
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<title>webSocket测试</title>
<script type="text/javascript">
$(function(){
var websocket;
if ('WebSocket' in window) {
alert("WebSocket");
websocket = new WebSocket("ws://localhost:8080/项目名称/websocket");
} else if ('MozWebSocket' in window) {
alert("MozWebSocket");
websocket = new MozWebSocket("ws://echo");
} else {
alert("SockJS");
websocket = new SockJS("http://localhost:8080/<span style="font-family: Arial, Helvetica, sans-serif;">项目名称</span><span style="font-family: Arial, Helvetica, sans-serif;">/sockjs/websocket");</span>
}
websocket.onopen = function (evnt) {
$("#tou").html("链接服务器成功!")
};
websocket.onmessage = function (evnt) {
$("#msg").html($("#msg").html() + "<br/>" + evnt.data);
};
websocket.onerror = function (evnt) {
};
websocket.onclose = function (evnt) {
$("#tou").html("与服务器断开了链接!")
}
$('#send').bind('click', function() {
send();
});
function send(){
if (websocket != null) {
var message = document.getElementById('message').value;
websocket.send(message);
} else {
alert('未与服务器链接.');
}
}
});
</script>

</head>
<body>

<div class="page-header" id="tou">
webSocket及时聊天Demo程序
</div>
<div class="well" id="msg">
</div>
<div class="col-lg">
<div class="input-group">
<input type="text" class="form-control" placeholder="发送信息..." id="message">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="send" >发送</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
</body>

</html></span>
现象:输入字符,服务器对输入的字符加上“hello”返回!

5. 错误

5.1Async support must be enabled on a servlet and for all filters involved in async request processing

如果直接运行,基本上会包上面的错误,我们还需要在web.xml中做如下的配置
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">[/code]然后在这个servlet中加入: 
<async-supported>true</async-supported>
如下:
<servlet>
<servlet-name>presto-engine</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:presto_servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
同时在各个filter也要加入async-supported

5.2 The extension [x-webkit-deflate-frame] is not supported
在HandshakeInterceptor的beforeHandshake方法中加入
<span style="font-size:10px;font-weight: normal;">@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
/**
* This is a bug,bug fix:The extension [x-webkit-deflate-frame] is not supported
*/
if(request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
}
return true;
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: