一步步学WebSocket(1)声明式WebSocket-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

一步步学WebSocket(1)声明式WebSocket

简介:

本节描述声明式WebSocket编程,可以与后一篇编程式WebSocket作对比学习:

首先上服务端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@ServerEndpoint("/chat")
public class DeclarativeServer {
    @OnOpen  
    public void onOpen(Session session) {  
        System.out.println("Somebody is coming!");
     }  
   
    @OnClose  
    public void onClose() {  
    }  
   
    @OnMessage  
    public void onMessage(String message, Session session) throws IOException {
      System.out.println(message); 
      session.getBasicRemote().sendText("it is sickening");
    }  
   
 
    @OnError  
    public void onError(Session session, Throwable error) {  
        error.printStackTrace();  
    }  
}

通过ServerEndpoint注解将一个POJO声明为WebSocket Server端点(Endpoint和web service的概念endpoint类同)。

ServerEndpoint注解声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ServerEndpoint {
 
    /**
     * URI or URI-template that the annotated class should be mapped to.
     * @return The URI or URI-template that the annotated class should be mapped
     *         to.
     */
    String value();
 
    String[] subprotocols() default {};
 
    Class<? extends Decoder>[] decoders() default {};
 
    Class<? extends Encoder>[] encoders() default {};
 
    public Class<? extends ServerEndpointConfig.Configurator> configurator()
            default ServerEndpointConfig.Configurator.class;
}

一般情况下,我们只需要用为ServerEndpoint注解配置value属性,表示该端点映射的URL路径。

subprotocols协议用于配websocket的子协议,比如superchat等,这一阶段我们先不理会它。

decoders,encoders用于定义编解码器,后面的文章我们会详细讨论他。

configurator属性,对于声明式编程的Server端点,可以不配值,会采用默认值ServerEndpointConfig.Configurator即可。

(有默认值,一般说明该属性不可或缺,在编程式WebSocketk中时,我们会看到Configurator的更多细节).


DeclarativeServer实现四个方法,分别带有注解 @OnOpen,@OnClose,@OnMessage , @OnError标示。

@OnOpen表明当有客户端连接到该端点,则回调@OnOpen标记的方法。

@OnClose当客户端断开连接时,即服务端收到连接断开指定,则回调@OnClose的方法。

@OnMessage当服务端接收到清息时,则回调该方法。

@OnError当服务端发现异常情况时,比如协议错误,则回调该方法。Error不代表连接需要关闭,很多错误是可恢复的。


将该类打入war包,部署到Tomcat上,一个WebSocket服务端就OK了。


本次我们不用javascript作为Client端点,而是采用胖客户端模式访问,即Java Application。

首先定义Client端点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@ClientEndpoint
public class DeclarativeClient {
    @OnOpen  
    public void onOpen(Session session) {  
       System.out.println("I was accpeted by her!");
    }  
   
    @OnClose  
    public void onClose() {  
    }  
   
    @OnMessage  
    public void onMessage(String message, Session session) { 
        System.out.println("she say: " + message); 
    }  
   
 
    @OnError  
    public void onError(Session session, Throwable error) {  
        error.printStackTrace();  
    }  
}

通过ClientEndpoint注解表示这是一个WebSocket的Client端点。

1
2
3
4
5
6
7
8
9
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ClientEndpoint {
    String[] subprotocols() default {};
    Class<? extends Decoder>[] decoders() default {};
    Class<? extends Encoder>[] encoders() default {};
    public Class<? extends Configurator> configurator()
            default Configurator.class;
}

与上面的ServerEndpoint只差一个value属性,不用讲大家也知道为什么了。

各个方法注解与Server一样,不再重述。主函数:

1
2
3
4
5
6
7
8
9
public class Client {
    public static void main(String[] args) throws DeploymentException, IOException, InterruptedException {
         WebSocketContainer ws = ContainerProvider.getWebSocketContainer();
         String url = "ws://localhost:8080/ChatWeb/chat";
         Session session =  ws.connectToServer(DeclarativeClient.class, URI.create(url)); 
         session.getBasicRemote().sendText("Hello,chick!");
         Thread.currentThread().sleep(10000);
    }
}

运行Client之前,需要将Tomcat相关包导入,这里你可以全部导入,不再细说,有兴趣可自已研究。


ContainerProvider使有ServiceLoader机制加载ContainerProvider的实现类。并提供WebSocketContainer实例,

在Tomcat上,这个实例为WSWebSocketContainer类。

通过session.getBasicRemote()方法获取RemoteEndpoint.Basic实例来发送消息。

一个简单的WebSocket通信息就完成了。


本文转自 anranran 51CTO博客,原文链接:http://blog.51cto.com/guojuanjun/1963498

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享: