WebSokcet之ServerEndPoint

来源:互联网 发布:python ide推荐 编辑:程序博客网 时间:2024/06/13 10:59

WebSocket是JavaEE7新支持的:

 

The javax.websocket.server package contains annotations, classes,and interfaces to create and configure server endpoints.

    Javax.websocket.server包含注解,类,接口用于创建和配置服务端点

The javax.websocket package contains annotations, classes,interfaces, and exceptions that are common to client and serverendpoints.

    Javax.websocket包则包含服务端点和客户断电公用的注解,类,接口,异常

 

To create a programmatic endpoint, you extend the Endpoint classand override its lifecycle methods.

创建一个编程式的端点,需要继承Endpoint类,重写它的方法。

To create an annotated endpoint, you decorate a Java class and someof its methods with the annotations provided by the packagesmentioned previously.

创建一个注解式的端点,将自己的写的类以及类中的一些方法用前面提到的包中的注解装饰(@EndPoint,@OnOpen等等)。

 

编程式注解示例:

 

@ServerEndpoint("/WebSocketServer")

public class ServerEndPoint808

{

 

@OnOpen

public void start(Sessionsession)

{

System.out.println("连接成功 " +session.getId());

}

 

@OnMessage

public void reMessage(Session session, Stringstr)

{

try

{

session.getBasicRemote().sendText(str+ " who areyou");

}

catch (IOExceptione)

{

e.printStackTrace();

}

}

 

@OnError

public void error(Session session, Throwablet)

{

t.printStackTrace();

 

}

 

@OnClose

public void close()

{

 

}

 

After you have created an endpoint,you deploy it to an specific URI in the application so that remoteclients can connect to it.

当创建好一个(服务)端点之后,将它以一个指定的URI发布到应用当中,这样远程客户端就能连接上它了。

 

WebSocket endpoints are representedby URIs that have the following form:

Websocket(服务)端点以URI表述,有如下的访问方式:

ws://host:port/path?query

wss://host:port/path?query

 

注解详解:

@ServerEndPoint:

    RequiredElements :

        Value: URI映射

    OptionalElemens:

        subprotocols:

        decoders:解码器

        encoders:编码器

        configurator:

Annotation

Event

Example

OnOpen

Connection opened

@OnOpen

Public void open(Sessionsession,

EndpointConfig conf) { }

OnMessage

Message received

@OnMessage

public void message(Sessionsession,

String msg) { }

OnError

Connection error

@OnError

public void error(Sessionsession,

Throwable error) { }

OnClose

Connection closed

@OnClose

public void close(Sessionsession,

CloseReason reason) { }

 

建立连接相关:

The Session parameter represents aconversation between this endpoint and the remoteendpoint.

Session代表着服务端点与远程客户端点的一次会话。

 

Because the container creates aninstance of the endpoint class for every connection, you can defineand use instance variables to store client stateinformation.

容器会为每一个连接创建一个EndPoint的实例,需要利用实例变量来保存一些状态信息。

 

the Session.getUserProperties methodprovides a modifiable map to store user

Session.getUserProperties提供了一个可编辑的map来保存properties,

properties. For example, thefollowing endpoint replies to incoming text messages

例如,下面的端点在收到文本消息时,将前一次收到的消息回复给其他的端点

with the contents of the previousmessage from each client:

 

@ServerEndpoint("/delayedecho")

public class DelayedEchoEndpoint

{

@OnOpen

public void open(Sessionsession)

{

session.getUserProperties().put("previousMsg""");

}

 

@OnMessage

public void message(Session session, Stringmsg)

{

 

String prev= (String) session.getUserProperties().get("previousMsg");

 

session.getUserProperties().put("previousMsg",msg);

try {

session.getBasicRemote().sendText(prev);

 

    catch (IOException e){ ... }

}

}

To store information common to allconnected clients, you can use class (static) variables; however,you are responsible for ensuring thread-safe access tothem

 

发送、接收消息:

WebSocket endpoints can send andreceive text and binary messages. In addition, they can also sendping frames and receive pong frames.

Websocketendpoint能够发送和接收文本、二进制消息,另外,也可以发送ping帧和接收pong 帧

发送消息:

  1. Obtain the Session object from theconnection.

