【数仓】DataX 通过SpringBoot项目自动生成 job.json 文件

相关文章

  • 【数仓】基本概念、知识普及、核心技术
  • 【数仓】数据分层概念以及相关逻辑
  • 【数仓】Hadoop软件安装及使用(集群配置)
  • 【数仓】Hadoop集群配置常用参数说明
  • 【数仓】zookeeper软件安装及集群配置
  • 【数仓】kafka软件安装及集群配置
  • 【数仓】flume软件安装及配置
  • 【数仓】flume常见配置总结,以及示例
  • 【数仓】Maxwell软件安装及配置,采集mysql数据
  • 【数仓】通过Flume+kafka采集日志数据存储到Hadoop
  • 【数仓】DataX软件安装及配置,从mysql同步到hdfs

DataX的任务脚本job.json格式基本类似,而且我们在实际同步过程中通常都是一个表对应一个job,那么如果需要同步的表非常多的话,需要编写的job.json文件也非常多。既然是类似文件结构,那么我们就有办法通过程序自动生成相关的job.json文件。

居于以上考虑,有了下面的SpringBoot项目自动生成job.json的程序!

一、job 配置说明

DataX的job配置中的readerwritersetting是构成数据同步任务的关键组件。

1、reader

reader是数据同步任务中的数据源读取配置部分,用于指定从哪个数据源读取数据以及如何读取数据。它通常包含以下关键信息:

  • name: 读取插件的名称,如mysqlreaderhdfsreader等,用于指定从哪种类型的数据源读取数据。
  • parameter: 具体的读取参数配置,包括数据源连接信息、读取的表或文件路径、字段信息等。

示例
假设要从MySQL数据库读取数据,reader的配置可能如下:

"reader": {"name": "mysqlreader","parameter": {"username": "root","password": "password","column": ["id", "name", "age"],"connection": [{"jdbcUrl": "jdbc:mysql://localhost:3306/test_db","table": ["test_table"]}]}
}

2、writer

writer是数据同步任务中的目标数据源写入配置部分,用于指定将数据写入哪个目标数据源以及如何写入数据。它通常包含以下关键信息:

  • name: 写入插件的名称,如mysqlwriterhdfswriter等,用于指定将数据写入哪种类型的数据源。
  • parameter: 具体的写入参数配置,包括目标数据源连接信息、写入的表或文件路径、字段映射等。

示例
假设要将数据写入HDFS,writer的配置可能如下:

"writer": {"name": "hdfswriter","parameter": {"writeMode": "append","fieldDelimiter": ",","compress": "gzip","column": [{"name": "id", "type": "int"}, {"name": "name", "type": "string"}, {"name": "age", "type": "int"}],"connection": [{"hdfsUrl": "hdfs://localhost:9000","file": ["/user/hive/warehouse/test_table"]}]}
}

3、setting

setting是数据同步任务的全局设置部分,用于配置影响整个任务行为的参数。它通常包含以下关键信息:

  • speed: 控制数据同步的速度和并发度,包括通道数(channel)和每个通道的数据传输速度(如byte)。
  • errorLimit: 设置数据同步过程中的错误容忍度,包括允许出错的记录数(record)和错误率(percentage)。

示例
一个典型的setting配置可能如下:

"setting": {"speed": {"channel": 3, // 并发通道数"byte": 1048576 // 每个通道的数据传输速度,单位是字节(1MB)},"errorLimit": {"record": 0, // 允许出错的记录数"percentage": 0.02 // 允许出错的记录数占总记录数的百分比}
}

综上所述,readerwritersetting三个部分共同构成了DataX数据同步任务的配置文件。通过合理配置这些部分,用户可以灵活地定义数据源、目标数据源以及数据同步的行为和性能。在实际应用中,用户应根据具体的数据源类型、目标数据源类型和数据同步需求来填写和调整这些配置。

二、示例,从mysql同步到hdfs

该配置文件定义了从一个 MySQL 数据库读取数据,并将这些数据写入到 HDFS 的过程。

{"job": {"content": [{"reader": {"name": "mysqlreader", "parameter": {"column": ["id","name","msg","create_time","status","last_login_time"], "connection": [{"jdbcUrl": ["jdbc:mysql://192.168.56.1:3306/user?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"], "table": ["t_user"]}], "password": "password", "username": "test", "where": "id>3"}}, "writer": {"name": "hdfswriter", "parameter": {"column": [{"name":"id","type":"bigint"},{"name":"name","type":"string"},{"name":"msg","type":"string"},{"name":"create_time","type":"date"},{"name":"status","type":"string"},{"name":"last_login_time","type":"date"}], "compress": "gzip", "defaultFS": "hdfs://hadoop131:9000", "fieldDelimiter": "\t", "fileName": "mysql2hdfs01", "fileType": "text", "path": "/mysql2hdfs", "writeMode": "append"}}}], "setting": {"speed": {"channel": "1"}}}
}
  • 参考 mysqlreader
  • 参考 hdfswriter

三、通过SpringBoot项目自动生成job文件

本例使用SpringBoot 3.0 结合 JDBC 读取mysql数据库表结构信息,生成job.json文件

1、创建SpringBoot项目,添加pom依赖以及配置

1)增加pom.xml依赖jar包

<!-- Spring Boot JDBC Starter -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MySQL JDBC Driver -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.25</version>
</dependency>

2)增加application.properties配置项

server.port=8080
# mysql 数据库链接
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/user?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
spring.datasource.username=test
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# datax 相关配置,在生成文件时使用
datax.hdfs.defaultFS=hdfs://hadoop131:9000
datax.hdfs.path=/origin_data
# 需要生成job文件的表,多个用逗号隔开
datax.mysql.tables=t_user,t_user_test,t_sys_dict
# job文件存储位置
datax.savepath=d:/temp/

2、按照job.json格式创建好各个 vo

1)基础结构vo

@Data
public class DataxJobRoot {private Job job;
}
@Data
public class Job {private List<Content> content;private Setting setting = new Setting();
}
@Data
public class Content {private Reader reader;private Writer writer;
}
@Data
public class Setting {private Speed speed = new Speed();@Datapublic static class Speed {private String channel = "1";}
}
@Data
public class Reader {private String name;private Parameter parameter;
}
@Data
public class Writer {private String name;private Parameter parameter;@Datapublic static class MysqlParameter {private List<String> column;private List<Connection> connection;private String password;private String username;private String writeMode = "replace";}@Datapublic static class Connection {private String jdbcUrl;private List<String> table;}
}public class Parameter {
}

2)mysql2hdfs的vo实现类

@EqualsAndHashCode(callSuper = true)
@Data
public class MysqlReader extends Reader {public String getName() {return "mysqlreader";}@EqualsAndHashCode(callSuper = true)@Datapublic static class MysqlParameter extends Parameter {private List<String> column;private List<Connection> connection;private String password;private String username;private String where;}@Datapublic static class Connection {private List<String> jdbcUrl;private List<String> table;}
}@EqualsAndHashCode(callSuper = true)
@Data
public class HdfsWriter extends Writer {public String getName() {return "hdfswriter";}@EqualsAndHashCode(callSuper = true)@Datapublic static class HdfsParameter extends Parameter {private List<Column> column;private String compress = "gzip";private String encoding = "UTF-8";private String defaultFS;private String fieldDelimiter = "\t";private String fileName;private String fileType = "text";private String path;private String writeMode = "append";}@Datapublic static class Column {String name;String type;}
}

3)hdfs2mysql的vo实现类

