jfinal 整合netty的痛点是f.channel().closeFuture().sync();的这个代码阻塞线程,通常的解决办法是新开一个线程,用于netty启动
在适当的地方新开线程,我的整合过程如下
NettyServerBootstrap
package com.litong.jfinal.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class NettyServerBootstrap implements Runnable {
private int port;
public NettyServerBootstrap(int port) {
this.port = port;
}
@Override
public void run() {
bind();
}
private void bind() {
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, worker);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.option(ChannelOption.SO_BACKLOG, 1024); // 连接数
bootstrap.option(ChannelOption.TCP_NODELAY, true); // 不延迟,消息立即发送
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); // 长连接
bootstrap.childHandler(new NettyChannelHandler());
ChannelFuture f = bootstrap.bind(port).sync();
if (f.isSuccess()) {
log.info("启动Netty服务成功,端口号:" + this.port);
}
f.channel().closeFuture().sync();
} catch (Exception e) {
log.info("启动Netty服务异常,异常信息:" + e.getMessage());
e.printStackTrace();
} finally {
log.info("关闭netty");
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}NettyChannelHandler
package com.litong.jfinal.netty; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; /** * @author bill robot * @date 2020年8月16日_下午3:07:27 * @version 1.0 * @desc */ public class NettyChannelHandler extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline p = socketChannel.pipeline(); p.addLast(new NettyServerHandler()); } }
NettyServerHandler
package com.litong.jfinal.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; /** * @author bill robot * @date 2020年8月16日_下午3:06:44 * @version 1.0 * @desc */ public class NettyServerHandler extends ChannelHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { try { ByteBuf in = (ByteBuf) msg; System.out.println("传输内容是"); System.out.println(in.toString(CharsetUtil.UTF_8)); // 这里调用service服务,数据库 } finally { ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // 出现异常就关闭 cause.printStackTrace(); ctx.close(); } }
然后在启动类中启动
@Override
public void onStart() {
int nioPort = PropKitUtil.getInt("noi.server.port");
NettyServerBootstrap server = new NettyServerBootstrap(nioPort);
Thread t1 = new Thread(server, "netty-server");
t1.start();
}最后编写一个client测试
package com.litong.jfinal.netty; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; /** * @author bill robot * @date 2020年8月16日_下午2:41:40 * @version 1.0 * @desc */ public class SocketClientSender { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 17902); OutputStream outputStream = socket.getOutputStream(); PrintWriter printWriter = new PrintWriter(outputStream); printWriter.write("$tmb00035ET3318/08/22 11:5804029.94,027.25,20.00,20.00$"); printWriter.flush(); socket.shutdownOutput(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }