??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人精品www牛牛影视,视频成人永久免费视频,亚洲精品永久免费视频http://www.aygfsteel.com/qbna350816/category/55091.html201103zh-cnSat, 23 Jul 2016 17:39:01 GMTSat, 23 Jul 2016 17:39:01 GMT60JSR 356- WebSocket Java API http://www.aygfsteel.com/qbna350816/archive/2016/07/24/431302.html胡小?/dc:creator>胡小?/author>Sat, 23 Jul 2016 17:35:00 GMThttp://www.aygfsteel.com/qbna350816/archive/2016/07/24/431302.htmlhttp://www.aygfsteel.com/qbna350816/comments/431302.htmlhttp://www.aygfsteel.com/qbna350816/archive/2016/07/24/431302.html#Feedback0http://www.aygfsteel.com/qbna350816/comments/commentRss/431302.htmlhttp://www.aygfsteel.com/qbna350816/services/trackbacks/431302.html原文Q?a style="cursor: pointer;">http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html

学习如何在你的应用程序中集成WebSockets.

Published April 2013

对于许多Z客户端-服务器程序来_老的HTTP h-响应模型已经有它的局限? 信息必须通过多次h才能其从服务端传送到客户?

q去许多的黑客用某些技术来l过q个问题Q例如:长轮?long polling)?span style="color: #333333;">Z HTTP 长连接的服务器推技?Comet)

然而,Z标准的、双向的、客L和服务器之间全双工的信道需求再不断增加?/div>

?011q? IETF发布了标准WebSocket协议QRFC 6455. 从那时vQ大多数Web览器都实现了支持WebSocket协议的客LAPIs.同时Q许多Java 包也开始实CWebSocket协议.

WebSocket协议利用HTTP升技术来HTTPq接升到WebSocket. 一旦升U后Q连接就有了在两个方向上怺独立(全双?发送消?数据?的能? 

不需要headers 或cookies,q大大降低了所需的带?/span>通常QWebSockets来周期性地发送小消息 (例如Q几个字?. 

额外?span style="font-family: 'Microsoft Yahei';">headers常常会开销大于有效负蝲Q?span style="font-family: 'Microsoft Yahei';">payloadQ?/div>

JSR 356

JSR 356, WebSocket的Java API, 明确规定了APIQ当Java开发者需要在应用E序中集成WebSocketӞ可以用此API—服务端和客户端均? 每个声明兼容JSR 356的WebSocket协议Q都必须实现q个API. 

因此Q开发h员可以自q写独立于底层WebSocket实现的WebSocket应用?/span>q是一个巨大的好处Q因为它可以防止供应商锁定,q允许更多的选择、自q库、应用程序服务器?/span>

JSR 356是即到来的java EE 7标准的一部分Q因此,所有与Java EE 7兼容的应用服务器都有JSR 365标准WebSocket的实?一旦徏立,WebSocket客户端和服务器节点已l是对称的了。客LAPI与服务器端API的区别是很小的,JSR 356定义的Java client API只是Java EE7完整API的子?

客户D-服务器端E序使用WebSocketsQ通常会包含一个服务器lg和多个客Llg, 如图Q所C?

Figure 1

?

在这个例子中Qserver application 是通过Java~写?WebSocket 协议l节是由包含在Java EE 7容器中JSR 356 实现来处理的.

JavaFX 客户端可依赖M与JSR 356兼容的客L实现来处理WebSocket协议问题. 

其它客户??iOS 客户端和HTML5客户?可用其?(非Java)与RFC6455兼容的实现来与server application通信.

~程模型

JSR 356定义的专家小l?希望支持Java EE开发h员常用的模式和技术?/span>因此,JSR 356使用了注释和注入?/span>

一般来_支持两种~程模型:

  • 注解驱动(annotation-driven). 通过使用注解POJOs, 开发者可与WebSocket生命周期事g交互.
  • 接口驱动(interface-driven). 开发者可实现Endpoint接口和与生命周期交互的方?

生命周期事g

典型的WebSocket 交互生命周期如下:

  • 一?(客户? 通过发送HTTP握手h来初始化q接.
  • 其它?服务? 回复握手响应.
  • 建立q接.从现在开始,q接是完全对U的.
  • 两端都可发送和接收消息.
  • 其中一端关闭连?

大部分WebSocket生命周期事g都与JavaҎ对应Q不是 annotation-driven q是interface-driven.

Annotation-Driven 方式

接受WebSocketh的端点可以是?nbsp;@ServerEndpoint 注解的POJO. 

此注解告知容器,此类应该被认为是WebSocket端点. 

必须?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">value 元素指定了WebSocket端点的\?

考虑下面的代码片?

@ServerEndpoint("/hello")  public class MyEndpoint { } 

此代码将会以相对路径hello来发布一个端?在后l方法调用中Q此路径可携带\径参敎ͼ如: /hello/{userid}是一个有效\径,在这?/code>{userid} 的|可在生命周期Ҏ使用@PathParam 注解获取.

在GlassFish中,如果你的应用E序是用上下?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">mycontextroot 部v的,且在localhost?span style="color: #000000; font-family: 'Microsoft Yahei';">8080端口上监?/span>, WebSocket可通过使用ws://localhost:8080/mycontextroot/hello来访?/code>.

初始化WebSocketq接的端点可以是?nbsp;@ClientEndpoint 注解的POJO.@ClientEndpoint ?@ServerEndpoint的主要区别是ClientEndpoint 不接受\径\值元素,因ؓ它监听进来的h?/p>

@ClientEndpoint  public class MyClientEndpoint {} 

Java中用注解驱动POJO方式来初始化WebSocketq接Q可通过如下代码来完?

javax.websocket.WebSocketContainer container = javax.websocket.ContainerProvider.getWebSocketContainer();  container.conntectToServer(MyClientEndpoint.class, new URI("ws://localhost:8080/tictactoeserver/endpoint")); 

此后Q以 @ServerEndpoint ?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">@ClientEndpoint 注解的类都称为注解端?

一旦徏立了WebSocketq接 Q就会创?nbsp;SessionQƈ且会调用注解端点中以@OnOpen注解的方? 

此方法包含了几个参数:

  • javax.websocket.Session 参数, 代表创徏?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">Session
  • EndpointConfig 实例包含了关于端炚w|的信息
  • Q个或多个以 @PathParam注解?/code>字符串参?指的是端点\径的path参数

下面的方法实C当打开WebSocketӞ会打印session的标识符:

@OnOpen public void myOnOpen (Session session) {    System.out.println ("WebSocket opened: "+session.getId()); } 

Session实例只要WebSocket未关闭就会一直有?/code>. SessioncM包含了许多有意思的ҎQ以允许开发者获取更多关于的信息?/p>

同时,Session 也包含了应用E序Ҏ的数据钩?即通过getUserProperties() Ҏ来返?nbsp;Map<String, Object>

q允许开发者可以用session-和需要在多个Ҏ调用间共享的应用E序特定信息来填?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">Session实例.

i当WebSocket端收到消息时Q将会调用以@OnMessage注解的方??code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">@OnMessage 注解的方法可包含下面的参?

  • javax.websocket.Session 参数.
  • Q个或多个以 @PathParam注解?/code>字符串参?指的是端点\径的path参数
  • 消息本n. 下面有可能消息类型描q?

当其它端发送了文本消息Ӟ下面的代码片断会打印消息内容:

@OnMessage public void myOnMessage (String txt) {    System.out.println ("WebSocket received message: "+txt); }  

如果?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">@OnMessage i注解的方法返回g?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">void, WebSocket实现会将q回值发送给其它端点.下面的代码片断会收到的文本消息以首字母大写的Ş式发回给发送?

@OnMessage public String myOnMessage (String txt) {    return txt.toUpperCase(); }  

另一U通过WebSocketq接来发送消息的代码如下:

RemoteEndpoint.Basic other = session.getBasicRemote(); other.sendText ("Hello, world"); 

在这U方式中Q我们从Session 对象开始,它可以从生命周期回调Ҏ中获?例如,?nbsp;@OnOpen注解的方?/code>).session实例?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">getBasicRemote() Ҏq回的是WebSocket其它部分的代?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">RemoteEndpoint. RemoteEndpoint 实例可用于发送文本或其它cd的消息,后面有描q?

当关闭WebSocketq接?会调用@OnClose 注解的方法。此Ҏ接受下面的参?

  • javax.websocket.Session 参数. 注意Q一旦WebSocket真正关闭了,此参数就不能被用了Q这通常发生?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">@OnClose 注解Ҏq回之后.
  • javax.websocket.CloseReason 参数Q用于描q关闭WebSocket的原?如:正常关闭Q协议错?服务q蝲{等.
  • Q个或多个以 @PathParam注解?/code>字符串参?指的是端点\径的path参数

下面的代码片D|CWebSocket关闭的原?

@OnClose public void myOnClose (CloseReason reason) {    System.out.prinlnt ("Closing a WebSocket due to "+reason.getReasonPhrase()); } 

完整情况下,q里q有一个生命周期注?如果收到了错误,会调用 @OnError 注解的方法?/p>

Interface-Driven 方式

annotation-driven 方式允许我们注解一个Javac,以及使用生命周期注解来注解方? 

使用interface-driven方式,开发者可l承javax.websocket.Endpoint q覆盖其中的onOpenonClose, 以及onError Ҏ:

public class myOwnEndpoint extends javax.websocket.Endpoint {    public void onOpen(Session session, EndpointConfig config) {...}    public void onClose(Session session, CloseReason closeReason) {...}    public void onError (Session session, Throwable throwable) {...} } 

Z拦截消息Q需要在onOpen实现中注册一?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">javax.websocket.MessageHandler:

public void onOpen (Session session, EndpointConfig config) {    session.addMessageHandler (new MessageHandler() {...}); } 

MessageHandler 接口有两个子接口: MessageHandler.Partial?/code> MessageHandler.Whole

MessageHandler.Partial 接口应该用于当开发者想要收到部分消息通知的时?MessageHandler.Whole的实现应该用于整个消息到N知?/p>

下面的代码片断会监听q来的文件消息,q将文本信息转换为大版本后发回l其它端点:

public void onOpen (Session session, EndpointConfig config) {    final RemoteEndpoint.Basic remote = session.getBasicRemote();    session.addMessageHandler (new MessageHandler.Whole<String>() {       public void onMessage(String text) {                  try {                      remote.sendString(text.toUpperCase());                  } catch (IOException ioe) {                      // handle send failure here                  }              }     }); } 

消息cdQ编码器Q解码器

WebSocket的JavaAPI非常强大Q因为它允许发送Q或接收Q何对象作为WebSocket消息.

基本上,有三U不同类型的消息:

  • Z文本的消?/li>
  • 二进制消?/li>
  • Pong 消息,它是WebSocketq接自n

当用interface-driven模式,每个session最多只能ؓq三个不同类型的消息注册一?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">MessageHandler.

当用annotation-driven模式,针对不同cd的消息,只允许出C?code style="font-family: Monaco, Consolas, Courier, 'Lucida Console', monospace; color: #666666; background-color: inherit;">@onMessage 注解Ҏ. 在注解方法中Q消息内容中允许的参C赖于消息cd?/p>

Javadoc for the @OnMessage annotation 明确指定了消息类型上允许出现的消息参?

  • "如果Ҏ用于处理文本消息: 

    • String 用于接收整个消息
    • Java 原型或等Lcȝ于接收整个消息ƈ其转换为此cd
    • String ?boolean 对用于部分接收消?/li>
    • Reader 用于以阻塞流的方式接收整个消?/li>
    • 端点的Q何对象参数存在文本解码器 (Decoder.Text ?nbsp;Decoder.TextStream).
  • 如果Ҏ用于处理二进制消? 

  • 如果Ҏ是用于处理pong消息: 

MJava对象使用~码器都可以~码为基于文本或二进制的消息.q种Z文本或二q制的消息将转输到其它端点,在其它端点,它可以解码成Java对象Q或者被另外的WebSocket 包解? 

通常情况下,XML或JSON用于来传送WebSocket消息, ~码/解码然后会将Java对象~组成XML或JSONq在另一端解码ؓJava对象.

encoder是以javax.websocket.Encoder 接口的实现来定义,decoder是以javax.websocket.Decoder 接口的实现来定义? 

有时Q端点实例必ȝ道encoders和decoders是什?使用annotation-driven方式, 可向@ClientEndpoint ?nbsp;@ServerEndpoint l注解中的encode和decoder元素传?encoders和decoders的列表?/p>

Listing 1 中的代码展示了如何注册一?nbsp;MessageEncoder c?它定义了MyJavaObject实例到文本消息的转换). MessageDecoder 是以相反的{换来注册?

@ServerEndpoint(value="/endpoint", encoders = MessageEncoder.class, decoders= MessageDecoder.class) public class MyEndpoint { ... }  class MessageEncoder implements Encoder.Text<MyJavaObject> {    @override    public String encode(MyJavaObject obj) throws EncodingException {       ...    } }  class MessageDecoder implements Decoder.Text<MyJavaObject> {    @override     public MyJavaObject decode (String src) throws DecodeException {       ...    }     @override     public boolean willDecode (String src) {       // return true if we want to decode this String into a MyJavaObject instance    } } 

Listing 1

Encoder 接口有多个子接口:

  • Encoder.Text 用于Java对象转成文本消息
  • Encoder.TextStream 用于Java对象d到字W流?/li>
  • Encoder.Binary 用于Java对象转换成二q制消息
  • Encoder.BinaryStream 用于Java对象dCq制中

cM?Decoder 接口有四个子接口:

  • Decoder.Text 用于文本消息{换成Java对象
  • Decoder.TextStream 用于从字W流中读取Java对象
  • Decoder.Binary 用于二q制消息转换成Java对象
  • Decoder.BinaryStream 用于从二q制中dJava对象

l论

WebSocket Java API为Java开发者提供了标准API来集成IETF WebSocket标准.通过q样做,Web 客户端或本地客户端可使用MWebSocket实现来轻易地与Java后端通信?/p>

Java Api是高度可配置的,灉|的,它允许java开发者用他们喜Ƣ的模式?/div>

也可参?/span>



]]> վ֩ģ壺 | | | Դ| ƶ| ϰ| | ɽ| Ƽ| | | | ͤ| | ɽ| | | Ϫ| | ֦| | | | ͷ| | ں| »| | | | Ϫ| | «ɽ| | ׿| | | ƺ| | ƽ| |