我想从像Wildfly这样的Java容器中提供一个套接字,但是在Oracle站点上找到了这个EJB限制。
为什么企业bean不能监听或接受套接字上的连接? 因为如果企业bean正在监听套接字,它就不能被钝化--它必须总是可用的。
我向一位Java专家提出了同样的问题,他回答说:“只有有状态的bean是被动的,所以从单一的无状态启动bean中提供套接字很好,因为它不是被动的”。
但是,我随后查阅了EJB3.2规范,并找到了另一种解释:
企业bean不得尝试在套接字上侦听、接受套接字上的连接离子或使用套接字进行多播。 EJB架构允许企业bean实例成为网络套接字客户端,但不允许它成为网络服务器。允许实例成为网络服务器将与企业bean的基本功能冲突--为EJB客户端服务。
呃。现在我很困惑。我不太明白。
这个限制是否已经过时?这是在没有单例启动bean (< EJB3.1)的时候遗留下来的吗?
如果采用类似于以下(使用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();
}
}发布于 2018-01-19 14:27:48
为什么企业bean不能监听或接受套接字上的连接?
因为EJB必须充当客户端,而不是服务器。这是确认的EJB3.2规范。技术原因是EJB本质上是可序列化的,而开放流(套接字、文件等)当然是不可序列化的。
功能需求的正确方法是只使用CDI托管bean,而不是EJB。
@ApplicationScoped
public class SocketServerBean {
public void startup(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {
// ...
}
@PreDestroy
private void shutdown() {
// ...
}
}@Observes @Initialized(ApplicationScoped.class)将确保在应用程序初始化期间构造它。
在这个CDI托管bean中,如果有必要,您可以直接注入一个EJB。
另请参阅:
与具体问题无关的,手动打开stinks上Java应用程序的套接字。您确定使用这种方法不会遇到另一个XY-问题吗?也许你真的想要使用网络套接字?如果是这样的话,使用JSR-356 @ServerEndpoint代替。
https://stackoverflow.com/questions/48342386
复制相似问题