阅读更多

18顶
5踩

企业架构

正如你可能已经看到的,Spring Framework 4.0 第一个里程碑版本已经宣布,且我们已经发布了早期的WebSocket支持。为什么WebSocket重要呢?在web上,需要在客户端(典型如浏览器)和服务器间进行高频率低延迟的消息交换是在应用中必不可少的,它使有效的,双向的通信成为可能。常见的例子包括交易,游戏,协作,数据可视化,其他的一系列场景和用例将随时间而增加。

 

WebSocket是非常宽泛的话题!你可以在InfoQ上观看我们SpringOne 2012的“WebSocket介绍”获取更全面的介绍。能够简单的使用WebSocket仅仅是一个开始。你将需要一个备用策略用于那些不支持它的浏览器(如 IE < 10)和用于阻止其使用的网络代理。此外,套接字编程,是非常,非常低级的编程。大多数的应用将受益于一个更高级的编程模型。这也是公认的,在WebSocket协议中通过一种机制 来允许使用一个“子协议”(例如一个更高级别的协议),就像今天我们都使用的HTTP,不是一个原始的TCP套接字。例如,子协议包括STOMPWAMP,和更多其它的。

 

请记住,这是一个早期版本。它关注的基本面包括JSR-356支持和浏览器内部使用的备选项(fallback options)。也没有子协议支持,那是下一个里程碑版本的目标。

  

WebSocket的Java API  (JSR-356)

 

WebSocket的Java API是最近完成的并是Java EE 7的一部分。它定义了两种类型的端点—Endpoint子类及注解的端点,如@ClientEndpoint和@ServerEndpoint。完整的介绍超出了本文的范围。我将只会提到在Spring应用中理解如何配置和使用端点的最低要求。

 

在JSR-356中有两种方法来部署服务器 — 通过Servlet容器扫描(Servlet 3.0特性)和在编程式启动。对于Servlet容器扫描,规范要求注解的端点有一个默认构造器,但Endpoint子类不能被自动部署。相反,Servlet容器扫描检测ServerApplicationConfig类型,其按照预期的循环为每一个Endpoint应用Server/ClientEndpointConfig。

 

在试图搞清楚这一切之前,你可能想知道的是它如何与你的Spring应用关联。M1版本通过Spring提供了用于初始化两种类型端点的全部支持,包括适当的构造器依赖注入以及每个连接和单例端点生命周期。此外,你应该关闭Servlet容器扫描,其是相当重量级的并扫描所有类包括第三方依赖。

 

给出代码!

 

用Spring初始化一个注解的端点,只需简单地用类级别注解配置一个SpringConfigurator:

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用于装载Spring配置, 但通常是在web应用的情况。除此之外没有别的要求。Servlet容器扫描发现注解的端点和SpringConfigurator为每个WebSocket会话初始化一个新的实例,这也是规范中定义的默认的生命周期。

 

如果你想使用一个单例或想关闭Servlet容器扫描,声明EchoEndpoint作为一个Spring bean,且也加添加一个forServerEndpointExporter bean声明(只需一次!)。如下示例使用Spring的Java配置,但你也可以添加基于XML配置等价的声明。

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();
  }
 
}

 Endpoint子类能连同一个ServerEndpointExporter声明(只需一次)一起通过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();
  }
 
  // ..
 
}

EndpointRegistration也有一个接受一个端点实例参数的构造器。这允许你在有每个WebSocket会话有一个新实例或单个实例服务所有会话间进行选择。

 

 

客户端呢?

 

JSR-356提供如下API用于连接服务器:

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(EchoEndpoint.class, new URI("ws:localhost:8080/webapp/echo"));

这是很简单的,但如果也能声明它也将是不错的。常见的情况是 — 当web应用启动时,它应该自动的连接到远程端点,开始处理消息并当应用关闭时停止。

 

你可以通过一个如下所示的连接管理器来做到,即当Spring ApplicationContext刷新或关闭时分别进行WebSocket连接建立和关闭。

import org.springframework.web.socket.client.endpoint.AnnotatedEndpointConnectionManager;
 
@Configuration
public class EndpointConfig {
 
  // For Endpoint sub-classes use EndpointConnectionManager instead
 
