Netty之ChannelHandler初解

news2025/7/22 23:23:55

目录

目标

Netty版本

Netty官方API

实战

Netty服务器

入栈ChannelHandler读入数据顺序案例

出栈ChannelHandler写出数据顺序案例

ChannelHandlerContext和NioSocketChannel写入数据时有什么不同

Pipeline添加多个ChannelHandler有什么意义


目标

  1. 掌握ChannelHandler基本使用方法。
  2. 熟悉入栈ChannelHandler和出栈ChannelHandler的执行顺序。
  3. 分析ChannelHandlerContext和NioSocketChannel写入数据时有什么不同。
  4. 了解Pipeline添加多个ChannelHandler有什么意义。

Netty版本

        <dependency>
			<groupId>io.netty</groupId>
			<artifactId>netty-all</artifactId>
			<version>4.1.87.Final</version>
		</dependency>

Netty官方API

Netty API Reference (4.1.89.Final)https://netty.io/4.1/api/index.html


实战

Netty服务器

package com.ctx.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * Netty服务器
 */
@Slf4j
public class HandlerTest {
    public static void main(String[] args) {
        new ServerBootstrap().group(new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel channel) throws Exception {
                        ChannelPipeline pipeline = channel.pipeline();
                        //new HandlerTest().inboundHandlerTest(channel, pipeline);
                        //new HandlerTest().outboundHandlerTest(channel, pipeline);
                        //new HandlerTest().diff(channel, pipeline);
                        new HandlerTest().packageTest(channel, pipeline);
                    }
                }).bind(8999);
    }
}

入栈ChannelHandler读入数据顺序案例

/**
     * 入栈ChannelHandler,读入数据时,调用顺序:先加入的ChannelHandler先执行。
     */
    public void inboundHandlerTest(NioSocketChannel channel, ChannelPipeline pipeline) {
        pipeline.addLast("InboundHandler", new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                log.info("InboundHandler读入数据");
                ctx.fireChannelRead(msg);
            }
        });

        pipeline.addLast("InboundHandler2", new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                log.info("InboundHandler2读入数据");
                ctx.fireChannelRead(msg);
            }
        });
    }

出栈ChannelHandler写出数据顺序案例

/**
     * 出栈Handler,写出数据时,调用顺序:先加入的Handler后执行。
     */
    public void outboundHandlerTest(NioSocketChannel channel, ChannelPipeline pipeline) {
        pipeline.addLast("OutboundHandler", new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.info("OutboundHandler写出数据");
                ctx.write(msg, promise);
            }
        });

        pipeline.addLast("OutboundHandler2", new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.info("OutboundHandler2写出数据");
                ctx.write(msg, promise);
            }
        });
    }

ChannelHandlerContext和NioSocketChannel写入数据时有什么不同

/**
     * ChannelHandlerContext和NioSocketChannel写入数据时有什么不同?
     * ChannelHandlerContext写入数据以后,调用顺序:从当前这个Handler(有写入操作的Handler)往前出栈的Handler。
     * NioSocketChannel写入数据以后,调用顺序:从Pipeline的头部往后寻找出栈的Handler。
     */
    public void diff(NioSocketChannel channel, ChannelPipeline pipeline){
        pipeline.addLast("OutboundHandler", new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.info("OutboundHandler写出数据");
                ctx.write(msg, promise);
            }
        });

        pipeline.addLast("InboundHandler", new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                log.info("InboundHandler读入数据");
                ctx.writeAndFlush(channel.alloc().buffer().writeBytes("Hello World!".getBytes()));
                //channel.writeAndFlush(channel.alloc().buffer().writeBytes("Hello World!".getBytes()));
                ctx.fireChannelRead(msg);
            }
        });

        pipeline.addLast("OutboundHandler2", new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.info("OutboundHandler2写出数据");
                ctx.write(msg, promise);
            }
        });
    }

Pipeline添加多个ChannelHandler有什么意义

    /**
     * Pipeline添加多个Handler有什么意义?
     * 相当于给流水线添加了多个工序,每个工序职责不同。在不同的Handler中写不同的业务,各个出栈入栈的Handler之间还可以通过:
     * ctx.write(msg, promise)或ctx.fireChannelRead(msg)传递封装的数据。
     *
     */
    public void packageTest(NioSocketChannel channel, ChannelPipeline pipeline){
        pipeline.addLast("InboundHandler", new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                log.info("InboundHandler读入数据");
                ByteBuf by = (ByteBuf) msg;
                String name = by.toString(Charset.forName("UTF-8"));
                Map<String, Object> map = new HashMap<>();
                map.put("name",name);
                ctx.fireChannelRead(map);
            }
        });

        pipeline.addLast("InboundHandler2", new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                log.info("InboundHandler2读入数据");
                Map map = (Map) msg;
                map.forEach((k,v)->{
                    System.out.println(k+"="+v);
                });
                ctx.fireChannelRead(msg);
            }
        });
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

