Java API实现WebSocket客户端

来源:互联网 发布:php程序员自我评价 编辑:程序博客网 时间:2024/06/05 07:11
上一篇是说浏览器与服务器建立WebSocket通信,而这篇来通过WebSocket-api提供的接口来实现客户端的功能。

客户端主要也是通过注解的方式来实现,但是创建的方式会用到其他类,注解为@ClientEndpoint,其他注解一样,WebSocketClient.java具体代码如下:

@ClientEndpointpublic class WebSocketClient {    private Logger logger = Logger.getLogger(WebSocketServer.class);    private Session session;    @OnOpen    public void open(Session session){        logger.info("Client WebSocket is opening...");        this.session = session;    }    @OnMessage    public void onMessage(String message){        logger.info("Server send message: " + message);    }    @OnClose    public void onClose(){        logger.info("Websocket closed");    }    @OnError    public void onError(Session session, Throwable t) {        t.printStackTrace();    }    public void send(String message){        this.session.getAsyncRemote().sendText(message);    }    public void close() throws IOException{        if(this.session.isOpen()){            this.session.close();        }    }}

另外添加两个方法sendclose,可以主动发送消息和关闭连接。只要可以获取到建立连接的session,就可以进行相关的操作,如消息发送、状态判断等等。
以上为客户端的简单实现,接下来,来看看@ClientEndpoint注解的代码:

@Retention(RetentionPolicy.RUNTIME)@Target({java.lang.annotation.ElementType.TYPE})public @interface ClientEndpoint{  String[] subprotocols() default {};  Class<? extends Decoder>[] decoders() default {};  Class<? extends Encoder>[] encoders() default {};  Class<? extends ClientEndpointConfig.Configurator> configurator() default ClientEndpointConfig.Configurator.class;}

可以看见,有四个配置参数,接下来分别对这些配置进行实现:

subprotocols: 为字符串数组,表示支持的子协议名称列表

无特别

Decoder的实现:

public class SampleDecoder implements Decoder.Text<String>{    public void init(EndpointConfig paramEndpointConfig) {        // Auto-generated method stub    }    public void destroy() {        // Auto-generated method stub    }    public String decode(String paramString) throws DecodeException {        // Auto-generated method stub        return paramString.toLowerCase();    }    public boolean willDecode(String paramString) {        // Auto-generated method stub        return true;    }}

Encoder实现

public class SimpleEncoder implements javax.websocket.Encoder.Text<String> {    public void init(EndpointConfig paramEndpointConfig) {        //Auto-generated method stub        System.out.println("Encoder init: " + paramEndpointConfig.getUserProperties());    }    public void destroy() {        //Auto-generated method stub    }    public String encode(String paramT) throws EncodeException {        //Auto-generated method stub        return paramT.toUpperCase();    }}

encode方法是接收到数据进行解码操作,如对字符串解码,对json格式转换为对象等等;

Configurator实现

public class SampleConfigurator extends Configurator {    @Override    public void beforeRequest(Map<String, List<String>> headers) {        //Auto-generated method stub        System.out.println(headers);    }    @Override    public void afterResponse(HandshakeResponse handshakeResponse) {        //Auto-generated method stub        System.out.println(handshakeResponse);    }}

可以通过打印来查看这些参数是什么,我们通过函数名称就可以知道,beforeRequest是在请求之前调用,可以对请求头进行修改或者查看;afterResponse是在握手成功后调用的,handshakeResponse为握手响应头;

而现在的客户端配置如下:

@ClientEndpoint(        configurator=SampleConfigurator.class,        decoders={SampleDecoder.class},        encoders={SimpleEncoder.class},        subprotocols={"subprotocol1"})public class WebSocketClient {    private Logger logger = Logger.getLogger(WebSocketServer.class);    private Session session;    ......}

添加主程序AppMain.java:

public class AppMain {    public static void main(String[] args)             throws DeploymentException, IOException, URISyntaxException, InterruptedException {        // Auto-generated method stub        WebSocketContainer conmtainer = ContainerProvider.getWebSocketContainer();        WebSocketClient client = new WebSocketClient();        conmtainer.connectToServer(client,                 new URI("ws://localhost:8080/websocket/chat?query=Picasso"));        int turn = 0;        while(turn++ < 10){            client.send("send text: " + turn);            Thread.sleep(1000);        }        client.close();    }}

先启动服务器,之后启动客户端的应用程序,查看控制台

服务端控制台:

2015-12-21 23:28:10,673  INFO (cc.eabour.websocket.filter.DispatcherFilter:30) - Request URL: http://localhost:8080/websocket/chat2015-12-21 23:28:10,684  INFO (cc.eabour.websocket.WebSocketServer:23) - WebSocket is opening...2015-12-21 23:28:10,685  INFO (cc.eabour.websocket.WebSocketServer:25) - Sesson id: 1a2015-12-21 23:28:10,685  INFO (cc.eabour.websocket.WebSocketServer:26) - Query string: query=Picasso2015-12-21 23:28:10,731  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: B2015-12-21 23:28:11,734  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: C2015-12-21 23:28:12,739  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: D2015-12-21 23:28:13,743  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: E2015-12-21 23:28:14,746  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: F2015-12-21 23:28:15,751  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: G2015-12-21 23:28:16,753  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: H2015-12-21 23:28:17,756  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: I2015-12-21 23:28:18,758  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: J2015-12-21 23:28:19,761  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: K2015-12-21 23:28:20,764  INFO (cc.eabour.websocket.WebSocketServer:42) - Websocket closed

客户端控制台:

{Sec-WebSocket-Version=[13], Upgrade=[websocket], Host=[localhost:8080], Sec-WebSocket-Key=[Wwy8SvU9vSmJClaLPw+z1w==], Connection=[upgrade]}org.apache.tomcat.websocket.WsHandshakeResponse@dd550cEncoder init: {}2015-12-21 23:28:10,700  INFO (cc.eabour.websocket.WebSocketServer:31) - Client WebSocket is opening...2015-12-21 23:28:10,731  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:11,735  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:12,740  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:13,744  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:14,748  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:15,752  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:16,754  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:17,757  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:18,759  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:19,762  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server

仔细一看,在注解中配置的Encoder和Decoder没有起作用,分别在encode和decode方法中添加打印语句,都没有生效:

    public String decode(String paramString) throws DecodeException {        // Auto-generated method stub        return "MESS:" + paramString.toLowerCase();    }    .....    public String encode(String paramT) throws EncodeException {        //Auto-generated method stub        System.out.println("encode: " + paramT);        return "mess:" + paramT.toUpperCase();    }

最后通过查看encode和decode方法的调用堆栈,而得知调用这些方法的方法为sendObject,这时才恍然大悟,当客户端发送的为Object类型的时候,才会去调用Encoder和Decoder,所以修改方法:

//WebSocketClient.java    public void send(Object message){        this.session.getAsyncRemote().sendObject(message);    }

到此,大功告成:

--服务器2015-12-21 23:37:47,637  INFO (cc.eabour.websocket.WebSocketServer:23) - WebSocket is opening...2015-12-21 23:37:47,638  INFO (cc.eabour.websocket.WebSocketServer:25) - Sesson id: 1b2015-12-21 23:37:47,638  INFO (cc.eabour.websocket.WebSocketServer:26) - Query string: query=Picasso2015-12-21 23:37:47,670  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: B2015-12-21 23:37:48,671  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: C2015-12-21 23:37:49,673  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: D2015-12-21 23:37:50,683  INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: E......--客户端{Sec-WebSocket-Version=[13], Upgrade=[websocket], Host=[localhost:8080], Sec-WebSocket-Key=[NGvTXYipeBUGuMn9SpwZWg==], Connection=[upgrade]}org.apache.tomcat.websocket.WsHandshakeResponse@1d28d39Encoder init: {}2015-12-21 23:37:47,639  INFO (cc.eabour.websocket.WebSocketServer:31) - Client WebSocket is opening...encode: send text: B2015-12-21 23:37:47,670  INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket serverencode: send text: C......

Java API WebSocket客户端基本实现,可以参照,实现更复杂的功能。

不吝赐教

项目Github地址:https://github.com/FlowerBirds/WebSocketExplorer

参考资料:

  • https://tools.ietf.org/html/rfc6455#section-11.5
  • https://tyrus.java.net/documentation/1.12/index/websocket-api.html
0 0
原创粉丝点击