Java EE 7中的WebSocket客户端API

在本文中,让我们探索谈论较少的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(例如TyrusUndertow等)实现都必须提供的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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值