Netty传输object并解决粘包拆包问题

⭐️ 前言

大家好,笔者之前写过一篇文章,《Netty中粘包拆包问题解决探讨》,就Netty粘包拆包问题及其解决方案进行了探讨,本文算是这篇博客的延续。探讨netty传输object的问题。

在这里插入图片描述

本文将netty结合java序列化来传输object并解决粘包拆包问题,虽然netty已经提供了ObjectEncoder和ObjectDecoder来完成此任务,但本文想把这个功能简单化,来拆解其中的原理。

⭐️ java序列化

java序列化相关的资料很多,这里就不再赘述,show the code!!!

⭐️ netty传输object

这里客户端发送了三条消息(对象实例),在最后一条消息发送时进行flush操作。

Trade类定义了我们要传输的对象,其中除了一般实体类应该具备的元素外,按ddd领域模型设计的思想,还封装了两个业务方法:toByteArray和fromByteArray,来方便Trade对象与字节数组的转换。

public class Trade implements Serializable {

    private int id;

    private String name;

    private float payment;

    private Date maturity;

    public Trade() {}

    public Trade(int id, String name, float payment, Date maturity) {
        this.id = id;
        this.name = name;
        this.payment = payment;
        this.maturity = maturity;
    }

    public String toString(){
        return String.format("id: %d, name: %s, payment: %f, maturity: %s", id, name, payment,
                new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(maturity));
    }

    /***
     * 对象序列化为字节数组
     * @return
     * @throws IOException
     */
    public byte[] toByteArray() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        byte[] data;
        try {
            oos = new ObjectOutputStream(baos);
            oos.writeObject(this);
            data = baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                oos.close();
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        return data;
    }

    /***
     * 从字节数组中读取对象
     * @param bytes
     * @return
     */
    public static Trade fromByteArray(byte[] bytes) {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(bais);
            return (Trade) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                ois.close();
                bais.close();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPayment() {
        return payment;
    }

    public void setPayment(float payment) {
        this.payment = payment;
    }

    public Date getMaturity() {
        return maturity;
    }

    public void setMaturity(Date maturity) {
        this.maturity = maturity;
    }
}

ServerTestHandler用以处理并显示客户端发给服务端的数据

public class ServerTestHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        // 消息(传输的对象)长度
        int len = buf.readInt();
        System.out.println(String.format("消息(传输的对象)长度:%s", len));
        // 接收对象内容的字节数组
        byte[] arr = new byte[len];
        // 将对象读到字节数组中
        buf.readBytes(arr);
        // 从字节数组中解析Trade对象
        Trade tr = Trade.fromByteArray(arr);
        System.out.println("来自client的消息:" + tr.toString());
    }
}

需要注意的是,在再给server设置Handler时,LengthFieldBasedFrameDecoder中的参数initialBytesToStrip要设置为0,因为我们用LengthFieldBasedFrameDecoder对Frame进行界定的同时,还要在ServerTestHandler读取对象的长度。

server端代码

public class Server {
        public static void main(String[] args) {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .childOption(ChannelOption.SO_KEEPALIVE, true)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            protected void initChannel(SocketChannel socketChannel) throws Exception {
                                ChannelPipeline pipeline = socketChannel.pipeline();
                                pipeline.addLast(new LoggingHandler())
                                        .addLast(new LengthFieldBasedFrameDecoder(1024,0, 4, 0, 0))
                                        .addLast(new ServerTestHandler());
                            }
                        });
                System.out.println("server ready");
                ChannelFuture sync = bootstrap.bind(8888).sync();
                sync.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
}

client端代码

