博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一步步学WebSocket(2)编程式WebSocket
阅读量:5960 次
发布时间:2019-06-19

本文共 5095 字,大约阅读时间需要 16 分钟。

接,这篇我们采用编程式WebSocket实现上篇的例子:

服务端Endpoint,不再使用ServerEndpoint注解:

public class ProgramerServer extends Endpoint {    @Override    public void onOpen(Session session, EndpointConfig edc) {        System.out.println("Somebody is coming!");                session.addMessageHandler(new MessageHandler.Whole
() {            @Override            public void onMessage(String message) {                System.out.println(message);                 try {                    session.getBasicRemote().sendText("it is sickening");                } catch (IOException e) {                    e.printStackTrace();                }            }        });    }   @Override   public void onClose(Session session, CloseReason closeReason) {        // NO-OP by default    }   @Override    public void onError(Session session, Throwable throwable) {        // NO-OP by default    }}

而是继承一个Endpoint抽像类,我们发现Endpoint提供的三个方法:onOpen,onClose,onError。

与在声明式WebSocket中存在的四件套:@OnOpen,@OnClose,@OnMessage , @OnError, 相比少了@OnMessage。

那收到消息之后回调什么呢? 从上面的代码可以看到为session增加的MessageHandler有一个相似方法onMessage。对,就是他。接收到消息为调用的就是这个handler的onMessage方法。

难道两种编程方式的运行逻辑还不相同? 其实不然,对于声明式编程,也是通过MessageHandler回调@OnMessage标记的方法。只是这个过程在声明式编程模式中,被Tomcat等作了包装。

(这里透一点,对于声明式编程, Tomcat都会将其转换成本篇的这种模式, 声明式编程中POJO没有继承Endpoint抽像类,Tomcat自已构造一个Endpoint的子类,在Tomcat8中叫PojoEndpointServer。如下继承关系:

public class PojoEndpointServer extends PojoEndpointBasepublic abstract class PojoEndpointBase extends Endpoint.

后端的运行采用PojoEndpointServer委托给我们的POJO类就可以,同样道理

@ClientEndpoint注解的POJO对应到PojoEndpointClient。)

发现没,没有ServerEndpoint注解, 无法配置端点的映射路径? 这里我们需要声明一个ServerApplicationConfig实体(还记和Restful WS中的那个javax.rs.ws.core.Application吗?)来完成这个功能:

public class MyApplicationConfig implements ServerApplicationConfig{    @Override    public Set
> getAnnotatedEndpointClasses(Set
> allClasses) {        return null;    }    @Override    public Set
 getEndpointConfigs(Set
> end) {        ServerEndpointConfig sec =  ServerEndpointConfig.Builder.create(ProgramerServer.class, "/chat")        .configurator(new ServerEndpointConfig.Configurator(){        }).build();                       return new HashSet
(){
{           add(sec);       }};    }}

getEndpointConfig构建了一个ServerEndpointConfig集合,上一篇声明式WebSocket为什么不需要这个? 同样需要,只是在声明式WebSocket中Tomcat可以通过@ServerEndpoint注解去构建他。参看Tomcat代码:

 @Override    public void addEndpoint(Class
 pojo) throws DeploymentException {        ServerEndpoint annotation = pojo.getAnnotation(ServerEndpoint.class);              // ServerEndpointConfig        ServerEndpointConfig sec;        Class
 configuratorClazz =                annotation.configurator();        Configurator configurator = null;        if (!configuratorClazz.equals(Configurator.class)) {            try {                configurator = annotation.configurator().newInstance();            } catch (InstantiationException | IllegalAccessException e) {                throw new DeploymentException(sm.getString(                        "serverContainer.configuratorFail",                        annotation.configurator().getName(),                        pojo.getClass().getName()), e);            }        }        sec = ServerEndpointConfig.Builder.create(pojo, path).                decoders(Arrays.asList(annotation.decoders())).                encoders(Arrays.asList(annotation.encoders())).                subprotocols(Arrays.asList(annotation.subprotocols())).                configurator(configurator).                build();        addEndpoint(sec);    }

Tomcat为每一个ServerEndpoint构造了一个ServerEndpointConfig。

将上面两个类同时,打入War包,部署到Tomcat上,一个WebSocket服务端就OK了。

现在你可以用上篇的Client去访问这个WebSocket。或者你已厌倦了Annocation. 来一个编程式Client吧:

public class ProgramerClient extends Endpoint {    @Override    public void onOpen(Session session, EndpointConfig edc) {        System.out.println("I was accpeted by her!");        session.addMessageHandler(new MessageHandler.Whole
() {            @Override            public void onMessage(String message) {                System.out.println("she say: " + message);             }        });    }}

为什么没有onClose,onError方法? 因为Endpoint中有默认实现,这里就没有重载。

public class Client {    public static void main(String[] args) throws DeploymentException, IOException, InterruptedException {        WebSocketContainer ws = ContainerProvider.getWebSocketContainer();        String url = "ws://localhost:8080/ChatWeb2/chat";                ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().configurator(new MyClientConfigurator()).build();        Session session = ws.connectToServer(ProgramerClient.class,cec,URI.create(url));        session.getBasicRemote().sendText("Hello,chick!");        Thread.currentThread().sleep(10000);    }}

等等,有点不同。当然了,这里没有了ClientEndpoint,当然也就没有了@ClientEndpoint.Configurator字段(还记得@ClientEndpoint的结构吗?)

当然也就没有了ClientEndpointConfig。所以需要我们自已加一个。

可以看出编程式WebSocket端点比Annotation复杂了很多。采用Annotation提示使用编程变得简单,

而对于WebSocket容器(即本文的Tomcat等)则需要将这种Annotation提示转换成执行代码。

为了大家对两种模式有个整体的认识,中间的细节我们都跳过了。希望不会对大家的理解带来障碍。

转载地址:http://tlkax.baihongyu.com/

你可能感兴趣的文章
html console 滚动条,JavaScript - 控制滚动条操作
查看>>
html5中按钮尺寸设计,UI设计中的按钮设计规范
查看>>
html方法介绍,jQuery html()等方法介绍
查看>>
Apache2月9日邮件:Tomcat请求漏洞(Request Smuggling)
查看>>
WPF外包技术分享—WPF的MVVM架构解析(分享)
查看>>
数字签名与数字证书
查看>>
GHOST -BATCH 参数的妙用
查看>>
控制反转 (Inversion of Control, IoC)
查看>>
Catalyst 3850 Series Switch Recovery
查看>>
python datetime模块的timedelta
查看>>
Spark笔记整理(二):RDD与spark核心概念名词
查看>>
定制带RAID阵列卡驱动的WINPE3.0系统
查看>>
Microsoft Office 2010 Service Pack 2
查看>>
Python 学习笔记 - Memcached
查看>>
apt-get方式安装lnmp环境
查看>>
ubuntu 安装 qt等软件
查看>>
js模态窗口
查看>>
LayoutInflater的infalte()
查看>>
TCP粘包, UDP丢包, nagle算法
查看>>
POJ 3280 Cheapest Palindrome (DP)
查看>>