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(); } } }