物流实时数仓ODS层——Mysql到Kafka

news2024/11/18 17:38:54

目录

1.采集流程

2.项目架构

3.resources目录下的log4j.properties文件

4.依赖

5.ODS层——OdsApp

6.环境入口类——CreateEnvUtil

7.kafka工具类——KafkaUtil

8.启动集群项目


        这一层要从Mysql读取数据,分为事实数据和维度数据,将不同类型的数据进行不同的ETL处理,发送到kakfa中。

代码

1.采集流程

2.项目架构

3.resources目录下的log4j.properties文件

log4j.rootLogger=error,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

4.依赖

<?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.atguigu.tms.realtime</groupId>
    <artifactId>tms-realtime</artifactId>
    <version>1.0-SNAPSHOT</version>


    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <flink.version>1.17.0</flink.version>
        <hadoop.version>3.3.4</hadoop.version>
        <flink-cdc.version>2.3.0</flink-cdc.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-java</artifactId>
            <version>${flink.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java</artifactId>
            <version>${flink.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-kafka</artifactId>
            <version>${flink.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.68</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-reload4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-clients</artifactId>
            <version>${flink.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
            <version>2.14.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.ververica</groupId>
            <artifactId>flink-connector-mysql-cdc</artifactId>
            <version>${flink-cdc.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-runtime</artifactId>
            <version>${flink.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-planner-loader</artifactId>
            <version>${flink.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>2.4.11</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-auth</artifactId>
            <version>${hadoop.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-reload4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-jdbc</artifactId>
            <version>3.1.0-1.17</version>
        </dependency>

        <dependency>
            <groupId>ru.yandex.clickhouse</groupId>
            <artifactId>clickhouse-jdbc</artifactId>
            <version>0.3.2</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.1.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <artifactSet>
                                <excludes>
                                    <exclude>com.google.code.findbugs:jsr305</exclude>
                                    <exclude>org.slf4j:*</exclude>
                                    <exclude>log4j:*</exclude>
                                    <exclude>org.apache.hadoop:*</exclude>
                                </excludes>
                            </artifactSet>
                            <filters>
                                <filter>
                                    <!-- Do not copy the signatures in the META-INF folder.Otherwise, this might cause SecurityExceptions when using the JAR. -->
                                    <!-- 打包时不复制META-INF下的签名文件,避免报非法签名文件的SecurityExceptions异常-->
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>

                            <transformers combine.children="append">
                                <!-- The service transformer is needed to merge META-INF/services files -->
                                <!-- connector和format依赖的工厂类打包时会相互覆盖,需要使用ServicesResourceTransformer解决-->
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

5.ODS层——OdsApp

package com.atguigu.tms.realtime.app.ods;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tms.realtime.utils.CreateEnvUtil;
import com.atguigu.tms.realtime.utils.KafkaUtil;
import com.esotericsoftware.minlog.Log;
import com.ververica.cdc.connectors.mysql.source.MySqlSource;
import com.ververica.cdc.debezium.JsonDebeziumDeserializationSchema;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.restartstrategy.RestartStrategies;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.kafka.sink.KafkaRecordSerializationSchema;
import org.apache.flink.connector.kafka.sink.KafkaSink;
import org.apache.flink.runtime.state.hashmap.HashMapStateBackend;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.CheckpointConfig;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.ProcessFunction;
import org.apache.flink.util.Collector;

/**
 * ODS数据的采集
 */
public class OdsApp {
    public static void main(String[] args) throws Exception {
        // TODO 1.获取流处理环境并指定检查点
        StreamExecutionEnvironment env = CreateEnvUtil.getStreamEnv(args);
        env.setParallelism(4);

        // TODO 2.使用FlinkCDC从Mysql中读取数据-事实数据-保存到kafka
        String dwdOption = "dwd";
        String dwdServerId = "6030";
        String dwdSourceName = "ods_app_dwd_source";
        mysqlToKafka(dwdOption, dwdServerId, dwdSourceName, env, args);

        // TODO 3.使用FlinkCDC从Mysql中读取数据-维度数据-保存到kafka
        String realtimeOption = "realtime_dim";
        String realtimeServerId = "6040";
        String realtimeSourceName = "ods_app_realtimeDim_source";
        mysqlToKafka(realtimeOption, realtimeServerId, realtimeSourceName, env, args);

        env.execute();
    }

    public static void mysqlToKafka(String option, String serverId, String sourceName, StreamExecutionEnvironment env, String[] args) {
        // TODO 1.使用FlinkCDC从Mysql中读取数据
        MySqlSource<String> mysqlSource = CreateEnvUtil.getMysqlSource(option, serverId, args);

        SingleOutputStreamOperator<String> strDS = env.fromSource(mysqlSource, WatermarkStrategy.noWatermarks(), sourceName)
                .setParallelism(1)// 并行度设置为1的原因是防止乱序
                .uid(option + sourceName);

        // TODO 2.简单的ETL
        SingleOutputStreamOperator<String> processDS = strDS.process(new ProcessFunction<String, String>() {
            @Override
            public void processElement(String jsonStr, ProcessFunction<String, String>.Context ctx, Collector<String> out) throws Exception {
                try {
                    // 将json字符串转为json对象
                    JSONObject jsonObj = JSON.parseObject(jsonStr);
                    // after属性不为空,并且不是删除
                    if (jsonObj.getJSONObject("after") != null && !"d".equals(jsonObj.getString("op"))) {
                        // 为了防止歧义,将ts_ms字段改为ts
                        Long tsMs = jsonObj.getLong("ts_ms");
                        jsonObj.put("ts", tsMs);
                        jsonObj.remove("ts_ms");// 移除原来的ts_ms字段
                        // 符合条件以后,向下传递之前先将json对象转为json字符串
                        out.collect(jsonObj.toJSONString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.error("从Flink-CDC得到的数据不是一个标准的json格式");
                }

            }
        }).setParallelism(1);// 防止乱序

        // TODO 3.按照主键进行分许,避免出现乱序,主键就是after下的id字段
        KeyedStream<String, String> keyedDS = processDS.keyBy(new KeySelector<String, String>() {
            @Override
            public String getKey(String jsonStr) throws Exception {
                // 获取当前的key
                // 流中的字符串转为json对象
                JSONObject jsonObj = JSON.parseObject(jsonStr);
                return jsonObj.getJSONObject("after").getString("id");
            }
        });

        //  TODO 4.将数据写到kafka主题中
                keyedDS.sinkTo(KafkaUtil.getKafkaSink("tms_ods", sourceName + "_transPre", args))
                .uid(option + "_ods_app_sink");
    }
}

6.环境入口类——CreateEnvUtil

package com.atguigu.tms.realtime.utils;

import com.esotericsoftware.minlog.Log;
import com.ververica.cdc.connectors.mysql.source.MySqlSource;
import com.ververica.cdc.connectors.mysql.source.MySqlSourceBuilder;
import com.ververica.cdc.connectors.mysql.table.StartupOptions;
import com.ververica.cdc.debezium.JsonDebeziumDeserializationSchema;
import org.apache.flink.api.common.restartstrategy.RestartStrategies;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.api.java.utils.ParameterTool;
import org.apache.flink.runtime.state.hashmap.HashMapStateBackend;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.environment.CheckpointConfig;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.hadoop.yarn.webapp.hamlet2.Hamlet;
import org.apache.kafka.connect.json.DecimalFormat;
import org.apache.kafka.connect.json.JsonConverterConfig;

import java.util.HashMap;

/**
 * 获取执行环境
 * flinkCDC读取mysqlSource的原因是将自己伪装成从机
 */
public class CreateEnvUtil {
    //获取流处理环境
    public static StreamExecutionEnvironment getStreamEnv(String[] args) {
        //TODO 1.基本环境准备
        //1.1 指定流处理环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        //TODO 2.检查点相关的设置
        //2.1 开启检查点
        env.enableCheckpointing(60000L, CheckpointingMode.EXACTLY_ONCE);
        //2.2 设置检查点的超时时间
        env.getCheckpointConfig().setCheckpointTimeout(120000L);
        //2.3 设置job取消之后 检查点是否保留
        env.getCheckpointConfig().setExternalizedCheckpointCleanup(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
        //2.4 设置两个检查点之间的最小时间间隔
        env.getCheckpointConfig().setMinPauseBetweenCheckpoints(30000L);
        //2.5 设置重启策略
        env.setRestartStrategy(RestartStrategies.failureRateRestart(3, Time.days(1), Time.seconds(3)));
        //2.6 设置状态后端
        env.setStateBackend(new HashMapStateBackend());
        env.getCheckpointConfig().setCheckpointStorage("hdfs://hadoop102:8020/tms/ck");
        //2.7 设置操作hdfs的用户
        //获取命令行参数
        ParameterTool parameterTool = ParameterTool.fromArgs(args);
        String hdfsUserName = parameterTool.get("hadoop-user-name", "atguigu");
        System.setProperty("HADOOP_USER_NAME", hdfsUserName);
        return env;
    }

    //获取MySqlSource
    public static MySqlSource<String> getMysqlSource(String option, String serverId, String[] args) {
        ParameterTool parameterTool = ParameterTool.fromArgs(args);
        String mysqlHostname = parameterTool.get("mysql-hostname", "hadoop102");
        int mysqlPort = Integer.valueOf(parameterTool.get("mysql-port", "3306"));
        String mysqlUsername = parameterTool.get("mysql-username", "root");
        String mysqlPasswd = parameterTool.get("mysql-passwd", "root");
        option = parameterTool.get("start-up-options", option);
        // serverId是对服务器节点进行标记
        serverId = parameterTool.get("server-id", serverId);

        // 创建配置信息 Map 集合,将 Decimal 数据类型的解析格式配置 k-v 置于其中
        HashMap config = new HashMap<>();
        config.put(JsonConverterConfig.DECIMAL_FORMAT_CONFIG, DecimalFormat.NUMERIC.name());
        // 将前述 Map 集合中的配置信息传递给 JSON 解析 Schema,该 Schema 将用于 MysqlSource 的初始化
        JsonDebeziumDeserializationSchema jsonDebeziumDeserializationSchema =
                new JsonDebeziumDeserializationSchema(false, config);

        MySqlSourceBuilder<String> builder = MySqlSource.<String>builder()
                .hostname(mysqlHostname)
                .port(mysqlPort)
                .username(mysqlUsername)
                .password(mysqlPasswd)
                .deserializer(jsonDebeziumDeserializationSchema);

        // 读取的数据可能是维度或事实,需要通过标记来区分,从而对不同类型的数据进不同的处理
        switch (option) {
            // 读取事实数据
            case "dwd":
                String[] dwdTables = new String[]{
                        "tms.order_info",
                        "tms.order_cargo",
                        "tms.transport_task",
                        "tms.order_org_bound"};// 只读取这4个事实表
                return builder
                        .databaseList("tms")
                        .tableList(dwdTables)
                        .startupOptions(StartupOptions.latest())// 表示从mysql的binlog最新位置读取最新的数据
                        .serverId(serverId)
                        .build();
            // 读取维度数据
            case "realtime_dim":
                String[] realtimeDimTables = new String[]{
                        "tms.user_info",
                        "tms.user_address",
                        "tms.base_complex",
                        "tms.base_dic",
                        "tms.base_region_info",
                        "tms.base_organ",
                        "tms.express_courier",
                        "tms.express_courier_complex",
                        "tms.employee_info",
                        "tms.line_base_shift",
                        "tms.line_base_info",
                        "tms.truck_driver",
                        "tms.truck_info",
                        "tms.truck_model",
                        "tms.truck_team"};// 读取维度数据表15张
                return builder
                        .databaseList("tms")
                        .tableList(realtimeDimTables)
                        .startupOptions(StartupOptions.initial())// 表示在第一次启动时对监控的数据库表执行初始快照,并继续读取最新的binlog。
                        .serverId(serverId)
                        .build();
            case "config_dim":
                return builder
                        .databaseList("tms_config")
                        .tableList("tms_config.tms_config_dim")
                        .startupOptions(StartupOptions.initial())
                        .serverId(serverId)
                        .build();
        }

        Log.error("不支持的操作类型!");
        return null;
    }
}

7.kafka工具类——KafkaUtil

package com.atguigu.tms.realtime.utils;

import org.apache.flink.api.common.serialization.DeserializationSchema;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.utils.ParameterTool;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.kafka.sink.KafkaRecordSerializationSchema;
import org.apache.flink.connector.kafka.sink.KafkaSink;
import org.apache.flink.connector.kafka.source.KafkaSource;
import org.apache.flink.connector.kafka.source.enumerator.initializer.OffsetsInitializer;
import org.apache.kafka.clients.consumer.OffsetResetStrategy;
import org.apache.kafka.clients.producer.ProducerConfig;

import java.io.IOException;

/**
 * 操作Kafka的工具类
 */
public class KafkaUtil {
    private static final String KAFKA_SERVER = "hadoop102:9092,hadoop103:9092,hadoop104:9092";

    // 获取kafkaSink的方法                                       事务id的前缀
    public static KafkaSink<String> getKafkaSink(String topic, String transIdPrefix, String[] args) {
        // 使用args参数的原因是为了从外部获取参数。在Java中,args是一个命令行参数数组,当你在命令行中运行Java程序时,你可以通过在命令行中输入参数来传递数据给程序。
        // 将命令行参数对象封装为 ParameterTool 类对象
        ParameterTool parameterTool = ParameterTool.fromArgs(args);

        // 提取命令行传入的 key 为 topic 的配置信息,并将默认值指定为方法参数 topic
        // 当命令行没有指定 topic 时,会采用默认值
        topic = parameterTool.get("topic", topic);
        // 如果命令行没有指定主题名称且默认值为 null 则抛出异常
        if (topic == null) {
            throw new IllegalArgumentException("主题名不可为空:命令行传参为空且没有默认值!");
        }

        // 获取命令行传入的 key 为 bootstrap-servers 的配置信息,并指定默认值
        String bootstrapServers = parameterTool.get("bootstrap-severs", KAFKA_SERVER);
        // 获取命令行传入的 key 为 transaction-timeout 的配置信息,并指定默认值
        String transactionTimeout = parameterTool.get("transaction-timeout", 15 * 60 * 1000 + "");

        KafkaSink<String> kafkaSink = KafkaSink.<String>builder()
                .setBootstrapServers(bootstrapServers)
                .setRecordSerializer(KafkaRecordSerializationSchema.builder()
                        .setTopic(topic)
                        .setValueSerializationSchema(new SimpleStringSchema())
                        .build()
                )
                .setDeliveryGuarantee(DeliveryGuarantee.EXACTLY_ONCE)
                .setTransactionalIdPrefix(transIdPrefix)
                .setProperty(ProducerConfig.TRANSACTION_TIMEOUT_CONFIG, transactionTimeout)
                .build();
        return kafkaSink;
    }

    // 使用这个就只需要传入topic和args即可
    public static KafkaSink<String> getKafkaSink(String topic, String[] args) {
        return getKafkaSink(topic, topic + "_trans", args);
    }
}

8.启动集群项目

开启消费者,然后启动java项目即可

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

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

相关文章

WPF前端实现人脸扫描动画效果

前言 本章实现的效果主要通过OpacityMask与LinearGradientBrush(径向渐变) 的组合应用来实现。最终实现效果如下: LinearGradientBrush线性渐变画刷 LinearGradientBrush其实很简单,我们只需要关注5个属性,使用这5个属性你就可以完成这个画刷几乎所有的变化。 属性介…

51综合程序01-DAC转换输出波形

文章目录 DAC转换输出波形使用DA转换输出正弦波&#xff0c;三角波&#xff0c;锯齿波&#xff08;1&#xff09;仿真电路图&#xff08;2&#xff09;源代码&#xff08;3&#xff09;实验结果 DAC转换输出波形 使用DA转换输出正弦波&#xff0c;三角波&#xff0c;锯齿波 &…

智能优化算法应用:基于入侵杂草算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于入侵杂草算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于入侵杂草算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.入侵杂草算法4.实验参数设定5.算法结果6.参考…

智慧城市包括哪些内容?有哪些智慧城市物联网方案?

数字城市、智慧城市的发展&#xff0c;离不开对公共基础设施的数字化、智慧化改造升级。通过融合边缘计算、5G、物联网、数字孪生、人工智能等新一代信息技术&#xff0c;助力传统公共基础设施提升增强全流程数据能力、计算能力、服务能力&#xff0c;从而不断丰富公共基础设施…

纹理烘焙:原理及实现

纹理烘焙是计算机图形学中常见的技术&#xff0c;用于将着色器的细节传输到纹理中。 如果你的着色器计算量很大&#xff0c;但会产生静态结果&#xff0c;例如&#xff0c;这非常有用。 复杂的噪音。 NSDT在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器…

【JMeter】菜单栏介绍

【菜单栏】 1. Tools 导入curl接口信息 作用&#xff1a;快速导入接口信息&#xff0c;响应头和缓存信息等 Log level临时修改日志等级 作用&#xff1a; 从勾选的level开始往更高等级level抓取log日志等级优先级&#xff1a; ALL < TRACE < DEBUG <INFO<WA…

汽车标定技术(十)--从CPU角度观察Overlay实现原理

目录 1.问题引入 2.功能概述 2.1 P1X 标定功能 2.2 MPC57xx标定功能 2.3 TC3xx标定功能 3.问题分析 3.1 英飞凌CPU子系统猜想 3.2 ARM内核CPU子系统分析 4.小结 1.问题引入 在分析瑞萨RH850-P1x系列、NXP S32K3系列和英飞凌TC3xx系列对标定测量功能的实现时&#xf…

JoySSL证书从申请到安装

为了保护网站和用户数据的安全&#xff0c;使用SSL证书是至关重要的一步。JoySSL是一种可靠的SSL证书提供商&#xff0c;它提供了简单易用的证书申请和安装流程。本文将详细介绍如何从申请到安装JoySSL证书的步骤。 一、申请JoySSL证书 1&#xff0c;访问JoySSL官方网站&#…

pycharm怎么同时打开2个项目?

pycharm怎么同时打开2个项目&#xff1f;当使用vue等前端的时候&#xff0c;后台也需要同时用pycharm打开操作&#xff0c;怎么用pycharm同时打开前后端呢&#xff1f; 当我们第一次用pycharm的时候&#xff0c;新建一个项目&#xff0c;习惯选择此窗口&#xff0c;而且勾选不再…

Linux:windows 和 Linux 之间文本格式转换

背景 在 Windows 上编辑的文件&#xff0c;放到 Linux 平台&#xff0c;有时会出现奇怪的问题&#xff0c;其中有一个是 ^M 引起的&#xff0c;例如这种错误&#xff1a; /bin/bash^M: bad interpreter 这个问题相信大家也碰到过&#xff0c;原因是 Windows 和 Linux 关于换行的…

2023.11.30 homework

兴趣最重要了&#xff0c;没兴趣不喜欢勉强带来的苦楚&#xff0c;并不能促使变好变优秀。 虽然我们的社会环境依旧很残酷&#xff0c;各种各样的硬性要求。

1、底层世界单片机

一、单片机简介 单片机是单片微型计算机的简称&#xff0c;MCU是Microcontroller的简称&#xff0c;也就是嵌入式微控制器。采用集成电路技术将具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、定时器/计时器、多种I/O口和中断系统等功能集成到一块硅片上。可…

Jenkins 如何查看已经记录登录服务器的凭证密码

文章目录 一、背景描述二、解决方案一&#xff08;查看所有账号密码&#xff09;三、解决方案二&#xff08;查询指定账号密码&#xff09; 一、背景描述 在日常的开发过程中&#xff0c;有时候会出现忘记开发、测试服务器的登录密码的情况。此时恰巧 Jenkins 上记录了登录该主…

java后端自学总结

自学总结 MessageSource国际化接口总结 MessageSource国际化接口 今天第一次使用MessageSource接口,比较意外遇到了一些坑 messageSource是spring中的转换消息接口&#xff0c;提供了国际化信息的能力。MessageSource用于解析 消息&#xff0c;并支持消息的参数化和国际化。 S…

mount创建本地yum源报错no medium found on /dev/sr0

今天在为服务器配置本地yum源的时候系统报错&#xff1a; 原因&#xff1a;经检查发现是设置cd/dvd的问题。 只要在虚拟机设置——硬件——CD/DVD处&#xff0c;将CD/DVD设置为连接即可

mockito加junit gd 单元测试 笔记

目录 一、简介1.1 单元测试的特点1.2 mock类框架使用场景1.3 常用mock类框架1.3.1 mockito1.3.2 easymock1.3.3 powermock1.3.4 JMockit 二、mockito的单独使用2.1 mock对象与spy对象2.2 初始化mock/spy对象的方式2.3 参数匹配2.4 方法插桩2.5 InjectMocks注解的使用断言工具 三…

Apache Flink(三):Flink核心特性及应用场景

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

chapter10-homework-Java

第十章作业 Homework01知识点 Homework02知识点 Homework03知识点 Homework04知识点 Homework05知识点 Homework06Homework07Homework08 Homework01 分析执行结果。 public static void main(String[] args) {Car_ c new Car_();Car_ c1 new Car_(100);System.out.println(…

YOLOv5独家原创改进:自研独家创新FT_Conv,卷积高效结合傅里叶分数阶变换

💡💡💡本文自研创新改进:卷积如何有效地和频域结合,引入分数阶傅里叶变换(FrFT)和分数阶Gabor变换(FrGT),最终创新到YOLOv5。 使用方法:1)直接替换原来的C2f;2)放在backbone SPPF后使用;等 推荐指数:五星 在道路缺陷检测任务中,原始map为0.8,FT_Conv为0.82 …