public class Client {
    public static void main(String[] args) {
        EventLoopGroup workGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.group(workGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast(new LoggingHandler())
                                    .addLast(new LengthFieldPrepender(4));
                        }
                    });
            System.out.println("client ok");
            ChannelFuture localhost = bootstrap.connect("localhost", 8888).sync();
            // 发送消息
            Calendar instance = Calendar.getInstance();
            instance.set(2023, 11, 11, 10, 10, 5);
            Trade trade1 = new Trade(1, "trade1", 1.5f, instance.getTime());
            byte[] trade1Bytes = trade1.toByteArray();
            localhost.channel().write(Unpooled.copiedBuffer(trade1Bytes));

            instance.set(2023, 10, 20, 9, 8, 5);
            Trade trade2 = new Trade(2, "trade2", 0.5f, instance.getTime());
            byte[] trade2Bytes = trade2.toByteArray();
            localhost.channel().write(Unpooled.copiedBuffer(trade2Bytes));

            instance.set(2023, 4, 11, 13, 13, 45);
            Trade trade3 = new Trade(3, "trade3", 7.1f, instance.getTime());
            byte[] trade3Bytes = trade3.toByteArray();
            localhost.channel().writeAndFlush(Unpooled.copiedBuffer(trade3Bytes));

            localhost.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workGroup.shutdownGracefully();
        }
    }
}

client端日志

         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 00 00 b1                                     |....            |
+--------+-------------------------------------------------+----------------+
2023/11/17 18:12:15,096 [DEBUG]AbstractInternalLogger-[id: 0xd71e6e91, L:/127.0.0.1:53675 - R:localhost/127.0.0.1:8888] WRITE: 177B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| ac ed 00 05 73 72 00 18 63 6f 6d 2e 78 68 63 2e |....sr..com.xhc.|
|00000010| 6e 65 74 2e 65 6e 74 69 74 79 2e 54 72 61 64 65 |net.entity.Trade|
|00000020| 99 8e 9b 76 ff dc b3 1f 02 00 04 49 00 02 69 64 |...v.......I..id|
|00000030| 46 00 07 70 61 79 6d 65 6e 74 4c 00 08 6d 61 74 |F..paymentL..mat|
|00000040| 75 72 69 74 79 74 00 10 4c 6a 61 76 61 2f 75 74 |urityt..Ljava/ut|
|00000050| 69 6c 2f 44 61 74 65 3b 4c 00 04 6e 61 6d 65 74 |il/Date;L..namet|
|00000060| 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 |..Ljava/lang/Str|
|00000070| 69 6e 67 3b 78 70 00 00 00 01 3f c0 00 00 73 72 |ing;xp....?...sr|
|00000080| 00 0e 6a 61 76 61 2e 75 74 69 6c 2e 44 61 74 65 |..java.util.Date|
|00000090| 68 6a 81 01 4b 59 74 19 03 00 00 78 70 77 08 00 |hj..KYt....xpw..|
|000000a0| 00 01 8c 56 a3 80 74 78 74 00 06 74 72 61 64 65 |...V..txt..trade|
|000000b0| 31                                              |1               |
+--------+-------------------------------------------------+----------------+
2023/11/17 18:12:15,098 [DEBUG]AbstractInternalLogger-[id: 0xd71e6e91, L:/127.0.0.1:53675 - R:localhost/127.0.0.1:8888] WRITE: 4B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 00 00 b1                                     |....            |
+--------+-------------------------------------------------+----------------+
2023/11/17 18:12:15,098 [DEBUG]AbstractInternalLogger-[id: 0xd71e6e91, L:/127.0.0.1:53675 - R:localhost/127.0.0.1:8888] WRITE: 177B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| ac ed 00 05 73 72 00 18 63 6f 6d 2e 78 68 63 2e |....sr..com.xhc.|
|00000010| 6e 65 74 2e 65 6e 74 69 74 79 2e 54 72 61 64 65 |net.entity.Trade|
|00000020| 99 8e 9b 76 ff dc b3 1f 02 00 04 49 00 02 69 64 |...v.......I..id|
|00000030| 46 00 07 70 61 79 6d 65 6e 74 4c 00 08 6d 61 74 |F..paymentL..mat|
|00000040| 75 72 69 74 79 74 00 10 4c 6a 61 76 61 2f 75 74 |urityt..Ljava/ut|
|00000050| 69 6c 2f 44 61 74 65 3b 4c 00 04 6e 61 6d 65 74 |il/Date;L..namet|
|00000060| 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 |..Ljava/lang/Str|
|00000070| 69 6e 67 3b 78 70 00 00 00 02 3f 00 00 00 73 72 |ing;xp....?...sr|
|00000080| 00 0e 6a 61 76 61 2e 75 74 69 6c 2e 44 61 74 65 |..java.util.Date|
|00000090| 68 6a 81 01 4b 59 74 19 03 00 00 78 70 77 08 00 |hj..KYt....xpw..|
|000000a0| 00 01 8b ea 45 31 34 78 74 00 06 74 72 61 64 65 |....E14xt..trade|
|000000b0| 32                                              |2               |
+--------+-------------------------------------------------+----------------+
2023/11/17 18:12:15,098 [DEBUG]AbstractInternalLogger-[id: 0xd71e6e91, L:/127.0.0.1:53675 - R:localhost/127.0.0.1:8888] WRITE: 4B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 00 00 b1                                     |....            |
+--------+-------------------------------------------------+----------------+
2023/11/17 18:12:15,099 [DEBUG]AbstractInternalLogger-[id: 0xd71e6e91, L:/127.0.0.1:53675 - R:localhost/127.0.0.1:8888] WRITE: 177B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| ac ed 00 05 73 72 00 18 63 6f 6d 2e 78 68 63 2e |....sr..com.xhc.|
|00000010| 6e 65 74 2e 65 6e 74 69 74 79 2e 54 72 61 64 65 |net.entity.Trade|
|00000020| 99 8e 9b 76 ff dc b3 1f 02 00 04 49 00 02 69 64 |...v.......I..id|
|00000030| 46 00 07 70 61 79 6d 65 6e 74 4c 00 08 6d 61 74 |F..paymentL..mat|
|00000040| 75 72 69 74 79 74 00 10 4c 6a 61 76 61 2f 75 74 |urityt..Ljava/ut|
|00000050| 69 6c 2f 44 61 74 65 3b 4c 00 04 6e 61 6d 65 74 |il/Date;L..namet|
|00000060| 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 |..Ljava/lang/Str|
|00000070| 69 6e 67 3b 78 70 00 00 00 03 40 e3 33 33 73 72 |ing;xp....@.33sr|
|00000080| 00 0e 6a 61 76 61 2e 75 74 69 6c 2e 44 61 74 65 |..java.util.Date|
|00000090| 68 6a 81 01 4b 59 74 19 03 00 00 78 70 77 08 00 |hj..KYt....xpw..|
|000000a0| 00 01 88 09 3a bf 54 78 74 00 06 74 72 61 64 65 |....:.Txt..trade|
|000000b0| 33                                              |3               |
+--------+-------------------------------------------------+----------------+
2023/11/17 18:12:15,099 [DEBUG]AbstractInternalLogger-[id: 0xd71e6e91, L:/127.0.0.1:53675 - R:localhost/127.0.0.1:8888] FLUSH

