Netty Review - StringEncoder字符串编码器和StringDecoder 解码器的使用与源码解读

文章目录

  • 概念
  • 概述
    • StringEncoder
    • StringDecoder
  • Code
  • 源码分析
    • StringEncoder
    • StringDecoder
  • 小结

在这里插入图片描述


概念

在这里插入图片描述


概述

Netty是一个高性能的网络应用程序框架,它提供了丰富的功能,包括编解码器,这些编解码器用于在网络中发送和接收数据时进行数据的编码和解码。

在Netty中,StringEncoderStringDecoder是两个常用的编解码器,它们的功能和用途如下:

  1. StringEncoder
    • 功能StringEncoder是一个字符编码器,它将字符串(String)数据转换为字节数组(byte[])。
    • 用途:在网络通信中,数据传输是以字节流的形式进行的,因此,当需要发送文本数据时,需要将字符串转换为字节。StringEncoder就是执行这种转换的组件。
    • 工作方式:它使用指定的字符集(如UTF-8)将字符串编码为字节。
  2. StringDecoder
    • 功能StringDecoder是一个字符解码器,它将接收到的字节数组(byte[])数据转换为字符串(String)。
    • 用途:当服务器或客户端接收到字节流数据时,需要将这些字节解码为文本格式,以便进行进一步处理。StringDecoder就是用来完成这个任务的。
    • 工作方式:它使用指定的字符集(如UTF-8)将字节解码为字符串。

Netty 中的 StringEncoderStringDecoder 是专门用于处理字符串数据的编码和解码器。这两个组件可以简化字符串在网络中的传输过程,让开发者能够更加方便地处理文本数据。

StringEncoder

StringEncoder 是一个将字符串编码为字节流的组件。在 Netty 的 pipeline 中,当你需要将字符串发送到网络时,你可以使用 StringEncoder 来实现。它会将字符串转换为字节流,以便可以在网络中传输。
例如,当你使用 Netty 的 Bootstrap 类来配置你的客户端时,你可以为你的 channel pipeline 添加一个 StringEncoder

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
       .channel(NioSocketChannel.class)
       .handler(new ChannelInitializer<SocketChannel>() {
           @Override
           public void initChannel(SocketChannel ch) throws Exception {
               ch.pipeline().addLast(new StringEncoder());
               // 添加其他 handlers...
           }
       });

在这个例子中,StringEncoder 被添加到了 channel 的 pipeline 中,这样在数据传输过程中,发送的字符串就会被自动编码为字节流。


StringDecoder

StringEncoder 相对应,StringDecoder 是用于将接收到的字节流解码为字符串的组件。当你在 Netty 的 pipeline 中接收到字节流时,你可以使用 StringDecoder 来自动将字节流转换为字符串。

继续上面的例子,如果你想在 pipeline 中添加 StringDecoder,你可以这样做:

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
       .channel(NioSocketChannel.class)
       .handler(new ChannelInitializer<SocketChannel>() {
           @Override
           public void initChannel(SocketChannel ch) throws Exception {
               ch.pipeline().addLast(new StringDecoder());
               // 添加其他 handlers...
           }
       });

在这个例子中,StringDecoder 被添加到了 channel 的 pipeline 中,这样在数据接收过程中,接收到的字节流就会被自动解码为字符串。
总的来说,StringEncoderStringDecoder 是 Netty 中专门用于处理字符串数据的编码和解码器,它们简化了字符串在网络中的传输过程,让开发者能够更加方便地处理文本数据。


Code

在这里插入图片描述

 package com.artisan.codec.stringencoder;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class NettyServer {
    // Netty服务器的主方法
    public static void main(String[] args) throws Exception {
        // 创建boss线程组,用于接受客户端连接
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // 创建worker线程组,用于进行SocketChannel的数据读写
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            // 创建ServerBootstrap,它是Netty服务端的启动助手
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            // 绑定线程组到ServerBootstrap
            serverBootstrap.group(bossGroup, workerGroup)
                    // 指定使用NioServerSocketChannel接受进来的连接
                    .channel(NioServerSocketChannel.class)
                    // 设置子通道处理器
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 获取通道的管道
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加字符串解码器
                            pipeline.addLast(new StringDecoder());
                            // 添加自定义的处理器
                            pipeline.addLast(new NettyServerHandler());
                        }
                    });

            // 打印服务启动信息
            System.out.println("netty server start。。");
            // 绑定端口号,并同步等待成功,即启动服务端
            ChannelFuture channelFuture = serverBootstrap.bind(1234).sync();
            // 等待服务器socket关闭
            channelFuture.channel().closeFuture().sync();
        } finally {
            // 优雅地关闭boss线程组
            bossGroup.shutdownGracefully();
            // 优雅地关闭worker线程组
            workerGroup.shutdownGracefully();
        }
    }
}


