九,自定义转换器详细操作(附+详细源码解析)

news2024/9/17 7:21:52

九,自定义转换器详细操作(附+详细源码解析)

文章目录

  • 九,自定义转换器详细操作(附+详细源码解析)
  • 1. 基本介绍
  • 2. 准备工作
  • 3. 自定义转换器操作
  • 4. 自定义转换器的注意事项和细节
  • 5. 总结:
  • 6. 最后:

Spring Boot 定义对象参数支持自动封装

  1. 在开发中,Spring Boot 在响应客户端请求时,也支持自定义对象参数
  2. 完成自动类型转换与格式化
  3. 支持级联封装

1. 基本介绍

  1. Spring Boot 在响应客户端请求时,将提交的数据封装成对象时,使用了内置的转换器。
  2. Spring Boot也支持自定义转换器,这个内置的转换器在debug的时候,可以看到,后面给大家演示,提供了 124个内置转换器,看下源码 GenericConverter ——> ConvertiblePair

在这里插入图片描述

2. 准备工作

在 pom.xml 文件当中配置相关的 jar 依赖。如下图所示:

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>springboot_parameters</artifactId>
    <version>1.0-SNAPSHOT</version>


    <!--    导入SpringBoot 父工程-规定写法-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <!--    导入web项目场景启动器:会自动导入和web开发相关的jar包所有依赖【库/jar】-->
    <!--    后面还会在说明spring-boot-starter-web 到底引入哪些相关依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

对应需要测试的 Bean 对象/POJO对象,两个 Car 和 Monster ,这里我们使用上 Lombok 插件,关于 Lombok的详细内容,大家可以移步至:✏️✏️✏️ 六,Spring Boot 容器中 Lombok 插件的详细使用,简化配置,提高开发效率-CSDN博客

在这里插入图片描述

package com.rainbowsea.springboot.bean;


import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class Car {
    private String name;
    private Double price;
}

package com.rainbowsea.springboot.bean;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;



@Data
@NoArgsConstructor
public class Monster {

    private Integer id;
    private String name;
    private Integer age;
    private Boolean isMarried;
    private Date birth;
    private Car car;
}

创建对应的controller 控制器,对应的请求路径的处理。

在这里插入图片描述


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;




//@RestController //  @Controller + @ResponseBody
@Controller
public class ParameterController {

    // 处理添加 monster 的方法
    @PostMapping("/savemonster")
    @ResponseBody
    public String saveMonster(Monster monster) {
        System.out.println("monster-" + monster);
        return "success";
    }
}

对应前端 ,浏览器提交数据的 表单 html 页面的编写内容。

自定义转换器关联 Car 对象,使用 , 号间隔。

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加妖怪</title>
</head>
<body>
<h1>添加妖怪-坐骑[测试封装POJO:]</h1>
<form action="/savemonster" method="post">
    编号: <input name="id" value="100"><br/>
    姓名: <input name="name" value="牛魔王"><br/>
    年龄: <input name="age" value="500"><br/>
    婚否: <input name="isMarried" value="true"><br/>
    生日: <input name="birth" value="2000/11/11"><br/>
<!--使用自定义转换器关联Car,字符串整体提交,使用,号间隔-->
    坐骑: <input name="car" value="避水金晶兽,666.6">
<!--    坐骑名称: <input name="car.name" value="法拉利"><br/>
    坐骑价格: <input name="car.price" value="999"><br/>-->
    <input type="submit" value="保存">

</form>
</body>
</html>

编写 Spring Boot 的应用程序的启动场景

在这里插入图片描述

package com.rainbowsea.springboot;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

3. 自定义转换器操作

编写 自定义转换器:将 前端的“String ”类型的数据转换为 后端“Car” 类型的数据 。

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.springboot.config;


