jfinal-4.2 整合netty的个小例子

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


评论区

JFinal

2020-08-16 16:15

在 onStart() 中开新线程是最好的,代码非常干净简洁,赞

热门分享

扫码入社