package com.artisan.codec.stringencoder;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("从客户端读取到String:" + msg.toString());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

这段代码是一个简单的Netty服务器启动类,其中包括了启动Netty服务器的所有必要步骤。代码中包含了中文注释,对每一部分的功能都做了简单解释。


package com.artisan.codec.stringencoder;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    // 当读取到客户端发送的消息时,会调用此方法
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 打印从客户端读取到的字符串消息
        System.out.println("从客户端读取到String:" + msg.toString());
    }

    // 当发生异常时,会调用此方法
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 打印异常堆栈信息
        cause.printStackTrace();
        // 关闭通道
        ctx.close();
    }
}


package com.artisan.codec.stringencoder;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class NettyClient {
    // Netty客户端的主方法
    public static void main(String[] args) throws Exception {
        // 创建事件循环组
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            // 创建Bootstrap,它是Netty客户端的启动助手
            Bootstrap bootstrap = new Bootstrap();
            // 绑定事件循环组到Bootstrap
            bootstrap.group(group).channel(NioSocketChannel.class)
                    // 设置通道初始化处理器
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 获取通道的管道
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加字符串编码器
                            pipeline.addLast(new StringEncoder());
                            // 添加自定义的处理器
                            pipeline.addLast(new NettyClientHandler());
                        }
                    });

            // 打印客户端启动信息
            System.out.println("netty client start。。");
            // 连接到服务器,同步等待成功,即启动客户端
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 1234).sync();
            // 等待客户端socket关闭
            channelFuture.channel().closeFuture().sync();
        } finally {
            // 优雅地关闭事件循环组
            group.shutdownGracefully();
        }
    }
}

这段代码是一个简单的Netty客户端启动类,其中包括了启动Netty客户端的所有必要步骤。代码中包含了中文注释,对每一部分的功能都做了简单解释。

package com.artisan.codec.stringencoder;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class NettyClientHandler extends ChannelInboundHandlerAdapter {

    // 当从服务器接收到消息时,会调用此方法
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 打印接收到的服务器消息
        System.out.println("收到服务器消息:" + msg);
    }

    // 当通道激活时,会调用此方法
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 定义要发送的字符串消息
        String msg = "字符串消息";
        // 打印发送消息的日志信息
        System.out.println("NettyClientHandler发送数据:" + msg);
        // 向服务器发送消息
        ctx.writeAndFlush(msg);
    }
}

这段代码是一个自定义的Netty客户端处理器,继承自ChannelInboundHandlerAdapter。其中包括了两个重写的方法,channelRead和channelActive,分别用于处理服务器消息的读取和通道激活时发送消息。代码中包含了中文注释,对每一部分的功能都做了简单解释


【测试结果】

在这里插入图片描述
在这里插入图片描述


源码分析

在这里插入图片描述

StringEncoder

// StringEncoder类继承自MessageToMessageEncoder,用于将字符序列(CharSequence)消息转换为另一个消息类型
@Sharable
public class StringEncoder extends MessageToMessageEncoder<CharSequence> {

    // 用于编码的字符集
    private final Charset charset;

    /**
     * 使用当前系统的默认字符集创建一个新的实例。
     */
    public StringEncoder() {
        this(Charset.defaultCharset());
    }

    /**
     * 使用指定的字符集创建一个新的实例。
     */
    public StringEncoder(Charset charset) {
        this.charset = ObjectUtil.checkNotNull(charset, "charset");
    }

    // 重写父类的encode方法,实现字符序列到字节的转换
    @Override
    protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
        // 如果字符序列为空,则直接返回
        if (msg.length() == 0) {
            return;
        }