import com.rainbowsea.springboot.bean.Car;
import com.rainbowsea.springboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration // 标志配置类
public class WebConfig {
    @Bean // 注如到 ioc容器当中
    public WebMvcConfigurer webMvcConfigurer() {

        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                /**
                 * 老师解读
                 * 1. 在addFormatters方法中,增加一个自定义的转换器
                 * 2. 增加自定义转换器 String->car
                 * 3. 增加的自定义转换器会注册到converters容器中
                 * 4. converters 底层结构时 ConcurrentHashMap 内置了124个转换器
                 * 5. 一会老师会使用 debug 来看到这些转换器
                 */
                registry.addConverter(new Converter<String, Car>() { // 第一个参数是要转换的类型,第二个参数是想要转换成什么类型
                    @Override
                    public Car convert(String source) {  // source 就是传入的字符串,避水金晶兽
                        // 这里就加入你的自定义的转换业务处理
                        //if(StringUtils) 或者 ObjectUtils 工具类都行。
                        if(!ObjectUtils.isEmpty(source)) {
                            Car car = new Car();
                            String[] split = source.split(",");
                            car.setName(split[0]);
                            car.setPrice(Double.parseDouble(split[1]));  // 将String类型的数据转换为 Double 类型的数据
                            return car;
                        }
                        return null;
                    }
                });
            }
        }
    }
}

运行测试:

在这里插入图片描述

上面是使用了 匿名的内部类 ,我们也可以不使用匿名内部类,分开来写也是可以的。

在这里插入图片描述

package com.rainbowsea.springboot.config;


import com.rainbowsea.springboot.bean.Car;
import com.rainbowsea.springboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration // 标志配置类
public class WebConfig {
    @Bean // 注如到 ioc容器当中
    public WebMvcConfigurer webMvcConfigurer() {

        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                /**
                 * 老师解读
                 * 1. 在addFormatters方法中,增加一个自定义的转换器
                 * 2. 增加自定义转换器 String->car
                 * 3. 增加的自定义转换器会注册到converters容器中
                 * 4. converters 底层结构时 ConcurrentHashMap 内置了124个转换器
                 * 5. 一会老师会使用 debug 来看到这些转换器
                 */
                Converter<String,Car> converter = new Converter<String, Car>() { // 第一个参数是要转换的类型,第二个参数是想要转换成什么类型
                    @Override
                    public Car convert(String source) {  // source 就是传入的字符串,避水金晶兽
                        // 这里就加入你的自定义的转换业务处理
                        //if(StringUtils)
                        if(!ObjectUtils.isEmpty(source)) {
                            Car car = new Car();
                            String[] split = source.split(",");
                            car.setName(split[0]);
                            car.setPrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                };
                // 添加自定义的转换器
                registry.addConverter(converter);
            }
        }

    }
}

运行测试:

在这里插入图片描述

注意:自定义转换器可以添加多个,默认 Spring Boot 内置的转换器是 124 个

这里,我们再添加一个转换器:将 前端的"Spring ’ 类型的数据,转换成 Monster 类型的数据,这里主要演示的是,可以添加多个自定义转换器,所以,自定义转换器内部的业务,我就不处理编写的,直接返回 null了。

在这里插入图片描述

package com.rainbowsea.springboot.config;


import com.rainbowsea.springboot.bean.Car;
import com.rainbowsea.springboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration // 标志配置类
public class WebConfig {
    @Bean // 注如到 ioc容器当中
    public WebMvcConfigurer webMvcConfigurer() {

        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                /**
                 * 老师解读
                 * 1. 在addFormatters方法中,增加一个自定义的转换器
                 * 2. 增加自定义转换器 String->car
                 * 3. 增加的自定义转换器会注册到converters容器中
                 * 4. converters 底层结构时 ConcurrentHashMap 内置了124个转换器
                 * 5. 一会老师会使用 debug 来看到这些转换器
                 */
                Converter<String,Car> converter = new Converter<String, Car>() { // 第一个参数是要转换的类型,第二个参数是想要转换成什么类型
                    @Override
                    public Car convert(String source) {  // source 就是传入的字符串,避水金晶兽
                        // 这里就加入你的自定义的转换业务处理
                        //if(StringUtils)
                        if(!ObjectUtils.isEmpty(source)) {
                            Car car = new Car();
                            String[] split = source.split(",");
                            car.setName(split[0]);
                            car.setPrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                };

                
                // 第2个自定义转换器
                // 还可以增加更多的转换器
                Converter<String,Monster> converter2 = new Converter<String, Monster>() { //
                    // 第一个参数是要转换的类型,第二个参数是想要转换成什么类型
                    @Override
                    public Monster convert(String source) {  // source 就是传入的字符串,避水金晶兽
                        // 这里就加入你的自定义的转换业务处理
                        //if(StringUtils)
                        if(!ObjectUtils.isEmpty(source)) {
                            Monster monster = new Monster();
                            String[] split = source.split(",");
                            return monster;
                        }
                        return null;
                    }
                };

                // 添加自定义的转换器
                registry.addConverter(converter);
                registry.addConverter(converter2);
            }
        }
    }
}