server端日志

         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 00 00 b1 ac ed 00 05 73 72 00 18 63 6f 6d 2e |........sr..com.|
|00000010| 78 68 63 2e 6e 65 74 2e 65 6e 74 69 74 79 2e 54 |xhc.net.entity.T|
|00000020| 72 61 64 65 99 8e 9b 76 ff dc b3 1f 02 00 04 49 |rade...v.......I|
|00000030| 00 02 69 64 46 00 07 70 61 79 6d 65 6e 74 4c 00 |..idF..paymentL.|
|00000040| 08 6d 61 74 75 72 69 74 79 74 00 10 4c 6a 61 76 |.maturityt..Ljav|
|00000050| 61 2f 75 74 69 6c 2f 44 61 74 65 3b 4c 00 04 6e |a/util/Date;L..n|
|00000060| 61 6d 65 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 |amet..Ljava/lang|
|00000070| 2f 53 74 72 69 6e 67 3b 78 70 00 00 00 01 3f c0 |/String;xp....?.|
|00000080| 00 00 73 72 00 0e 6a 61 76 61 2e 75 74 69 6c 2e |..sr..java.util.|
|00000090| 44 61 74 65 68 6a 81 01 4b 59 74 19 03 00 00 78 |Datehj..KYt....x|
|000000a0| 70 77 08 00 00 01 8c 56 a3 80 74 78 74 00 06 74 |pw.....V..txt..t|
|000000b0| 72 61 64 65 31 00 00 00 b1 ac ed 00 05 73 72 00 |rade1........sr.|
|000000c0| 18 63 6f 6d 2e 78 68 63 2e 6e 65 74 2e 65 6e 74 |.com.xhc.net.ent|
|000000d0| 69 74 79 2e 54 72 61 64 65 99 8e 9b 76 ff dc b3 |ity.Trade...v...|
|000000e0| 1f 02 00 04 49 00 02 69 64 46 00 07 70 61 79 6d |....I..idF..paym|
|000000f0| 65 6e 74 4c 00 08 6d 61 74 75 72 69 74 79 74 00 |entL..maturityt.|
|00000100| 10 4c 6a 61 76 61 2f 75 74 69 6c 2f 44 61 74 65 |.Ljava/util/Date|
|00000110| 3b 4c 00 04 6e 61 6d 65 74 00 12 4c 6a 61 76 61 |;L..namet..Ljava|
|00000120| 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 78 70 00 |/lang/String;xp.|
|00000130| 00 00 02 3f 00 00 00 73 72 00 0e 6a 61 76 61 2e |...?...sr..java.|
|00000140| 75 74 69 6c 2e 44 61 74 65 68 6a 81 01 4b 59 74 |util.Datehj..KYt|
|00000150| 19 03 00 00 78 70 77 08 00 00 01 8b ea 45 31 34 |....xpw......E14|
|00000160| 78 74 00 06 74 72 61 64 65 32 00 00 00 b1 ac ed |xt..trade2......|
|00000170| 00 05 73 72 00 18 63 6f 6d 2e 78 68 63 2e 6e 65 |..sr..com.xhc.ne|
|00000180| 74 2e 65 6e 74 69 74 79 2e 54 72 61 64 65 99 8e |t.entity.Trade..|
|00000190| 9b 76 ff dc b3 1f 02 00 04 49 00 02 69 64 46 00 |.v.......I..idF.|
|000001a0| 07 70 61 79 6d 65 6e 74 4c 00 08 6d 61 74 75 72 |.paymentL..matur|
|000001b0| 69 74 79 74 00 10 4c 6a 61 76 61 2f 75 74 69 6c |ityt..Ljava/util|
|000001c0| 2f 44 61 74 65 3b 4c 00 04 6e 61 6d 65 74 00 12 |/Date;L..namet..|
|000001d0| 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e |Ljava/lang/Strin|
|000001e0| 67 3b 78 70 00 00 00 03 40 e3 33 33 73 72 00 0e |g;xp....@.33sr..|
|000001f0| 6a 61 76 61 2e 75 74 69 6c 2e 44 61 74 65 68 6a |java.util.Datehj|
|00000200| 81 01 4b 59 74 19 03 00 00 78 70 77 08 00 00 01 |..KYt....xpw....|
|00000210| 88 09 3a bf 54 78 74 00 06 74 72 61 64 65 33    |..:.Txt..trade3 |
+--------+-------------------------------------------------+----------------+
消息(传输的对象)长度:177
来自client的消息:id: 1, name: trade1, payment: 1.500000, maturity: 2023-12-11 10:10:05
消息(传输的对象)长度:177
来自client的消息:id: 2, name: trade2, payment: 0.500000, maturity: 2023-11-20 09:08:05
消息(传输的对象)长度:177
来自client的消息:id: 3, name: trade3, payment: 7.100000, maturity: 2023-05-11 01:13:45
2023/11/17 18:12:15,143 [DEBUG]AbstractInternalLogger-[id: 0x143e8152, L:/127.0.0.1:8888 - R:/127.0.0.1:53675] READ COMPLETE

