大家可以从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...
}
}