本节描述声明式WebSocket编程,能够与后一篇编程式WebSocket做对比学习:javascript
首先上服务端:java
@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类同)。web
ServerEndpoint注解声明以下:编程
@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路径。websocket
subprotocols协议用于配websocket的子协议,好比superchat等,这一阶段咱们先不理会它。session
decoders,encoders用于定义编×××,后面的文章咱们会详细讨论他。app
configurator属性,对于声明式编程的Server端点,能够不配值,会采用默认值ServerEndpointConfig.Configurator便可。socket
(有默认值,通常说明该属性不可或缺,在编程式WebSocketk中时,咱们会看到Configurator的更多细节).ide
DeclarativeServer实现四个方法,分别带有注解 @OnOpen,@OnClose,@OnMessage , @OnError标示。函数
@OnOpen代表当有客户端链接到该端点,则回调@OnOpen标记的方法。
@OnClose当客户端断开链接时,即服务端收到链接断开指定,则回调@OnClose的方法。
@OnMessage当服务端接收到清息时,则回调该方法。
@OnError当服务端发现异常状况时,好比协议错误,则回调该方法。Error不表明链接须要关闭,不少错误是可恢复的。
将该类打入war包,部署到Tomcat上,一个WebSocket服务端就OK了。
本次咱们不用javascript做为Client端点,而是采用胖客户端模式访问,即Java Application。
首先定义Client端点:
@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端点。
@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同样,再也不重述。主函数:
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通讯息就完成了。