Maven 依赖的深入理解(二)

news/2025/2/26 5:58:36

四、Maven 依赖传递原理

(一)传递依赖的概念

在 Maven 项目中,传递依赖是一个非常重要的特性。它指的是当项目引入一个依赖时,这个依赖所依赖的其他组件库也会被 Maven 自动引入到项目中,而无需我们在项目的pom.xml文件中显式地声明这些间接依赖。

假设我们有三个项目 A、B、C,它们之间存在这样的依赖关系:A 依赖于 B,B 依赖于 C。在这种情况下,对于项目 A 来说,B 是它的直接依赖,因为我们在 A 的pom.xml文件中明确声明了对 B 的依赖;而 C 则是 A 的间接依赖,虽然我们没有在 A 的pom.xml中直接声明对 C 的依赖,但由于 B 依赖于 C,Maven 会自动将 C 引入到项目 A 中。这种依赖传递的关系可以用 “A->B->C” 来表示,其中箭头表示依赖方向。

例如,在一个 Spring Boot 项目中,我们通常会引入spring-boot-starter-web依赖,它是 Spring Boot 的 Web 启动器模块,用于快速搭建 Web 应用。在spring-boot-starter-web的pom.xml文件中,它依赖于spring-webmvc、spring-boot-starter等多个组件。当我们在项目中引入spring-boot-starter-web依赖时,Maven 会自动将spring-webmvc、spring-boot-starter以及它们所依赖的其他组件一并引入到项目中,这就是依赖传递的实际应用。通过依赖传递,我们可以大大简化项目的依赖管理,避免手动引入大量的间接依赖,提高开发效率。

(二)依赖范围对传递依赖的影响

依赖范围不仅决定了依赖在项目构建过程中的作用阶段,还对传递依赖的范围产生重要影响。不同的依赖范围组合会导致传递依赖在项目中的不同作用范围。下面通过表格详细说明不同依赖范围组合下传递依赖的范围变化:

第一直接依赖范围

第二直接依赖范围为 compile

第二直接依赖范围为 test

第二直接依赖范围为 provided

第二直接依赖范围为 runtime

compile

compile

-

-

runtime

provided

provided

-

provided

-

runtime

runtime

-

-

runtime

test

-

-

-

-

  1. compile 与 compile 组合:当第一直接依赖范围是compile,第二直接依赖范围也是compile时,传递依赖的范围与第一直接依赖的范围一致,即也是compile。这意味着该传递依赖在编译、测试和运行阶段都有效。例如,项目 A 依赖于项目 B(compile范围),项目 B 又依赖于项目 C(compile范围),那么项目 C 对于项目 A 来说就是compile范围的传递依赖,在项目 A 的整个生命周期中都能被使用。
  1. compile 与 test 组合:如果第二直接依赖范围是test,则依赖不会得以传递。这是因为test范围的依赖仅在测试阶段有效,对于其他依赖它的项目来说,在编译和运行阶段并不需要这些测试相关的依赖。例如,项目 A 依赖于项目 B(compile范围),项目 B 依赖于 JUnit(test范围),那么 JUnit 不会作为传递依赖被引入到项目 A 中。
  1. compile 与 provided 组合:当第二直接依赖范围是provided时,只传递第一直接依赖范围也为provided的依赖,且传递性依赖的范围同样为provided。例如,项目 A 依赖于项目 B(compile范围),项目 B 依赖于javax.servlet:servlet-api(provided范围),由于项目 A 对项目 B 的依赖范围不是provided,所以javax.servlet:servlet-api不会作为传递依赖被引入到项目 A 中。但如果项目 A 对项目 B 的依赖范围也是provided,那么javax.servlet:servlet-api就会以provided范围传递到项目 A 中,在编译和测试阶段可用,运行时由容器提供。
  1. compile 与 runtime 组合:当第二直接依赖范围是runtime时,传递性依赖的范围与第一直接依赖的范围一致,但有一个特殊情况,当第一直接依赖范围是compile时,此时传递的依赖范围为runtime。例如,项目 A 依赖于项目 B(compile范围),项目 B 依赖于 MySQL 的 JDBC 驱动(runtime范围),那么 MySQL 的 JDBC 驱动对于项目 A 来说是runtime范围的传递依赖,在测试和运行阶段有效,编译阶段不需要。
  1. 其他组合:对于provided、runtime、test与其他依赖范围的组合,按照表格中的规则进行判断。例如,provided与provided组合时,传递依赖范围为provided;runtime与runtime组合时,传递依赖范围为runtime等。通过理解这些依赖范围对传递依赖的影响规则,我们可以更加精准地控制项目中的依赖,避免不必要的依赖引入,提高项目的稳定性和可维护性。