可以看到,三个对象成功的被服务器接收并正确的解析了。

笔者水平有限,若有不对的地方欢迎评论指正!

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

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

相关文章

3dMax2024新功能和工作流增强功能速览

3dMax2024新功能和工作流增强功能速览 Autodesk发布的3dMax2024引入了一系列新功能和工作流增强功能&#xff0c;如下所示&#xff1a; 更新的“指定控制器”卷展栏&#xff1a;这个现代化的功能为动画师提供了更高效的工作方式&#xff0c;简化了他们的动画流程。 布尔修饰符…

【DevOps】Git 图文详解(三):常用的 Git GUI

Git 图文详解&#xff08;三&#xff09;&#xff1a;常用的 Git GUI 1.SourceTree2.TortoiseGit3.VSCode 中的 Git 如果不想用命令行工具&#xff0c;完全可以安装一个 Git 的 GUI 工具&#xff0c;用的更简单、更舒服。不用记那么多命令了&#xff0c;极易上手&#xff0c;不…

二、ST-Link驱动的安装

1、灵动mm32单片机 (1)上海灵动微电子股份有限公司 (2)mm32单片机支持ST-Link下载程序。 2、ST-Link驱动的安装 (1)下载地址 ST-Link 官网下载地址 (2)点击获取软件下载ST-Link驱动。(需要登陆ST官网账户) (3)下载后解压&#xff0c;根据电脑位数安装 .exe 文件即可。 6…