这里我们进行一个 Debug 进行追踪源码:看看是不是真的添加上了2个我们自己编写的转换器,记住Spring Boot 默认是 124个,这里我们添加了 2个就是 126个了

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4. 自定义转换器的注意事项和细节

从上面的我们的Debug分析可以知道的 Spring Boot 是使用 Map集合存储我们的转换器的,而对应 Map 当中的 key 就是我们转换的内容信息

=在这里插入图片描述

而 Map 集合当中 key 是唯一的不可以重复的,所以,当我们自定义了多个转换内容类型是重复(一样)的 转换器的时候,会覆盖掉,我们前面转换内容信息一样的 转换器。

如下:我们再定义一个“将 前端的“String ”类型的数据转换为 后端“Car” 类型的数据 的转换器”。

在这里插入图片描述

package com.rainbowsea.springboot.config;


import com.rainbowsea.springboot.bean.Car;
import com.rainbowsea.springboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration // 标志配置类
public class WebConfig {
    @Bean // 注如到 ioc容器当中
    public WebMvcConfigurer webMvcConfigurer() {

        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                /**
                 * 老师解读
                 * 1. 在addFormatters方法中,增加一个自定义的转换器
                 * 2. 增加自定义转换器 String->car
                 * 3. 增加的自定义转换器会注册到converters容器中
                 * 4. converters 底层结构时 ConcurrentHashMap 内置了124个转换器
                 * 5. 一会老师会使用 debug 来看到这些转换器
                 */
                Converter<String,Car> converter = new Converter<String, Car>() { // 第一个参数是要转换的类型,第二个参数是想要转换成什么类型
                    @Override
                    public Car convert(String source) {  // source 就是传入的字符串,避水金晶兽
                        // 这里就加入你的自定义的转换业务处理
                        //if(StringUtils)
                        if(!ObjectUtils.isEmpty(source)) {
                            Car car = new Car();
                            String[] split = source.split(",");
                            car.setName(split[0]);
                            car.setPrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                };


                // 添加转换器converter3 重复了
                Converter<String,Car> converter3 = new Converter<String, Car>() { // 第一个参数是要转换的类型,第二个参数是想要转换成什么类型
                    @Override
                    public Car convert(String source) {  // source 就是传入的字符串,避水金晶兽
                        // 这里就加入你的自定义的转换业务处理
                        //if(StringUtils)
                        if(!ObjectUtils.isEmpty(source)) {
                            System.out.println("source-" + source);
                        }
                        return null;
                    }
                };

                // 第2个自定义转换器
                // 还可以增加更多的转换器
                Converter<String,Monster> converter2 = new Converter<String, Monster>() { //
                    // 第一个参数是要转换的类型,第二个参数是想要转换成什么类型
                    @Override
                    public Monster convert(String source) {  // source 就是传入的字符串,避水金晶兽
                        // 这里就加入你的自定义的转换业务处理
                        //if(StringUtils)
                        if(!ObjectUtils.isEmpty(source)) {
                            Monster monster = new Monster();
                            String[] split = source.split(",");
                            return monster;
                        }
                        return null;
                    }
                };

                // 添加自定义的转换器
                registry.addConverter(converter);
                registry.addConverter(converter2);
                registry.addConverter(converter3);
            }
        };



    }
}

在这里插入图片描述

从上述结果上来看,我们可以十分清楚的明白了。

因为:因为Spring Boot是用 Map存储我们的转换器的,而Map其中的 key 存储的是我们转换器的内容信息,Spring Boot以我们转换的内容信息,作为 key 唯一,不可重复。所以一旦我们出现了,转换内容信息是一样的转换器,那么前面的转换器会被最后一个重复的转换器给替换掉。

5. 总结:

  1. Spring Boot 内置有 124 个转换器。我们可以自定义多个转换器。
  2. Spring Boot是用 Map 存储我们的转换器的,而Map其中的 key 存储的是我们转换器的内容信息,Spring Boot以我们转换的内容信息,作为 key 唯一,不可重复。所以一旦我们出现了,转换内容信息是一样的转换器,那么前面的转换器会被最后一个重复的转换器给替换掉。
  3. 实际开发中 Spring Boot 内置的 124个转换器,以及Spring Boot的自动封装对象的机制,足够我们实际开发中使用了。

6. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

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

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

相关文章

【前端学习】AntV G6-07 深入图形与图形分组、自定义节点、节点动画(上、中)

课程链接 AntV G6&#xff1a;深入图形与图形分组、自定义节点、节点动画&#xff08;上&#xff09;_哔哩哔哩_bilibili AntV G6&#xff1a;深入图形与图形分组、自定义节点、节点动画&#xff08;中&#xff09;_哔哩哔哩_bilibili 图形分组 Group | G6 (antgroup.com) 自…

ARM32开发——DMA内存到内存

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 需求数据交互流程开发流程依赖引入DMA初始DMA传输请求完整代码 关心的内容DMA初始化DMA初始化DMA数据传输请求完整代码 DMA中断开启…

封装智能指针 qt实现登录界面

1.封装独占智能指针——unique_ptr #include <iostream> #include <utility> // For std::move// 命名空间 namespace custom_memory { template <typename T> class myPtr { public:// 使用初始化列表进行初始化explicit myPtr(T* p nullptr) noexcept : …

卡西莫多的诗文集2022-2024.9月6-校庆国庆专版定版

通过网盘分享的文件&#xff1a;卡西莫多的诗文集2022-2024.9月6-A5-校庆国庆专版-定版.pdf 链接: https://pan.baidu.com/s/1cpFK5k1baGXbSGxY30GL_A?pwdjgnt 提取码: jgnt 卡西莫多的诗文集2022-2024.9月6-校庆国庆专版&#xff0c;又稍作修改并勘误了一些错字&#xff0c;…

AWQ量化(Activation-aware Weight Quantization)

论文&#xff1a; AWQ: Activation-aware Weight Quantization for On-Device LLM Compression and Acceleration 中文解读&#xff1a; 深入理解AWQ量化技术 - 知乎 (zhihu.com) 动机&#xff1a;端侧设备用LLM&#xff0c;为了减少显存占用量&#xff0c;所以要用INT4量化&am…

【Jupyter Notebook】汉化