五、Maven 依赖冲突及解决

(一)依赖冲突的表现和原因

在 Maven 项目中,依赖冲突是一个常见且棘手的问题,它可能会给项目的开发和运行带来诸多困扰。依赖冲突通常有以下几种表现形式:

  1. 编译错误:当项目依赖的不同模块或库引入了同一个依赖项的不同版本,且这些版本之间存在 API 不兼容的情况时,就可能导致编译失败。例如,一个模块依赖gson库的 2.8.6 版本,而另一个模块依赖gson库的 2.7 版本,这两个版本的某些 API 可能存在差异,在编译时就会出现找不到方法或类的错误。
  1. 运行时错误:即使项目能够成功编译,依赖冲突也可能在运行时引发错误。由于不同版本的依赖项在功能实现上可能存在差异,当项目在运行时调用到这些有差异的部分时,就会出现运行时异常,如NoSuchMethodError、ClassNotFoundException等。比如,一个依赖项在新版本中删除了某个类或方法,但项目中其他部分仍然依赖该类或方法,就会导致运行时错误。
  1. 循环依赖报错:循环依赖是一种特殊的依赖冲突情况,当项目中的模块之间形成了相互依赖的闭环时,就会出现循环依赖问题。例如,模块 A 依赖模块 B,而模块 B 又依赖模块 A,这会导致 Maven 在解析依赖关系时陷入死循环,无法正确构建项目,通常会抛出类似于 “Circular dependency between...” 的错误信息。

依赖冲突的产生原因主要包括以下几个方面:

  1. 直接依赖和间接依赖导致的版本冲突:在 Maven 项目中,我们通常会直接声明一些依赖项,但这些直接依赖项又会引入它们自己的间接依赖。当不同的直接依赖项引入了同一个间接依赖的不同版本时,就会产生版本冲突。例如,项目中直接依赖了spring-boot-starter-web和spring-boot-starter-data-jpa,spring-boot-starter-web间接依赖spring-core的 5.3.10 版本,而spring-boot-starter-data-jpa间接依赖spring-core的 5.3.8 版本,这样就会出现spring-core的版本冲突。
  1. 循环依赖:循环依赖的产生往往是由于项目结构设计不合理,模块之间的职责划分不清晰,导致模块之间的依赖关系混乱。比如,在一个分层架构的项目中,如果业务逻辑层的模块 A 调用了数据访问层的模块 B,而模块 B 又反过来调用了模块 A 中的某些方法,就会形成循环依赖。循环依赖不仅会导致 Maven 构建失败,还会使代码的维护和理解变得困难,因为模块之间的依赖关系变得复杂且难以理清。

(二)解决依赖冲突的方法

面对依赖冲突问题,我们可以采用以下几种方法来解决:

  1. 依赖调解原则:Maven 在处理依赖冲突时遵循两个重要原则,即路径优先和声明优先原则。路径优先原则是指在依赖传递路径上离项目根节点最近的依赖项版本优先。例如,假设项目 A 依赖于 B 和 C,B 又依赖于 D 的 1.0 版本,C 依赖于 D 的 2.0 版本,且 B 到 D 的依赖路径比 C 到 D 的依赖路径短,那么 Maven 会优先选择 B 所依赖的 D 的 1.0 版本。声明优先原则是指如果在同一层级上有多个依赖项引入了同一个依赖项的不同版本,那么会选择首次声明的依赖项版本。例如,在pom.xml文件中,先声明了依赖com.example:library:1.0,后声明了依赖com.example:library:2.0,那么 Maven 会优先使用com.example:library:1.0版本。通过理解和运用这两个原则,我们可以通过调整依赖的声明顺序或引入更合适的依赖路径来解决部分依赖冲突问题。
  1. 显示声明依赖:为了解决依赖冲突,我们可以在项目中显式声明需要的依赖项版本。这样,Maven 会优先使用我们声明的版本,从而避免冲突。例如,当项目中存在多个模块对log4j库的依赖版本不一致时,我们可以在pom.xml文件中明确声明所需的log4j版本:
 

<dependencies>

<dependency>

<groupId>org.apache.logging.log4j</groupId>

<artifactId>log4j-core</artifactId>

<version>2.14.1</version>

</dependency>

</dependencies>

通过这种方式,无论其他依赖项如何传递引入log4j,Maven 都会以我们显式声明的 2.14.1 版本为准,从而确保项目中使用的log4j版本一致性,避免因版本冲突导致的问题。

3. 使用 dependencyManagement:dependencyManagement是 Maven 中用于统一管理依赖版本的重要机制。通过在项目的<dependencyManagement>标签中声明依赖项版本,我们可以在子模块中引入依赖项时无需指定版本,Maven 会自动使用<dependencyManagement>中声明的版本。例如,在一个多模块的项目中,父模块的pom.xml文件中可以这样配置:

 

<dependencyManagement>

<dependencies>

<dependency>

<groupId>com.example</groupId>

<artifactId>conflicting-library</artifactId>

<version>3.0.0</version>

</dependency>

</dependencies>

</dependencyManagement>

在子模块中引入conflicting-library依赖时,只需声明groupId和artifactId,无需指定版本:

 

<dependencies>

<dependency>

<groupId>com.example</groupId>

<artifactId>conflicting-library</artifactId>

</dependency>

</dependencies>

这样做的好处是,当需要升级或切换依赖版本时,只需在父模块的<dependencyManagement>中修改版本号,所有子模块都会自动使用新的版本,大大提高了依赖版本管理的效率和一致性,同时也减少了因版本不一致导致的依赖冲突风险。

4. 使用 dependencyExclusions:如果我们确定某个依赖项不需要传递其依赖关系,或者某个传递依赖会导致冲突,我们可以使用<dependencyExclusions>标签排除不需要的依赖项。例如,当项目中引入library-a依赖时,发现它传递引入的conflicting-library与其他依赖存在冲突,我们可以这样配置:

 

<dependencies>

<dependency>

<groupId>com.example</groupId>

<artifactId>library-a</artifactId>

<version>1.0.0</version>

<exclusions>

<!-- 排除冲突的依赖项 -->

<exclusion>

<groupId>com.example</groupId>

<artifactId>conflicting-library</artifactId>

</exclusion>

</exclusions>

</dependency>

</dependencies>

通过上述配置,library-a将不再传递引入conflicting-library,从而避免了因该依赖项导致的冲突。这种方式可以让我们更加精确地控制项目的依赖关系,排除不必要的依赖,减少依赖冲突的可能性。

5. 解决循环依赖:当遇到循环依赖时,单纯地调整依赖配置往往无法解决问题,需要我们深入分析项目结构和代码,对项目进行重构。例如,在一个 Java Web 项目中,业务逻辑层的UserService类依赖于数据访问层的UserDao类来获取用户数据,而UserDao类又依赖于UserService类中的某些业务逻辑方法来进行数据处理,这就形成了循环依赖。为了解决这个问题,我们可以重新审视业务逻辑,将UserService和UserDao之间的依赖关系进行梳理和重构。可以将UserService中被UserDao依赖的业务逻辑提取出来,放到一个独立的服务类中,或者通过接口回调等方式来解耦它们之间的依赖关系,从而打破循环依赖,使项目结构更加清晰,依赖关系更加合理。

六、Maven 依赖管理高级技巧

(一)依赖排除

在 Maven 项目中,依赖排除是一种非常重要的依赖管理技巧,它可以帮助我们避免引入不必要的传递依赖,从而减少依赖冲突的风险,提高项目的稳定性和可维护性。

依赖排除的作用主要体现在以下几个方面:当项目依赖的某个组件库引入了一些我们不需要的传递依赖时,这些不必要的依赖可能会带来一些问题。例如,它们可能会与项目中其他已有的依赖产生版本冲突,导致编译错误或运行时异常;或者增加项目的构建时间和部署包大小,影响项目的性能和可部署性。通过依赖排除,我们可以精确地控制项目的依赖关系,只保留真正需要的依赖。

在 Maven 中,我们通过<exclusions>标签来实现依赖排除。例如,假设我们的项目依赖了spring-boot-starter-web,而spring-boot-starter-web又传递依赖了commons-logging,但我们在项目中已经使用了SLF4J作为日志框架,不希望引入commons-logging,以免造成日志框架冲突。这时,我们可以在spring-boot-starter-web的依赖配置中添加<exclusions>标签来排除commons-logging依赖,具体配置如下:

 

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

<version>2.7.5</version>

<exclusions>

<exclusion>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

</exclusion>

</exclusions>

</dependency>

</dependencies>

