首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

以MySQL为例,来看看maven-shade-plugin如何解决多版本驱动共存的问题?

编程知识
2024年09月02日 07:49

开心一刻

清明节那天,看到一小孩在路边烧纸
时不时地偷偷往火堆里扔几张考试卷子
边烧边念叨:爷爷呀,你岁数大了,在那边多做做题吧,对脑子好,要是有不懂的地方,就把我老师带走,让他教您!

开心一刻

前提说明

假设 MySQL 5.7.36 的库 qsl_datax

mysql5

有表 qsl_datax_source 和 数据

CREATE TABLE `qsl_datax_source`  (
  `id` bigint(20) NOT NULL COMMENT '自增主键',
  `username` varchar(255) NOT NULL COMMENT '姓名',
  `password` varchar(255) NOT NULL COMMENT '密码',
  `birth_day` date NOT NULL COMMENT '出生日期',
  `remark` text,
  PRIMARY KEY (`id`)
) ENGINE = InnoDB ;
INSERT INTO `qsl_datax_source` VALUES (1, '张三', 'z123456', '1991-01-01', '张三');
INSERT INTO `qsl_datax_source` VALUES (2, '李四', 'l123456', '1992-01-01', '李四');
INSERT INTO `qsl_datax_source` VALUES (3, '王五', 'w123456', '1993-01-01', '王五');
INSERT INTO `qsl_datax_source` VALUES (4, '麻子', 'm123456', '1994-01-01', '麻子');

需要将表中数据同步到 MySQL 8.0.30

mysql8

sql_db 库的 qsl_datax_source 表中,并且只用 JDBC 的方式,该如何实现?你们可能觉得非常简单,直接引入 mysql-connector-j 依赖

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>

然后直接写同步代码

public static void main(String[] args) throws Exception {
    String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
    String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
    Properties pro = new Properties();
    pro.put("user", "root");
    pro.put("password", "123456");
    // 加载驱动类
    Class.forName("com.mysql.cj.jdbc.Driver");
    // 建立连接
    Connection conn5 = DriverManager.getConnection(url5, pro);
    // 查数据
    Statement statement = conn5.createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * FROM qsl_datax_source");
    StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES ");
    while (resultSet.next()) {
        // 拼接sql
        insertSql.append("(")
                .append(resultSet.getLong("id")).append(",")
                .append("'").append(resultSet.getString("username")).append("',")
                .append("'").append(resultSet.getString("password")).append("',")
                .append("'").append(resultSet.getString("birth_day")).append("',")
                .append("'").append(resultSet.getString("remark")).append("'")
                .append("),");
    }
    // 因为mysql5和mysql8的账密是一样的,所以用的同一个 pro
    Connection conn8 = DriverManager.getConnection(url8, pro);
    Statement stmt = conn8.createStatement();
    int count = stmt.executeUpdate(insertSql.substring(0, insertSql.length() - 1));
    System.out.println("新插入记录数:" + count);

    resultSet.close();
    statement.close();
    stmt.close();
    conn5.close();
    conn8.close();
}

执行后输出

新插入记录数:4

MySQL 8.0.30 的库 sql_db 查看表 qsl_datax_source 的数据

同驱动同步成功

同步完成,这不是有手就行吗?

行不行

一般来说,高版本的驱动会兼容低版本的数据库,但也不绝对,或者说兼容不全;MySQL版本、驱动版本、JDK版本对应关系如下

mysql版本驱动版本jdk版本对应关系

mysql-connector-j 8.0.33 驱动兼容 MySQL 5.7.36,所以上面的同步没问题,但如果 MySQL 版本很低(比如:5.1.x),例如从 MySQL 5.1.8 同步到 MySQL 8.0.30 ,如上同步代码还能同步成功吗(我就不去试了,你们也别去试了,因为引申目的已经达到了),所以保险做法是

mysql-connector-j 8.0.33 操作 MySQL 8.0.30

mysql-connector-java 5.1.49 操作 MySQL 5.7.36

mysql-connector-java 5.0.x 操作 MySQL 5.0.x

所以问题就来了

如何用 mysql-connector-java 5.1.49 从 MySQL 5.7.36 查数据后,用 mysql-connector-j 8.0.33 将数据插入 MySQL 8.0.30

多驱动操作

你们肯定也觉得简单,继续引入 mysql-connector-java 5.1.49 依赖

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.49</version>
</dependency>

然后调整代码

public static void main(String[] args) throws Exception {
    String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
    String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
    Properties pro = new Properties();
    pro.put("user", "root");
    pro.put("password", "123456");
    // 加载驱动类
    Class.forName("com.mysql.jdbc.Driver");
    // 建立连接
    Connection conn5 = DriverManager.getConnection(url5, pro);
    // 查数据
    Statement statement = conn5.createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * FROM qsl_datax_source");
    StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES ");
    while (resultSet.next()) {
        // 拼接sql
        insertSql.append("(")
                .append(resultSet.getLong("id")).append(",")
                .append("'").append(resultSet.getString("username")).append("',")
                .append("'").append(resultSet.getString("password")).append("',")
                .append("'").append(resultSet.getString("birth_day")).append("',")
                .append("'").append(resultSet.getString("remark")).append("'")
                .append("),");
    }
    Class.forName("com.mysql.cj.jdbc.Driver");
    // 因为mysql5和mysql8的账密是一样的,所以用的同一个 pro
    Connection conn8 = DriverManager.getConnection(url8, pro);
    Statement stmt = conn8.createStatement();
    int count = stmt.executeUpdate(insertSql.substring(0, insertSql.length() - 1));
    System.out.println("新插入记录数:" + count);

    resultSet.close();
    statement.close();
    stmt.close();
    conn5.close();
    conn8.close();
}

和之前代码对比下

多驱动使用前后代码比较

调整甚微;执行后输出结果如下

Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
新插入记录数:4

如果只从结果来看,确实同步成功了,但第一行的 警告 值得得我们琢磨下

类 com.mysql.jdbc.Driver 加载中。这个类已经被弃用。新的驱动类是 com.mysql.cj.jdbc.Driver,这个驱动通过 SPI 机制已经自动注册了,不需要手动加载

从中我们会产生 2 个疑问

  1. com.mysql.jdbc.Driver 不应该是 mysql-connector-java 5.1.49 的吗,怎么会被弃用
  2. SPI 机制是什么,com.mysql.cj.jdbc.Driver 什么时候加载的

我们先来看问题 2,关于 SPI 机制可查看

记一次 JDK SPI 配置不生效的问题 → 这么简单都不会,还是回家养猪吧

DriverManager 有静态代码块

static {
    loadInitialDrivers();
    println("JDBC DriverManager initialized");
}

loadInitialDrivers() 中有这样一段代码

loadInitialDrivers

自动加载了驱动,而驱动类中往往有类似如下代码

驱动类注册驱动实例

将驱动实例注册给 DriverManager,所以不需要再去手动加载驱动类了

从 JDBC 4.0 开始,JDBC 驱动支持自动加载功能,不再需要调用 Class.forName 来加载驱动

我们回到问题 1,同步的告警信息

Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

肯定是 mysql-connector-j 8.0.33 告警出来的,因为 mysql-connector-java 5.1.49 没有类

com.mysql.cj.jdbc.Driver

对不对?全局搜索下

This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'

同步告警信息出处

点进去,我们会发现 mysql-connector-j 8.0.33 也有类

com.mysql.jdbc.Driver

大家看仔细了,这个 Driver 是没有把自己的实例注册进 java.sql.DriverManager

mysql8驱动com_mysql_jdbc_Driver类

这说明什么,说明是从 mysql-connector-j 8.0.33 加载的类:com.mysql.jdbc.Driver,而不是从 mysql-connector-java 5.1.49 加载

我们来捋一捋整个同步流程

  1. 通过 SPI 机制,会加载文件 META-INF/services/java.sql.Driver 中配置的类

    mysql-connector-j 8.0.33 的 java.sql.Driver 文件内容

    mysql8驱动java_sql_Driver

    mysql-connector-java 5.1.49 的 java.sql.Driver 文件内容

    mysql5驱动_java_sql_Driver

    类加载器加载 com.mysql.cj.jdbc.Driver 的时候,毫无疑问找到的肯定是 mysql-connector-j 8.0.33 jar包中的,而加载 com.mysql.jdbc.Driver 的时候,类加载器找到的却是 mysql-connector-j 8.0.33 jar包中的,而非 mysql-connector-java 5.1.49 jar包中的,所以告警了

  2. 代码中手动调用 Class.forName("com.mysql.jdbc.Driver"); 进行类加载,根据 双亲委派模型,已经加载过的类不会再加载,所以相当于没做任何操作

    前面的告警信息不是这里触发出来的!!!不信的话可以注释掉该行代码执行下,你们会发现仍有同样的告警信息

  3. 从 MySQL5 查数据,用的驱动实际是 com.mysql.cj.jdbc.Driver

    连接mysql5的实际驱动

    因为 DriverManager 中合适的驱动只有这一个

  4. 代码中手动调用 Class.forName("com.mysql.cj.jdbc.Driver"); 进行类加载,根据 双亲委派模型,已经加载过的类不会再加载,所以相当于没做任何操作

  5. 从 MySQL8 查数据,用的驱动毫无疑问也只能是 com.mysql.cj.jdbc.Driver

所以整个同步,用的都是 mysql-connector-j 8.0.33 下的驱动,mysql-connector-java 5.1.49 压根就没用到,是不是在你们的意料之外?

小孩 震惊

所以如何实现我们最初的想法?

如何用 mysql-connector-java 5.1.49 从 MySQL 5.7.36 查数据后,用 mysql-connector-j 8.0.33 将数据插入 MySQL 8.0.30

maven-shade-plugin

甲方扔给两个存在包名与类名均相同的Jar包,要在工程中同时使用怎么办? 中谈到了好些解决办法,但 maven-shade-plugin 相对而言是最优解,其具体使用可参考

maven 插件之 maven-shade-plugin,解决同包同名 class 共存问题的神器

那如何应该到当前案例中来了,其实很简单,只需要用到 maven-shade-plugin 的 重定位 class 功能即可,请看我表演

  1. 对 mysql-connector-j 8.0.33 进行 class 重定位

    新建一个工程 mysql-jdbc,没有任何代码和配置文件

    mysql-jdbc8

    只有一个 pom.xml

    <?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.qsl</groupId>
        <artifactId>mysql-jdbc8</artifactId>
        <version>8.0.33</version>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>8.0.33</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.6.0</version>
                    <executions>
                        <execution>
                            <!-- 和 package 阶段绑定 -->
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <relocations>
                                    <relocation>
                                        <pattern>com.mysql.jdbc</pattern>
                                        <shadedPattern>com.mysql.jdbc8</shadedPattern>
                                    </relocation>
                                </relocations>
                                <filters>
                                    <filter>
                                        <artifact>com.qsl:mysql-jdbc8</artifact>
                                        <excludes>
                                            <exclude>META-INF/*.*</exclude>
                                        </excludes>
                                    </filter>
                                </filters>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    

    mvn install 一下,将重新打包后的 jar 部署到本地仓库

    mysql-jdbc8_8_0_30
  2. 调整示例代码的 maven 依赖

    mysql-connector-j 8.0.33 调整成 mysql-jdbc8 8.0.33,mysql-connector-java 5.1.49 原样保留

    <dependencies>
        <dependency>
            <groupId>com.qsl</groupId>
            <artifactId>mysql-jdbc8</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>
    
  3. 调整同步代码

    去掉手动加载驱动,增加 connection 驱动信息版本输出

    public static void main(String[] args) throws Exception {
        String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
        String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
        Properties pro = new Properties();
        pro.put("user", "root");
        pro.put("password", "123456");
        // 建立连接
        Connection conn5 = DriverManager.getConnection(url5, pro);
        // 查数据
        Statement statement = conn5.createStatement();
        System.out.println("conn5 driver version: " + conn5.getMetaData().getDriverVersion());
        ResultSet resultSet = statement.executeQuery("SELECT * FROM qsl_datax_source");
        StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES ");
        while (resultSet.next()) {
            // 拼接sql
            insertSql.append("(")
                    .append(resultSet.getLong("id")).append(",")
                    .append("'").append(resultSet.getString("username")).append("',")
                    .append("'").append(resultSet.getString("password")).append("',")
                    .append("'").append(resultSet.getString("birth_day")).append("',")
                    .append("'").append(resultSet.getString("remark")).append("'")
                    .append("),");
        }
        // 因为mysql5和mysql8的账密是一样的,所以用的同一个 pro
        Connection conn8 = DriverManager.getConnection(url8, pro);
        System.out.println("conn8 driver version: " + conn8.getMetaData().getDriverVersion());
        Statement stmt = conn8.createStatement();
        int count = stmt.executeUpdate(insertSql.substring(0, insertSql.length() - 1));
        System.out.println("新插入记录数:" + count);
    
        resultSet.close();
        statement.close();
        stmt.close();
        conn5.close();
        conn8.close();
    }
    

处理就算完成,我们执行一下看结果

maven-shade-plugin改造后执行结果

之前的警告确实没了,但新的问题又来了:为什么驱动用的是同一个,mysql-connector-java 5.1.49 中的驱动为什么没有被用到?

一个bug改一天

mysql-connector-java 5.1.49 中的 com.mysql.jdbc.Driver 肯定是被正常加载了,并且注册到了 DriverManager 中,这点大家认同不?(不认同也没关系,后面会得到证明)那它为什么没有被使用了,我们需要跟一下 DriverManager.getConnection 的源码了;源码跟进去比较简单,我就带你们一步一步跟了,最终回来到如下方法

java.sql.DriverManager#getConnection(java.lang.String, java.util.Properties, java.lang.Class<?>)

这个方法里面有这么一段代码

for(DriverInfo aDriver : registeredDrivers) {
    // If the caller does not have permission to load the driver then
    // skip it.
    if(isDriverAllowed(aDriver.driver, callerCL)) {
        try {
            println("    trying " + aDriver.driver.getClass().getName());
            Connection con = aDriver.driver.connect(url, info);
            if (con != null) {
                // Success!
                println("getConnection returning " + aDriver.driver.getClass().getName());
                return (con);
            }
        } catch (SQLException ex) {
            if (reason == null) {
                reason = ex;
            }
        }

    } else {
        println("    skipping: " + aDriver.getClass().getName());
    }

}

我们打个断点跟一下(com.mysql.cj.jdbc.Driver 排在 com.mysql.jdbc.Driver 前面!!!)

debug_驱动列表

isDriverAllowed 作用是检查一个给定的Driver对象是否被允许通过指定的ClassLoader加载,我们不需要关注,而我们需要关注的是

Connection con = aDriver.driver.connect(url, info);

跟进去来到 com.mysql.cj.jdbc.NonRegisteringDriver#connect

debug_connect

感兴趣的可以继续跟进 ConnectionUrl.acceptsUrl(url),但我觉得没必要了,很明显就是根据正则表达式去匹配 url,看看是否适配,因为 MySQL5 的 url 与 MySQL8 的 URL 格式一致

String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";

因为 com.mysql.cj.jdbc.Driver 排在 com.mysql.jdbc.Driver 前面,所以用它连接了 MySQL5 和 MySQL8,前面的问题

为什么驱动用的是同一个,mysql-connector-java 5.1.49 中的驱动为什么没有被用到?

是不是就清楚了?你们可能又有疑问了:为什么不是 com.mysql.jdbc.Driver 排在前面?这个跟类加载的顺序有关,超出了本文范围,你们自行去查阅。那还能实现最初的目的吗

用 mysql-connector-java 5.1.49 从 MySQL 5.7.36 查数据后,用 mysql-connector-j 8.0.33 将数据插入 MySQL 8.0.30

肯定是能的,看我调整下代码

public static void main(String[] args) throws Exception {
    String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
    String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
    Properties pro = new Properties();
    pro.put("user", "root");
    pro.put("password", "123456");

    // 建立连接
    Driver driver5 = getDriver("com.mysql.jdbc.Driver");
    Connection conn5 = driver5.connect(url5, pro);
    // 查数据
    Statement statement = conn5.createStatement();
    System.out.println("conn5 driver version: " + conn5.getMetaData().getDriverVersion());
    ResultSet resultSet = statement.executeQuery("SELECT * FROM qsl_datax_source");
    StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES ");
    while (resultSet.next()) {
        // 拼接sql
        insertSql.append("(")
                .append(resultSet.getLong("id")).append(",")
                .append("'").append(resultSet.getString("username")).append("',")
                .append("'").append(resultSet.getString("password")).append("',")
                .append("'").append(resultSet.getString("birth_day")).append("',")
                .append("'").append(resultSet.getString("remark")).append("'")
                .append("),");
    }
    // 因为mysql5和mysql8的账密是一样的,所以用的同一个 pro
    Driver driver8 = getDriver("com.mysql.cj.jdbc.Driver");
    Connection conn8 = driver8.connect(url8, pro);
    System.out.println("conn8 driver version: " + conn8.getMetaData().getDriverVersion());
    Statement stmt = conn8.createStatement();
    int count = stmt.executeUpdate(insertSql.substring(0, insertSql.length() - 1));
    System.out.println("新插入记录数:" + count);

    resultSet.close();
    statement.close();
    stmt.close();
    conn5.close();
    conn8.close();
}

private static Driver getDriver(String driverClassName) {
    Enumeration<Driver> drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver driver = drivers.nextElement();
        if (driver.getClass().getName().equals(driverClassName)) {
            return driver;
        }
    }
    throw new RuntimeException("未找到驱动:" + driverClassName);
}

执行一下看结果

改造成功_执行结果

此时我就想说一句:还有谁?

还有谁

总结

  1. 示例代码:mysql-driver-demo

    不包括 mysql-jdbc8 的代码

  2. 就 MySQL 而言,mysql-connector-j 8 驱动兼容 MySQL 5.5、5.6、5.7,实际工作中是可以用 mysql-connector-j 8 去连 MySQL 5.7的

  3. SQL Server 就存在驱动不兼容的情况

    Microsoft JDBC Driver for SQL Server 支持矩阵

    SQLServer驱动兼容情况
  4. maven-shade-plugin 来实现多版本驱动的共存,简单高效,值得掌握!

    maven 插件之 maven-shade-plugin,解决同包同名 class 共存问题的神器

From:https://www.cnblogs.com/youzhibing/p/18390525
本文地址: http://shuzixingkong.net/article/1649
0评论
提交 加载更多评论
其他文章 【解决方案】项目重构之如何使用 MySQL 替换原来的 MongoDB
笔者今天要分享的是一个项目重构过程中如何将数据库选型由原来的 MongoDB 改为 MySQL 的思考,涉及到业务当前的痛点、选型分析、解决的核心思路,最后会给出简单的 demo。
【解决方案】项目重构之如何使用 MySQL 替换原来的 MongoDB 【解决方案】项目重构之如何使用 MySQL 替换原来的 MongoDB
博客园20年纪念T恤上架:艰难的时光,燃烧的希望
2024年9月开始了,救园的最后一个月到了,园子的20年纪念T恤终于赶在天凉好个秋之前上架了。用这件设计简约清新给人希望的T恤,纪念过去二十年充满艰难而满怀希望的时光。园子的二十年,是困难重重的二十年,是走了很多弯路摔了很多跟头的二十年,但也是心中一直燃烧着希望的二十年
博客园20年纪念T恤上架:艰难的时光,燃烧的希望 博客园20年纪念T恤上架:艰难的时光,燃烧的希望 博客园20年纪念T恤上架:艰难的时光,燃烧的希望
【工程应用十二】Bayer图像格式中Hamilton-Adams及Zhang Wu 基于LMMSS算法的Demosaic过程优化。
Demosaic,中文直接发翻译为去马赛克, 但是其本质上并不是去除马赛克,这让很多第一次接触这个名词或者概念的人总会想的更多。本文提供了经典的HA算法代码,并针对HA的缺点,分析了Zhang Wu基于LMMSE算法改进后的优化过程。
【工程应用十二】Bayer图像格式中Hamilton-Adams及Zhang Wu 基于LMMSS算法的Demosaic过程优化。 【工程应用十二】Bayer图像格式中Hamilton-Adams及Zhang Wu 基于LMMSS算法的Demosaic过程优化。 【工程应用十二】Bayer图像格式中Hamilton-Adams及Zhang Wu 基于LMMSS算法的Demosaic过程优化。
Go plan9 汇编:说透函数栈
原创文章,欢迎转载,转载请注明出处,谢谢。 0. 前言 函数是 Go 的一级公民,本文从汇编角度出发看看我们常用的一些函数在干什么。 1. 函数 1.1 main 函数 在 main 函数中计算两数之和如下: package main func main() { x, y := 1, 2 z :=
Go plan9 汇编:说透函数栈 Go plan9 汇编:说透函数栈 Go plan9 汇编:说透函数栈
金九银十来了,你的简历写好了么?
大家好,我是晓凡。 写在前面 时间过得真快,转眼间就来到了九月份。都说金九银十,又到了一年一度的求职跳槽黄金季。 这两年就业环境应该不用我多说了吧,只能用一个惨字来形容。 即使就业环境再怎么不堪,但毕业了工作总要找的,总不可能啃老摆烂吧。 在这竞争激烈的时期,一份优质的简历,无疑是你求职路上的敲门砖
金九银十来了,你的简历写好了么? 金九银十来了,你的简历写好了么? 金九银十来了,你的简历写好了么?
PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
我们在某宝或某多多上抢购商品时,如果只是下了订单但没有进行实际的支付,那在订单页面会有一个支付倒计时,要是过了这个时间点那么订单便会自动取消。在这样的业务场景中,一般情况下就会使用到延时队列。
PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践 PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践 PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
【ETL工具】DataX + DataXWeb 初使用过程记录
ETL:将大量的原始数据,经过抽取(Extract)和清洗转换(Transform)后,加载(Load)到目的端的过程,称为ETL,实现这种过程的工具,也就是ETL工具 版本:DataX v202309 DataXWeb 2.1.3-alpha-release DataX:阿里云开源的一个异构数据源
【ETL工具】DataX + DataXWeb  初使用过程记录 【ETL工具】DataX + DataXWeb  初使用过程记录 【ETL工具】DataX + DataXWeb  初使用过程记录
WiFi基础(二):最新WiFi信道、无线OSI模型与802.11b/g/n
liwen01 2024.09.01 前言 最近十几年,通信技术发展迅猛,通信标准更新频繁,有的设备还在使用 802.11/b/g/n 协议,有的已支持到 WiFi6、WiFi7。 而国内有关无线 WiFi 的书籍或资料却很少,就算能找着的,大多也是比较老旧。本文试图使用最新的数据来介绍 WiFi
WiFi基础(二):最新WiFi信道、无线OSI模型与802.11b/g/n WiFi基础(二):最新WiFi信道、无线OSI模型与802.11b/g/n WiFi基础(二):最新WiFi信道、无线OSI模型与802.11b/g/n