欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解WebSocket+spring示例demo(已使用sockJs库)

程序员文章站 2024-03-07 20:23:03
1、简介 作为下一代的web标准,html5拥有许多引人注目的新特性,如 canvas、本地存储、多媒体编程接口、websocket等等。这其中有“web的 tcp...

1、简介

作为下一代的web标准,html5拥有许多引人注目的新特性,如 canvas、本地存储、多媒体编程接口、websocket等等。这其中有“web的 tcp”之称的 websocket格外吸引开发人员的注意。websocket的出现使得浏览器提供对 socket的支持成为可能,从而在浏览器和服务器之间提供了一个基于tcp连接的双向通道。web开发人员可以非常方便地使用websocket构建实时 web 应用,开发人员的手中从此又多了一柄神兵利器。

web 应用的信息交互过程通常是客户端通过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特别频繁的应用尚能相安无事,但是对于那些实时要求比较高的应用来说,比如说在线游戏、在线证券、设备监控、新闻在线播报、rss订阅推送等等,当客户端浏览器准备呈现这些信息的时候,这些信息在服务器端可能已经过时了。

所以保持客户端和服务器端的信息同步是实时 web应用的关键要素,对 web开发人员来说也是一个难题。在 websocket规范出来之前,开发人员想实现这些实时的web应用,不得不采用一些折衷的方案,其中最常用的就是轮询(polling)和 comet 技术,而comet技术实际上是轮询技术的改进,又可细分为两种实现方式,一种是长轮询机制,一种称为流技术。

html5 websocket 设计出来的目的就是要取代轮询和 comet技术,使客户端浏览器具备像 c/s架构下桌面系统的实时通讯能力。浏览器通过javascript向服务器发出建立 websocket连接的请求,连接建立以后,客户端和服务器端就可以通过 tcp连接直接交换数据。因为 websocket连接本质上就是一个tcp连接,所以在数据传输的稳定性和数据传输量的大小方面,和轮询以及comet技术比较,具有很大的性能优势。

但是鉴于web socket 对浏览器要求比较高,为了解决这个问题,推出了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-app version="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/javaee http://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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
 http://www.springframework.org/schema/context http://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

package zyy.sockjs.config; 
import java.util.map; 
import org.springframework.http.server.serverhttprequest; 
import org.springframework.http.server.serverhttpresponse; 
import org.springframework.stereotype.component; 
import org.springframework.web.socket.websockethandler; 
import org.springframework.web.socket.server.support.httpsessionhandshakeinterceptor; 
 
@component 
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"); 
 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); 
} 
} 

(4)infosocketendpoint.java

package zyy.sockjs.config; 
import org.springframework.stereotype.component; 
import org.springframework.web.socket.textmessage; 
import org.springframework.web.socket.websocketsession; 
import org.springframework.web.socket.handler.textwebsockethandler; 
 
@component 
public class infosocketendpoint extends textwebsockethandler { 
public infosocketendpoint() { 
} 
 
@override 
protected void handletextmessage(websocketsession session, 
 textmessage message) throws exception { 
 super.handletextmessage(session, message); 
 textmessage returnmessage = new textmessage(message.getpayload() 
 + " received at server"); 
 session.sendmessage(returnmessage); 
} 
} 

(5)systemwebsockethandler.java

package zyy.sockjs.config; 
import org.springframework.stereotype.component; 
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; 
/** 
* 
* @author dayu 
*/ 
 
@component 
public class systemwebsockethandler implements websockethandler { 
 @override 
 public void afterconnectionestablished(websocketsession session) throws exception { 
  system.out.println("connect to the websocket success......"); 
  session.sendmessage(new textmessage("server:connected ok!")); 
 } 
 
 @override 
 public void handlemessage(websocketsession wss, websocketmessage<?> wsm) throws exception { 
  textmessage returnmessage = new textmessage(wsm.getpayload() 
  + " received at server"); 
  wss.sendmessage(returnmessage); 
 } 
 
 @override 
 public void handletransporterror(websocketsession wss, throwable thrwbl) throws exception { 
  if(wss.isopen()){ 
   wss.close(); 
  } 
  system.out.println("websocket connection closed......"); 
 } 
 
 @override 
 public void afterconnectionclosed(websocketsession wss, closestatus cs) throws exception { 
  system.out.println("websocket connection closed......"); 
 } 
 
 @override 
 public boolean supportspartialmessages() { 
  return false; 
 } 
} 

(6)websocketconfig.java

package zyy.sockjs.config; 
import org.springframework.context.annotation.bean; 
import org.springframework.context.annotation.configuration; 
import org.springframework.web.servlet.config.annotation.enablewebmvc; 
import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter; 
import org.springframework.web.socket.websockethandler; 
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 extends webmvcconfigureradapter implements 
  websocketconfigurer { 
 public websocketconfig() { 
 } 
 
 @override 
 public void registerwebsockethandlers(websockethandlerregistry registry) { 
  registry.addhandler(systemwebsockethandler(), "/websck").addinterceptors(new handshakeinterceptor()); 
  system.out.println("registed!"); 
  registry.addhandler(systemwebsockethandler(), "/sockjs/websck/info").addinterceptors(new handshakeinterceptor()) 
    .withsockjs(); 
 } 
 
 @bean 
 public websockethandler systemwebsockethandler() { 
  return new systemwebsockethandler(); 
 } 
} 