        // 使用ByteBufUtil.encodeString方法将字符序列编码为字节,并使用ctx.alloc()分配内存缓冲区
        // 然后将编码后的字节添加到输出列表out中,以便后续处理
        out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));
    }
}

  1. 类继承关系

    • StringEncoder继承自MessageToMessageEncoder<CharSequence>,后者又继承自ChannelOutboundHandlerAdapterMessageToMessageEncoder接口用于将消息对象转换为另一个消息对象,而这里的参数CharSequence表示输入的消息对象类型,即字符序列。
      在这里插入图片描述
  2. 构造函数

    • StringEncoder():默认构造函数,使用默认字符集(UTF-8)。
    • StringEncoder(Charset charset):指定字符集的构造函数。这里使用了ObjectUtil.checkNotNull方法来检查字符集是否为空,保证字符集的有效性。
  3. 核心方法

    • encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out):将字符序列消息编码为字节。这个方法重写了MessageToMessageEncoder接口的encode方法。
    • 在编码过程中,首先检查字符序列是否为空,如果为空,则直接返回。
    • 使用ByteBufUtil.encodeString方法将字符序列编码为字节,并使用ctx.alloc()分配内存缓冲区。
    • 将编码后的字节添加到输出列表out中,以便后续处理。
  4. 异常处理

    • encode方法中,如果发生异常,会抛出异常。
      通过以上分析,我们可以看出StringEncoder的主要作用是将字符序列消息编码为字节。它利用指定的字符集进行编码,并在异常情况下抛出异常。这段代码简洁明了,实现了字符串编码的核心功能。

StringDecoder

/**
 * 字符串解码器,继承自Netty的MessageToMessageDecoder,用于将ByteBuf消息解码为字符串消息。
 */
@Sharable
public class StringDecoder extends MessageToMessageDecoder<ByteBuf> {

    // 字符集解码器,用于解码ByteBuf中的数据为字符串
    private final Charset charset;

    /**
     * 使用默认的系统字符集创建一个新的解码器实例。
     */
    public StringDecoder() {
        this(Charset.defaultCharset());
    }

    /**
     * 使用指定的字符集创建一个新的解码器实例。
     */
    public StringDecoder(Charset charset) {
        this.charset = ObjectUtil.checkNotNull(charset, "charset");
    }

    /**
     * 重写decode方法,将ByteBuf中的数据解码为字符串,并添加到解码消息列表中。
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        // 将ByteBuf转换为字符串,并使用指定的字符集解码
        out.add(msg.toString(charset));
    }
}

StringDecoder是Netty网络通信框架中的一个解码器,用于将接收到的字节缓冲区(ByteBuf)解码为字符串。下面是对StringDecoder源码的分析:

  1. 类定义:StringDecoder继承自MessageToMessageDecoder,并实现了Sharable接口。Sharable接口主要用于实现解码器的共享,表示同一个解码器实例可以在不同的ChannelHandlerContext中使用。
@Sharable
public class StringDecoder extends MessageToMessageDecoder<ByteBuf> {

在这里插入图片描述

  1. 字段定义:StringDecoder类中有一个私有字段charset,它表示用于解码的字符集。
private final Charset charset;
  1. 构造函数:StringDecoder类有两个构造函数,一个是无参构造函数,另一个是带有字符集参数的构造函数。无参构造函数会使用系统默认的字符集创建解码器实例,而有参构造函数允许用户指定字符集。
public StringDecoder() {
    this(Charset.defaultCharset());
}
public StringDecoder(Charset charset) {
    this.charset = ObjectUtil.checkNotNull(charset, "charset");
}
  1. decode方法:decode方法是MessageToMessageDecoder类的一个抽象方法,用于实现具体的解码逻辑。在StringDecoder中,它将接收到的字节缓冲区(ByteBuf)转换为字符串,并使用指定的字符集进行解码。最后,将解码后的字符串添加到解码消息列表中。
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
    out.add(msg.toString(charset));
}

总结:StringDecoder是Netty中的一个解码器,用于将接收到的字节缓冲区(ByteBuf)解码为字符串。它提供了两个构造函数,允许用户指定字符集。在decode方法中,它将ByteBuf转换为字符串,并使用指定的字符集进行解码,将解码后的字符串添加到解码消息列表中。


小结

在Netty的通道处理器(ChannelHandler)中,StringEncoderStringDecoder通常以管道(Pipeline)的形式添加到通道(Channel)中,这样,在数据传输过程中,发送的数据会被StringEncoder编码,接收的数据会被StringDecoder解码。通过这种方式,Netty保证了字符串数据在网络中的高效传输和正确解析。

简而言之,StringEncoderStringDecoder是Netty中处理字符串数据编解码的关键组件,它们让字符串数据可以在网络中安全、准确地传输。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mac电脑安装虚拟机教程

1、准备一台虚拟机&#xff0c;安装CentOS7 常用的虚拟化软件有两种&#xff1a; VirtualBoxVMware 这里我们使用VirtualBox来安装虚拟机&#xff0c;下载地址&#xff1a;Downloads – Oracle VM VirtualBox 001 点击安装 002 报错&#xff1a;he installer has detected an…

uni-app 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码&#xff1a; uCharts: 高性能跨平台图表库&#xff0c;支持H5、APP、小程序&#xff08;微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序&#xff09;、Vue、Taro等更多支持canvas的框架平台&#…

在Windows系统平台下部署运行服务端Idea工程的jar服务

前言 目前云原生docker等技术&#xff0c;加上部署流水线大大的简化了各种流程&#xff0c;我们后端开发的人员只需要提交代码后&#xff0c;构建、部署、测试、发布等环节都无需人员接入&#xff0c;完全的自动化交付了。那么你肯定不禁想问&#xff0c;如题的需求不是点击一…

pyCharm 创建一个FastApi web项目,实现接口调用

FastApi和Django区别 我这边演示项目使用的fastApi作为web框架&#xff0c;当然主流一般都是使用Django做web框架&#xff0c;但是Django是一个重量级web框架他有很多组件&#xff0c;如授权&#xff0c;分流等全套web功能。我这边呢只需要有个接口可以被别人调用&#xff0c;…

python 绘制网格图/马赛克图

python 绘制网格图/马赛克图 文章目录 python 绘制网格图/马赛克图前言 前言 python绘制网格并在相应的坐标填充颜色 参考博客 def mplot_intf(t, data):plt.rcParams["figure.figsize"] (t, len(data))plt.rcParams["xtick.major.size"] 0plt.rcParams…

ios微信小程序table头部与左侧固定双重滚动会抖动的坑,解决思路

正常情况是左右滑动时&#xff0c;左侧固定不动&#xff0c;上下滑动时表头不动&#xff1b;而且需求不是完整页面滚动。而是单独这个表滚动&#xff1b; 第一个坑是他有一个ios自带的橡胶上下回弹效果。导致滚动时整个表都跟着回弹&#xff1b; 这个是很好解决。微信开发官网…

Achronix提供由FPGA赋能的智能网卡(SmartNIC)解决方案来打破智能网络性能极限

作者&#xff1a;Achronix 随着人工智能/机器学习&#xff08;AI/ML&#xff09;和其他复杂的、以数据为中心的工作负载被广泛部署&#xff0c;市场对高性能计算的需求持续飙升&#xff0c;对高性能网络的需求也呈指数级增长。高性能计算曾经是超级计算机这样一个孤立的领域&a…

【控制器局域网】CAN报文学习笔记(四)之 字节排序、信号提取实例1

以下面的表格来表示字节顺序和位顺序&#xff0c;用红色表示高位MSB&#xff0c;蓝色表示低位LSB&#xff0c;绿色为LSB到MSB的过度 Bit oderMSB→→→→→→LSBByte oder\Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0MSBByte076543210↓Byte115141312111098↓Byte22322212019181716↓By…

谷歌手机安装证书到根目录

1、前提你已经root&#xff0c;安装好面具 2&#xff0c;下载movecert模块&#xff0c;自动帮你把证书从用户证书移动成系统证书 视频教程&#xff0c;手机为谷歌手机 https://www.bilibili.com/video/BV1pG4y1A7Cj?p11&vd_source9c0a32b00d6d59fecae05b4133f22f06 软件下…

【C语言指针专题(4)】指针与一维数组

一、数组名的理解 在之前我们我们使用指针访问数组的时候&#xff0c;使用到了这样一段代码&#xff1a; int arr[10] { 0 }; int* pa &arr[0]; 这里我们使用 &arr[0] 的方式拿到了数组第一个元素的地址&#xff0c;但是其实数组名本来就是地址&#xff0c;而且 是…

使用opencv实现图像中几何图形检测

1 几何图形检测介绍 1.1 轮廓(contours) 什么是轮廓&#xff0c;简单说轮廓就是一些列点相连组成形状、它们拥有同样的颜色、轮廓发现在图像的对象分析、对象检测等方面是非常有用的工具&#xff0c;在OpenCV 中使用轮廓发现相关函数时候要求输入图像是二值图像&#xff0c;这…

麒麟V10 ARM 离线生成RabbitMQ docker镜像并上传Harbor私有仓库

第一步在外网主机执行&#xff1a; docker pull arm64v8/rabbitmq:3.8.9-management 将下载的镜像打包给离线主机集群使用 在指定目录下执行打包命令&#xff1a; 执行&#xff1a; docker save -o rabbitmq_arm3.8.9.tar arm64v8/rabbitmq:3.8.9-management 如果懒得打包…

力扣:77. 组合(回溯, path[:]的作用)

题目&#xff1a; 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ] 示例 2&#xff1a; 输入&…

机器学习数据的清洗,转化,汇总及建模完整步骤(基于Titanic数据集)

目录 介绍&#xff1a; 一、数据 二、检查数据缺失 三、数据分析 四、数据清洗 五、数据类别转化 六、数据汇总和整理 七、建模 介绍&#xff1a; 线性回归是一种常用的机器学习方法&#xff0c;用于建立一个输入变量与输出变量之间线性关系的预测模型。线性回归的目标…

Inkscape SVG 编辑器 导入 Gazebo

概述 本教程描述了拉伸 SVG 文件的过程&#xff0c;这些文件是 2D 的 图像&#xff0c;用于在 Gazebo 中为您的模型创建 3D 网格。有时是 更容易在 Inkscape 或 Illustrator 等程序中设计模型的一部分。 在开始之前&#xff0c;请确保您熟悉模型编辑器。 本教程将向您展示如…

神经网络:池化层知识点

1.CNN中池化的作用 池化层的作用是对感受野内的特征进行选择&#xff0c;提取区域内最具代表性的特征&#xff0c;能够有效地减少输出特征数量&#xff0c;进而减少模型参数量。按操作类型通常分为最大池化(Max Pooling)、平均池化(Average Pooling)和求和池化(Sum Pooling)&a…

使用STM32微控制器读取和显示DHT11温湿度传感器数据

在本文中&#xff0c;我们将介绍如何使用STM32微控制器读取和显示DHT11温湿度传感器的数据。我们将使用C语言和STM32的库函数来实现这个功能。本文包含硬件连接和软件编程两个方面的内容。 硬件连接 首先&#xff0c;我们需要将DHT11温湿度传感器连接到STM32微控制器上。DHT11…

基于ASF-YOLO融合空间特征和尺度特征的新型注意力尺度序列融合模型开发构建涵洞隧道场景下墙壁建筑缺陷分割检测系统

在ASF-YOLO提出之初&#xff0c;我们就进行了相应的实践开发&#xff0c;感兴趣的话可以自行移步阅读&#xff1a; 《基于ASF-YOLO融合空间特征和尺度特征的新型注意力尺度序列融合模型开发构建医学场景下细胞分割检测识别系统&#xff0c;以【BCC、DSB2018数据集为基准】》 …

性能压力测试--确保企业数字化业务稳健运行

随着企业的数字化转型和依赖云计算的普及&#xff0c;软件系统的性能已经成为企业成功运营的关键因素之一。性能压力测试作为确保系统在各种条件下都能高效运行的关键步骤&#xff0c;对企业的重要性不可忽视。以下是性能压力测试对企业的几个重要方面的影响和作用&#xff1a;…

行为型设计模式(二)责任链模式 策略模式

责任链模式 Chain of Responsibility 1、什么是责任链模式 责任链模式为请求创建一个接收者对象的链&#xff0c;每个接收者都包含对另一个接收者的引用。如果一个对象不能处理请求&#xff0c;它会将请求传递给链中的下一个接收者&#xff0c;如此模式下&#xff0c;请求沿着…