
Mybatis 源码系列
文章平均质量分 89
深入剖析Mybatis 源码和应用场景
冰糖心书房
Hi:欢迎来到"冰糖心书房",人个目前就职于一家外企业500强公司担任架构师一职,在这里我会着重分享我多年来在Java开发领域的实战经验和心得体会。从企业级项目架构设计、高并发处理到微服务架构的落地实施。
展开
-
Mybatis 如何编写自定义TypeHandler,来实现特殊类型的处理?
,处理好 Java 类型与 JDBC 类型之间的双向转换逻辑。然后通过配置文件、注解或在 Mapper XML 中显式指定的方式将其注册给 MyBatis,即可实现对特殊类型的无缝处理。之后,你就可以像处理普通类型一样在你的实体类中使用。来创建自定义的类型处理器。是你这个处理器要处理的 Java 类型。(指定对应的 JDBC 类型) 注解。(指定处理的 Java 类型) 和。枚举,MyBatis 会通过你的。接口或继承其抽象基类。有三种主要方式注册你的。可以在具体的参数映射 (值检查,简化了实现。原创 2025-04-05 09:42:46 · 876 阅读 · 0 评论 -
Mybatis Interceptor 接口的作用是什么? 它提供了哪些拦截点?
这四个核心组件的关键方法执行时插入自定义逻辑,从而实现对 MyBatis 功能的灵活扩展和定制,而无需修改框架本身。接口是 MyBatis 提供的一个钩子 (Hook),允许开发者通过实现该接口并配置,在。MyBatis 并非允许拦截所有内部方法,而是预定义了四个核心接口的特定方法作为。,它能够在 MyBatis 执行 SQL 的关键路径上插入自定义的处理代码。注解来声明希望拦截的具体方法签名。接口是 MyBatis。原创 2025-04-04 10:42:07 · 311 阅读 · 0 评论 -
MyBatis 的插件体系是如何设计的? 如何编写自定义插件?
【代码】MyBatis 的插件体系是如何设计的?如何编写自定义插件?原创 2025-04-03 11:48:46 · 934 阅读 · 0 评论 -
Mybatis 如何自定义缓存?
接口来自定义二级缓存,我们可以集成各种第三方缓存(如 Redis, Ehcache, Memcached 等)或实现自己特定的缓存逻辑。如果自定义缓存需要一些配置参数(比如 Redis 的主机、端口、密码等),你可以在。根据选择的缓存技术(或自定义逻辑)来实现上述接口的所有方法。在需要使用自定义缓存的 Mapper XML 文件中,使用。接口本身没有直接定义接收这些属性的方法。接口,并在 Mapper XML 中通过。自定义 MyBatis 缓存的核心是实现。属性指定你的自定义缓存类的。原创 2025-04-02 11:48:08 · 1035 阅读 · 0 评论 -
Mybatis 缓存是如何工作的? 缓存的 key 是如何生成的? 缓存的淘汰策略有哪些?
缓存的淘汰策略定义了当缓存达到其配置的最大容量时,应该移除哪些条目以便为新条目腾出空间。这些策略在 Mapper XML 文件的。选择哪种淘汰策略取决于具体的应用场景和对缓存数据访问模式的预估。对于确保缓存的正确性至关重要。MyBatis 需要确保只有在。对象随后被用作在一级缓存和二级缓存(通常是。是最常用且通常效果不错的选择。或类似结构)中存取值的键。原创 2025-04-01 09:42:02 · 738 阅读 · 0 评论 -
MyBatis 有哪些缓存? 一级缓存和二级缓存有什么区别?
MyBatis 有哪些缓存?一级缓存和二级缓存有什么区别?原创 2025-03-31 09:33:20 · 754 阅读 · 0 评论 -
Mybatis 是如何处理动态SQL的, 用到了哪些设计模式?
MyBatis 处理动态 SQL 的方式非常巧妙,它并没有直接在运行时去解析 XML 字符串,而是在。则在初始解析阶段发挥作用。这种设计使得动态 SQL 的处理逻辑清晰、结构化且易于扩展。)来解释这棵树,动态地生成最终的 SQL。这个树结构,最终生成可执行的 SQL。就将动态 SQL 解析成了一个。将动态 SQL 解析成。MyBatis 通过。原创 2025-03-30 08:33:56 · 780 阅读 · 0 评论 -
Mybatis MappedStatement 封装了哪些信息? 它是如何被创建和使用的?
是 MyBatis 中定义和存储单个 SQL 操作所有静态配置信息的。中的配置信息(如结果映射、缓存策略等)来执行数据库操作和处理结果。它在 MyBatis 初始化时被解析和创建,并存储在全局的。在运行时,MyBatis 根据方法调用找到对应的。这个创建过程在应用程序启动时完成一次,之后。对象就会常驻内存,供后续运行时使用。,并结合传入的参数动态生成 SQL (,当 MyBatis 解析配置文件(它封装了执行这条 SQL 所需的。是 MyBatis 框架中一个。的创建发生在 MyBatis。原创 2025-03-29 10:53:42 · 1097 阅读 · 0 评论 -
MyBatis ResultSetHandler支持哪些结果映射方式? 如何处理一对一、一对多、多对多关系?
在 MyBatis 中提供了强大的结果映射能力,支持多种灵活的结果映射方式,以适应各种复杂的数据库查询结果到 Java 对象的转换需求。提供的这些灵活的结果映射方式,使得 MyBatis 能够处理各种复杂的数据库查询结果,并将数据库数据高效、准确地转换为 Java 对象,满足各种应用场景的需求。最基本的结果映射方式,适用于单表查询,将结果集中的列直接映射到 Java 对象的简单属性。元素的配置,处理一对一关联关系。元素的配置,处理一对多或多对多关联关系。实现了根据数据内容动态选择映射规则的多态映射。原创 2025-03-27 09:59:22 · 303 阅读 · 0 评论 -
Mybatis 的运行原理?
MyBatis 通过动态代理、反射、类型转换、缓存等技术,实现了 SQL 语句与 Java 代码的解耦,简化了数据库访问操作。、创建执行器、创建语句处理器、创建参数处理器、执行 SQL 语句、创建结果集处理器、结果映射、返回结果、提交/回滚事务、关闭。、获取 Mapper 接口代理对象、执行 Mapper 接口方法、查找。MyBatis 的运行原理可以概括为:加载配置、构建。原创 2025-03-25 10:16:32 · 911 阅读 · 0 评论 -
MyBatis ResultSetHandler 是如何将数据库返回的结果集转换为 Java 对象的?
的角色,它的核心职责是将 JDBC 驱动程序返回的。进行简单的自动映射。MyBatis 默认只提供了一个。在 MyBatis 中扮演着。(数据库结果集) 转换为。原创 2025-03-24 09:08:23 · 444 阅读 · 0 评论 -
MyBatis ParameterHandler支持哪些参数类型? 如何处理 # 和 $ 占位符?
因为参数值是直接拼接在 SQL 语句中的,如果参数值包含恶意的 SQL 代码,就可能导致 SQL 注入攻击。的参数绑定机制设置的,而不是直接拼接在 SQL 语句中,避免了 SQL 注入的风险。支持各种不同的 Java 参数类型,并且能够根据不同的参数类型和占位符类型 (,因为数据库可以预编译 SQL 语句,并复用执行计划。特别是在需要传递参数值的情况下,必须使用。会将传入的 Java 参数值 (例如。转换为 JDBC 类型的值,并通过。,理解它们的区别至关重要。) 进行相应的处理。原创 2025-03-23 10:20:19 · 686 阅读 · 0 评论 -
MyBatis ParameterHandler 是如何将 Java 对象转换为 SQL 语句中的参数的?
它封装了参数绑定的复杂性,使得 MyBatis 的其他组件 (例如。MyBatis 默认只提供了一个。) 无需关心具体的参数绑定细节。在 Mybatis中。原创 2025-03-22 11:02:22 · 1014 阅读 · 0 评论 -
MyBatis StatementHandler是如何创建 Statement 对象的? 如何执行 SQL 语句?
StatementHandler充当 MyBatis 和原始 JDBC API 之间的桥梁。原创 2025-03-21 13:45:58 · 634 阅读 · 0 评论 -
MyBatis StatementHandler 是如何与数据库进行交互的?
对象相关的操作,使得 MyBatis 的其他组件 (例如。) 无需直接操作 JDBC API,而是通过。接口的实现类,对应不同的 JDBC。在 MyBatis 中扮演着。MyBatis 提供了以下几种。提供的接口与数据库进行交互。封装了所有与 JDBC。原创 2025-03-21 10:36:57 · 628 阅读 · 0 评论 -
Mybatis 有哪些不同的 Executor 实现? 它们有什么区别?
实现类采用了不同的 SQL 执行策略,从而在性能、功能和适用场景上有所区别。MyBatis 默认提供了以下三种主要的。除了这三种主要的执行器,MyBatis 还有一个 CachingExecutor。执行器已经足够使用。如果需要提高性能,可以考虑使用。并不是一个独立的执行器类型,而是一个。MyBatis 提供了几种不同的。接口的实现类,这些实现类被称为。在 MyBatis 中,可以通过。执行器,或者启用二级缓存。在大多数情况下,默认的。原创 2025-03-20 09:58:29 · 626 阅读 · 0 评论 -
MyBatis Executor 的作用是什么?
是 MyBatis 框架的核心和灵魂,它负责 SQL 执行的方方面面,并将底层的数据库操作细节隐藏起来,在开发过程中为我们提供了简洁、高效、可配置的数据库访问接口。, Mappers) 提供了更高层次的、更易于使用的 SQL 执行接口。抽象了底层的 JDBC 操作,为 MyBatis 的其他组件 (如。在 MyBatis 中扮演着至关重要的角色,它是。MyBatis 提供了三种内置的。原创 2025-03-20 09:39:18 · 493 阅读 · 0 评论 -
MyBatis 配置文件解析使用了哪些设计模式
MyBatis 配置文件解析过程中,主要运用了以下几种设计模式。原创 2025-03-19 12:19:41 · 860 阅读 · 0 评论 -
MyBatis 如何管理和查找TypeHandler?
MyBatis 需要管理大量的 TypeHandler,并能够根据需要快速找到合适的 TypeHandler 来进行类型转换。当 MyBatis 需要进行类型转换时 (例如设置 PreparedStatement 参数,获取 ResultSet 结果),会通过。来存储 TypeHandler,以便根据不同的查找条件进行高效检索。TypeHandler 可以通过多种方式注册到。查找合适的 TypeHandler。子元素来注册 TypeHandler。方法手动注册 TypeHandler。原创 2025-03-19 10:19:46 · 1183 阅读 · 0 评论 -
MyBatis MapperRegistry 的作用是什么? 它是如何管理 Mapper 接口的?
就像一个人才中介,它管理着所有注册的 Mapper 接口 (人才),并能够根据需要,为开发者提供 Mapper 接口的代理对象 (人才代理),让开发者可以通过操作代理对象来间接执行数据库操作 (管理人才来完成工作)。它确保 MyBatis 能够正确地将 Mapper 接口与对应的 SQL 映射配置关联起来,并在运行时为 Mapper 接口创建代理对象,使得开发者可以通过调用 Mapper 接口方法来执行 SQL 操作。属性指定的包下的所有接口,并将这些接口作为 Mapper 接口注册到。原创 2025-03-18 14:10:38 · 378 阅读 · 0 评论 -
MyBatis XMLMapperBuilder 是如何将 SQL 语句解析成可执行的对象? 如何将结果映射规则解析成对应的处理器?
元素的结果映射配置,用于将查询结果集映射到 Java 对象。等 SQL 语句元素时,并不仅仅是简单地读取 SQL 文本,而是要将 SQL 语句和相关的配置信息。对象包含了执行一个 SQL 操作所需的所有信息,是 MyBatis 运行时执行 SQL 的核心对象。对象才是 MyBatis 运行时真正可执行的 SQL 对象。会解析 SQL 语句中的参数映射配置。注册时,会使用 Mapper 接口的全限定名 + SQL 语句的。会根据 SQL 语句文本的类型,创建不同的。定义的映射规则,映射到 Java 对象。原创 2025-03-18 10:50:12 · 526 阅读 · 0 评论 -
MyBatis SqlSession 是如何创建的? 它与 SqlSessionFactory 有什么关系?
是 MyBatis 中与数据库交互的核心接口,它提供了执行 SQL 语句、管理事务、获取 Mapper 接口代理对象等关键功能。的生命周期管理,对于正确使用 MyBatis 至关重要。在 MyBatis 应用中,开发时遵循。是轻量级对象,用于执行 SQL 语句和管理事务。是 MyBatis 与数据库交互的核心接口,它通过。的标准流程,确保资源正确释放和事务的正确性。方法的重载版本,用于创建不同类型的。是重量级对象,负责创建和配置。原创 2025-03-17 08:42:58 · 1091 阅读 · 0 评论 -
MyBatis XMLMapperBuilder 是如何解析 SQL 映射文件的? 它读取了哪些信息?
它使用 XPath 技术高效地解析 Mapper XML 文件,读取 SQL 语句、参数映射、结果映射、缓存配置等信息,并将这些信息封装在。SQL 映射文件定义了 SQL 语句、参数映射、结果映射、缓存配置等信息,用于将 Java 方法调用映射到具体的 SQL 操作。的主要职责就是读取这些 XML 文件,解析其中的 SQL 映射配置,并将这些配置信息存储到。根元素,定义 Mapper 映射文件的命名空间 (namespace)。方法完成 SQL 映射文件的解析和注册后,解析过程结束。原创 2025-03-17 07:25:04 · 863 阅读 · 0 评论 -
MyBatis XMLConfigBuilder 是如何解析 MyBatis 配置文件的? 它读取了哪些信息? 如何将这些信息存储到 Configuration 对象中?
XPath 允许以路径的方式选择 XML 文档中的节点,使得解析器可以方便地访问和提取特定元素和属性的值。它使用 XPath 技术高效地解析 XML 文件,读取各种配置信息,并将这些信息以结构化的方式存储到。它的主要职责是从 XML 文件中读取 MyBatis 的配置信息,并将这些信息构建并存储到。在解析 XML 配置文件的过程中,会将读取到的信息通过以下方式存储到。会按照一定的顺序解析 XML 配置文件中的元素,大致顺序如下 (与。方法完成 XML 文件的解析后,会将构建好的。实例,并将配置文件的。原创 2025-03-16 13:07:14 · 723 阅读 · 0 评论 -
MyBatis SqlSessionFactoryBuilder 的作用是什么?
建造者模式的核心思想是将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。一旦工厂组装完成,工程师的任务就完成了,他就可以离开了 (一次性使用)。这种多配置源的支持,使得 MyBatis 的配置方式更加灵活,可以适应不同的应用场景和配置管理需求。) 负责根据设计图纸 (MyBatis 配置) 和原材料 (配置源),一步步地组装出最终的工厂 (在 MyBatis 中扮演着至关重要的角色,它的主要作用是。理解为 SqlSessionFactory。的创建逻辑解耦,提高了代码的灵活性。原创 2025-03-16 11:12:54 · 1040 阅读 · 0 评论 -
MyBatis SqlSessionFactory 是如何创建的?
之前,首先需要加载和解析 MyBatis 的配置信息。实例是 MyBatis 与数据库交互的主要接口,负责执行 SQL 语句、管理事务等。的方法,可以从不同的配置源 (如 XML 配置文件、Java 代码配置) 构建。是 MyBatis 的核心接口之一,它是创建。参数,用于读取 XML 配置文件。方法内部会执行以下关键步骤来创建。方法,用于根据不同的配置源构建。遵循建造者模式,提供多种构建。原创 2025-03-15 12:45:26 · 1003 阅读 · 0 评论 -
MyBatis 如何创建 SqlSession 对象的?
接口及其实现类来完成。MyBatis 创建。MyBatis 创建。原创 2025-03-15 11:49:35 · 845 阅读 · 0 评论 -
MyBatis 如何解析 XML 配置文件和 SQL 映射文件
MyBatis 使用 SAX(Simple API for XML)解析器来解析 XML 文件,SAX 是一种基于事件驱动的 XML 解析方式,具有高效、低内存消耗的优点。MyBatis 的解析过程是其初始化过程中的关键步骤,理解解析过程有助于我们更好地理解 MyBatis 的工作原理,以及如何进行更高级的配置和定制。MyBatis 对 XML 配置文件的解析是其初始化过程中的关键步骤,它负责读取和解释 XML 文件中的配置信息,并将其转换为 MyBatis 内部使用的。负责解析 SQL 映射文件。原创 2025-03-14 11:15:42 · 696 阅读 · 0 评论 -
MyBatis 如何处理参数? 支持哪些参数类型? 如何传递多个参数? 如何使用 # 和 $ 占位符?
MyBatis 在处理参数方面非常灵活,它支持多种参数类型,并提供了多种方式来传递参数和使用占位符。理解 MyBatis 的参数处理机制、参数类型、传递多个参数的方式以及。占位符的区别,对于正确编写和使用 MyBatis 至关重要。原创 2025-03-14 09:38:50 · 602 阅读 · 0 评论 -
如何将查询结果映射到 Java 对象? MyBatis 支持哪些结果映射方式? 它们有什么区别?
将查询结果映射到 Java 对象是 MyBatis 的核心功能之一,它使得我们可以方便地将数据库中的数据转换为 Java 对象,进行后续的处理和操作。MyBatis 提供了多种结果映射方式,以适应不同的场景和需求。理解 MyBatis 的各种结果映射方式及其区别,对于正确配置 MyBatis 并高效地将查询结果映射为 Java 对象至关重要。用于映射一对一关联关系。例如,一个用户(User)对应一个地址(Address)。用于映射一对多关联关系。例如,一个用户(User)对应多个订单(Order)。原创 2025-03-13 08:29:34 · 872 阅读 · 0 评论 -
MyBatis 中SQL 映射文件是如何与 Mapper 接口关联起来的? MyBatis 如何知道应该调用哪个 SQL 语句?
SQL 映射文件与 Mapper 接口的关联是 MyBatis 的核心机制之一,它使得我们可以通过调用 Mapper 接口的方法来执行 SQL 语句,而无需直接操作。对象,然后执行 SQL 语句,并进行参数绑定和结果映射。当我们在 Java 代码中调用 Mapper 接口的方法时,实际上调用的是 MyBatis 生成的 Mapper 接口代理对象的方法。属性将 Mapper 接口中的方法与 SQL 映射文件中的具体 SQL 语句建立了唯一的对应关系。属性的值必须与 Mapper 接口中对应方法的名称相同。原创 2025-03-12 10:14:49 · 1000 阅读 · 0 评论 -
MyBatis 的核心配置文件是干什么的? 它的结构是怎样的? 哪些是必须配置的,哪些是可选的?
MyBatis 的核心配置文件是 MyBatis 应用程序的入口点,它定义了 MyBatis 的全局配置信息,指导 MyBatis 的行为和工作方式。了解核心配置文件的结构和各部分配置的含义,对于正确配置和使用 MyBatis 至关重要。)是 MyBatis 应用程序的入口点,它定义了 MyBatis 的全局配置信息,指导 MyBatis 的行为和工作方式。可以将核心配置文件视为 MyBatis 的“控制面板”。MyBatis 的核心配置文件(通常命名为。是必须配置的,其他元素都是可选的。原创 2025-03-12 09:29:19 · 988 阅读 · 0 评论 -
MyBatis 类型处理器TypeHandler作用
是 MyBatis 中用于处理 Java 类型与 JDBC 类型之间转换的接口。它在 MyBatis 的参数绑定和结果映射过程中起着至关重要的作用。是 MyBatis 中用于处理 Java 类型与 JDBC 类型之间转换的关键组件。当 MyBatis 执行 SQL 语句时,需要将 Java 对象中的数据设置到 JDBC 的。的作用和使用方法,对于正确配置 MyBatis 和处理各种数据类型转换问题至关重要。,并通过 XML 配置或注解的方式注册自定义的。,在大多数情况下,我们可以直接使用内置的。原创 2025-03-11 13:53:48 · 1604 阅读 · 0 评论 -
MyBatis 的配置对象 Configuration 作用详解
是 MyBatis 的核心配置对象,它包含了 MyBatis 运行时所需的几乎所有配置信息。对象是 MyBatis 的核心配置对象,它包含了 MyBatis 运行时所需的几乎所有配置信息,并负责管理。对象的作用和结构,有助于我们更深入地理解 MyBatis 的工作原理,以及如何进行更高级的配置和定制。、创建核心组件、提供配置信息的访问接口以及作为插件机制的入口。对象保存了 MyBatis 的全局配置信息,这些信息通常在。对象的作用对于深入理解 MyBatis 的工作原理至关重要。对象来执行各种操作。原创 2025-03-11 08:55:47 · 976 阅读 · 0 评论 -
MyBatis 与 Hibernate 等 ORM 框架的区别?
MyBatis 更像是一个“SQL Mapper”,它提供了对 SQL 的精细控制,适合复杂的、性能敏感的场景;Hibernate 更像是一个“全自动 ORM”,它强调对象与数据库的自动映射,适合简单的、快速开发的场景。选择哪种框架取决于项目的具体需求、团队的技术栈以及开发者的偏好。MyBatis 和 Hibernate 都是流行的 Java ORM(Object-Relational Mapping,对象关系映射)框架,但它们在设计理念、使用方式和适用场景上存在显著的区别。原创 2025-03-10 10:25:43 · 907 阅读 · 0 评论 -
MyBatis SqlSession 的作用,以及如何使用 SqlSession 执行 SQL 语句
对于保证 MyBatis 应用程序的正确性和性能至关重要。推荐使用 Mapper 接口的方式来执行 SQL 语句,这种方式更加简洁、类型安全,并且易于维护。是 MyBatis 中执行 SQL 语句、管理事务和获取 Mapper 接口实例的核心接口。是 MyBatis 中非常重要的一个接口,它代表了与数据库的一次会话(session)。在应用程序的生命周期内只需要创建一个实例(单例模式)。对象加上一系列操作数据库的方法。方法关闭会话,释放资源。,以确保资源被正确释放。),需要手动提交事务(原创 2025-03-10 09:26:17 · 1366 阅读 · 0 评论 -
MyBatis Mapper 接口的作用,以及如何将 Mapper 接口与 SQL 映射文件关联起来
无论使用哪种方式,MyBatis 都会根据 Mapper 接口的方法名和参数类型,自动查找并执行对应的 SQL 语句,并将结果映射为 Java 对象或基本类型。Mapper 接口是 MyBatis 的核心概念之一,理解其作用和关联方式对于使用 MyBatis 至关重要。MyBatis Mapper 接口在 MyBatis 框架中扮演着至关重要的角色,它充当了 Java 代码与 SQL 映射文件之间的桥梁,使得我们可以通过面向对象的方式来操作数据库。原创 2025-03-09 14:32:52 · 973 阅读 · 0 评论 -
MyBatis 中常用的 SQL 语句
MyBatis 的核心在于将 SQL 语句与 Java 代码分离,并通过 XML 或注解的方式进行配置。掌握这些基础知识,结合 MyBatis 的动态 SQL 功能,可以灵活地构建各种复杂的 SQL 查询,并有效地管理数据库操作。MyBatis 中常用的 SQL 语句与标准 SQL 语句基本一致,但 MyBatis 提供了一些额外的特性和标签来更方便地构建和管理 SQL 语句。: 占位符,表示传入的参数,MyBatis 会自动进行参数绑定和类型转换,防止 SQL 注入。关键字,并处理多余的。原创 2025-03-09 08:22:07 · 863 阅读 · 0 评论 -
MyBatis SQL 映射文件的作用和结构
MyBatis SQL 映射文件是 MyBatis 框架的核心,它定义了 SQL 语句以及如何将 SQL 语句的参数和结果映射到 Java 对象。好的,让我们深入探讨 MyBatis SQL 映射文件,它定义了 SQL 语句以及如何将 SQL 语句的参数和结果映射到 Java 对象。SQL 映射文件是 MyBatis 的核心,也是 MyBatis 灵活性的体现。,它包含多个子元素,用于定义 SQL 语句、参数映射、结果映射等信息。定义如何将 SQL 语句的查询结果映射到 Java 对象。原创 2025-03-08 10:59:30 · 1105 阅读 · 0 评论 -
什么是 MyBatis? 它的优点和缺点是什么?
MyBatis 是一款优秀的持久层框架,它简化了 Java 应用程序与数据库之间的交互,并提供了灵活的、易于维护的数据访问解决方案。MyBatis 的优点包括灵活性、易于学习和使用、良好的性能、对现有数据库的兼容性好、以及强大的动态 SQL 功能。在选择持久层框架时,需要根据具体的项目需求,权衡 MyBatis 的优缺点,并选择最合适的解决方案。如果想快速开发, 并减少数据库相关的维护工作, 可以选择Hibernate这类全自动ORM框架。原创 2025-03-07 14:42:22 · 866 阅读 · 0 评论