若依前后端分离版,快速上手

哈喽~大家好&#xff0c;这篇来看看若依前后端分离版&#xff0c;快速上手&#xff08;肝了挺久的&#xff09;。 &#x1f947;个人主页&#xff1a;个人主页​​​​​ &#x1f948; 系列专栏&#xff1a;【Springboot和Vue全栈开发】…

Javaweb之Vue指令案例的详细解析

2.3.5 案例 需求&#xff1a; 如上图所示&#xff0c;我们提供好了数据模型&#xff0c;users是数组集合&#xff0c;提供了多个用户信息。然后我们需要将数据以表格的形式&#xff0c;展示到页面上&#xff0c;其中&#xff0c;性别需要转换成中文男女&#xff0c;等级需要…

QTableWidget——表格的合并与拆分

一、整体思路 表格的操作使用QTableView::setSpan可以实现表格的行和列的合并 表格拆分没有对应的处理函数 主要思路&#xff1a;对表格的属性、内容、拆分与合并的参数进行存储&#xff0c;在进行拆分时对表格内容进行重新创建&#xff08;不考虑效率问题&#xff09; 二、效…

MyBatis使用注解操作及XML操作

文章目录 1. 注解操作1.1 打印日志1.2 参数传递1.3 增&#xff08;Insert&#xff09;注意1&#xff1a;重命名注意2&#xff1a;返回主键 1.4 删&#xff08;Delete&#xff09;1.5 改&#xff08;Update&#xff09;1.6 查&#xff08;Select&#xff09;1. 配置&#xff0c;…

Windows10下Tomcat8.5安装教程

文章目录 1.首先查看是否安装JDK。2.下载3.解压到指定目录&#xff08;安装路径&#xff09;4.启动Tomcat5.常见问题5.1.如果出现报错或者一闪而过5.2.Tomcat乱码 1.首先查看是否安装JDK。 CMD窗口输入命令 java -version 2.下载 历史版本下载地址&#xff1a;https://archi…

量化交易:传统小市值策略 VS AI市值策略

在BigQuant平台上可以快速开发股票传统策略和股票AI策略&#xff0c;今天拿市值因子来练手&#xff0c;看看两个策略在2015-01-01到2016-12-31这两年时间各自的收益风险情形。 市值因子是国内股票市场能够带来超额收益的alpha因子&#xff0c;已经被验证为长期有效的因子&…

向pycdc项目提的一个pr

