讲一下websocketbot例子

大家可以从JDK7还是JDK8那里下载到这个源代码。

首先是CDI的bean, BotBean,这个class就是一个用来respond聊天的,根据收到的信息经过一系列处理然后返回一个值。

@Named
public class BotBean {
    public String respond(String msg) { ... }
}

第二个是 WebSocket endpoint (BotEndpoint) is an annotated endpoint,可以执行下列功能:

1. 从客户端接受信息

2.给客户端转发信息

3.管理所有连接的客户端

4.调用一些bot的方法

注意这个endpoint的开头, 在定义endpoint的同时,也定义了decoder和encoder

/* Websocket endpoint */
@ServerEndpoint(
        value = "/websocketbot",
        decoders = { MessageDecoder.class }, 
        encoders = { JoinMessageEncoder.class, ChatMessageEncoder.class, 
                     InfoMessageEncoder.class, UsersMessageEncoder.class }
        )

这个Encoder和decoder的用法就是,如果你想用text来发送不同的 Message,你可以在encoder里面来处理这个message然后才发送,decoder里面处理后才使用,一个message需要一个自定义的encoder和decoder。

比如,这个就是写给JoinMessage的一个encoder

public class JoinMessageEncoder implements Encoder.Text {
    @Override
    public void init(EndpointConfig ec) { }
    
    @Override
    public void destroy() { }
    
    @Override
    public String encode(JoinMessage joinMessage) throws EncodeException {
        StringWriter swriter = new StringWriter();
        try (JsonGenerator jsonGen = Json.createGenerator(swriter)) {
            jsonGen.writeStartObject()
                .write("type", "join")
                .write("name", joinMessage.getName())
            .writeEnd();
        }
        return swriter.toString();
    }
}

再回到endpoint

判断这个message是ChatMessage还是JoinMessage,做一些业务处理。然后发送出去。

注意这个

Asynchronous Processing and Concurrency Considerations

在endpoint里面有这一行

String resp = botstockbean.respond(cmsg.getMessage());

如果这个respond很久没有反应,这个程序是阻塞后面的,这个时候需要用一个ManagedExecutorService.submit

                /* The bot replies to the message */
                mes.submit(new Runnable() {
                    public void run() {
                        String resp = botstockbean.respond(cmsg.getMessage());
                        sendAll(session, new ChatMessage("Duke", cmsg.getName(), resp));
                    }
                });

正常情况下,一个JEE component只会初始化一个endpoint,如果我们用上面这个方法,就需要里面是线程安全。

respond()是线程安全,sendAll也是

 public synchronized void sendAll(Session session, Object msg) {)

当调用

session.getBasicRemote.sendObject(msgA);

的时候,message会自动被encoder处理后才发出去。

同理,decoder会在收到信息之后自动处理

@OnMessage
public void message(Session session, Message msg) {
   if (msg instanceof MessageA) {
      // We received a MessageA object...
   } else if (msg instanceof MessageB) {
      // We received a MessageB object...
   }
}

 

 

你可能感兴趣的:(Java杂谈)