  @Bean
  public AnnotatedEndpointConnectionManager connectionManager() {
    return new AnnotatedEndpointConnectionManager(echoEndpoint(), "ws://localhost:8080/webapp/echo");
  }
 
  @Bean
  public EchoEndpoint echoEndpoint() {
    // ...
  }
 
}

你也可以使用autoStartup属性来开启/禁用自动连接。如果禁用,你可以手工调用start()和stop()。

 

到此总结了JSR-356支持的概述。

  

Spring WebSocket API

 

除了JSR-356的支持,这个版本提供了导致一些明显问题的Spring WebSocket API的新的开始。

 

为什么是我们自己的API?我们在内部它作为更高级服务的基础如SockJS。它允许我们有可能插入额外的Java WebSocket实现并添加额外的特性。例如JSR-356没有提供从一个存在的Servlet初始化WebSocket握手的方式,当添加SockJS支持时这让我们发现非常有用。此外,尽管Jetty也没有提供JSR-356支持,我们也是能够在这个版本插入(所有新的)Jetty 9 WebSocket API和包括Jetty 9支持。我们可以坚持使用Jetty API直接前进,因为它提供了一组更丰富的WebSocket配置和处理选项及比Java WebSocket API更频繁的更新。

 

为什么仅基于类型(例如,不是注解)?Spring WebSocket API以框架使用为主为目标。应用当然可以使用它,但我们相信,到套接字的编程对于大多数应用来组织他们的业务逻辑和提供健壮的消息处理太低级了。为了更好地体会到这一点,可以考虑如果一个应用暴露单个WebSocket连接(在大多数情况,它应该),它将不得不从单个类中处理所有应用消息类型。即使是注解,不可能自适应实际应用的复杂性。想像一下REST没有名词(URLs)和动词(HTTP methods),仅有原始的socket。这就是为什么子协议支持和更高级别编程模型是非常必要的,这也是我们更像是要有一些注解。

 

希望注意到“为什么”问题。现在,让我们来看一些代码。

 

Spring WebSocket API核心接口是WebSocketHandler。下面是对一个它的实现用于处理文本消息。基类有个空方法,只是按照协议中定义的以状态1003(not acceptable)关闭会话来拒绝二进制消息。

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);
  }
 
}

 注意,handleTextMessage允许异常传播。这不同于JSR-356,它不允许。如果一个Exception(或Throwable)逸出方法,会话会自动以状态1011关闭(server error)。这意味着你可以选择处理异常,如果有任何有意义的事情去做;或者否则让它以默认方式处理。默认异常处理通过WebSocketHandlerDecorator机制提供。它能被扩展和/或替换。这些仅是几个我们自己的API能让我们去做什么的例子。

 

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是一个浏览器JavaScript类库,其提供了WebSocket类似的编程模型和一系列特定浏览器的传输(transport),如果WebSocket在浏览器不支持或网络问题阻止它时使用。我们很高兴的宣布在这个版本中支持SockJS。SockJS的更多细节和各种传输选项,请访问sockjs-client项目页面。

 

开启SockJS支持,简单地声明一个SockJsService,映射它到一些URL,并提供一个用于出入传入消息(incoming message)的WebSocketHandler。注意,WebSocketHandler是之上讨论的相同的处理器。换句话说,当使用SockJS,编程模型仍然相同,但底层传输可能改变为HTTP流,长轮询,或其他的东西是必要的。

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;
  }
 
}

如果你想知道之上 的任务调度用于各种SockJS相关的任务,例如在HTTP流请求上定期发送心跳信息(以防止代理认为连接是不新鲜的),移除过期的SockJS会话等。

  

最后

 

可以在Github上找到一个示例和介绍的项目。它包括配置JSR-356端点的示例,Spring WebSocketHandler,以及SockJS服务。对于所有示例,建议使用Google Chrome网络选项卡开发工具,为了观察WebSocket和HTTP流量,观察错误等。

 

如果您有反馈意见和建议,我们很乐意听到它!

 

原文:http://blog.springsource.org/2013/05/22/spring-framework-4-0-m1-websocket-support/

 

相关阅读:

 

 