向pycdc项目提的一个pr 前言 pycdc这个项目&#xff0c;我之前一直有在关注&#xff0c;之前使用他反编译python3.10项目&#xff0c;之前使用的 uncompyle6无法反编译pyhton3.10生成的pyc文件&#xff0c;但是pycdc可以&#xff0c;但是反编译效果感觉不如uncompyle6。但是版…

Appium混合页面点击方法tap的使用

原生应用开发&#xff0c;是在Android、IOS等移动平台上利用官方提供的开发语言、开发类库、开发工具进行App开发&#xff1b;HTML5&#xff08;h5&#xff09;应用开发&#xff0c;是利用Web技术进行的App开发。目前&#xff0c;市面上很多app都是原生和h5混合开发&#xff0c…

SELinux

目录 1.概述 1.1.概念 1.2.作用 1.3. SELinux与传统的权限区别 2. SELinux工作原理 2.1.名词解释 2.1.1.主体(Subject) 2.1.2.目标(Object) 2.1.3.策略(Policy) 2.1.4.安全上下文(Security Context) 2.2.文件安全.上下文查看 2.2.1.命令: 2.2.2.分析 3. **SELinu…

Flutter 3.16 中带来的更新

Flutter 3.16 中带来的更新 目 录 1. 概述2. 框架更新2.1 Material 3 成为新默认2.2 支持 Material 3 动画2.3 TextScaler2.4 SelectionArea 更新2.5 MatrixTransition 动画2.6 滚动更新2.7 在编辑菜单中添加附加选项2.8 PaintPattern 添加到 flutter_test 3. 引擎更新&#xf…

BUUCTF 被偷走的文件 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 一黑客入侵了某公司盗取了重要的机密文件&#xff0c;还好管理员记录了文件被盗走时的流量&#xff0c;请分析该流量&#xff0c;分析出该黑客盗走了什么文件。 密文&#xff1a; 下载附件&#xff0c;解压得到一个…

QT专栏1 -Qt安装教程

#本文时间2023年11月18日&#xff0c;Qt 6.6# Qt 安装简要说明&#xff1a; Qt有两个版本一个是商业版本&#xff08;收费&#xff09;&#xff0c;另一个是开源版本&#xff08;免费&#xff09;&#xff1b; 打开安装程序时&#xff0c;通过判断账号是否有公司&#xff0c;安…

【Linux系统化学习】进程的父子关系 | fork 进程

个人主页点击直达&#xff1a;小白不是程序媛 Linux专栏&#xff1a;Linux系统化学习 目录 前言&#xff1a; 父子进程 父子进程的引入 查看父子进程 查询进程的动态目录 更改进程的工作目录 fork创建进程 fork的引入 fork的使用 fork的原理 fork如何实现的&#…

搜索引擎ElasticSearch分布式搜索和分析引擎学习,SpringBoot整合ES个人心得

ElasticSearch Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java语言开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是一种流行的企业级搜索引擎。Elas…

ajax,axios,fetch

文章目录 ajax工作原理ajax发请求四个步骤创建xmlhttprequest对象设置请求方式设置回调函数发送请求 自封装ajax axiosaxios 特性如何用配置拦截器fetch 三者区别 ajax 工作原理 Ajax的工作原理相当于在用户和服务器之间加了—个中间层(AJAX引擎)&#xff0c;使用户操作与服务…

MFC 常用控件

目录 一、控件的交互方式 二、CButton/CheckBox/RadioButton 三、EditControl 四、ListBox 五、ComBox 六、Progress/Timer 七、PictureController 八、ListControl 九、Tree 一、控件的交互方式 得到控件的类的对象&#xff0c;就可以通过这个对象来操作类 CWnd* G…

Spring Framework 6.1 正式 GA

Spring Framework 6.1在运行时方面针对 JDK 21 和 Jakarta EE 10 上提供了一级支持&#xff0c;同时保留了 JDK 17 和 Jakarta EE 9 基线。Spring 还通过精细的元数据推理跟踪 GraalVM for JDK 21 的演变&#xff0c;同时暂时保持与 GraalVM 22.3 的兼容性。 主要变化 支持 JD…