海康工业相机使用教程

工业相机使用一、硬件连接1、准备材料2、相机供电&#xff08;1&#xff09;区分电源适配器正负极&#xff08;2&#xff09;连接相机电源线缆&#xff08;3&#xff09;连接完成后&#xff0c;相机蓝色灯常亮则成功3、软件连接&#xff08;1&#xff09;MVS客户端下载地址&…

你真的会在阳光下拍照片么?

你好&#xff0c;我是小麥。 上节课我们讲了如何通过影子判断光的质量&#xff0c;也就是光的软硬&#xff0c;这节课我们来接着说一说光的方向和环境光的实际运用。 虽然在现实生活里&#xff0c;我们可能没有从软硬的角度观察过光线&#xff0c;但我相信你在拍照片的时候一…

第九章:Java集合

第九章&#xff1a;Java集合 9.1&#xff1a;Java集合框架概述 数组、集合都是对多个数据进行存储(内存层面&#xff0c;不涉及持久化)操作的结构&#xff0c;简称Java容器。 数组存储多个数据方面的特点 一旦初始化以后&#xff0c;其长度就确定了。数组一旦定义好&#xff…

计算机操作系统:实验三存储管理程序设计

一、目的和要求 目的 存储管理的主要功能之一是合理地分配主存空间。请求页式管理是一种常用的虚拟存储管理技术。 本实验的目的是通过请求页式存储管理中页面置换算法的模拟设计&#xff0c;来了解虚拟存储技术的特点&#xff0c;掌握请求页式存储管理的页面置换算法。 要求…

数字工厂管理系统的应用案例

数字工厂管理系统是制造企业应用数字化工厂技术实现研发设计数字化、生产准备数字化、 生产制造数字化、运营管理数字化和营销服务数字化的重要手段&#xff0c;即通过应用数字相关技术提升产品全生命周期数字化水平&#xff0c;从而提升企业经营的可靠性、安全性和经济性。 任…

C++回顾(十)—— 多态

10.1 问题引出 10.1.1 如果子类定义了与父类中原型相同的函数会发生什么&#xff1f; 函数重写 在子类中定义与父类中原型相同的函数&#xff0c;函数重写只发生在父类与子类之间 重载与重写区别&#xff1a; &#xff08;1&#xff09;重载&#xff1a;同一个作用域&#xf…

A、力扣刷题——数组

提示&#xff1a;这是力扣上数组类题目里的简单题&#xff0c;按顺序做下来的23道题。 第一题&#xff1a; 关键词&#xff1a;原地修改&#xff0c;有序数组 我的答案&#xff1a; &#xff08;for循环&#xff09; &#xff08;1&#xff09;有序数组 class Solution{pu…

平安大视野前瞻2023投资策略:资产格局“危中有机”,关注科技、绿色、安全领域

3月3日&#xff0c;平安私人银行全新云端沙龙《平安大视野》第一站在杭州举办&#xff0c;活动聚焦2023年宏观经济展望&#xff0c;邀请中国首席经济学家论坛理事、鹏扬基金首席经济学家陈洪斌&#xff0c;平安私人银行首席策略分析师彭伟伟就国内外宏观经济变化和资产配置策略…

干货系列:高通量测序后的下游实验验证方法——m6A RNA甲基化篇|易基因

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。此前&#xff0c;我们分享了m6A RNA甲基化研究的数据挖掘思路&#xff08;点击查看详情&#xff09;&#xff0c;进而筛选出m6A修饰目标基因。做完MeRIP-seq测序后&#xff0c;如果需要对分…

【JavaWeb】Servlet详解

文章目录1. 前置知识2.servlet生命周期2.1 默认情况下&#xff0c;服务器启动时&#xff0c;servlet对象并没有被创建2.2 用户执行一次请求2.3用户执行第二次请求2.4 3,4,5,6....次请求2.5 关闭服务器3.servlet方法解析4.适配器模式改造servlet4.1不使用servlet模式4.2使用适配…

【微服务】(十五)—— Seata 的部署和集成

文章目录1. 部署Seata的tc-server1.1 下载Seata1.2 解压1.3 修改配置1.4 在nacos添加配置1.5 创建数据库表1.6 启动TC服务2. 微服务集成seata2.1 引入依赖2.2 修改配置文件3. TC服务的高可用和异地容灾3.1 模拟异地容灾的TC集群3.2 将事务组映射配置到nacos3.3 微服务读取nacos…

软测入门(八)Selenium项目实战

自动化项目实战 项目计划设计 测试计划测试范围设定目标规划活动 实际项目中&#xff0c;需要根据项目的实际情况创建自己的项目计划&#xff0c;没有固定的格式和内容要求&#xff1a; 项目简介自动化实现网上购票项目启动前置条件1.购票网站工作正常 2.自动化测试环境准备…

JAVA的16 个实用代码优化小技巧

一、类成员与方法的可见性最小化 举例&#xff1a;如果是一个private的方法&#xff0c;想删除就删除。 如果一个public的service方法&#xff0c;或者一个public的成员变量&#xff0c;删除一下&#xff0c;不得思考很多。 二、使用位移操作替代乘除法 计算机是使用二进制…

垒骰子(爆搜/DP)

动态规划方格取数垒骰子方格取数 题目描述 设有 NNN \times NNN 的方格图 (N≤9)(N \le 9)(N≤9)&#xff0c;我们将其中的某些方格中填入正整数&#xff0c;而其他的方格中则放入数字 000。如下图所示&#xff08;见样例&#xff09;: A0 0 0 0 0 0 0 00 0 13 0 …

ChatGPT助力校招----面试问题分享(一)

1 ChatGPT每日一题&#xff1a;期望薪资是多少 问题&#xff1a;面试官问期望薪资是多少&#xff0c;如何回答 ChatGPT&#xff1a;当面试官问及期望薪资时&#xff0c;以下是一些建议的回答方法&#xff1a; 1、调查市场行情&#xff1a;在回答之前&#xff0c;可以先调查一…

Python基础之while循环

一&#xff1a;while语法 while 条件:代码1 代码2 代码3....while的运行步骤&#xff1a; 步骤1&#xff1a;如果条件为真&#xff0c;那么依次执行&#xff1a;代码1、代码2、代码3、...... 步骤2&#xff1a;执行完毕后再次判断条件,如果条件为True则再次执行&#…

通用缓存存储设计实践

目录介绍 01.整体概述说明 1.1 项目背景介绍1.2 遇到问题记录1.3 基础概念介绍1.4 设计目标1.5 产生收益分析 02.市面存储方案 2.1 缓存存储有哪些2.2 缓存策略有哪些2.3 常见存储方案2.4 市面存储方案说明2.5 存储方案的不足 03.存储方案原理 3.1 Sp存储原理分析3.2 MMKV存储…

【数据挖掘】4、关联分析:Apriori、FP-Growth 算法、买面包是否也爱买啤酒

文章目录一、概念1.1 支持度1.2 置信度1.3 提升度二、Apriori 算法2.1 频繁项集的定义2.2 算法工作原理三、FP-Growth 算法3.1 算法步骤3.1.1 创建项头表3.1.2 构造 FP 树3.1.3 通过 FP 树挖掘频繁项集3.2 手动推导3.2.1 计算单一项的频率&#xff08;支持度计数&#xff09;3.…

shusheng007编程手记

[版权申明] 非商业目的注明出处可自由转载 出自&#xff1a;shusheng007 文章目录概述工具篇IntelliJ IDEA在Idea中下载源码时&#xff0c;报无法下载源码PostmanPost请求被识别成Get请求Linux开启关闭防火墙开放端口关闭端口如何修复磁盘Nginx如何使用docker来安装Nginx概述 …

VMware虚拟网络编辑桥接/NAT/仅主机模式详解

VMware虚拟网络编辑 安装VMware后 默认虚拟网络设置&#xff1a; VMnet0&#xff1a;桥接模式 VMnet1&#xff1a;仅主机 VMnet8&#xff1a;NAT模式 可以打开VMware的虚拟网络适配器查看 NAT模式 NAT模式借助虚拟NAT设备和虚拟DHCP服务器&#xff0c;使得虚拟机可以联网…