SSM框架知识总结

ops/2025/2/22 13:51:38/

1.Spring常用的设计模式

  1. 单例模式
    • Spring 容器默认情况下,Bean 的作用域是单例的。这意味着在整个应用程序生命周期内,一个 Bean 只有一个实例。例如,对于数据库连接池这个 Bean,只需要一个实例来管理所有的数据库连接请求。单例模式减少了对象的创建和销毁开销,节省了系统资源。
    • Spring 通过维护一个单例 Bean 的缓存来确保只有一个实例存在。当第一次请求某个单例 Bean 时,Spring 会创建它并将其存储在缓存中,后续的请求直接从缓存中获取这个 Bean,而不是再次创建。
  2. 工厂模式
    • 简单工厂模式:Spring 的 BeanFactory 就是简单工厂模式的体现。它负责创建和管理 Bean 对象。就像一个工厂生产产品一样,BeanFactory 根据配置(如 XML 配置文件或 Java 配置类)创建 Bean 实例。例如,在基于 XML 配置的 Spring 应用中,BeanFactory 读取<bean>标签的配置信息,包括类名、属性等,然后利用反射机制创建对应的 Bean。
  3. 代理模式
    • JDK 动态代理:Spring AOP(面向切面编程)在为接口类型的 Bean 创建代理时,常常使用 JDK 动态代理。当有切面逻辑(如事务管理、日志记录)需要应用到一个接口的实现类时,Spring 会在运行时动态生成一个代理类,这个代理类实现了目标接口。代理类拦截对目标接口方法的调用,在方法执行前后插入切面逻辑。例如,在事务管理中,代理类在目标方法执行前开启事务,方法执行成功后提交事务,出现异常时回滚事务。
    • CGLIB 代理:对于没有实现接口的类,Spring AOP 使用 CGLIB 代理。CGLIB 通过继承目标类生成一个子类作为代理。例如,当要对一个具体的类进行性能监控切面时,CGLIB 代理类会重写目标类的方法,在方法调用前后记录时间,从而实现性能监控,而不需要修改目标类的代码。
  4. 模板方法模式
    • Spring 的 JdbcTemplate 是模板方法模式的典型应用。它定义了操作数据库的基本模板,包括获取数据库连接、执行 SQL 语句、处理结果集、释放连接等步骤。其中获取连接和释放连接等步骤是固定的,而执行 SQL 语句和处理结果集这些步骤可以由用户通过提供回调方法(如RowMapper接口的实现)来定制。例如,在执行查询操作时,用户可以通过RowMapper接口实现将查询结果映射为 Java 对象的逻辑,JdbcTemplate 则按照其内部定义的模板方法流程完成整个数据库操作。

2.@Autowired和@Resource之间的区别?

  1. 来源和所属框架

    • @Autowired:是 Spring 框架提供的注解。它是 Spring 依赖注入(Dependency Injection,DI)机制的重要组成部分,用于自动装配 Bean。Spring 通过扫描类路径,根据类型(byType)自动匹配并注入对应的 Bean。
    • @Resource:是 Java EE(Java Platform, Enterprise Edition)规范中的注解,在 JSR - 250 中定义。它并不是 Spring 特有的,不过 Spring 也支持这个注解用于依赖注入。
  2. 注入方式

    • @Autowired
      • 默认是按照类型(byType)进行注入。例如,如果有一个接口UserService,并且有两个实现类UserServiceImpl1UserServiceImpl2,当在一个需要注入UserService的类中使用@Autowired注解时,Spring 会根据类型寻找对应的 Bean。如果只有一个UserService类型的 Bean,那么就会成功注入;如果有多个,就需要通过其他方式(如@Qualifier注解)来指定具体注入哪一个。
      • 也可以结合@Qualifier注解来按照名称(byName)进行注入。例如,@Autowired @Qualifier("userServiceImpl1") private UserService userService;,这里就是明确指定要注入名称为userServiceImpl1UserService类型的 Bean。
    • @Resource
      • 默认是按照名称(byName)进行注入。它会先在容器中查找名称与注解中指定的名称(可以通过name属性设置,如@Resource(name = "userServiceImpl1"))相同的 Bean 进行注入。如果没有指定名称,就会按照变量名作为 Bean 名称来查找。
      • 如果按照名称找不到匹配的 Bean,才会按照类型进行注入。这与@Autowired的默认行为正好相反。

3. Spring常用注解

  1. @Component
    • 作用:这是一个通用的 Spring 注解,用于将一个类标记为 Spring 容器中的组件。当 Spring 扫描到带有 @Component 注解的类时,会将其作为一个 Bean 进行管理。
    • 示例:假设我们有一个简单的服务类UserService,在类定义上添加@Component注解后,Spring 就会自动把这个类纳入容器管理。
  • 使用场景:用于自定义的普通 Java 类,只要希望被 Spring 容器管理,都可以使用这个注解。
  1. @Service
    • 作用:@Service 是 @Component 的一个特化注解,主要用于标注业务逻辑层(Service 层)的类。它的功能和 @Component 基本相同,只是语义上更加明确,用于区分不同层次的组件。
  • 使用场景:在构建企业级应用的三层架构(Controller - Service - DAO)时,用于标记服务层的类,让开发人员能够更直观地理解代码结构。
  1. @Repository
    • 作用:这是专门用于数据访问层(DAO 层)的注解,用于将数据访问类标记为 Spring 容器中的 Bean。它还具有将数据访问异常(如 SQLException)转换为 Spring 的DataAccessException的功能,使得数据访问层的异常处理更加统一和易于管理.
  • 使用场景:在和数据库交互的应用中,用于标记所有和数据访问相关的类,包括对各种数据库(如 MySQL、Oracle 等)的操作类。
  1. @Controller
    • 作用:用于标记 Spring MVC 中的控制器类。它将一个类标识为处理 HTTP 请求的前端控制器,配合 Spring MVC 的其他注解(如 @RequestMapping 等)可以方便地处理各种请求路径和请求方法。
  • 使用场景:在构建 Web 应用时,用于标记所有接收和处理用户请求的类,这些类通常会调用 Service 层的方法来完成业务逻辑,并将结果返回给视图层。
  1. @Autowired
    • 作用:用于自动注入 Bean。Spring 会根据类型自动寻找匹配的 Bean 并注入到对应的变量、方法参数或者构造函数参数中。
  • 使用场景:在需要在一个类中使用其他 Bean 时,避免手动获取和实例化,通过这个注解可以方便地完成依赖注入,提高代码的可维护性和可测试性。
  1. @RequestMapping
    • 作用:用于在 Spring MVC 中映射 HTTP 请求路径和请求方法。它可以用在类级别和方法级别,类级别的注解用于定义一个基础路径,方法级别的注解用于具体定义每个方法对应的路径和方法组合。
  • 使用场景:在构建 Web 应用的控制器中,用于定义每个请求处理方法对应的 URL 路径和请求方式,是实现前后端交互的关键注解之一。
  1. @Configuration
    • 作用:用于标记一个类为 Spring 的配置类。在这个类中,可以通过@Bean注解定义各种 Bean,替代传统的 XML 配置文件。
  • 使用场景:在基于 Java 配置的 Spring 项目中,用于集中定义和管理所有的 Bean,使得配置更加灵活和易于维护,尤其适用于大型项目和团队协作开发。
  1. @Bean
    • 作用:在@Configuration类中使用,用于定义一个方法,该方法返回的对象将作为一个 Bean 被 Spring 容器管理。
  • 使用场景:用于在 Java 配置类中创建和配置各种对象,包括自定义对象、第三方库对象等,是构建 Spring 容器的重要手段之一。

4.什么是Spring IOC ?

  1. 深入理解控制反转(IOC)概念
    • 控制权的转移
      public class LoginController {private UserService userService = new UserService();private UserDao userDao = new UserDaoImpl();public void login(String username, String password) {// 调用userService和userDao的方法来处理登录逻辑}
      }
      
       
      • 在传统的程序设计中,对象的控制权完全在开发者编写的代码手里。例如,在一个简单的 Java Web 应用程序中,如果要实现用户登录功能,开发者可能会在LoginController类中手动创建UserServiceUserDao的实例来处理用户登录的业务逻辑。像这样:
      • 这种方式下,LoginController类不仅要负责自身的业务逻辑(处理用户登录请求),还要负责创建和管理它所依赖的对象(UserServiceUserDao)。而在 Spring IOC 模式下,控制权被反转到了 Spring 容器。Spring 容器就像一个大管家,它负责创建UserServiceUserDao这些对象,LoginController只需要从容器中获取已经创建好并且配置好依赖关系的对象就可以了。
  2. 详细分析依赖注入(DI)
    • 构造函数注入的细节
      public class OrderService {private OrderDao orderDao;public OrderService(OrderDao orderDao) {this.orderDao = orderDao;}// 其他业务方法
      }
      
  • 参数匹配:当使用构造函数注入时,Spring 容器会根据构造函数的参数类型来匹配要注入的对象。例如,有一个OrderService类,它的构造函数接受一个OrderDao类型的参数:
  • 假设在 Spring 配置中有一个OrderDaobean定义,容器在创建OrderService的实例时,会查找类型为OrderDaobean,并将其作为参数传递给OrderService的构造函数。如果有多个OrderDao的实现类,还可以通过在配置中指定bean的名称或者使用@Qualifier注解等来精确匹配要注入的对象。
  • 对象的完整性保证:构造函数注入的一个优点是可以保证注入的对象在OrderService实例化时就已经准备好。这样可以确保OrderService对象从创建的那一刻起就处于一个完整的状态,不会出现因为某些依赖对象没有注入而导致的NullPointerException等问题。
  • Setter 方法注入的更多细节
    • 灵活性:Setter 方法注入提供了一种更加灵活的方式来注入依赖。例如,ProductService类有一个setProductDao的 Setter 方法:
    public class ProductService {private ProductDao productDao;public void setProductDao(ProductDao productDao) {this.productDao = productDao;}// 其他业务方法
    }
    
     
    • 在某些情况下,可能并不需要在ProductService对象创建时就注入ProductDao对象。比如,ProductService对象可能有一个初始化阶段,在这个阶段之后才需要ProductDao对象来执行一些数据查询操作。此时,Setter 方法注入就可以在需要的时候再注入ProductDao对象,而不是像构造函数注入那样必须在对象创建时就完成注入。
    • 循环依赖处理:Setter 方法注入在处理某些循环依赖的情况时可能会更加灵活。例如,A类依赖B类,B类又依赖A类。在这种情况下,使用 Setter 方法注入可能更容易解决循环依赖问题,因为对象可以先被创建,然后再通过 Setter 方法来解决相互之间的依赖关系,当然,Spring 在处理循环依赖时还有一些复杂的机制和限制。

5.什么是SpringAOP?

  1. 概念定义
    • Spring AOP(Aspect - Oriented Programming,面向切面编程)是 Spring 框架提供的一种编程范式,用于在不修改原有业务逻辑代码的基础上,实现横切关注点(Cross - Cutting Concerns)的功能。横切关注点是指那些会分散在多个业务模块中的功能,如日志记录、事务管理、安全验证等。
    • 例如,在一个包含多个业务方法的系统中,可能每个业务方法都需要记录日志来跟踪其执行情况。如果不使用 AOP,就需要在每个业务方法中添加日志记录的代码,这样会导致代码冗余且难以维护。而 Spring AOP 允许将日志记录这个横切关注点从业务方法中分离出来,集中进行管理。
  2. AOP 中的基本概念
    • 切面(Aspect):切面是一个包含了横切关注点相关逻辑的模块。它是 AOP 中的核心概念,将横切逻辑(如日志记录逻辑)封装在一个独立的单元中。切面由切点和通知组成。
    • 切点(Pointcut):切点用于定义在哪些连接点(Join Point)上应用切面的通知。连接点是程序执行过程中的某个特定位置,如方法调用、方法执行、异常抛出等。切点可以使用表达式来精确地指定在哪些类的哪些方法上应用切面。例如,可以定义一个切点,使其应用于某个包下所有以 “save” 命名的方法。
    • 通知(Advice):通知是切面中定义的在切点所匹配的连接点上执行的具体动作。Spring AOP 中有五种通知类型:
      • 前置通知(Before Advice):在目标方法执行之前执行的通知。例如,在业务方法执行前记录开始时间用于性能分析。
      • 后置通知(After Advice):在目标方法执行之后执行的通知。它不管目标方法是否抛出异常都会执行。比如,在业务方法执行后关闭数据库连接。
      • 返回通知(After - Returning Advice):在目标方法正常返回结果后执行的通知。可以用于对返回结果进行处理,如对返回的数据进行加密。
      • 异常通知(After - Throwing Advice):在目标方法抛出异常时执行的通知。用于处理异常情况,如记录异常信息到日志文件。
      • 环绕通知(Around Advice):环绕通知可以在目标方法执行前后都进行操作,它就像一个拦截器一样,可以控制目标方法是否执行、何时执行以及如何执行。例如,可以在环绕通知中实现缓存机制,先检查缓存中是否有目标方法的结果,如果有则直接返回,否则执行目标方法并将结果存入缓存。
  3. 工作原理
    • Spring AOP 是基于代理(Proxy)模式实现的。当一个目标对象(被代理的对象,如业务服务类)被配置为需要应用 AOP 时,Spring 会为其创建一个代理对象。这个代理对象会拦截对目标对象的方法调用。
    • 以 JDK 动态代理为例(当目标对象实现了接口时使用),代理对象和目标对象实现相同的接口。当客户端调用目标对象的接口方法时,实际上调用的是代理对象的方法。代理对象会根据切点的定义,判断是否需要执行切面的通知。如果需要,就会按照通知的类型(前置、后置等)在合适的时机执行通知中的逻辑,然后再调用目标对象的真实方法。
    • 例如,有一个UserService接口和它的实现类UserServiceImpl,并且配置了一个切面来记录UserService方法的执行日志。当客户端调用UserService接口的saveUser方法时,实际上调用的是 Spring 为UserServiceImpl创建的代理对象的saveUser方法。代理对象首先会检查日志记录这个切面的切点是否匹配saveUser方法,如果匹配,就会执行前置通知(记录方法开始执行的日志),然后调用UserServiceImpl的真实saveUser方法,最后执行后置通知(记录方法执行结束的日志)。
    • 应用场景
      • 日志记录:如前面所述,AOP 可以方便地在多个业务方法中统一添加日志记录功能。可以记录方法的执行时间、参数、返回结果等信息,便于系统的监控和调试。
      • 事务管理:在企业级应用中,事务管理是非常重要的。AOP 可以用于在多个业务方法周围添加事务控制逻辑。例如,对于数据库操作方法,在方法执行前开启事务,在方法正常执行完成后提交事务,在方法抛出异常时回滚事务。
      • 安全验证:可以在需要进行安全验证的方法调用前添加验证逻辑。例如,验证用户是否具有访问某个资源的权限。如果没有权限,就抛出异常或者返回错误信息,而不需要在每个业务方法中都编写安全验证的代码。

 6.Spring的循环依赖问题(重点)

  1. 循环依赖的概念
    • 循环依赖是指在 Spring 容器中,两个或多个 Bean 之间存在相互依赖的关系。例如,有 Bean A 和 Bean B,Bean A 依赖于 Bean B,同时 Bean B 又依赖于 Bean A。这种相互依赖的情况可能会导致在对象创建和初始化过程中出现问题。
    • 从代码角度看,假设存在两个类ClassAClassB,在 Spring 配置中定义为两个 Bean。ClassA中有一个属性是ClassB类型,ClassB中也有一个属性是ClassA类型,像这样:
    public class ClassA {private ClassB classB;// 构造函数或Setter方法注入ClassB
    }
    public class ClassB {private ClassA classA;// 构造函数或Setter方法注入ClassA
    }
    
  2. 循环依赖产生的问题及原因
    • 对象创建的死循环:在没有适当处理机制的情况下,当 Spring 容器试图创建ClassA的 Bean 时,它发现ClassA依赖于ClassB,所以它会去创建ClassB。但在创建ClassB的过程中,又发现ClassB依赖于ClassA,于是又回头去创建ClassA,这样就陷入了一个无限循环的创建过程,导致程序无法正常运行。
    • 未初始化的对象引用:即使通过某种方式避免了死循环,还可能出现另一个问题。例如,如果采用构造函数注入,当ClassA在构造函数中等待ClassB的完全初始化实例,而ClassB又在其构造函数中等待ClassA的完全初始化实例,这样两个对象都无法完成初始化,最终得到的是两个未完全初始化的对象引用,这可能会导致后续使用这些对象时出现NullPointerException或其他错误。
  3. Spring 解决循环依赖的方式
    • 三级缓存机制(针对单例 Bean)
      • Spring 使用了三级缓存来解决单例 Bean 的循环依赖问题。这三级缓存分别是:
        • singletonObjects:这是一级缓存,用于存放完全初始化好的单例 Bean。一旦一个 Bean 完成了创建、属性注入和初始化等所有步骤,就会被放入这个缓存中。
        • earlySingletonObjects:这是二级缓存,用于存放提前暴露的单例 Bean(还没有完成所有初始化步骤)。当一个 Bean 在创建过程中发现存在循环依赖,并且需要将自己提前暴露出来以解决依赖问题时,就会先将自己放入这个缓存。
        • singletonFactories:这是三级缓存,存放的是创建单例 Bean 的工厂对象。这个工厂对象可以用于创建 Bean,同时也可以用于在循环依赖情况下获取提前暴露的 Bean。
      • 当 Spring 容器创建一个单例 Bean 时,首先会尝试从singletonObjects缓存中获取,如果没有找到,就会创建这个 Bean。在创建过程中,如果发现存在循环依赖,就会将这个 Bean 提前暴露(放入earlySingletonObjects或通过singletonFactories来提供),使得其他依赖它的 Bean 可以获取到这个未完全初始化的 Bean,从而避免死循环。
      • 例如,假设创建ClassA,发现依赖ClassB,在创建ClassB时又发现依赖ClassA。此时,ClassA还没有完成全部初始化,但可以通过三级缓存机制提前暴露自己。ClassB就可以获取到这个提前暴露的ClassA,完成自己的创建,然后ClassA再获取已经创建好的ClassB,完成自己的剩余初始化步骤,最后将完全初始化好的ClassA放入singletonObjects缓存。
    • 构造函数注入的限制:Spring 在处理循环依赖时,对于构造函数注入有一定的限制。因为构造函数注入要求在对象创建时就注入所有依赖,所以如果存在循环依赖且都是通过构造函数注入的情况,Spring 无法解决,会抛出BeanCurrentlyInCreationException异常。这是因为在构造函数注入的场景下,很难像 Setter 方法注入那样先创建一个未完全初始化的对象并暴露出来解决循环依赖。
    • Setter 方法注入的优势:Setter 方法注入在处理循环依赖时相对更灵活。在这种情况下,Spring 可以先创建对象,将其放入缓存(通过三级缓存机制),然后再通过 Setter 方法注入依赖。例如,ClassAClassB通过 Setter 方法注入相互依赖,Spring 可以先创建ClassA,将其放入缓存,然后在创建ClassB时,从缓存中获取ClassA,注入到ClassB中,反之亦然。

7.Bean的生命周期(重点)

在 Spring 框架中,Bean 的生命周期是指从 Bean 的创建、初始化到销毁的整个过程。以下是 Bean 生命周期的详细过程:

  1. 实例化

    Spring 容器根据配置信息,如 XML 配置文件或注解,使用反射机制创建 Bean 的实例。例如,当配置了一个@Component注解的类时,Spring 会在启动时扫描并实例化该类。
  2. 属性赋值

    在 Bean 实例化后,Spring 会按照配置为 Bean 的属性进行赋值。可以通过 XML 中的<property>标签或@Autowired@Value等注解来指定属性的值或依赖关系。
  3. 初始化前

    在 Bean 的属性赋值完成后,会执行BeanPostProcessorpostProcessBeforeInitialization方法。这个阶段可以对 Bean 进行一些前置处理,例如修改 Bean 的属性值等。
  4. 初始化

    Spring 会检查 Bean 是否实现了InitializingBean接口,如果实现了,则调用其afterPropertiesSet方法。此外,还可以通过在 Bean 类的方法上添加@PostConstruct注解来指定初始化方法,该方法也会在这个阶段被调用。初始化方法通常用于执行一些需要在 Bean 创建完成后立即进行的操作,如资源的初始化、数据的加载等。
  5. 初始化后

    执行BeanPostProcessorpostProcessAfterInitialization方法。这个阶段可以对 Bean 进行后置处理,例如为 Bean 生成代理对象等。
  6. 使用

    Bean 初始化完成后,就可以在应用中被其他组件使用了。此时,Bean 已经处于可用状态,可以提供相应的服务和功能。
  7. 销毁前

    当 Spring 容器关闭时,会先执行DestructionAwareBeanPostProcessorpostProcessBeforeDestruction方法,允许在 Bean 销毁前进行一些自定义的处理。
  8. 销毁

    Spring 会检查 Bean 是否实现了DisposableBean接口,如果实现了,则调用其destroy方法。此外,还可以通过在 Bean 类的方法上添加@PreDestroy注解来指定销毁方法。销毁方法通常用于释放 Bean 占用的资源,如关闭数据库连接、释放文件资源等。
  9. 销毁后

    Bean 销毁完成后,它所占用的资源被释放,不再在 Spring 容器中管理,从内存中移除。

8.Mybatis的一级、二级缓存

MyBatis 提供了两级缓存机制:一级缓存和二级缓存,用于提升查询性能,减少数据库访问次数。

1. 一级缓存(Local Cache)

  • 作用范围:一级缓存是 SqlSession 级别的缓存,默认开启。

  • 生命周期:与 SqlSession 绑定,SqlSession 关闭或清空时,缓存失效。

  • 工作机制

    • 同一 SqlSession 中,相同查询语句和参数的结果会被缓存。

    • 执行更新操作(如 insert、update、delete)时,缓存会被清空,以保证数据一致性。

  • 特点

    • 自动启用,无需额外配置。

    • 仅对当前 SqlSession 有效,其他 SqlSession 无法共享。

2. 二级缓存(Global Cache)

  • 作用范围:二级缓存是 Mapper 级别的缓存,多个 SqlSession 共享。

  • 生命周期:与 Mapper 绑定,应用关闭或显式清空时,缓存失效。

  • 工作机制

    • 需要手动配置启用。

    • 多个 SqlSession 可以共享缓存数据。

    • 执行更新操作时,缓存会被清空。


http://www.ppmy.cn/ops/160518.html

相关文章

Ollama Docker 镜像部署

文章来源&#xff1a;Docker 部署文档 -- Ollama 中文文档|Ollama官方文档 仅 CPU docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama英伟达 GPU 安装 NVIDIA Container Toolkit。 使用 Apt 安装 配置存储库 curl -fsSL https://nvidia.g…

架构学习第七周--Prometheus

目录 一、监控系统基础 二、Prometheus介绍 三、Prometheus单机部署 四、服务发现与告警功能 4.1&#xff0c;服务发现 4.2&#xff0c;告警功能实现 五、Prometheus与Kubernetes 5.1&#xff0c;Kubernetes指标 5.2&#xff0c;Prometheus集群部署 一、监控系统基础…

科技赋能体育:Xsens MVN Analyze如何重塑运动训练新纪元

在哈尔滨亚洲冬季运动会备战期间&#xff0c;各国代表队都在积极使用新技术帮助运动员提升成绩。Xsens MVN Analyze运动分析系统以其高精度的数据采集与快速生成分析报告等特点&#xff0c;正在悄然改变着传统运动训练的模式&#xff0c;为运动员成绩提升开辟了新的路径。 一、…

Android Studio安装配置及运行

一、下载Android Studio 官网下载&#xff1a;下载 Android Studio 和应用工具 - Android 开发者 | Android Developers 跳转到下载界面&#xff0c;选择同意条款&#xff0c;并点击下载&#xff0c;如图&#xff1a; 二、详细安装 双击下载的文件 三、配置Android Studio …

拆解微软CEO纳德拉战略蓝图:AI、量子计算、游戏革命如何改写未来规则!

2025年2月19日 知名博主Dwarkesh Patel对话微软CEO萨蒂亚纳德拉 在最新访谈释放重磅信号&#xff1a;AI将掀起工业革命级增长&#xff0c;量子计算突破引爆材料科学革命&#xff0c;游戏引擎进化为世界模拟器。 整个视频梳理出几大核心观点&#xff0c;揭示科技巨头的未来十年…

【Kubernets】Kubernets资源类型Deployment详细介绍

文章目录 Kubernets资源概览Kubernetes Deployment 资源类型详细介绍Deployment 的主要功能Deployment 的核心字段字段详解1. **metadata**2. **spec**3. **template**4. **containers**5. **strategy**6. **restartPolicy** Deployment 的生命周期Deployment 的常用操作1. 创建…

ClickHouse分布式高可用实战:ReplicatedMergeTree引擎深度解析与代码实践

引言 在大数据场景下&#xff0c;数据的高可用性和容灾能力是核心需求。ClickHouse作为一款高性能的列式数据库&#xff0c;其 ReplicatedMergeTree 引擎完美解决了数据复制与分布式存储的难题。本文将通过代码实战原理解析&#xff0c;带你快速掌握这一核心引擎的使用技巧&am…

PDF文档中文本解析

常用的PDF文档解析解决方案有两种。 一是通过文档结构读取解析&#xff0c;另一种是通过ocr技术处理。 这里我们主要说一下文档读取解析的方案&#xff0c;现在常用的解析库有mupdf、pdfium、Aspose等第三方库来处理。其中mupdf、pdfium为开源、免费的。Aspose是一款收费的商业…