详解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技术实际上是轮询技术的改进,又可细分为两种实现方式,一种是长轮询机制,一种称为流技术。

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>

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

时间: 2017-01-17

JS实现websocket长轮询实时消息提示的效果

效果图如下: 参考代码如下: jsp代码: <%@ page contentType="text/html;charset=UTF-8" language="java"%> <div class="page-header navbar navbar-fixed-top"> <div class="page-header-inner"> <div class="page-log

Javascript WebSocket使用实例介绍(简明入门教程)

一旦你了解了网络套接字与WEB服务器的连接,你将可以从浏览器发送数据到服务器并且可以接收由服务器返回的响应数据. 以下是创建一个新的WebSocket对象的API: 复制代码 代码如下: var Socket = new WebSocket(url, [protocal] ); 这里第一个参数是指要连接的URL,第二个参数是可选的,如果需要的话,则是指定一个的服务器支持的协议. WEB Socket属性: 属性 说明 Socket.readyState readyState的代表的ReadOnl

基于html5和nodejs相结合实现websocket即使通讯

最近都在学习HTML5,做canvas游戏之类的,发现HTML5中除了canvas这个强大的工具外,还有WebSocket也很值得注意.可以用来做双屏互动游戏,何为双屏互动游戏?就是通过移动端设备来控制PC端网页游戏.这样的话就要用到实时通讯了,而WebSocket无疑是最合适的.WebSocket相较于HTTP来说,有很多的优点,主要表现在WebSocket只建立一个TCP连接,可以主动推送数据到客户端,而且还有更轻量级的协议头,减少数据传送量.所以WebSocket暂时来说是实时通讯的最佳协

Python通过websocket与js客户端通信示例分析

具体的 websocket 介绍可见 http://zh.wikipedia.org/wiki/WebSocket 这里,介绍如何使用 Python 与前端 js 进行通信. websocket 使用 HTTP 协议完成握手之后,不通过 HTTP 直接进行 websocket 通信. 于是,使用 websocket 大致两个步骤:使用 HTTP 握手,通信. js 处理 websocket 要使用 ws 模块: Python 处理则使用 socket 模块建立 TCP 连接即可,比一般的 soc

浅析nodejs实现Websocket的数据接收与发送

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术.在WebSocket API中,浏览器和服务器只需要要做一个握手(handshaking)的动作,然后,浏览器和服务器之间就形成了一条快速通道.两者之间就直接可以数据互相传送. WebSocket是一个通信的协议,分为服务器和客户端.服务器放在后台,保持与客户端的长连接,完成双方通信的任务.客户端一般都是实现在支持HTML5浏览器核心中,通过提供JavascriptAPI使用网页可以建立websocket连接.

JavaScript之WebSocket技术详解

概述 HTTP协议是一种无状态协议,服务器端本身不具有识别客户端的能力,必须借助外部机制,比如session和cookie,才能与特定客户端保持对话.这多多少少带来一些不便,尤其在服务器端与客户端需要持续交换数据的场合(比如网络聊天),更是如此.为了解决这个问题,HTML5提出了浏览器的WebSocket API. WebSocket的主要作用是,允许服务器端与客户端进行全双工(full-duplex)的通信.举例来说,HTTP协议有点像发电子邮件,发出后必须等待对方回信:WebSocket则是

javascript中indexOf技术详解

JavaScript提供了几种技术,来在字符串中搜索一个单词.数字或其他的一串字符.搜索可能很方便,例如,如果你想要知道访问者使用哪种Web浏览器来浏览你的站点.每个Web浏览器在一个字符串中标识关于自己的信息,该字符串包含了很多不同的统计数据.可以通过在一个Web页面中添加下面这段JavaScript,并且在Web浏览器预览,从而看到这个字符串: <script> alert(navigator.userAgent): </script> Navigator是一个Web浏览器对象

JavaScript之cookie技术详解

运用JS设置cookie.读取cookie.删除cookie JavaScript是运行在客户端的脚本,因此一般是不能够设置Session的,因为Session是运行在服务器端的. 而cookie是运行在客户端的,所以可以用JS来设置cookie. 假设有这样一种情况,在某个用例流程中,由A页面跳至B页面,若在A页面中采用JS用变量temp保存了某一变量的值,在B页面的时候,同样需要使用JS来引用temp的变量值,对于JS中的全局变量或者静态变量的生命周期是有限的,当发生页面跳转或者页面关闭的时

基于JavaScript表单脚本(详解)

什么是表单? 一个表单有三个基本组成部分: 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法. 表单域:包含了文本框.密码框.隐藏域.多行文本框.复选框.单选框.下拉选择框和文件上传框等. 表单按钮:包括提交按钮.复位按钮和一般按钮:用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作. JavaScript与表单间的关系:JS最初的应用就是用于分担服务器处理表单的责任,打破依赖服务器的局面,尽管目前web和jav

javascript异常处理实现原理详解

这篇文章主要介绍了javascript异常处理实现原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.什么是例外处理 当 JavaScript程序在运行中发生了诸如数组索引越界.类型不匹配或者语法错误时,JavaScript解释器就会引发例外处理. ECMAScript定义了六种类型的错误,除此之外,我们可以使用Error对象和throw语句来创建并引发自定义的例外处理信息. 通过运用例外处理技术,我们可以实现用结构化的方式来响应错误事

JavaScript数据结构链表知识详解

最近在看<javascript数据结构和算法>这本书,补一下数据结构和算法部分的知识,觉得自己这块是短板. 链表:存储有序的元素集合,但不同于数组,链表中的元素在内存中不是连续放置的.每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 好处:可以添加或移除任意项,它会按需扩容,且不需要移动其他元素. 与数组的区别: 数组:可以直接访问任何位置的任何元素: 链表:想要访问链表中的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素. 做点小笔记. funct

JavaScript里 ==与===区别详解

1.对于string,number等基础类型,==和===是有区别的 1)不同类型间比较,==之比较"转化成同一类型后的值"看"值"是否相等,===如果类型不同,其结果就是不等 2)同类型比较,直接进行"值"比较,两者结果一样 2.对于Array,Object等高级类型,==和===是没有区别的 进行"指针地址"比较 3.基础类型与高级类型,==和===是有区别的 1)对于==,将高级转化为基础类型,进行"值&quo

JavaScript String 对象常用方法详解

字符串是不可变的.字符串方法,不会改变原有字符串的内容,而是返回一个新字符串. charAt():返回在指定位置的字符. concat():连接两个字符串文本,并返回一个新的字符串. indexOf(): indexOf() 方法返回指定值在字符串对象中首次出现的位置. match(): 使用正则表达式与字符串相比较. replace(): 被用来在正则表达式和字符串直接比较,然后用新的子串来替换被匹配的子串. slice(): 摘取一个字符串区域,返回一个新的字符串. split(): 通过分

java多线程编程技术详解和实例代码

 java多线程编程技术详解和实例代码 1.   Java和他的API都可以使用并发. 可以指定程序包含不同的执行线程,每个线程都具有自己的方法调用堆栈和程序计数器,使得线程在与其他线程并发地执行能够共享程序范围内的资源,比如共享内存,这种能力被称为多线程编程(multithreading),在核心的C和C++语言中并不具备这种能力,尽管他们影响了JAVA的设计. 2.   线程的生命周期 新线程的生命周期从"新生"状态开始.程序启动线程前,线程一直是"新生"状态:

JavaScript hasOwnProperty() 函数实例详解

hasOwnProperty()函数用于指示一个对象自身(不包括原型链)是否具有指定名称的属性.如果有,返回true,否则返回false. 该方法属于Object对象,由于所有的对象都"继承"了Object的对象实例,因此几乎所有的实例对象都可以使用该方法. IE 5.5+.FireFox.Chrome.Safari.Opera等主流浏览器均支持该函数. 语法 object.hasOwnProperty( propertyName ) 参数 参数 描述 propertyName Str