详解WebSocket+spring示例demo(已使用sockJs库)
1、简介
作为下一代的Web标准,HTML5拥有许多引人注目的新特性,如Canvas、本地存储、多媒体编程接口、WebSocket等等。这其中有“Web的TCP”之称的WebSocket格外吸引开发人员的注意。WebSocket的出现使得浏览器提供对Socket的支持成为可能,从而在浏览器和服务器之间提供了一个基于TCP连接的双向通道。Web开发人员可以非常方便地使用WebSocket构建实时web应用,开发人员的手中从此又多了一柄神兵利器。
Web应用的信息交互过程通常是客户端通过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特别频繁的应用尚能相安无事,但是对于那些实时要求比较高的应用来说,比如说在线游戏、在线证券、设备监控、新闻在线播报、RSS订阅推送等等,当客户端浏览器准备呈现这些信息的时候,这些信息在服务器端可能已经过时了。
所以保持客户端和服务器端的信息同步是实时Web应用的关键要素,对Web开发人员来说也是一个难题。在WebSocket规范出来之前,开发人员想实现这些实时的Web应用,不得不采用一些折衷的方案,其中最常用的就是轮询(Polling)和Comet技术,而Comet技术实际上是轮询技术的改进,又可细分为两种实现方式,一种是长轮询机制,一种称为流技术。
Html5WebSocket设计出来的目的就是要取代轮询和Comet技术,使客户端浏览器具备像C/S架构下桌面系统的实时通讯能力。浏览器通过JavaScript向服务器发出建立WebSocket连接的请求,连接建立以后,客户端和服务器端就可以通过TCP连接直接交换数据。因为WebSocket连接本质上就是一个TCP连接,所以在数据传输的稳定性和数据传输量的大小方面,和轮询以及Comet技术比较,具有很大的性能优势。
但是鉴于websocket对浏览器要求比较高,为了解决这个问题,推出了sockJS,SockJS是一个JavaScript库,提供跨浏览器javascript的API,创建了一个低延迟、全双工的浏览器和web服务器之间通信通道。
2、相关环境要求
Spring4.0.6(要选择4.0+),tomcat7.0.55版本,JDK1.7。
3、具体代码
(以下代码亲测可用!)
(1)web.xml:
<?xmlversionxmlversion="1.0"encoding="UTF-8"?> <web-appversion="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <description>用来测试WebSocket基础上推送的功能</description> <distributable/> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <async-supported>true</async-supported> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--Spring刷新Introspector防止内存泄露--> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file>testSocket.jsp</welcome-file> </welcome-file-list> </web-app>
(2)dispatcher-servlet.xml
<?xmlversionxmlversion="1.0"encoding="UTF-8"?> <beans:beansxmlnsbeans:beansxmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"> <annotation-driven/> <!--自动扫描的包名--> <context:component-scanbase-packagecontext:component-scanbase-package="zyy.sockjs.config"></context:component-scan> </beans:beans>
(3)HandshakeInterceptor.java
packagezyy.sockjs.config;
importjava.util.Map;
importorg.springframework.http.server.ServerHttpRequest;
importorg.springframework.http.server.ServerHttpResponse;
importorg.springframework.stereotype.Component;
importorg.springframework.web.socket.WebSocketHandler;
importorg.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
@Component
publicclassHandshakeInterceptorextendsHttpSessionHandshakeInterceptor{
@Override
publicbooleanbeforeHandshake(ServerHttpRequestrequest,
ServerHttpResponseresponse,WebSocketHandlerwsHandler,
Map<String,Object>attributes)throwsException{
System.out.println("BeforeHandshake");
returnsuper.beforeHandshake(request,response,wsHandler,attributes);
}
@Override
publicvoidafterHandshake(ServerHttpRequestrequest,
ServerHttpResponseresponse,WebSocketHandlerwsHandler,
Exceptionex){
System.out.println("AfterHandshake");
super.afterHandshake(request,response,wsHandler,ex);
}
}
(4)InfoSocketEndPoint.Java
packagezyy.sockjs.config;
importorg.springframework.stereotype.Component;
importorg.springframework.web.socket.TextMessage;
importorg.springframework.web.socket.WebSocketSession;
importorg.springframework.web.socket.handler.TextWebSocketHandler;
@Component
publicclassInfoSocketEndPointextendsTextWebSocketHandler{
publicInfoSocketEndPoint(){
}
@Override
protectedvoidhandleTextMessage(WebSocketSessionsession,
TextMessagemessage)throwsException{
super.handleTextMessage(session,message);
TextMessagereturnMessage=newTextMessage(message.getPayload()
+"receivedatserver");
session.sendMessage(returnMessage);
}
}
(5)SystemWebSocketHandler.java
packagezyy.sockjs.config;
importorg.springframework.stereotype.Component;
importorg.springframework.web.socket.CloseStatus;
importorg.springframework.web.socket.TextMessage;
importorg.springframework.web.socket.WebSocketHandler;
importorg.springframework.web.socket.WebSocketMessage;
importorg.springframework.web.socket.WebSocketSession;
/**
*
*@authordayu
*/
@Component
publicclassSystemWebSocketHandlerimplementsWebSocketHandler{
@Override
publicvoidafterConnectionEstablished(WebSocketSessionsession)throwsException{
System.out.println("connecttothewebsocketsuccess......");
session.sendMessage(newTextMessage("Server:connectedOK!"));
}
@Override
publicvoidhandleMessage(WebSocketSessionwss,WebSocketMessage<?>wsm)throwsException{
TextMessagereturnMessage=newTextMessage(wsm.getPayload()
+"receivedatserver");
wss.sendMessage(returnMessage);
}
@Override
publicvoidhandleTransportError(WebSocketSessionwss,Throwablethrwbl)throwsException{
if(wss.isOpen()){
wss.close();
}
System.out.println("websocketconnectionclosed......");
}
@Override
publicvoidafterConnectionClosed(WebSocketSessionwss,CloseStatuscs)throwsException{
System.out.println("websocketconnectionclosed......");
}
@Override
publicbooleansupportsPartialMessages(){
returnfalse;
}
}
(6)WebSocketConfig.java
packagezyy.sockjs.config;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.web.servlet.config.annotation.EnableWebMvc;
importorg.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
importorg.springframework.web.socket.WebSocketHandler;
importorg.springframework.web.socket.config.annotation.EnableWebSocket;
importorg.springframework.web.socket.config.annotation.WebSocketConfigurer;
importorg.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebMvc
@EnableWebSocket
publicclassWebSocketConfigextendsWebMvcConfigurerAdapterimplements
WebSocketConfigurer{
publicWebSocketConfig(){
}
@Override
publicvoidregisterWebSocketHandlers(WebSocketHandlerRegistryregistry){
registry.addHandler(systemWebSocketHandler(),"/websck").addInterceptors(newHandshakeInterceptor());
System.out.println("registed!");
registry.addHandler(systemWebSocketHandler(),"/sockjs/websck/info").addInterceptors(newHandshakeInterceptor())
.withSockJS();
}
@Bean
publicWebSocketHandlersystemWebSocketHandler(){
returnnewSystemWebSocketHandler();
}
}
(7)testSocket.jsp
<%@pagelanguage="java"contentType="text/html;charset=ISO-8859-1"pageEncoding="ISO-8859-1"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html;charset=ISO-8859-1">
<title>WebSocket/SockJSEchoSample(AdaptedfromTomcat'sechosample)</title>
<styletype="text/css">
#connect-container{
float:left;
width:400px
}
#connect-containerdiv{
padding:5px;
}
#console-container{
float:left;
margin-left:15px;
width:400px;
}
#console{
border:1pxsolid#CCCCCC;
border-right-color:#33333333;
border-bottom-color:#999999;
height:170px;
overflow-y:scroll;
padding:5px;
width:100%;
}
#consolep{
padding:0;
margin:0;
}
</style>
<scriptsrc="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<scripttype="text/javascript">
varws=null;
varurl=null;
vartransports=[];
functionsetConnected(connected){
document.getElementById('connect').disabled=connected;
document.getElementById('disconnect').disabled=!connected;
document.getElementById('echo').disabled=!connected;
}
functionconnect(){
if(!url){
log('SelectwhethertouseW3CWebSocketorSockJS');
return;
}
//ws=(url.indexOf('sockjs')!=-1)?newSockJS(url,undefined,{protocols_whitelist:transports}):newWebSocket(url);
if('WebSocket'inwindow){
ws=newWebSocket("ws://localhost:8080/SpringSocketJs/websck");
}else{
ws=newSockJS("http://localhost:8080/SpringSocketJs/sockjs/websck/info");
}
//websocket=newSockJS("http://localhost:8084/SpringWebSocketPush/sockjs/websck");
ws.onopen=function(){
setConnected(true);
//log('Info:connectionopened.');
};
ws.onmessage=function(event){
log('Received:'+event.data);
};
ws.onclose=function(event){
setConnected(false);
log('Info:connectionclosed.');
log(event);
};
}
functiondisconnect(){
if(ws!=null){
ws.close();
ws=null;
}
setConnected(false);
}
functionecho(){
if(ws!=null){
varmessage=document.getElementById('message').value;
log('Sent:'+message);
ws.send(message);
}else{
alert('connectionnotestablished,pleaseconnect.');
}
}
functionupdateUrl(urlPath){
if(urlPath.indexOf('sockjs')!=-1){
url=urlPath;
document.getElementById('sockJsTransportSelect').style.visibility='visible';
}
else{
if(window.location.protocol=='http:'){
url='ws://'+window.location.host+urlPath;
}else{
url='wss://'+window.location.host+urlPath;
}
document.getElementById('sockJsTransportSelect').style.visibility='hidden';
}
}
functionupdateTransport(transport){
transports=(transport=='all')?[]:[transport];
}
functionlog(message){
varconsole=document.getElementById('console');
varp=document.createElement('p');
p.style.wordWrap='break-word';
p.appendChild(document.createTextNode(message));
console.appendChild(p);
while(console.childNodes.length>25){
console.removeChild(console.firstChild);
}
console.scrollTop=console.scrollHeight;
}
</script>
</head>
<body>
<noscript><h2style="color:#ff0000">Seemsyourbrowserdoesn'tsupportJavascript!Websockets
relyonJavascriptbeingenabled.Pleaseenable
Javascriptandreloadthispage!</h2></noscript>
<div>
<divid="connect-container">
<inputid="radio1"type="radio"name="group1"onclick="updateUrl('/SpringSocketJs/websocket');">
<labelfor="radio1">W3CWebSocket</label>
<br>
<inputid="radio2"type="radio"name="group1"onclick="updateUrl('/SpringSocketJs/sockjs/websocket');">
<labelfor="radio2">SockJS</label>
<divid="sockJsTransportSelect"style="visibility:hidden;">
SockJStransport:
<selectonchange="updateTransport(this.value)">
<optionvalue="all">all</option>
<optionvalue="websocket">websocket</option>
<optionvalue="xhr-polling">xhr-polling</option>
<optionvalue="jsonp-polling">jsonp-polling</option>
<optionvalue="xhr-streaming">xhr-streaming</option>
<optionvalue="iframe-eventsource">iframe-eventsource</option>
<optionvalue="iframe-htmlfile">iframe-htmlfile</option>
</select>
</div>
<div>
<buttonid="connect"onclick="connect();">Connect</button>
<buttonid="disconnect"disabled="disabled"onclick="disconnect();">Disconnect</button>
</div>
<div>
<textareaid="message"style="width:350px">Hereisamessage!</textarea>
</div>
<div>
<buttonid="echo"onclick="echo();"disabled="disabled">Echomessage</button>
</div>
</div>
<divid="console-container">
<divid="console"></div>
</div>
</div>
</body>
</html>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。