`
jinnianshilongnian
  • 浏览: 21499436 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2417776
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008075
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5638960
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259807
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597045
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250111
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858157
Group-logo
跟我学Nginx+Lua开...
浏览量:701791
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:784902
社区版块
存档分类
最新评论

Spring Framework 4.0 M1: WebSocket 支持

 
阅读更多

 

 

正如你可能已经看到的,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/

 

相关阅读:

Spring Framework 4.0M1 & 3.2.3 发布了

JSR-356 WebSocket API规范中文版

Servlet 3.1规范

 

6
7
分享到:
评论
9 楼 xieqing9505 2016-04-28  
大神您好,请问,分布式部署的时候是怎么统一管理WebSocketSession啊,谢谢!
8 楼 红旗下的流氓 2016-02-25  
好全的博客,上次去京东面试还提到博主了
7 楼 jinnianshilongnian 2013-06-05  
tongyitaiwan 写道
我们每天的时间都放在上班写代码上,搞得头晕转向,哪有时间关注最新技术。

俺也是利用周末+业余时间   都花在这上边了
6 楼 tongyitaiwan 2013-06-05  
我们每天的时间都放在上班写代码上,搞得头晕转向,哪有时间关注最新技术。
5 楼 keer2345 2013-05-24  
jinnianshilongnian 写道
hyl523 写道
对技术的热爱,可敬,榜样。辛苦了,很感谢分享
榜样不敢,只是热爱

紧跟开涛的脚步  
4 楼 jinnianshilongnian 2013-05-24  
hyl523 写道
对技术的热爱,可敬,榜样。辛苦了,很感谢分享
榜样不敢,只是热爱
3 楼 hyl523 2013-05-24  
对技术的热爱,可敬,榜样。辛苦了,很感谢分享
2 楼 jinnianshilongnian 2013-05-24  
osacar 写道
速度好快啊

  昨天晚上翻译了半晚上 希望有用
1 楼 osacar 2013-05-24  
速度好快啊

相关推荐

    spring framework4.0 GA

    2. **WebSocket支持**:Spring 4.0引入了WebSocket支持,提供了WebSocket消息处理和STOMP协议的支持,为实时Web应用程序提供了强大基础。 3. **HTTP/2准备**:虽然HTTP/2标准在Spring 4.0发布后不久才正式推出,但...

    Spring Framework 4.0 Documentation

    在Spring Framework 4.x的新特性中,文档突出了Java 8、Java EE 6和Java EE 7的支持,Groovy Bean定义DSL的引入,以及核心容器、Web层、WebSocket、SockJS和STOMP消息传递的改进。测试模块也得到了增强,为开发人员...

    springframework 4.0版本下载

    3. **WebSocket支持**:Spring 4.0增强了对WebSocket协议的支持,提供了WebSocket消息传递API,允许实时双向通信,为构建现代Web应用提供了强大的后端支持。 4. **Reactor项目集成**:Spring 4.0集成了Reactor,这...

    C#.net4.0框架下实现Websockeet(服务端+客户端)

    在C#.NET 4.0框架下实现WebSocket功能,虽然.NET Framework 4.5及更高版本原生支持WebSocket API,但通过一些技巧和第三方库,我们仍然可以在4.0框架下实现这一功能。 首先,了解WebSocket的基本概念是必要的。...

    Spring-framework4.0

    3. **WebSocket支持**:Spring 4.0提供了对WebSocket协议的支持,通过Spring Websocket模块,开发者可以构建实时双向通信的应用,例如聊天室、股票更新等。 4. **Reactor项目集成**:Spring 4.0集成了Reactor,这是...

    Spring Framework 4.0 Reference

    Spring Framework 4.0 是由 Rod Johnson, Juergen Hoeller, Keith Donald 等人编写的,是一份详尽的参考文档,涵盖了Spring Framework的各个方面。文档主要包含了Spring Framework的各个模块介绍、新版本的新特性和...

    Spring4.0系列9-websocket简单应用

    在Spring 4.0版本中,框架引入了对WebSocket的支持,大大简化了开发实时应用的过程。 在本文中,我们将深入探讨如何在Spring应用程序中集成WebSocket,以及如何创建一个简单的WebSocket应用。首先,我们需要理解...

    spring mvc 4.0

    12. **整合WebSocket**:Spring MVC 4.0开始支持WebSocket协议,允许实现实时通信,如聊天应用、股票实时推送等。 13. **移动设备检测**:Spring MVC 4.0引入了DeviceDelegatingViewResolver,可以根据用户的设备...

    简单实现了websocket功能:websocket客户端、winformsocket客户端

    WebSocket是一种在客户端与服务器之间建立持久连接的协议,它允许双方进行全双工通信,即数据可以在两个方向上同时传输,极大地提高了实时性。在本项目中,"简单实现了websocket功能:websocket客户端、winform...

    在Spring3.3版本中使用4.0中的WebSocket

    在Spring 3.3版本中引入对WebSocket的支持是Spring框架为了适应现代Web应用程序对实时通信需求的增强。WebSocket协议是一种在客户端和服务器之间建立长期连接的协议,它提供了双向通信的能力,即服务器和客户端都...

    增加Microsoft .NET Framework 4.0 及4.5补丁包

    .NET Framework 4.0是2010年发布的一个重大版本,引入了许多新特性,例如并行计算的支持(Task Parallel Library)、异步编程模型(async/await)、动态类型(dynamic)以及WCF和WF的增强等。而.NET Framework 4.5是...

    spring-websocket-5.0.8.RELEASE-API文档-中文版.zip

    标签:springframework、spring、websocket、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明...

    最新springframework-4.0.2开发文档

    - **WebSocket、SockJS和STOMP消息传递**:Spring 4.0增强了对实时通信的支持,包括WebSocket、SockJS和STOMP协议。 - **测试改进**:提供了更多测试工具和API,简化了Spring应用的测试过程。 ### 核心技术:IoC...

    spring4.0框架demo

    2. WebSocket支持:Spring 4.0引入了对WebSocket协议的支持,提供了更高效、实时的通信机制,为Web应用带来了新的交互体验。 3. 改进的类型安全:在Spring 4.0中,依赖注入(DI)更加类型安全,降低了因配置错误...

    spring-websocket-5.0.8.RELEASE-API文档-中英对照版.zip

    标签:springframework、spring、websocket、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和...

    java源码:WebSocket协议的Java实现 WebSocket4J.rar

    4. **扩展支持**:WebSocket协议允许自定义扩展以增强功能,WebSocket4J也提供了扩展点,开发者可以根据需要实现自己的扩展机制。 5. **安全考虑**:WebSocket4J考虑了安全性,支持SSL/TLS加密,确保在不安全的网络...

    spring-framework-4.0.0.RELEASE-dist.zip

    2. **WebSocket支持**:为了满足实时通信的需求,Spring 4.0引入了WebSocket支持,通过Spring WebSocket模块,开发者可以轻松实现双向通信的应用。 3. **反应式编程支持**:Spring 4.0开始接触反应式编程,为未来...

    spring-framework-5.3.23 源码

    此外,Spring还提供了对WebSocket、RESTful API、JSON序列化和反序列化的支持,以满足现代Web应用程序的需求。Spring Boot简化了Spring应用程序的启动和配置,而Spring Cloud则为微服务架构提供了工具和服务发现、...

    Spring4.0 jar包

    2. **AOP(面向切面编程)**:Spring支持面向切面编程,允许开发者通过定义切面来实现代码的解耦,比如日志、事务管理等。在4.0版本中,AOP的性能得到提升,并且与Java 8的lambda表达式有更好的兼容性。 3. **...

Global site tag (gtag.js) - Google Analytics