(7)testsocket.jsp

<%@ page language="java"contenttype="text/html; charset=iso-8859-1" pageencoding="iso-8859-1"%> 
<!doctype htmlpublic"-//w3c//dtd html 4.01 transitional//en""http://www.w3.org/tr/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="content-type"content="text/html; charset=iso-8859-1"> 
<title>websocket/sockjs echo sample (adapted from tomcat's echo sample)</title> 
 <style type="text/css"> 
  #connect-container { 
   float: left; 
   width: 400px 
  } 
  #connect-container div { 
   padding: 5px; 
  } 
  #console-container { 
   float: left; 
   margin-left: 15px; 
   width: 400px; 
  } 
  #console { 
   border:1px solid #cccccc; 
   border-right-color:#33333333; 
   border-bottom-color:#999999; 
   height: 170px; 
   overflow-y: scroll; 
   padding: 5px; 
   width: 100%; 
  } 
  #console p { 
   padding: 0; 
   margin: 0; 
  } 
 </style> 
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script> 
<script type="text/javascript"> 
  var ws = null; 
  var url = null; 
  var transports = []; 
  function setconnected(connected) { 
   document.getelementbyid('connect').disabled = connected; 
   document.getelementbyid('disconnect').disabled = !connected; 
   document.getelementbyid('echo').disabled = !connected; 
  } 
  function connect() { 
   if (!url) {    
   log('select whether to use w3c websocket or sockjs');    
    return; 
   } 
   //ws = (url.indexof('sockjs') != -1) ?new sockjs(url, undefined, {protocols_whitelist: transports}) : new websocket(url); 
   if ('websocket'in window) { 
    ws= new websocket("ws://localhost:8080/springsocketjs/websck"); 
   }else { 
    ws = new sockjs("http://localhost:8080/springsocketjs/sockjs/websck/info"); 
   } 
   //websocket = new sockjs("http://localhost:8084/springwebsocketpush/sockjs/websck"); 
   ws.onopen = function () { 
    setconnected(true); 
    //log('info: connection opened.'); 
   }; 
   ws.onmessage = function (event) {    
    log('received: ' + event.data); 
   }; 
   ws.onclose = function (event) { 
    setconnected(false); 
    log('info: connection closed.'); 
    log(event); 
   }; 
  } 
  function disconnect() { 
   if (ws != null) { 
    ws.close(); 
    ws = null; 
   } 
   setconnected(false); 
  } 
  function echo() { 
   if (ws != null) { 
    var message = document.getelementbyid('message').value; 
    log('sent: ' + message); 
    ws.send(message); 
   } else { 
    alert('connection not established, please connect.'); 
   } 
  } 
  function updateurl(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'; 
   } 
  } 
  function updatetransport(transport) { 
   transports = (transport == 'all') ? [] : [transport]; 
  }  
  function log(message) { 
   var console = document.getelementbyid('console'); 
   var p = 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><h2 style="color:#ff0000">seems your browser doesn't supportjavascript!websockets 
 rely on javascript being enabled. please enable 
 javascript and reload this page!</h2></noscript> 
<div> 
 <div id="connect-container"> 
  <input id="radio1"type="radio"name="group1"onclick="updateurl('/springsocketjs/websocket');"> 
   <label for="radio1">w3c websocket</label> 
  <br> 
  <input id="radio2"type="radio"name="group1"onclick="updateurl('/springsocketjs/sockjs/websocket');"> 
   <label for="radio2">sockjs</label> 
  <div id="sockjstransportselect" style="visibility:hidden;"> 
   sockjs transport: 
   <select onchange="updatetransport(this.value)"> 
    <option value="all">all</option> 
    <option value="websocket">websocket</option> 
    <option value="xhr-polling">xhr-polling</option> 
    <option value="jsonp-polling">jsonp-polling</option> 
    <option value="xhr-streaming">xhr-streaming</option> 
    <option value="iframe-eventsource">iframe-eventsource</option> 
    <option value="iframe-htmlfile">iframe-htmlfile</option> 
   </select> 
  </div> 
  <div> 
   <button id="connect"onclick="connect();">connect</button> 
   <button id="disconnect"disabled="disabled"onclick="disconnect();">disconnect</button> 
  </div> 
  <div> 
   <textarea id="message"style="width:350px">here is a message!</textarea> 
  </div> 
  <div> 
   <button id="echo"onclick="echo();"disabled="disabled">echo message</button> 
  </div> 
 </div> 
 <div id="console-container"> 
  <div id="console"></div> 
 </div> 
</div> 
</body> 
</html> 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。