【发布时间】:2018-01-19 13:36:58
【问题描述】:
我想从像 Wildfly 这样的 Java EE 容器中提供一个套接字,但是在 Oracle site 上发现了这个 EJB 限制:
为什么企业 bean 不能侦听或接受套接字上的连接?
因为如果企业 bean 正在侦听套接字,它就不能被钝化——它必须始终可用。
我向 Java EE 专家提出了同样的问题,他回答“只有有状态的 bean 被钝化,所以从单例无状态启动 bean 提供套接字很好,因为它没有被钝化”。
不过,我随后查阅了 EJB 3.2 规范,发现了另一种解释:
企业 bean 不得尝试侦听套接字,接受连接 离子在套接字上,或使用套接字进行多播
EJB 架构允许企业 bean 实例成为网络套接字客户端,但不允许它成为网络服务器。允许实例成为网络服务器会与企业 bean 的基本功能相冲突——为 EJB 客户端提供服务。
呃。现在我很困惑。我真的不明白。
这个限制过时了吗? 它是从没有单例启动 bean (
类似于以下的方法(使用 Netty)甚至更简单的 Java 的 ServerSocketChannel 方法有什么问题,它在托管线程中接受客户端连接。 (不确定 Netty 是否会产生自己的线程)。
有人可以解释一下这个限制吗?
@Singleton
@Startup
public class SocketServerBean {
@Resource
private ManagedExecutorService managedExecutorService;
private Channel channel;
@PostConstruct
private void startup() {
EventLoopGroup bossGroup = new NioEventLoopGroup(1, managedExecutorService);
EventLoopGroup workerGroup = new NioEventLoopGroup(1, managedExecutorService);
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
// ...
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// Bind and start to accept incoming connections.
channel = b.bind(6789).channel();
} catch (Exception e) {
e.printStackTrace();
}
}
@PreDestroy
private void shutdown() {
channel.close();
}
}
【问题讨论】:
-
首先,为什么一定是EJB?我没有看到任何需要它成为 EJB 的东西。您真的了解何时使用 EJB 吗?如果只是为了@Startup,那你的理由就错了。
-
我认为几乎所有容器管理的都是 EJB,但老实说,我不是 Java EE 专家。我想使用在托管环境中使用的连接和消息,例如使用 CDI 和 JPA 来持久化消息。我研究过 GenericServlet,但要与其他无状态 EJB 通信,它也将成为托管 bean。
标签: jakarta-ee ejb netty