@EqualsAndHashCode(callSuper = true)
@Data
public class HdfsReader extends Reader {@Overridepublic String getName() {return "hdfsreader";}public HdfsParameter getParameter() {return new HdfsParameter();}@EqualsAndHashCode(callSuper = true)@Datapublic static class HdfsParameter extends Parameter {private List<String> column = Collections.singletonList("*");private String compress = "gzip";private String encoding = "UTF-8";private String defaultFS;private String fieldDelimiter = "\t";private String fileName;private String fileType = "text";private String path;private String nullFormat = "\\N";}
}
@EqualsAndHashCode(callSuper = true)
@Data
public class MysqlWriter extends Writer {public String getName() {return "mysqlwriter";}public MysqlParameter getParameter() {return new MysqlParameter();}@EqualsAndHashCode(callSuper = true)@Datapublic static class MysqlParameter extends Parameter {private List<String> column;private List<Connection> connection;private String password;private String username;private String writeMode = "replace";}@Datapublic static class Connection {private String jdbcUrl;private List<String> table;}
}

3、创建Repository、Service类读取数据库表结构

@Repository
public class DatabaseInfoRepository {private final JdbcTemplate jdbcTemplate;@Autowiredpublic DatabaseInfoRepository(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}// 获取所有表名public List<String> getAllTableNames() {String sql = "SHOW TABLES";return jdbcTemplate.queryForList(sql, String.class);}// 根据表名获取字段信息public List<Map<String, Object>> getTableColumns(String tableName) {String sql = "SHOW FULL COLUMNS FROM " + tableName;return jdbcTemplate.queryForList(sql);}
}
@Service
public class DatabaseInfoService {private final DatabaseInfoRepository databaseInfoRepository;@Autowiredpublic DatabaseInfoService(DatabaseInfoRepository databaseInfoRepository) {this.databaseInfoRepository = databaseInfoRepository;}public void printAllTablesAndColumns() {// 获取所有表名List<String> tableNames = databaseInfoRepository.getAllTableNames();// 遍历表名,获取并打印每个表的字段信息for (String tableName : tableNames) {System.out.println("Table: " + tableName);// 获取当前表的字段信息List<Map<String, Object>> columns = databaseInfoRepository.getTableColumns(tableName);// 遍历字段信息并打印for (Map<String, Object> column : columns) {System.out.println("  Column: " + column.get("Field") + " (Type: " + column.get("Type") + ")" + " (Comment: " + column.get("Comment") + ")");}System.out.println(); // 打印空行作为分隔}}/** 查询指定表的所有字段列表 */public List<String> getColumns(String tableName) {List<String> list = new ArrayList<>();// 获取当前表的字段信息List<Map<String, Object>> columns = databaseInfoRepository.getTableColumns(tableName);// 遍历字段信息并打印for (Map<String, Object> column : columns) {list.add(column.get("Field").toString());}return list;}/** 查询指定表的所有字段列表,封装成HdfsWriter格式 */public List<HdfsWriter.Column> getHdfsColumns(String tableName) {List<HdfsWriter.Column> list = new ArrayList<>();// 获取当前表的字段信息List<Map<String, Object>> columns = databaseInfoRepository.getTableColumns(tableName);// 遍历字段信息并打印for (Map<String, Object> column : columns) {String name = column.get("Field").toString();String typeDb = column.get("Type").toString();String type = "string";if (typeDb.equals("bigint")) {type = "bigint";} else if (typeDb.startsWith("varchar")) {type = "string";} else if (typeDb.startsWith("date") || typeDb.endsWith("timestamp")) {type = "date";}HdfsWriter.Column columnHdfs = new HdfsWriter.Column();columnHdfs.setName(name);columnHdfs.setType(type);list.add(columnHdfs);}return list;}
}

4、创建Service生成job.json文件

@Service
public class GenHdfs2mysqlJsonService {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.username}")private String username;@Value("${datax.mysql.tables}")private String tables;@Value("${datax.hdfs.defaultFS}")private String defaultFS;@Value("${datax.hdfs.path}")private String path;@Value("${datax.savepath}")private String savepath;@Autowiredprivate DatabaseInfoService databaseInfoService;/*** 生成 hdfs2mysql的job.json* @param table*/public void genHdfs2mysqlJson(String table) {DataxJobRoot root = new DataxJobRoot();Job job = new Job();root.setJob(job);Content content = new Content();HdfsReader reader = new HdfsReader();MysqlWriter writer = new MysqlWriter();content.setReader(reader);content.setWriter(writer);job.setContent(Collections.singletonList(content));HdfsReader.HdfsParameter hdfsParameter = reader.getParameter();hdfsParameter.setPath(path);hdfsParameter.setFileName(table + "_hdfs");hdfsParameter.setDefaultFS(defaultFS);MysqlWriter.MysqlParameter mysqlParameter = writer.getParameter();mysqlParameter.setPassword(password);mysqlParameter.setUsername(username);List<String> columns = databaseInfoService.getColumns(table);mysqlParameter.setColumn(columns);MysqlWriter.Connection connection = new MysqlWriter.Connection();connection.setJdbcUrl(url);connection.setTable(Collections.singletonList(table));mysqlParameter.setConnection(Collections.singletonList(connection));String jsonStr = JSONUtil.parse(root).toJSONString(2);System.out.println(jsonStr);File file = FileUtil.file(savepath, table + "_h2m.json");FileUtil.appendString(jsonStr, file, "utf-8");}/*** 生成 mysql2hdfs 的job.json* @param table*/public void genMysql2HdfsJson(String table) {DataxJobRoot root = new DataxJobRoot();Job job = new Job();root.setJob(job);Content content = new Content();HdfsWriter writer = new HdfsWriter();MysqlReader reader = new MysqlReader();content.setReader(reader);content.setWriter(writer);job.setContent(Collections.singletonList(content));HdfsWriter.HdfsParameter hdfsParameter = new HdfsWriter.HdfsParameter();writer.setParameter(hdfsParameter);hdfsParameter.setPath(path);hdfsParameter.setFileName(table + "_hdfs");hdfsParameter.setDefaultFS(defaultFS);List<HdfsWriter.Column> lstColumns = databaseInfoService.getHdfsColumns(table);hdfsParameter.setColumn(lstColumns);MysqlReader.MysqlParameter mysqlParameter = new MysqlReader.MysqlParameter();reader.setParameter(mysqlParameter);mysqlParameter.setPassword(password);mysqlParameter.setUsername(username);List<String> columns = databaseInfoService.getColumns(table);mysqlParameter.setColumn(columns);MysqlReader.Connection connection = new MysqlReader.Connection();connection.setJdbcUrl(Collections.singletonList(url));connection.setTable(Collections.singletonList(table));mysqlParameter.setConnection(Collections.singletonList(connection));String jsonStr = JSONUtil.parse(root).toJSONString(2);System.out.println(jsonStr);File file = FileUtil.file(savepath, table + "_m2h.json");FileUtil.appendString(jsonStr, file, "utf-8");}public void genAllTable() {Splitter.on(",").split(tables).forEach(this::genMysql2HdfsJson);}}

5、执行测试

调用genAllTable()方法,在配置的存储目录中自动生成每个表的job.json文件,结构示例如下:

{"job": {"content": [{"reader": {"name": "mysqlreader","parameter": {"column": ["id","name","msg","create_time","last_login_time","status"],"connection": [{"jdbcUrl": ["jdbc:mysql://127.0.0.1:3306/user?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"],"table": ["t_user"]}],"password": "password","username": "test"}},"writer": {"name": "hdfswriter","parameter": {"column": [{"name": "id","type": "bigint"},{"name": "name","type": "string"},{"name": "msg","type": "string"},{"name": "create_time","type": "date"},{"name": "last_login_time","type": "date"},{"name": "status","type": "bigint"}],"compress": "gzip","encoding": "UTF-8","defaultFS": "hdfs://hadoop131:9000","fieldDelimiter": "\t","fileName": "t_user_hdfs","fileType": "text","path": "/origin_data","writeMode": "append"}}}],"setting": {"speed": {"channel": "1"}}}
}

至此,通过SpringBoot项目自动生成DataX的job.json文件,功能完成!

其中细节以及其他的reader\writer转换可以按照例子实现。

参考

  • 【数仓】DataX软件安装及配置,从mysql同步到hdfs
  • https://github.com/alibaba/DataX/blob/master/userGuid.md

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

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

相关文章

Gradle 实战 - 插件-ApiHug准备-工具篇-015

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace ApiHug …

Unity WebGL 2021 Release-Notes

&#x1f308;WebGL 2021 Release-Notes 版本更新内容2021.3.33WebGL: Fixed a bug that caused for input to not be released when focus was removed from canvas on Windows Chrome.(UUM-53519)2021.3.33WebGL: Fixed the bug that caused for an error to be thrown when …

rv1103/buildroot系统中添加包如v4l2

v4l2: rv1103给出的包中已经有v4l,只需要在menuconfig中打开编译选项&#xff0c;步骤如下&#xff1a; 在luckfox的github网站中下载的源代码在~/linux/luckfox/luckfox-pico-main中目录结构如下&#xff1a; 打开编译选项 cd ./sysdrv/source/buildroot/buildroot-2023.02.…

一种驱动器的功能安全架构介绍

下图提供了驱动器实现安全功能的架构 具有如下特点&#xff1a; 1.通用基于总线或者非总线的架构。可以实现ethercat的FSOE&#xff0c;profinet的profisafe&#xff0c;或者伺服本体安全DIO现实安全功能。 2.基于1oo2D架构&#xff0c;安全等级可以达到sil3。 3.高可用性。单…

第十五篇【传奇开心果系列】Python自动化办公库技术点案例示例:深度解读Python 自动化处理图像在各行各业的应用场景

传奇开心果博文系列 系列博文目录Python自动化办公库技术点案例示例系列 博文目录前言一、行业应用场景介绍二、 **计算机视觉研究与开发示例代码**三、人工智能与机器学习示例代码四、医疗健康领域示例代码五、制造业与质量控制示例代码六、农业与环境科学示例代码七、电子商务…

ai智能机器人怎样获取评分等级话术分组

随着科技的进步&#xff0c;人工智能的理解能力和学习能力会不断加强&#xff0c;从而解放更多的人力&#xff0c;让他们去做更有意义的事情&#xff0c;那要创建一个 AI 电销机器人来获取评分等级并进行话术分组&#xff0c;可以按照以下步骤进行&#xff1a; 数据收集和准备&…

小米汽车值得去吗?最终拒了 offer。

车企选择 今天逛某职场 App 时&#xff0c;无意间看到一篇寻求 offer 抉择意见的帖子&#xff1a; 这位同学刚从加班闻名&#xff08;但 CEO 强调既学华为狼性&#xff0c;也学华为分配&#xff09;的理想汽车离职。 经过了 6 轮面试&#xff0c;收到了小米 offer&#xff0c;但…

【合合TextIn】智能文档处理系列—电子文档解析技术全格式解析

一、引言 在当今的数字化时代&#xff0c;电子文档已成为信息存储和交流的基石。从简单的文本文件到复杂的演示文档&#xff0c;各种格式的电子文档承载着丰富的知识与信息&#xff0c;支撑着教育、科研、商业和日常生活的各个方面。随着信息量的爆炸性增长&#xff0c;如何高…

网络网络层之(2)ARP协议

网络网络层之(2)ARP协议 Author&#xff1a;Once Day Date: 2024年4月1日 漫漫长路&#xff0c;有人对你笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的博客-CSDN博客。 参考文档: 《TCP/IP详解卷一》arp(8) - Linux manual page (man7.org)彻底搞懂系…

C语言中的数据结构--链表的应用2(3)

前言 上一节我们学习了链表的应用&#xff0c;那么这一节我们继续加深一下对链表的理解&#xff0c;我们继续通过Leetcode的经典题目来了解一下链表在实际应用中的功能&#xff0c;废话不多说&#xff0c;我们正式进入今天的学习 单链表相关经典算法OJ题4&#xff1a;合并两个…

pyppeteer和requests简单应用

pyppeteer和requests简单应用 本文章只是分享pyppeteer技术。有些反扒网站可以使用pyppeteer库&#xff0c;完整代码没有分享。 获取相关开发工具软件&#xff0c;可以关注公众号&#xff1a;爬虫探索者。 发送下面图片的关键字可以获取对应软件。sql指的是Navicat。 破解教程可…

Netty之ByteBuff

1、Jdk自带ByteBuffer 1.1、ByteBuffer简介 事实上&#xff0c;jdk自1.4版本&#xff0c;就已经提供了nio的ByteBuffer&#xff0c;用于在Java程序中操作原始数据。ByteBuffer可以用来读取和写入二进制数据&#xff0c;例如网络传输的数据、文件的内容等。 ByterBuffer的部分…

【大数据】Apache Knox 概述

Apache Knox 概述 1.概述1.1 Kerberos 封装1.2 简化客户端证书的管理1.3 Apache Ranger 集成1.4 Hadoop URLs VS Knox URLs 2.自定义 Apache Knox2.1 Topology2.2 Provider2.3 Services2.4 Personalized services 3.Tips3.1 Setting up SSL3.2 常见问题3.2.1 Bulky answer3.2.2…

财务软件行业背景-易舟云

财税是每个企业的基本基石之一。财务报告讲述了公司的故事——它的利润和亏损、收益和债务、税收支出以及可用于未来增长的资产。随着信息时代的飞速发展&#xff0c;财务信息化建设日益完善&#xff0c;大量基于计算机网络的应用系统已经逐步深入财务管理领域。传统的会计录入…

过冲、振铃、非单调性

1、过冲&#xff08;Overshoot&#xff09;和振铃&#xff08;Ringing&#xff09;是电路中常见的信号失真现象&#xff0c;主要出现在开关电源、数字信号传输、通信系统以及其他涉及快速开关动作的电子设备中。它们通常与电路的瞬态响应有关&#xff0c;尤其是当电路受到阶跃输…

【学习笔记十三】EWM常见上架策略介绍

一、手工维护上架策略 系统不确定Storage type 和 bin&#xff0c;需要在创建仓库任务时或者确认仓库任务时手工输入仓位 1.后台配置-定义存储类型的类型0010 ①存储行为&#xff1a;标准仓位 ②入库规则&#xff1a;空仓未或添加至现有库存/空仓位 ③通用仓库任务&#x…

postgresql 备份恢复相关知识点整理归纳 —— 筑梦之路

概述 PG一般有两种备份方式&#xff1a;逻辑备份和物理备份 逻辑备份对于数据量大的场景下耗时较长&#xff0c;恢复也会耗时较长 物理备份拷贝文件的方式相对来说耗时较短&#xff0c;跟磁盘读写性能和网络传输性能有关 逻辑备份 pg_dump pg_dump 将表结构及数据以SQL语句…

Docker in Docker (DinD): 深入探索与实际应用

引言 在软件开发的多样化环境中&#xff0c;Docker已成为一种重要的工具&#xff0c;用于实现应用的快速部署和可靠性。Docker in Docker&#xff08;DinD&#xff09;进一步推进了这一概念&#xff0c;使开发者能在一个Docker容器中运行另一个Docker实例。本文将详细探讨DinD…

微信小程序实现预约生成二维码

业务需求&#xff1a;点击预约按钮即可生成二维码凭码入校参观~ 一.创建页面 如下是博主自己写的wxml&#xff1a; <swiper indicator-dots indicator-color"white" indicator-active-color"blue" autoplay interval"2000" circular > &…

SpringBoot - Logback 打印第三方 Jar 日志解决方案

问题描述 最近碰到一个很苦恼的问题&#xff0c;就是第三方的 Jar 在自己项目里日志可以正常输出&#xff0c;但是一旦被引用到其他项目里&#xff0c;就日志死活打不出来…… 解决方案 这是原来的配置 - logback.xml <?xml version"1.0" encoding"UTF-8…