    从连接中获得Session对象

    The Session object is available as aparameter in the annotated lifecycle methods of the endpoint, likethose in Table 18–1.

        Session对象是endPoint中那些被注解标注的方法中可得到的参数

When your message is a response to amessage from the peer,

当你的message作为另外的消息的响应

you have the Session objectavailable inside the method that received the message (the methodannotated with @OnMessage).

在@OnMessage标注的方法中,有session对象接收message

If you have to send messages thatare not responses, store the Session object as an instance variableof the endpoint class in the method annotated with@OnOpen

如果你必须主动发送message,需要在标注了@OnOpen的方法中将session对象作为实例变量保存

so that you can access it from othermethods.

这样,你可以再其他方法中得到该session对象

 

  1. Use the Session object to obtain aRemote Endpoint object.

    通过Session对象获得Remoteendpoint对象

    The Session.getBasicRemotemethod andthe Session.getAsyncRemotemethod

    return RemoteEndpoint.BasicandRemoteEndpoint.Asyncobjects respectively.

    The RemoteEndpoint.Basicinterfaceprovides blocking methods to send

    messages; theRemoteEndpoint.Asyncinterface provides nonblockingmethods.

  2. Use the RemoteEndpoint object to sendmessages to the peer.

    利用RemoteEndpoint对象来发送message

    The following list shows some of themethods you can use to send messages to the

    peer.

    ■ voidRemoteEndpoint.Basic.sendText(String text)

    Send a text message to the peer.This method blocks until the whole message

    has been transmitted.

    ■ voidRemoteEndpoint.Basic.sendBinary(ByteBuffer data)

    Send a binary message to the peer.This method blocks until the whole

    message has beentransmitted.

    ■ voidRemoteEndpoint.sendPing(ByteBuffer appData)

    Send a ping frame to thepeer.

    ■ voidRemoteEndpoint.sendPong(ByteBuffer appData)

    Send a pong frame to thepeer.

代码示例:

@ServerEndpoint("/echoall")

public class EchoAllEndpoint

{

@OnMessage

public void onMessage(Session session, Stringmsg)

{

try {

for (Session sess :session.getOpenSessions())

{

if (sess.isOpen())

sess.getBasicRemote().sendText(msg);

}

catch (IOExceptione) { ... }

}

}

接收消息:

TheOnMessage annotation designates methods that handle incomingmessages.

OnMessage注解指定方法来处理接收的messages

You canhave at most three methods annotated with @OnMessage in anendpoint,

在一个端点类中,至多可以为三个方法标注@OnMessage注解

one foreach message type: text, binary, and pong.

消息类型分别为:textbinarypong

 

Encoders and Decoders(编码器和解码器):

The Java API for WebSocket providessupport for converting between WebSocket messages and custom Javatypes using encoders and decoders.

WebSocket Api 提供了encoders 和decoders用于 Websocket Messages 与传统java 类型之间的转换

An encoder takes a Java object andproduces a representation that can be transmitted as a WebSocketmessage;

编码器输入java对象,生成一种表现形式,能够被转换成Websocketmessage

for example, encoders typicallyproduce JSON, XML, or binary representations.

例如:编码器通常生成json、XML、二进制三种表现形式

A decoder performs the reversefunction; it reads a WebSocket message and creates a Javaobject.

解码器执行相反的方法,它读入Websocket消息,然后输出java对象

编码器编码:

  1. Implement one of the followinginterfaces:

    Encoder.Textfor textmessages

    Encoder.Binaryfor binarymessages

    These interfaces specify the encodemethod. Implement an encoder class for each custom Java type thatyou want to send as a WebSocket message.

    这些接口指定编码方法,为你想作为WebsocketMessage传递的java 类型实现编码类

  2. Add the names of your encoderimplementations to the encoders optional parameter of theServerEndpoint annotation.

     

    将实现的编码器类的names添加到@ServerEndPoint注解中

     