在上述配置中,<exclusion>标签内的groupId和artifactId分别指定了要排除的依赖的组 ID 和构件 ID。通过这样的配置,Maven 在解析依赖时,会忽略spring-boot-starter-web对commons-logging的传递依赖,从而确保项目中不会引入commons-logging。

(二)可选依赖

可选依赖是 Maven 依赖管理中的另一个重要概念,它为我们提供了一种更加灵活的依赖控制方式。可选依赖允许我们将某些依赖声明为可选的,这意味着当其他项目依赖当前项目时,这些可选依赖不会自动传递给依赖它的项目。

具体来说,通过在<dependency>标签内添加<optional>标签并设置其值为true,我们就可以将一个依赖设置为可选依赖。例如:

 

<dependencies>

<dependency>

<groupId>com.example</groupId>

<artifactId>library</artifactId>

<version>1.0.0</version>

<optional>true</optional>

</dependency>

</dependencies>

在这个例子中,com.example:library:1.0.0被声明为可选依赖。当其他项目依赖当前项目时,com.example:library:1.0.0不会自动作为传递依赖被引入到其他项目中。

可选依赖的应用场景非常广泛。以持久化框架引入数据库驱动包为例,假设我们开发了一个通用的持久化框架,它支持多种数据库,如 MySQL、Oracle、PostgreSQL 等。在框架的pom.xml文件中,我们需要引入各种数据库的驱动包依赖,但是对于使用这个框架的项目来说,它们可能只需要使用其中一种数据库,并不需要引入所有的数据库驱动包。这时,我们就可以将这些数据库驱动包的依赖设置为可选依赖。例如:

 

<dependencies>

<!-- MySQL驱动,设置为可选依赖 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>8.0.26</version>

<optional>true</optional>

</dependency>

<!-- Oracle驱动,设置为可选依赖 -->

<dependency>

<groupId>com.oracle.database.jdbc</groupId>

<artifactId>ojdbc8</artifactId>

<version>21.3.0.0</version>

<optional>true</optional>

</dependency>

<!-- PostgreSQL驱动,设置为可选依赖 -->

<dependency>

<groupId>org.postgresql</groupId>

<artifactId>postgresql</artifactId>

<version>42.3.3</version>

<optional>true</optional>

</dependency>

</dependencies>

这样,当其他项目使用我们的持久化框架时,如果它只需要连接 MySQL 数据库,那么只需要在自己的pom.xml文件中显式引入mysql-connector-java依赖即可,而不会引入其他不必要的数据库驱动包依赖,从而减少了项目的依赖复杂性和部署包大小。

(三)使用依赖树分析工具

在 Maven 项目中,随着依赖关系的日益复杂,准确分析和定位依赖冲突变得至关重要。依赖树分析工具可以帮助我们清晰地了解项目的依赖结构,快速发现和解决依赖冲突问题,提高依赖管理的效率。

Maven 自带的dependency tree是一个非常实用的依赖分析工具。我们可以在命令行中进入项目的根目录,然后执行mvn dependency:tree命令,Maven 会以树状结构输出项目的所有直接和间接依赖关系。例如:

 

mvn dependency:tree

执行上述命令后,我们会得到类似以下的输出:

 

[INFO] com.example:my-project:jar:1.0.0

[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.5:compile

[INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.7.5:compile

[INFO] | | +- org.springframework.boot:spring-boot:jar:2.7.5:compile

[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.7.5:compile

[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.7.5:compile

[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.6:compile

[INFO] | | | | +- ch.qos.logback:logback-core:jar:1.2.6:compile

[INFO] | | | | \- org.slf4j:slf4j-api:jar:1.7.32:compile

[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.14.1:compile

[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.14.1:compile

[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:1.7.32:compile

[INFO] | | \- org.yaml:snakeyaml:jar:1.29:runtime

[INFO] | +- org.springframework.boot:spring-boot-starter-json:jar:2.7.5:compile

[INFO] | | +- com.fasterxml.jackson.core:jackson-databind:jar:2.13.3:compile

[INFO] | | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.13.3:compile

[INFO] | | | \- com.fasterxml.jackson.core:jackson-core:jar:2.13.3:compile

[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.3:compile

[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.13.3:compile

[INFO] | | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.3:compile

[INFO] | +- org.springframework:spring-web:jar:5.3.18:compile

[INFO] | | +- org.springframework:spring-beans:jar:5.3.18:compile

[INFO] | | +- org.springframework:spring-context:jar:5.3.18:compile

[INFO] | | \- org.springframework:spring-webmvc:jar:5.3.18:compile

[INFO] | | +- org.springframework:spring-aop:jar:5.3.18:compile

[INFO] | | +- org.springframework:spring-expression:jar:5.3.18:compile

[INFO] | | \- org.springframework:spring-core:jar:5.3.18:compile

[INFO] | | \- org.springframework:spring-jcl:jar:5.3.18:compile

[INFO] | \- org.springframework:spring-tx:jar:5.3.18:compile

[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.7.5:test

[INFO] | +- org.springframework.boot:spring-boot-test:jar:2.7.5:test

[INFO] | +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.7.5:test

[INFO] | +- com.jayway.jsonpath:jsonpath:jar:2.6.0:test

[INFO] | | +- net.minidev:json-smart:jar:2.4.8:test

[INFO] | | | \- net.minidev:accessors-smart:jar:1.2:test

[INFO] | | | \- org.ow2.asm:asm:jar:5.0.4:test

[INFO] | | \- org.slf4j:slf4j-api:jar:1.7.32:test

[INFO] | +- junit:junit:jar:4.13.2:test

[INFO] | +- org.assertj:assertj-core:jar:3.22.0:test

[INFO] | +- org.mockito:mockito-core:jar:4.1.0:test

[INFO] | | +- net.bytebuddy:bytebuddy:jar:1.12.16:test

[INFO] | | +- net.bytebuddy:bytebuddy-agent:jar:1.12.16:test

[INFO] | | \- org.objenesis:objenesis:jar:3.2:test

[INFO] | +- org.hamcrest:hamcrest-core:jar:1.3:test

[INFO] | +- org.hamcrest:hamcrest-library:jar:1.3:test

[INFO] | +- org.skyscreamer:jsonassert:jar:1.5.0:test

[INFO] | | \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test

[INFO] | +- org.springframework:spring-core:jar:5.3.18:test

[INFO] | \- org.springframework:spring-test:jar:5.3.18:test

[INFO] \- org.projectlombok:lombok:jar:1.18.24:compile

从这个输出中,我们可以清晰地看到项目的依赖层次结构,每个依赖的坐标(groupId、artifactId、version)以及依赖范围。如果存在依赖冲突,例如某个依赖的不同版本被引入,dependency tree会在输出中显示冲突的情况,我们可以根据这些信息来分析和解决依赖冲突。

除了dependency tree,一些三方 IDE(如 IntelliJ IDEA)中的冲突检测工具,如Maven Helper,也为我们提供了更加直观和便捷的依赖分析功能。以Maven Helper为例,我们可以在 IDEA 的插件市场中搜索并安装Maven Helper插件。安装完成后,在项目的pom.xml文件中,点击下方的Dependency Analyzer标签,就可以进入依赖分析界面。在这个界面中,Maven Helper提供了多个选项卡,其中Conflicts选项卡可以帮助我们快速查看项目中存在的依赖冲突,它会以列表的形式展示冲突的依赖项,包括冲突的版本信息;All Dependencies as Tree选项卡则以树状结构展示项目的所有依赖,与mvn dependency:tree命令的输出类似,但在 IDE 中查看更加方便,并且可以直接在界面上进行一些操作,如排除冲突依赖等。当我们发现某个依赖存在冲突时,只需在Conflicts选项卡中右键点击冲突的依赖项,选择Exclude选项,Maven Helper会自动在pom.xml文件中添加相应的依赖排除配置,帮助我们快速解决依赖冲突问题。通过使用这些依赖树分析工具,我们能够更加高效地管理项目的依赖关系,及时发现和解决依赖冲突,确保项目的顺利构建和运行。

七、总结与展望

在 Java 项目开发的浩瀚海洋中,Maven 依赖宛如一座明亮的灯塔,为我们指引着依赖管理的方向。通过本文的深入探讨,我们对 Maven 依赖有了全面而深刻的理解。从基础概念入手,我们明晰了依赖的定义和坐标,它们是 Maven 依赖体系的基石,让我们能够准确地定位和引入所需的依赖组件。

依赖范围的详解使我们掌握了依赖在不同阶段的作用域,能够根据项目的实际需求,精确地控制依赖的使用,避免不必要的依赖引入,提高项目的稳定性和可维护性。依赖传递原理的揭示,让我们看到了 Maven 在依赖管理中的强大自动化能力,它能够自动解析和引入项目所需的间接依赖,大大简化了依赖管理的过程。

然而,依赖冲突是我们在项目开发中不可避免的挑战。我们深入分析了依赖冲突的表现和原因,并掌握了一系列有效的解决方法,如依赖调解原则、显示声明依赖、使用 dependencyManagement 和 dependencyExclusions 等。这些方法就像是我们手中的利剑,能够帮助我们斩断依赖冲突的困扰,确保项目的顺利构建和运行。

此外,我们还学习了 Maven 依赖管理的高级技巧,如依赖排除、可选依赖和使用依赖树分析工具等。依赖排除让我们能够灵活地排除不必要的传递依赖,可选依赖则为我们提供了更加灵活的依赖控制方式,而依赖树分析工具则帮助我们清晰地了解项目的依赖结构,快速发现和解决依赖冲突问题。

深入理解和掌握 Maven 依赖管理对于 Java 项目开发至关重要。它不仅能够提高我们的开发效率,减少依赖冲突带来的问题,还能使我们的项目结构更加清晰、稳定和可维护。在未来的项目开发中,希望读者能够不断实践和优化依赖管理,充分发挥 Maven 依赖的强大功能。同时,随着技术的不断发展和项目需求的日益复杂,Maven 依赖管理也将不断演进和完善,我们需要持续关注相关技术的发展动态,不断学习和探索新的依赖管理方法和技巧,以更好地应对项目开发中的各种挑战,打造更加优质、高效的 Java 项目。


http://www.niftyadmin.cn/n/5868126.html

相关文章

​Linux 服务器上部署搭建 Jupyter notebook【详细教程】​

安装anaconda3 一、linux服务器手动安装Anaconda3教程 1.首先清华镜像站 下载anaconda3。 此次下载的版本如下&#xff1a; 2.下载好后&#xff0c;使用WinSCP将下载好的文件上传到服务器。 3.切换到anaconda3所在文件位置 在文件目录下执行 bash Anaconda3-5.2.0-Linux-x8…

AI领域风云变幻:Deepseek爆火现象深度解析

摘要 神州数码集团首席AI专家谢国斌深入分析了Deepseek爆火背后的现象&#xff0c;揭示了AI领域竞争格局的深刻变革。随着算力内卷加剧&#xff0c;AI企业正面临前所未有的挑战与机遇。谢国斌指出&#xff0c;Deepseek的成功不仅在于其强大的算法和数据处理能力&#xff0c;更在…

猿大师播放器:网页内嵌VLC/FFPlayer在Web端直接播放RTSP/RTMP/H.265视频流

据统计&#xff0c;2024年中国视频转码服务器市场规模已突破百亿&#xff0c;但企业IT投入中约40%用于转码服务器的采购与维护&#xff0c;消防、安防等场景对实时性的严苛要求&#xff08;如火灾预警需秒级响应&#xff09;&#xff0c;使得传统转码方案因延迟过高而屡屡失效&…

Python生成器250224

是由函数与yield关键字创造出来的写法&#xff0c;在特定情况下&#xff0c;可以帮助我们节省内存执行一个生成器函数&#xff0c;函数体代码不会运行&#xff0c;会返回一个生成器对象要想执行函数体内容&#xff0c;就需要使用这个生成器对象来执行 def func():print(123)yi…

渗透测试实验

1、seacmsv9注入管理员密码 获取管理员账号&#xff08;name&#xff09; http://www.test2.com/comment/api/index.php?gid1&page2&rlist[]%27,%20extractvalue(1,%20concat_ws(0x20,%200x5c,(select%20(name)from%20sea_admin))),%27 2、获取管理员密码 http://www…

【项目】基于Boost自主实现搜索引擎

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…

【System Verilog and UVM基础入门26】Verdi使用教程指南

《Verdi使用教程指南 》 下载链接&#xff1a; https://download.csdn.net/download/TommiWei/90429701https://download.csdn.net/download/TommiWei/90429701 朋友你好&#xff0c;不管你是否使用过Verdi这款EDA仿真工具。 不管你是否还在寻找免费的使用教材。 不管你是否…

50周学习go语言:第五周 复合类型与词频统计

以下是第五周复合类型&#xff08;数组、切片与映射&#xff09;的详细学习内容&#xff0c;按照第四周的深度要求设计&#xff1a; 第五周&#xff1a;复合类型与词频统计 一、复合类型详解 1. 数组&#xff08;Array&#xff09; // 声明与初始化 var arr1 [3]int …