本節描述聲明式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通訊息就完成了。