Spring4.0系列9-websocket简单应用
Spring4.0系列4-Meta Annotation(元注解)
Spring4.0系列6-Generic Qualifier(泛型限定)
Spring4.0系列7-Ordering Autowired Collections
Spring 4.0的一个最大更新是增加了websocket的支持。websocket提供了一个在web应用中的高效、双向的通讯,需要考虑到客户端(浏览器)和服务器之间的高频和低延时消息交换。一般的应用场景有:在线交易、游戏、协作、数据可视化等。
使用websocket需要考虑的浏览器的支持(IE<10不支持),目前主流的浏览器都能很好的支持websocket。
websocket协议中有一些子协议,可以从更高的层次实现编程模型,就像我们使用HTTP而不是TCP一样。这些子协议有STOMP,WAMP等。
本教程只考虑websocket的简单实用,包含Spring对JSR-356的支持及Spring WebSocket API。
1、Java API for WebSocket(JSR-356)
Java API for WebSocket已经是Java EE 7的一部分。它定义了两类endpoit(都是EndPoint类的子类),使用注解标识@ClientEndpoint和@ServerEndpoint。
1.1 Servlet容器扫描初始化
通过Spring初始化一个endpoint,只需配置一个SpringConfigurator在类上的@ServerEndpoint注解上。
- import javax.websocket.server.ServerEndpoint;
- import org.springframework.web.socket.server.endpoint.SpringConfigurator;
- @ServerEndpoint(value = "/echo", configurator = SpringConfigurator.class);
- public class EchoEndpoint {
- private final EchoService echoService;
- @Autowired
- public EchoEndpoint(EchoService echoService) {
- this.echoService = echoService;
- }
- @OnMessage
- public void handleMessage(Session session, String message) {
- // ...
- }
- }
上例假设SpringContextLoaderListener用来加载配置,这是个典型的web应用。Servlet容器将通过扫描@ServerEndpoint和SpringConfigurator初始化一个新的websocket会话。
1.2 Spring 初始化
如果你想使用一个单独的实例而不使用Servlet容器扫描,将EchoEndpoint类声明称一个bean,并增加一个ServerEndpointExporter的bean:
- import org.springframework.web.socket.server.endpoint.ServerEndpointExporter;
- @Configuration
- public class EndpointConfig {
- @Bean
- public EchoEndpoint echoEndpoint() {
- return new EchoEndpoint(echoService());
- }
- @Bean
- public EchoService echoService() {
- // ...
- }
- @Bean
- public ServerEndpointExporter endpointExporter() {
- return new ServerEndpointExporter();
- }
- }
EchoEndpoint 可以通过EndPointRegistration发布:
- import org.springframework.web.socket.server.endpoint.ServerEndpointExporter;
- import org.springframework.web.socket.server.endpoint.ServerEndpointRegistration;
- @Configuration
- public class EndpointConfig {
- @Bean
- public EndpointRegistration echoEndpoint() {
- return new EndpointRegistration("/echo", EchoEndpoint.class);
- }
- @Bean
- public ServerEndpointExporter endpointExporter() {
- return new ServerEndpointExporter();
- }
- // ..
- }
本例源码:spring-websocket-test-endpoint.zip
2、Spring WebSocket API
Spring WebSocket API提供了SockJS的支持,且有些容器如Jetty 9目前还没有对JSR-356的支持,所以有Spring WebSocket API是必要的。
Spring WebSocket API的核心接口是WebSocketHandler。下面是一个处理文本消息的handler的实现:
- import org.springframework.web.socket.adapter.TextWebSocketHandlerAdapter;
- public class EchoHandler extends TextWebSocketHandlerAdapter {
- @Override
- public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
- session.sendMessage(message);
- }
- }
WebSocketHandler可以通过WebSocketHttpRequestHandler插入到Spring MVC里:
- import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
- @Configuration
- public class WebConfig {
- @Bean
- public SimpleUrlHandlerMapping handlerMapping() {
- Map<String, Object> urlMap = new HashMap<String, Object>();
- urlMap.put("/echo", new WebSocketHttpRequestHandler(new EchoHandler()));
- SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping();
- hm.setUrlMap(urlMap);
- return hm;
- }
- }
SockJS服务器端的支持
SockJs是一个脚本框架,它提供类似于websocket的编程模式但是可以适应不同的浏览器(包括不支持websocket的浏览器)。
开启SockJS的支持,声明一个SockJsService,和一个url映射,然后提供一个WebSocketHandler来处理消息。虽然 我们是哟个SockJS我们开发的方式是一样的,但是随着浏览器的不同传输的协议可以是Http Streaming,long polling等。
- import org.springframework.web.socket.sockjs.SockJsService;
- // ...
- @Configuration
- public class WebConfig {
- @Bean
- public SimpleUrlHandlerMapping handlerMapping() {
- SockJsService sockJsService = new DefaultSockJsService(taskScheduler());
- Map<String, Object> urlMap = new HashMap<String, Object>();
- urlMap.put("/echo/**", new SockJsHttpRequestHandler(sockJsService, new EchoHandler()));
- SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping();
- hm.setUrlMap(urlMap);
- return hm;
- }
- @Bean
- public ThreadPoolTaskScheduler taskScheduler() {
- ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
- taskScheduler.setThreadNamePrefix("SockJS-");
- return taskScheduler;
- }
- }
在我们实际使用中我们会使用WebSocketConfigurer集中注册WebSocket服务:
- @Configuration
- @EnableWebMvc
- @EnableWebSocket//开启websocket
- public class WebConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
- @Override
- public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
- registry.addHandler(echoWebSocketHandler(), "/echo"); //提供符合W3C标准的Websocket数据
- registry.addHandler(snakeWebSocketHandler(), "/snake");
- registry.addHandler(echoWebSocketHandler(), "/sockjs/echo").withSockJS();//提供符合SockJS的数据
- registry.addHandler(snakeWebSocketHandler(), "/sockjs/snake").withSockJS();
- }
- @Bean
- public WebSocketHandler echoWebSocketHandler() {
- return new EchoWebSocketHandler(echoService());
- }
- @Bean
- public WebSocketHandler snakeWebSocketHandler() {
- return new PerConnectionWebSocketHandler(SnakeWebSocketHandler.class);
- }
- @Bean
- public DefaultEchoService echoService() {
- return new DefaultEchoService("Did you say \"%s\"?");
- }
- // Allow serving HTML files through the default Servlet
- @Override
- public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
- configurer.enable();
- }
- }
SockJS客户端代码:
- ws = new SockJS(url, undefined, {protocols_whitelist: transports}) ; //初始化 websocket
- 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);
- };
- ws.send(message);//向服务端发送消息
程序用maven打成war后用tomcat 8发布查看效果。
本例源码:spring-websocket-test-master.zip
新书推荐《JavaEE开发的颠覆者: Spring Boot实战》,涵盖Spring 4.x、Spring MVC 4.x、Spring Boot企业开发实战。
京东地址:http://item.jd.com/11894632.html
当当地址:http://product.dangdang.com/23926195.html
亚马逊地址:http://www.amazon.cn/图书/dp/B01D5ZBFUK/ref=zg_bsnr_663834051_6
淘宝地址:https://item.taobao.com/item.htm?id=528426235744&ns=1&abbucket=8#detail
或自己在京东、淘宝、亚马逊、当当、互动出版社搜索自选。

Spring4.0系列9-websocket简单应用的更多相关文章
- [CXF REST标准实战系列] 二、Spring4.0 整合 CXF3.0,实现测试接口(转)
转自:[CXF REST标准实战系列] 二.Spring4.0 整合 CXF3.0,实现测试接口 文章Points: 1.介绍RESTful架构风格 2.Spring配置CXF 3.三层初设计,实现W ...
- [CXF REST标准实战系列] 二、Spring4.0 整合 CXF3.0,实现测试接口
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章Points: 1.介绍RESTful架构 ...
- HTTP协议系列(3)---包括WebSocket简单介绍
一.HTTPS HTTP是超文本传输协议,那HTTPS是什么尼?要明白HTTPS是什么先要明白HTTP的缺点,想一下我们在使用HTTP的时候会有那些缺点尼? 1.通信使用的明文(不加密),内容 ...
- Spring 4.0 中的 WebSocket 架构
两年前,客户端与服务器端的全双工双向通信作为一个很重要的功能被纳入到WebSocket RFC 6455协议中.在HTML5中,WebSocket已经成为一个流行词,大家对这个功能赋予很多构想,很多时 ...
- [渣译文] SignalR 2.0 系列: SignalR简介
原文:[渣译文] SignalR 2.0 系列: SignalR简介 英文渣水平,大伙凑合着看吧,并不是逐字翻译的…… 这是微软官方SignalR 2.0教程Getting Started with ...
- SignalR 2.0 系列: SignalR简介
SignalR 2.0 系列: SignalR简介 英文渣水平,大伙凑合着看吧,并不是逐字翻译的…… 这是微软官方SignalR 2.0教程Getting Started with ASP.NET S ...
- 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)
并发编程概述 前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...
- [转]Struts2.3.16.1+Hibernate4.3.4+Spring4.0.2 框架整合
原文地址:http://blog.csdn.net/ycb1689/article/details/22928519 最新版Struts2+Hibernate+Spring整合 目前为止三大框架最新版 ...
- Spring4.0编程式定时任务配置
看过很多定时调度的配置,大多使用XML配置,觉得比较麻烦,也比较老套.这里介绍一种基于spring4.0注解编程式配置定时任务,简单清晰,使用方便.. 至于引入spring相关jar这里不多说,直接切 ...
随机推荐
- eclipse tomcat路径更改后启动报错
eclipse tomcat路径更改后启动报错 CreateTime--2018年5月3日14:48:22 Author:Marydon 1.情景还原 2.原因 本地的tomcat路径修改后,ec ...
- 〖Linux〗iptables使用实例
1. 使局域网用户可共享外网(拨号上网) > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -o ppp0 -j MA ...
- 查询SQL存储过程创建时间
select [name] ,create_date ,modify_date FROM sys.all_objects where type_desc = N'SQL_STORED_PROCE ...
- 用C/C++开发android应用
在某些情况下,比如原来与很多c/c++的代码, 可能希望采用c/c++编写android应用程序.在这种情况下,一般使用NDK.但是由于android直提供了java接口,因此不能够直接调用andro ...
- Androidmanifest.xml在Android项目中的作用
以下是一个项目中的AndroidManifest.xml文件: <?xml version="1.0" encoding="utf-8"?> < ...
- 更改 pandas dataframe 中两列的位置
更改 pandas dataframe 中两列的位置: 把其中的某列移到第一列的位置. 原来的 df 是: df = pd.read_csv('I:/Papers/consumer/codeandpa ...
- SELECT控件add方法 ie 类型不匹配
s = document.createElement('select'); try{ //for ie8 or earlier s.add(new Option('text','value'),s.o ...
- go 学习笔记(1)--package
引入包有以下几种方式: 1. 最简单的方式引入一个包的方式是直接引入包,例如: import "fmt" import "os" 2. 也可以通过下面的方式将包 ...
- Linux内核(6) - 模块机制与“Hello World!
有一种感动,叫内牛满面,有一种机制,叫模块机制.显然,这种模块机制给那些Linux的发烧友们带来了方便,因为模块机制意味着人们可以把庞大的Linux内核划分为许许多多个小的模块.对于编写设备驱动程序的 ...
- LeetCode94 Binary Tree Inorder Traversal(迭代实现) Java
题目: Given a binary tree, return the inorder traversal of its nodes' values. For example: Given binar ...