在本文中,让我们探索谈论较少的Web Socket Client API,以及如何在Java EE 7容器本身中利用它。
Web套接字服务器API规则
JSR 356的服务器端API(Java的Web套接字API)最常用于构建Web套接字端点实现。 从客户端的角度来看,基于JavaScriptHTML5(浏览器)客户端经常利用标准JavaScript Web套接字API,这些客户端将自己附加到Web套接字服务器端点,并享受双向和全双工通信。 您将看到常见的示例,例如实时地图,股票行情自动收录器,游戏,屏幕共享等应用程序-所有这些用例都是Web套接字的完美选择,而Java EE 7是构建可扩展Web套接字驱动的后端的理想平台。
Web Socket客户端API呢?
Web套接字规范还包括客户端API,并且它对于所有JSR 356(例如Tyrus , Undertow等)实现都必须提供的API。 在相当多的用例中, 可能不需要面向浏览器/面向Web套接字客户端的最终用户。
例
考虑一种情况,您想连接到第三方Web Socket端点,使用其信息并将其保留以备后用? 也许有待进一步分析? 在这种情况下,利用Java EE容器本身内的客户端API很有用。
让我们通过一个简单的示例对此进行探讨。
(带注释)Web Socket Client
注意: @OnMessage的逻辑是有意排除的,并且已以不同的方式实现(稍后说明)
package blog.abhirockzz.wordpress.com;
import javax.websocket.ClientEndpoint;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.Session;
@ClientEndpoint
public class StockTickerClient {
@OnClose
public void closed(Session session) {
System.out.println("Session " + session + " closed");
}
@OnError
public void error(Throwable error) {
System.out.println("Error: " + error.getMessage());
}
}
股票代码(信息)JPA实体
package blog.abhirockzz.wordpress.com;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "STOCK_TICK")
public class StockTick implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String price;
public StockTick(String name, String price) {
this.name = name;
this.price = price;
}
public StockTick() {
//for JPA
}
//getters and setters omitted ...
}
无状态豆
- 处理股票行情信息的持久性
- 针对Java EE 7容器提供的默认JDBC数据源执行其操作( 约定优于配置 !)
package blog.abhirockzz.wordpress.com;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
public class StockInfoPersistenceService {
@PersistenceContext
EntityManager em;
public void save(String name, String price){
em.persist(new StockTick(name, price));
}
}
单例EJB
- 利用Web Socket ContainerProvider API
- 启动与Web套接字服务器的连接
- 注入StockInfoPersistenceService bean并在addMessageHandler实现中使用它
如前所述,这里包含了(持久性)逻辑,该逻辑可以嵌入在StockTickerClient类的@OnMessage注释方法中。 这是因为StockInfoPersistenceService (无状态)bean的注入失败,并且实例本身被解析为null。
package blog.abhirockzz.wordpress.com;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
@Singleton
@Startup
public class StockServiceBootstrapBean {
private final String WS_SERVER_URL = "ws://api.stocks/ticker"; //fictitious
private Session session = null;
@Inject
StockInfoPersistenceService tickRepo;
@PostConstruct
public void bootstrap() {
WebSocketContainer webSocketContainer = null;
try {
webSocketContainer = ContainerProvider.getWebSocketContainer();
session = webSocketContainer.connectToServer(StockTickerClient.class, new URI(WS_SERVER_URL));
System.out.println("Connected to WS endpoint " + WS_SERVER_URL);
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String msg) {
tickRepo.save(msg.split(":")[0], msg.split(":")[1]);
}
});
} catch (DeploymentException | IOException | URISyntaxException ex) {
Logger.getLogger(StockServiceBootstrapBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
@PreDestroy
public void destroy() {
close();
}
private void close() {
try {
session.close();
System.out.println("CLOSED Connection to WS endpoint " + WS_SERVER_URL);
} catch (IOException ex) {
Logger.getLogger(StockServiceBootstrapBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
就是这样。 尽管这是一个相对简单的示例,但很难想象可以在Web套接字服务器终结点接收的信息上应用各种复杂的业务逻辑。 您可能还想考虑使用session.getAsyncRemote#sendAsync方法以异步方式向连接的客户端发送消息。
干杯!
翻译自: https://www.javacodegeeks.com/2015/07/websocket-client-api-in-java-ee-7.html