Bozhidar Bozhanov是Ontotext AD的高级软件工程师,拥有多年的从业经验,也是stackoverflow上的活跃用户。他精通于Java与Java技术栈,如Spring、JPA、JavaEE等,同时还是http://computoser.comhttp://welshare.com的创始人。曾开发过爱立信的项目、保加利亚电子政务项目以及大型招聘平台等。近日Bozhidar撰文谈到了WebSocket与Java,并给出了相应的代码示例。Bozhidar在文中详细分析了WebSocket的原理、适用范围,以及如何通过Java来使用WebSocket。

WebSocket是一个很酷的新技术,可以实现浏览器与服务器之间实时、双向的通信,几乎没有任何额外的代价。我这里要做的事情就是提供一个非常简洁,但却内容丰富的概览,介绍如何开始使用这门技术。首先读者需要了解如下一些事情:

  • 首先在浏览器与服务器之间需要开启一个TCP Socket连接,每一方都可以向对方发送消息(比如说,服务器可以在有数据时将其推送出去,无需使用轮询、长轮询、iframes等技术)。
  • 并不是所有浏览器都支持WebSocket技术,IE 10是首个支持WebSocket的IE版本,Android依然还存在着一些问题。幸好有SockJS,在不支持WebSocket的情况下,它会退回到其他的推送技术。
  • 并不是所有的代理服务器都支持或是允许WebSocket,因此这时还是需要退回到其他的推送技术。
  • WebSocket适合于游戏、交易型应用,事实上,它适合于任何服务器要向浏览器推送数据的场景。
  • Java有标准API(JSR-356),你可以在服务端通过它来处理WebSocket连接。
  • Spring在Java API的基础之上提供了一个API。对于Spring提供的支持来说,好消息是它对SockJS提供了服务器端的支持,你也可以毫无压力地使用依赖注入。Spring还对消息驱动的架构提供了STOMP支持。上面的两篇Spring文章都给出了GitHub上示例项目的链接,我强烈建议大家看看。
  • 长久以来,Atmosphere框架一直是服务器推送技术的解决方案。这里是WebSocket上手指南。另外,Cometd也提供了WebSocket支持

在给出具体的示例代码前,我首先来介绍一下Socket的生命周期,包括客户端的与服务器端的:

  1. 浏览器发出一个HTTP请求,带有一个特殊的Upgrade头,其值是“websocket”。
  2. 如果服务器能够“理解”WebSocket,那么它会使用状态101进行应答——交换协议。从现在开始,我们就不再使用HTTP了。
  3. 当服务器接收这个TCP Socket连接后,一个初始化方法会得到调用,当前的WebSocket Session会被传递进来。每个Socket都有唯一一个Session id。
  4. 当浏览器向服务器发送消息时,另一个方法会得到调用,你在这里获得Session与消息负载。
  5. 根据某个负载参数,应用代码会执行一个动作。负载的格式完全取决于开发者。一般来说会使用JSON序列化的对象。
  6. 当服务器需要发送消息时,它需要获得这个Session对象,然后通过它来发送消息。
  7. 当浏览器关闭连接时,服务器会得到通知,这样它就可以清理与特定Session关联的一些资源了。

目前,还没有任何一个API或框架能够支持基于注解的路由。Java API支持基于注解的端点处理器,不过每个连接URL需要一个类来处理,通常情况下,你希望在单个连接上执行多个操作。也就是说,你连接到ws://yourserver.com/game/,然后想要传递“joinGame”和“leaveGame”等消息。类似地,服务器需要发送回多种类型的消息。我使用了枚举来实现这一点,枚举中包含了所有可能的动作与事件类型,然后使用switch来确定该调用哪一个。

因此,我决定为我的算法音乐作曲家开发一个简单的游戏。它使用了Spring API,感兴趣的读者可以看看这个介绍,这是我在公司所做的一次演讲。下面是一些示例代码:

@Component
public class GameHandler extends WebSocketHandlerAdapter {
private Map

下面来看一个示例场景,其中服务器需要向客户端发送消息。这就好比一个玩家加入了游戏一样,这时其他所有玩家都会收到有新人加入的通知。系统中的中心类是Game,它拥有一个玩家列表。如你所见,一个Player包含了一个对WebSocket Session的引用。这样,当新的玩家加入时,下面的Game中的方法就会得到调用:

public boolean playerJoined(Player player) {
for (Player otherPlayer : players.values()) {
otherPlayer.playerJoined(player);
}
players.put(player.getSession().getId(), player);
return true;
}

player.playerJoined(..)会在连接之上发送一条消息,通知浏览器有新的玩家加入了:

public void playerJoined(Player player) {
GameEvent event = new GameEvent(GameEventType.PLAYER_JOINED);
event.setPlayerId(player.getSession().getId());
event.setPlayerName(player.getName());
try {
session.sendMessage(new TextMessage(event.toJson()));
} catch (IOException e) {
new IllegalStateException(e);
}
}

从服务器向浏览器发送消息可能还需要一个调度job进行触发。

关键在于你维护了一个所有已连接的浏览器列表,这样就可以向回发送信息了。这个列表可以是个静态属性,不过对于单例的Spring Bean来说就没必要这么做了。

现在,有两个重要的方面需要我们注意——安全与认证。这是来自于Heroku的一篇很不错的文章,对安全与认证进行了详细的介绍。如果还有其他敏感信息,你就应该使用wss(Websocket over TLS)了。你还应该在服务器端与客户端验证输入,而不应该依赖于Origin头,因为攻击者可以轻而易举地骗过浏览器。

认证可以依赖于HTTP Session cookie,不过显而易见的是,有些人更喜欢实现自己的类cookie工作流,从而获取一个短暂的令牌,它可以用于执行认证操作。

WebSocket使得DDD变得更加自然。你不必再处理贫血对象了,你的对象有各自的状态以及对这些状态的操作。与之相关的是,WebSocket应用的测试变得更加容易了。

在开发WebSocket应用时还有不少需要注意的事情。值得注意的是,你没有必要在任何地方都使用WebSocket,我将其限定在需要“推送”的场景下。

总的来说,WebSocket是一个很棒、很有趣的技术,它非常有希望灭掉所有采用hack手段实现的推送模拟技术。

原文来自于:http://www.infoq.com/cn/news/2013/12/websocket-and-java

最新文章

  1. TCP状态变迁流程
  2. IOS开发UI基础UIImagePickerController的属性
  3. js严格模式“use strict”
  4. AMD机制与cMD的区别和概念简要介绍
  5. 【JQGRID DOCUMENTATION】.学习笔记.6.Editing:Common Rules
  6. SQL 批量删除数据表
  7. C#反射实例化类并调用类的方法
  8. jquery实现简单的ajax
  9. Hadoop伪分布模式配置部署
  10. 设置透明navigationBar
  11. Java 基于log4j的日志工具类
  12. HDU 5547 暴力
  13. mac中的myeclipse的控制台中文乱码问题解决办法
  14. minimun path sum(最小路径和)
  15. pip的更新问题
  16. PowerDesin把name复制到Comment,把Comment复制到Name
  17. M2项目测试
  18. quartz.net实现集群部署的笔记
  19. android手机安全性测试手段
  20. 获取windows可执行文件的version信息(版本号)

热门文章

  1. 【jquery mobile笔记二】jquery mobile调用豆瓣api示例
  2. JS中timestamp日期类型的转换
  3. Away3D 4.1.4 中实现骨骼绑定
  4. VS2012 无法启动IIS Express Web服务器的解决方案
  5. lvchange的available參数
  6. iOS工具种之16进制颜色转为UIColor
  7. Meth | elementary OS常用配置
  8. 生成package.json和bower.json
  9. android - 调试
  10. class-loader.