1.打开:Anaconda Prompt 2.输入:"activate Zhui01"(注意&#xff1a;Zhui01是刚创建的环境名字) activate Zhui01 3.输入:"pip install jupyterlab-language-pack-zh-CN" pip install jupyterlab-language-pack-zh-CN 4.打开:Jupyter Notebook 5.点击&q…

Mysql高级篇(中)——七种常见的 join 查询图

注意&#xff1a; MySQL是不支持 FULL OUTER JOIN 这种语法的&#xff0c;因此要实现图中 6、7的查询结果&#xff0c;可以使用 UNION 关键字结合 LEFT JOIN、RIGHT JOIN 实现&#xff0c;UNION可以实现去重的效果&#xff1b; 参考如下代码&#xff1a; -- MySQL中 图标6 的实…

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物&#xff0c;今天我们实现一下人物实现移动和跳起&#xff0c;依次点击&#xff0c;我们准备创建一个C#文件 创建好我们点击进去&#xff0c;就会跳转到我们的Vision Studio&#xff0c;然后输入这些代码 using UnityEngine;public class M…

MarginNote 4 激活码 - 苹果电脑(Mac)全能型的阅读工具

对广大求学者来说&#xff0c;如何科学有效地掌握知识&#xff0c;一定是大家不懈追求的方向。 众多求学者使用的&#xff0c;深度阅读学习工具 MarginNote&#xff0c;终于为 Mac 推出了官网 4.0 版。带来了众多创新的学习辅助工具。 MarginNote 4 功能简介 1、快速理清各版…

大数据新视界--大数据大厂之Java 与大数据携手:打造高效实时日志分析系统的奥秘

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

探索fastFM:Python中的高效推荐系统库

文章目录 &#x1f680; 探索fastFM&#xff1a;Python中的高效推荐系统库背景&#xff1a;为何选择fastFM&#xff1f;快照&#xff1a;fastFM是什么&#xff1f;安装指南&#xff1a;如何将fastFM加入你的项目&#xff1f;快速入门&#xff1a;五个基础函数的使用实战演练&am…

猫眼电影字体破解(图片转码方法)

问题 随便拿一篇电影做样例。我们发现猫眼的页面数据在预览窗口中全是小方框。在当我们拿到源码以后&#xff0c;数据全是加密后的。所以我们需要想办法破解加密&#xff0c;拿到数据。 破解过程 1.源码获取问题与破解 分析 在我们刚刚请求url的时候是可以得到数据的&#xff…

halcon 由离散点云生成3d模型(2步)

一&#xff0c;创建立方体的3d坐标&#xff0c;定义X,Y,Z坐标 dev_open_window (0, 0, 512, 512, black, WindowHandle) x:[0,0,1,1,0,0,1,1] y:[0,1,1,0,0,1,1,0] z:[0,0,0,0,2,2,2,2] 二&#xff0c;由3创建3d模型&#xff08;在这里是将所有的点集合为一体&#xff09; ge…

多路转接之select(fd_set介绍,参数详细介绍),实现非阻塞式网络通信

目录 多路转接之select 引入 介绍 fd_set 函数原型 nfds readfds / writefds / exceptfds readfds 总结 fd_set操作接口 timeout timevalue 结构体 传入值 返回值 代码 注意点 -- 调用函数 select的参数填充 获取新连接 注意点 -- 通信时的调用函数 添…

JavaScript使用高德API显示地图

前言 在JavaScript中&#xff0c;使用Leaflet库显示地图是一种常见的做法。Leaflet是一个开源的JavaScript库&#xff0c;用于在Web应用程序中创建互动地图。它非常轻量级&#xff0c;易于使用&#xff0c;并且提供了多种功能&#xff0c;使开发者能够轻松地将地图集成到他们的…

【Python报错已解决】 SyntaxError: positional argument follows keyword argument

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;调整参数顺序2.2 步骤二…

银行贷款产品

1、对公贷款 1.1 一般贷款 按贷款期限可分为短期贷款和中长期贷款。短期贷款是指金融企业根据有关规定发放的,期限在1年(含1年)以下的各种贷款。中长期贷款是指金融企业发放的贷款期限在1年以上的各种贷款。 按提供方式不同可分为信用贷款、担保贷款等。信用贷款是指金融企…

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 &#xff08;1&#xff09;前后端的大致学习模块 &#xff08;2&#xff09;后端 &#xff08;3&#xff09;前端 二、开发模式 一、实战学习的引言 &#xff08;1&#xff09;前后端的大致学习模块 &#xff08;2&#xff09;后端 Validation&#xf…

ubuntu上通过openvswitch卸载实现roce over vxlan

环境 操作系统&#xff1a; uname -a Linux 5.4.0-187-generic #207-Ubuntu SMP Mon Jun 10 08:16:10 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux Mellanox网卡&#xff1a; ethtool -i ens6np0 driver: mlx5_core version: 23.10-2.1.3 firmware-version: 20.39.3004 (MT_0…

在Linux下查看HBA卡的速率和状态

平时在Linux下映射存储&#xff0c;都是映射哪台就给哪台插线&#xff0c;然后在存储端扫描WWPN&#xff0c;简单粗暴&#xff0c;没技术含量。当然&#xff0c;光交下也可以看。 1&#xff0c;查看当前卡的品牌&#xff0c;常用的卡有两种&#xff0c;Emulex和Qlogic。 lspc…