javascript
websockets_使用Java WebSockets,JSR 356和JSON映射到POJO的
websockets
因此,我一直在研究Tyrus (JSR 356 WebSocket for Java規(guī)范的參考實(shí)現(xiàn))。 因?yàn)槲乙恢痹趯ふ覝y(cè)試工具,所以我對(duì)在Java中同時(shí)運(yùn)行客戶端和服務(wù)器端感興趣。 因此,恐怕此博客文章中沒有HTML5。
在此示例中,我們想來回發(fā)送JSON,并且因?yàn)槲疫^時(shí)了,所以我希望能夠綁定到POJO對(duì)象。 我將為此使用Jackson,因此我的Maven文件如下所示:
因此,我們需要做的第一件事就是定義Encode / Decoder接口的實(shí)現(xiàn)來為我們完成這項(xiàng)工作。 這將做一些簡(jiǎn)單的反映來鍛煉bean類是什么。 像使用JAX-WS一樣,將它們放在同一個(gè)類中也更容易。 請(qǐng)注意,我們使用接口的流版本,并且僅處理文本內(nèi)容。 (暫時(shí)忽略發(fā)送二進(jìn)制數(shù)據(jù)的能力)
package websocket;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.IOException; import java.io.Reader; import java.io.Writer;import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type;import javax.websocket.DecodeException; import javax.websocket.Decoder; import javax.websocket.EncodeException; import javax.websocket.Encoder; import javax.websocket.EndpointConfig;public abstract class JSONCoder<T>implements Encoder.TextStream<T>, Decoder.TextStream<T>{private Class<T> _type;// When configured my read in that ObjectMapper is not thread safe//private ThreadLocal<ObjectMapper> _mapper = new ThreadLocal<ObjectMapper>() {@Overrideprotected ObjectMapper initialValue() {return new ObjectMapper();}};@Overridepublic void init(EndpointConfig endpointConfig) {ParameterizedType $thisClass = (ParameterizedType) this.getClass().getGenericSuperclass();Type $T = $thisClass.getActualTypeArguments()[0];if ($T instanceof Class) {_type = (Class<T>)$T;}else if ($T instanceof ParameterizedType) {_type = (Class<T>)((ParameterizedType)$T).getRawType();}}@Overridepublic void encode(T object, Writer writer) throws EncodeException, IOException {_mapper.get().writeValue(writer, object);}@Overridepublic T decode(Reader reader) throws DecodeException, IOException {return _mapper.get().readValue(reader, _type);}@Overridepublic void destroy() {}}Bean類實(shí)際上非常簡(jiǎn)單,帶有Coder的靜態(tài)子類,以后我們可以使用它。
package websocket;public class EchoBean {public static class EchoBeanCode extendsJSONCoder<EchoBean> {}private String _message;private String _reply;public EchoBean() {}public EchoBean(String _message) {super();this._message = _message;}public void setMessage(String _message) {this._message = _message;}public String getMessage() {return _message;}public void setReply(String _reply) {this._reply = _reply;}public String getReply() {return _reply;}}因此,我們需要實(shí)現(xiàn)服務(wù)器端點(diǎn),因此可以采用兩種方式之一,即注釋POJO或擴(kuò)展端點(diǎn)。 我要為服務(wù)器使用第一個(gè),為客戶端使用第二個(gè)。 實(shí)際上,此服務(wù)所做的全部工作就是將消息發(fā)布回客戶端。 請(qǐng)注意編碼和解碼器的注冊(cè)。 在這種情況下是相同的類。
package websocket;import java.io.IOException;import javax.websocket.EncodeException; import javax.websocket.EndpointConfig; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import static java.lang.System.out;@ServerEndpoint(value="/echo",encoders = {EchoBean.EchoBeanCode.class},decoders = {EchoBean.EchoBeanCode.class}) public class EchoBeanService {@OnMessagepublic void echo (EchoBean bean, Session peer) throws IOException, EncodeException {//bean.setReply("Server says " + bean.getMessage());out.println("Sending message to client");peer.getBasicRemote().sendObject(bean);}@OnOpenpublic void onOpen(final Session session, EndpointConfig endpointConfig) {out.println("Server connected " + session + " " + endpointConfig);} }讓我們看一下客戶端bean,這次擴(kuò)展了標(biāo)準(zhǔn)Endpoint類并為消息添加了特定的偵聽器。 在這種情況下,當(dāng)收到消息時(shí),只需關(guān)閉連接即可簡(jiǎn)化我們的測(cè)試案例。 在現(xiàn)實(shí)世界中,管理這種連接顯然會(huì)更加復(fù)雜。
package websocket;import java.io.IOException;import javax.websocket.ClientEndpoint; import javax.websocket.CloseReason; import javax.websocket.EncodeException; import javax.websocket.Endpoint; import javax.websocket.EndpointConfig; import javax.websocket.MessageHandler; import javax.websocket.Session;import static java.lang.System.out;@ClientEndpoint(encoders = {EchoBean.EchoBeanCode.class},decoders = {EchoBean.EchoBeanCode.class}) public class EchoBeanClient extends Endpoint {public void onOpen(final Session session, EndpointConfig endpointConfig) {out.println("Client Connection open " + session + " " + endpointConfig);// Add a listener to capture the returning event//session.addMessageHandler(new MessageHandler.Whole() {@Overridepublic void onMessage(EchoBean bean) {out.println("Message from server : " + bean.getReply());out.println("Closing connection");try {session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "All fine"));} catch (IOException e) {e.printStackTrace();}}});// Once we are connected we can now safely send out initial message to the server//out.println("Sending message to server");try {EchoBean bean = new EchoBean("Hello");session.getBasicRemote().sendObject(bean);} catch (IOException e) {e.printStackTrace();} catch (EncodeException e) {e.printStackTrace();}} }現(xiàn)在,使用Tyrus運(yùn)行WebSocket獨(dú)立非常簡(jiǎn)單,您只需實(shí)例化服務(wù)器并啟動(dòng)它。 請(qǐng)注意,這會(huì)啟動(dòng)守護(hù)程序線程,因此您需要確保它是否在main方法中,并且您需要執(zhí)行一些操作來保持JVM的生命。
import org.glassfish.tyrus.server.Server;Server server = new Server("localhost", 8025, "/", EchoBeanService.class); server.start();因此客戶相對(duì)簡(jiǎn)單; 但是在執(zhí)行聲明式方法時(shí),我們需要在注冊(cè)客戶端類時(shí)顯式注冊(cè)編碼器和解碼器。
import javax.websocket.ClientEndpointConfig; import javax.websocket.Decoder; import javax.websocket.Encoder; import javax.websocket.Session;import org.glassfish.tyrus.client.ClientManager;// Right now we have to create a client, which will send a message then close // when it has received a reply //ClientManager client = ClientManager.createClient(); EchoBeanClient beanClient = new EchoBeanClient();Session session = client.connectToServer(beanClient, ClientEndpointConfig.Builder.create().encoders(Arrays.<Class<? extends Encoder>>asList(EchoBean.EchoBeanCode.class)).decoders(Arrays.<Class<? extends Decoder>>asList(EchoBean.EchoBeanCode.class)).build(),URI.create("ws://localhost:8025/echo"));// Wait until things are closed downwhile (session.isOpen()) {out.println("Waiting");TimeUnit.MILLISECONDS.sleep(10); }現(xiàn)在,其輸出如下所示:
Server connected SessionImpl{uri=/echo, id='e7739cc8-1ce5-4c26-ad5f-88a24c688799', endpoint=EndpointWrapper{endpointClass=null, endpoint=org.glassfish.tyrus.core.AnnotatedEndpoint@1ce5bc9, uri='/echo', contextPath='/'}} javax.websocket.server.DefaultServerEndpointConfig@ec120d Waiting Client Connection open SessionImpl{uri=ws://localhost:8025/echo, id='7428be2b-6f8a-4c40-a0c4-b1c8b22e1338', endpoint=EndpointWrapper{endpointClass=null, endpoint=websocket.EchoBeanClient@404c85, uri='ws://localhost:8025/echo', contextPath='ws://localhost:8025/echo'}} javax.websocket.DefaultClientEndpointConfig@15fdf14 Sending message to server Waiting Waiting Waiting Waiting Waiting Waiting Waiting Waiting Waiting Waiting Sending message to client Message from server : Server says Hello Closing connection Waiting有趣的是,這是第一次運(yùn)行,會(huì)有一個(gè)暫停,我懷疑這是由于杰克遜(Jackson)自己設(shè)置的,但我沒有時(shí)間進(jìn)行分析。 我確實(shí)發(fā)現(xiàn),這種漫長(zhǎng)的延遲發(fā)生在第一篇文章上-盡管顯然,這比一般地傳遞??純文本消息要慢。 差異是否對(duì)您很重要取決于您的應(yīng)用程序。
將純文本的性能與JSON流API(例如由新JSR提供的JSON流API)以及將這些值綁定到JSON POJO的版本進(jìn)行比較將會(huì)很有趣。 也許是另一天的事情。
翻譯自: https://www.javacodegeeks.com/2013/05/using-java-websockets-jsr-356-and-json-mapped-to-pojos.html
websockets
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的websockets_使用Java WebSockets,JSR 356和JSON映射到POJO的的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果Mac下如何创建快捷方式如何在电脑桌
- 下一篇: spring aop示例_Spring