18
5
评论 共 8 条 请登录后发表评论
8 楼 bluky999 2014-02-26 17:09
虽然看起来很庞杂, 但是也算一种支持啦。


如果真到了websocket的场景,很多人都选择了  Node.js
7 楼 jinnianshilongnian 2013-05-27 16:58
lj6684 写道
机器翻译的吧,好多地方语句不通顺

人工翻译的,英语水平有限,希望指正
6 楼 lj6684 2013-05-27 15:42
机器翻译的吧,好多地方语句不通顺
5 楼 moshalanye 2013-05-27 11:55
elgs 写道
Spring越来越要把Java开发人员变傻了。


这是中间件或者准中间件的目标,基于JavaEE6规约的应用哪个不是想把应用开发人员
开发门槛变低的。

如果不是EJB2.0开发的繁琐,容器内测试的麻烦,也不回让Spring有这么多发展空间。

大家都在追求应用开发的简洁和便利而已。
4 楼 elgs 2013-05-25 20:29
elgs 写道
Spring越来越要把Java开发人员变傻了。

应该是Spring绑架Java开发人员。
3 楼 elgs 2013-05-25 20:29
Spring越来越要把Java开发人员变傻了。
2 楼 need_faith 2013-05-25 00:42
目测Web Socket最大的有点就是为了实现推送,坐等楼下补充
1 楼 xlaohe1 2013-05-24 11:15
不错 

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • ERP(SAP)基础知识

    ERP(SAP)基础知识[@more@]一、ERP的实施1.ERP的实施分哪些阶段?ERP的实施通常分为(1)项目准备;(2)业务蓝图;(3)实现过程;(4)最后准备;(5)上线与技术支持 5个阶段。2.准备阶段的主要工作有哪些...

  • 详解Spring Framework及设计理念

    为开发Java应用程序提供全面的基础设施支持,开发者只需专注于应用程序开发,其他的交给Spring。 (2)Spring Framework设计理念:可配置、灵活、向后兼容、注重API设计和高质量代码。 (3)Spring Framework分为6个...

  • Spring IOC 容器源码详解分析

    Spring IOC 容器源码分析 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器。既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文并不能让你成为 ...

  • Spring的IOC的注解详解

    什么是注解传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会...

  • 《Spring实战》读书笔记-第1章 Spring之旅

    文章目录1.1 简化Java开发1.1.1 激发POJO的潜能1.1.2 依赖注入1.1.3 应用切面1.1.4 使用模板消除样板式代码1.2 容纳你的Bean1.2.1 使用应用上下文1.2.2 bean的生命周期1.3 俯瞰Spring风景线1.3.1 Spring模块1.3.2 ...

  • Spring IOC?彻底搞懂它!

    &lt;groupId&gt;org.springframework &lt;artifactId&gt;spring-context &lt;version&gt;4.3.11.RELEASE spring-context 会自动将 spring-core、spring-beans、spring-aop、spring-expression 这几个基础 jar 包带进来。 ...

  • SpringBoot面试题*92(含详解)

    页面 ,我们 就会 看到 可以 在我 们的 应用 程序 中使 用的所有 Spring 项目 的不 同功 能。 如果 必须 启动 一个 新的 Spring 项目 ,我 们必 须添加构 建路 径或 添加 Maven 依赖关系 ,配 置应 用程 序服 务器 ...

  • Spring总结学习

    Spring是开源轻量级java开发框架,能更好的实现高内聚低耦合编程思想,根本使命是解决企业级应用开发的复杂性,即简化java开发 底层都依赖于它的两个核心特性,也就是DI依赖注入(dependency injection,DI)和面向切...

  • java spring代码_Spring实战读书笔记第1章 Spring之旅

    Spring的bean容器介绍Spring的核心模块更为强大的Spring生态系统Spring的新功能1.1 简化Java开发Spring是一个开源框架,最早由Rod Johnson创建,并在《Expert Oneon-One:J2EE Design and Development》这本著作中...

  • Spring IOC源码解析

    前言 说到Spring,似乎IOC、DI成为了我们的共鸣。工作中,Spring无处不在,如影随形,Spring给我们开发者带来了一个春天。这么优秀而美丽的框架,我想,源码是...group 'org.springframework' version '5.0.16.BUILD-S

  • Java八股文

    泛型使用过程中操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法 Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的...

  • 左耳听风——笔记二:程序员练级攻略

    集合(collections)、缓存(caching)、原生类型支持(primitives support)、并发库(concurrency libraries)、通用注解(common annotations)、字符串处理(string processing)、I/O 等库,其还是 Effective ...

  • 转自 静心梦工厂

    [转]Android开源git40个App源码 Android开源git40个App源码 ...[转]Spring Boot 中使用 Dubbo 详解 Spring Boot 中使用 Dubbo 详解 Dubbo是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,...

  • Netty——搭建一个聊天室(笔记)

    这256bytes字节就会缓冲在接收方的滑动窗口中,当滑动窗口中缓冲多了个报文就会黏包 Nagle算法:会造成黏包TCP系列29—窗口管理&流控—3、Nagle算法 半包 现象:发送abcdef,收到abc、def 应用层:接收方ByteBuf小于...

  • 自然语言处理讲义

      1.综述.1.1. 绪论.1.1.1. 背景,目标.1.1.1.1. 研究自然语言的动力1. 语言是思维的裁体,是人际交流的重要工具。在人类历史上以语言文字形式记载和流传的知识占到知识总量的80%以上。就计算机的应用而言,据统计用于数学计算的仅占10%,用于过程控制的不到5%,其余85%左右都是用于语言文字的信息处理。在这样的社会需求下,自然语言理解作为语言信息处理技术的一个高层次的重要方向,

  • 人工智能传奇——关于AI起源与发展的故事

    人工智能传奇——关于AI起源与发展的故事 一、图林与人工智能   介绍人工智能, 不能不从图林说起。英国著名学者 阿兰·图林(A. Turing) 不仅以“纸上下棋机”率先探讨了下棋与机器智能的联系,他还是举世公认的“人工智能之父”。   图林的一生充满着未解之谜,他就象上天派往下界的神祗 ,匆匆而来,又匆匆而去,为人间留下了智慧,留下了深邃的思想,后人必须为之思索几十年甚至几百年。   许多文献

  • 人工智能的认识论问题

    人工智能的认识论问题董军 潘云鹤近50年来,人工智能走的是一条曲折发展的道路。1990年代初,研究者深感人工智能理论及技术的局限性,从而从不同角度和层次进行反思。同时,人工智能有待于人类对人脑工作机理的深入了解,需要神经生理学、神经解剖学给出更加详细的信息和证据。  人工智能交融了诸多学科,与哲学更是密不可分。尽管事实上,新近的哲学进展基本上没给科学带来任何冲击,并且哲学的讨论对象往往是悬而未决的

  • 图灵机与计算问题

    图灵机与计算问题张江(email: jakezj@163.com)自从20世纪30年代以来,图灵机、计算这些重要的概念在科学的天空中就一直闪烁着无限的光彩。尤其是近年来量子计算机、生物计算机、DNA计算等领域的创新工作引起了世人的广泛关注。我们不禁问这样的问题,国外究竟为什么能发明出这些各式各样的计算机呢?这些意味着什么呢?其实这一切的源头都来源于计算理论。国内在介绍计算理论方面的教材虽然有不少,

  • Web 文本挖掘(TextMining)技术

    文本挖掘的起源  文本数据库(web文档数据)  半结构化数据(semistructure data)  信息检索技术(information retrieval)  Web文本挖掘的过程   Web文本挖掘的一般处理过程     特征的建立   特征集的缩减   学习与知识模式的提取   知识模式   模式质量的评价   文档集  文本特征的建立   定义:文本特征指的是关于文本的元数据。  分

  • 智能算法学习笔记

    作者:hisky(苍竹琴声)这是我自己看智能算法的时候的一些笔记,贴出来给大家看一下,如果有理解错误的地方,千万请指出,小生在这里先谢过了^_^一个比方在工程实践中,经常会接触到一些比较“新颖”的算法或理论,比如模拟退火,遗传算法,禁忌搜索,神经网络等。这些算法或理论都有一些共同的特性(比如模拟自然过程),通称为“智能算法”。它们在解决一些复杂的工程问题时大有用武之地。这些算法都有什么含义?首

Global site tag (gtag.js) - Google Analytics