🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、概述 可以集成netty,作为通讯框架,将应用作为一个驻留监听通讯程序; >[danger] 平台集成netty的时候,为避免传统的方式集成导致阻塞主线程,需要用线程池异步的方式来启动Netty方可; ## 二、配置 ``` rayframework.enabled.socket=true ``` ``` rayframework.socket.netty-daemon-port=6666 ``` ### **ChannelInboundHandlerAdapter配置** 无需配置,按照约定实现指定接口即可,如果系统中,对该接口提供了多于一个实现,则需要指定启用的那个实现,用@RayConventionEnabled注解它即可; ## 三、定制 主要的工作,就是实现自己的ChannelInboundHandlerAdapter 类; 参考: ``` public class RayNettyChannelInboundHandler extends ChannelInboundHandlerAdapter { private Logger logger = LoggerFactory.getLogger(RayNettyChannelInboundHandler.class); private SysLogDao sysLogDao = ServerIocHolder.getBean(SysLogDao.class); /** * 从客户端收到新的数据时,这个方法会在收到消息时被调用 * @param ctx * @param msg */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception, IOException { ByteBuf byteBuf = (ByteBuf) msg; SysLog log = new SysLog(); log.setOperateContent(byteBuf.toString(CharsetUtil.UTF_8)); sysLogDao.save(log); ctx.writeAndFlush(Unpooled.copiedBuffer("你好啊,客户端", Charset.forName("GBK"))); } /** * 从客户端收到新的数据、读取完成时调用 * @param ctx */ @Override public void channelReadComplete(ChannelHandlerContext ctx) throws IOException { logger.info("channelReadComplete"); ctx.flush(); } /** * 当出现 Throwable 对象才会被调用,即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时 * @param ctx * @param cause */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws IOException { logger.info("channelReadComplete"); cause.printStackTrace(); ctx.close(); } /** * 客户端与服务端第一次建立连接时 执行 * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception, IOException { super.channelActive(ctx); ctx.channel().read(); InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); String clientIp = insocket.getAddress().getHostAddress(); logger.info("channelActive:{},{}", clientIp, ctx.name()); } /** * 客户端与服务端断连时执行 * @param ctx * @throws Exception */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception, IOException { super.channelInactive(ctx); InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); String clientIp = insocket.getAddress().getHostAddress(); ctx.close(); logger.info("channelInactive{}" + clientIp); } /** * 服务端当read超时, 会调用这个方法 * @param ctx * @param evt * @throws Exception */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception, IOException { super.userEventTriggered(ctx, evt); InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); String clientIp = insocket.getAddress().getHostAddress(); ctx.close(); logger.info("userEventTriggered{}", clientIp); } @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { logger.info("channelRegistered"); } @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { logger.info("channelUnregistered"); } @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { logger.info("channelWritabilityChanged"); } } ``` >[danger] 特别注意: > 1、业务处理器类中,无法直接用@Autowired获取注入的资源,必须用ServerIocHolder.getBean()的方式获取;