  3. Use the sendObject(Object data) methodof the RemoteEndpoint.Basic or RemoteEndpoint.Async interfaces tosend your objects as messages. The container

looks for an encoder thatmatches your type and uses it to convert the object to a WebSocketmessage.

利用RemoteEndpoint.Basic或者RemoteEndpoint.Async的sendObject(Objectdata)方法将对象作为消息发送,容器寻找一个符合此对象的编码器,

利用此编码器将此对象转换成Websocketmessage

代码示例:

public class MessageATextEncoder implements Encoder.Text

{

@Override

public void init(EndpointConfig ec) {}

@Override

public void destroy() {}

@Override

public String encode(MessageAmsgA) throws EncodeException

{

// Access msgA's properties and convert to JSONtext...

return msgAJsonString;

}

}

Then, add theencodersparameter to the ServerEndpointannotation asfollows:

@ServerEndpoint(

value= "/myendpoint",

encoders ={ MessageATextEncoder.class, MessageBTextEncoder.class }

)

解码器解码:

  1. Implement one of the followinginterfaces:

     

    Decoder.Textfor textmessages

Decoder.Binaryfor binarymessages

These interfaces specify thewillDecode and decode methods.

  1. Add the names of your decoderimplementations to the decoders optional parameter of theServerEndpoint annotation.

     

  2. Use the OnMessage annotation in theendpoint to designate a method that takes your custom Java type asa parameter.

     

    When the endpoint receives amessage that can be decoded by one of the decoders youspecified,

the container calls themethod annotated with @OnMessage that takes your custom Java typeas a parameter if this method exists.

public class MessageTextDecoder implements Decoder.Text

{

@Override

public void init(EndpointConfigec)

{

}

 

@Override

public void destroy()

{

}

 

@Override

public Message decode(Stringstring) throws DecodeException

{

// Read message...

if  )

return new MessageA(...);

else if  )

return new MessageB(...);

}

 

@Override

public boolean willDecode(Stringstring)

{

// Determine if the message can be converted into eithera

// MessageA object or a MessageB object...

return canDecode;

}

}

 

Then, add thedecoderparameter to the ServerEndpointannotation asfollows:

 

@ServerEndpoint(

value= "/myendpoint",

encoders ={ MessageATextEncoder.class, MessageBTextEncoder.class },

decoders ={ MessageTextDecoder.class }

)

 

处理错误:

Todesignate a method that handles errors in an annotated WebSocketendpoint, decorate it with @OnError:

 

为一个注解式的端点指定一个处理error的方法,为此方法加上@OnError注解:

 

@ServerEndpoint("/testendpoint")

public class TestEndpoint{

...

@OnError

public void error(Session session, Throwablet)

{

t.printStackTrace();

...

}

}

 

This methodis invoked when there are connection problems, runtime errors frommessage handlers, or conversion errors when decodingmessages.

 

当出现连接错误,运行时错误或者解码时转换错误,该方法才会被调用

 

指定端点配置类:

The JavaAPI for WebSocket enables you to configure how the containercreates server endpoint instances.

 

Websocketapi允许配置容器合适创建serverendpoint 实例

 

You canprovide custom endpoint configuration logic to:

 

Access thedetails of the initial HTTP request for a WebSocketconnection

Performcustom checks on the OriginHTTP header

Modify theWebSocket handshake response

Choose aWebSocket subprotocol from those requested by the client

Control theinstantiation and initialization of endpoint instances

 

To providecustom endpoint configuration logic, you extend theServerEndpointConfig.Configurator class and override some of itsmethods.

继承ServerEndpointConfig.Configurator 类并重写一些方法,来完成customendpoint configuration 的逻辑代码

In theendpoint class, you specify the configurator class using theconfigurator parameter of the ServerEndpoint annotation.

 

代码示例:

public class CustomConfigurator extends ServerEndpointConfig.Configurator

{

@Override

public void modifyHandshake(ServerEndpointConfigconf,

HandshakeRequest req, HandshakeResponseresp)

{

conf.getUserProperties().put("handshakereq",req);

}

}

 

Thefollowing endpoint class configuresendpoint instances with thecustom configurator, which enables them to access the handshakerequest object:

 

@ServerEndpoint(

value ="/myendpoint",

configurator= CustomConfigurator.class

)

 

public class MyEndpoint

{

@OnOpen

public void open(Session s, EndpointConfigconf)

{

HandshakeRequest req= (HandshakeRequest)conf.getUserProperties()

.get("handshakereq");

Map> headers =req.getHeaders();

...

}

}