当前位置: 首页 > news >正文

【Spring篇】初识之Spring的入门程序及控制反转与依赖注入

 

      🧸安清h:个人主页

   🎥个人专栏:【计算机网络】,【Mybatis篇】

🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。


 文章目录

🎯初始Spring 

🎯Spring的体系结构

🎯Spring的下载及目录结构

🎯Spring的入门程序

🚦pom.xml文件

🚦创建类Hello

🚦创建配置文件applicationContext.xml

🚦创建测试类

🎯控制反转与依赖注入

🚦控制反转概念

🚦依赖注入概念

🚦依赖注入类型

✨构造方法注入

🍔编写用户类

 🍔配置Bean信息

🍔编写测试类

✨setter方法注入

🍔编写用户类

 🍔配置Bean信息

🍔编写测试类

🚦依赖注入应用

🍔编写Dao层

🍔编写Service层

🍔编写applicationContext.xml配置文件

🍔编写测试类


🎯初始Spring 

Spring框架是一个开源的Java平台,用于简化企业级应用程序的开发。它提供了一系列的功能,使得开发者能够更容易地构建和维护应用程序。以下是Spring框架的一些主要优点:

  1. 依赖注入(DI):Spring通过依赖注入提供了一种松耦合的方式来组装应用程序的不同部分。
  2. 面向切面编程(AOP):Spring支持面向切面编程,允许开发者将横切关注点(如日志记录、事务管理等)与业务逻辑分离。
  3. 声明式事务管理:Spring提供了声明式事务管理,使得事务管理变得更加简单和透明。
  4.  集成多种数据访问技术:Spring整合了JDBC、Hibernate、JPA等数据访问技术,提供了一致的编程模式。
  5.  支持多种视图层技术:Spring支持多种视图层技术,如JSP、Thymeleaf、JSF等。
  6.  支持MVC:Spring提供了一个灵活的Web MVC框架,使得Web应用程序的开发更加简单。
  7. 轻量级:Spring框架本身是轻量级的,不会对应用程序的性能造成太大影响。
  8. 模块化:Spring框架是高度模块化的,开发者可以根据需要选择使用特定的模块。
  9. 支持多种配置方式:Spring支持XML、Java配置以及注解等多种配置方式。
  10. 支持响应式编程:Spring 5引入了对响应式编程的支持,使得开发非阻塞应用程序变得更加容易。

这些优点使得Spring成为Java企业级应用程序开发的首选框架之一。
 

🎯Spring的体系结构

Spring是模块化的,允许使用者只选择适用于自己的模块。下面对部分模块进行简单介绍:

  1. 核心容器

    • Spring Core:提供了依赖注入(DI)和面向切面编程(AOP)的支持。
    • Spring Beans:管理配置元数据,处理Bean的生命周期。
    • Spring Context:扩展了核心容器,提供了更高级的特性,如国际化支持、资源访问、事件传播等。
    • Spring Expression Language (SpEL):提供了强大的表达式语言,可以在运行时查询和操作对象图。

  2. 数据访问/集成

    • JDBC:提供JDBC抽象层,简化数据库操作。
    • ORM:整合了Hibernate、JPA等对象关系映射框架。
    • OXM:提供了对象XML映射的支持。
    • JMS:支持Java消息服务。
    • 事务管理:提供了声明式和编程式事务管理。
  3. Web

    • Spring MVC:实现了MVC模式,支持Web应用程序的开发。
    • Spring WebFlux:支持响应式编程的Web框架。
    • Spring Web Services:支持SOAP和RESTful Web服务。
  4. AOP
  1. 提供了面向切面编程的支持,允许开发者定义切面和通知。

🎯Spring的下载及目录结构

在使用Spring之前需要获取它的jar包,这些jar包可以在Spring官网下载。下载完成后会得到如下:

🎯Spring的入门程序

🚦pom.xml文件

在pom.xml文件中添加以下代码:

 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.8.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>5.2.8.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>

🚦创建类Hello

在包com.haust.pojo中编写类Hello,具体代码如下:

public class Hello {private String username;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public void show(){System.out.println(username+"欢迎来到Spring");}
}

🚦创建配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="helloSpring" class="com.haust.pojo.Hello"><property name="username" value="清"></property></bean>
</beans>

🚦创建测试类

public class HelloTest {public static void main(String[]args){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");Hello hello= (Hello) applicationContext.getBean("helloSpring");hello.show();}
}

🎯控制反转与依赖注入

🚦控制反转概念

控制反转(Inversion of Control,IoC)是一种设计原则,用来减少计算机编程中的耦合度。这个概念的核心思想是将对象之间的控制逻辑从对象本身转移到外部容器或框架中,从而实现解耦。

在传统的编程模式中,对象通常自己负责获取它们所需的依赖项,例如,通过直接创建对象或者从全局上下文中查找它们。这种方式会导致代码之间的高度耦合,使得代码难以测试、维护和重用。

控制反转通过以下两种主要方式实现:

  1. 依赖注入(Dependency Injection,DI): 这是控制反转最常见的形式。在依赖注入中,对象不需要自己查找或创建依赖项,而是被动地从外部“注入”这些依赖。依赖注入可以是显式的(通过构造函数、setter方法或接口)或隐式的(通过注解或约定)。

  2. 服务定位器模式(Service Locator pattern): 在服务定位器模式中,对象不直接创建或查找依赖项,而是通过一个中介(服务定位器)来访问它们。服务定位器负责查找和提供所需的依赖项。

控制反转的好处包括:

  • 降低耦合度:对象不再需要知道如何创建或查找它们的依赖项,因此减少了对象之间的依赖关系。
  • 提高模块化:由于依赖项是通过外部注入的,因此可以更容易地替换模块或组件。
  • 增强测试性:可以更容易地对对象进行单元测试,因为可以注入模拟(mock)对象或存根(stub)。
  • 提高代码的可读性和可维护性:代码更加清晰,因为对象不再包含复杂的逻辑来查找或创建依赖项。

🚦依赖注入概念

依赖注入(Dependency Injection,简称DI)是一种实现控制反转(Inversion of Control,IoC)的设计模式。它是一种编程技巧,用于减少代码间的耦合度,从而使得代码更容易测试、维护和重用。依赖注入的核心思想是将组件(对象)的依赖关系由外部传递进来,而不是由组件自己创建或查找依赖。

依赖注入的主要目的是:

  1. 降低组件之间的耦合度:组件不需要知道如何创建或获取它们的依赖项,这些依赖项将由外部提供。
  2. 提高组件的可测试性:由于依赖项是外部提供的,可以很容易地替换为模拟对象(mocks)或存根(stubs)进行单元测试。
  3. 增强代码的可读性和可维护性:组件的创建和依赖项的获取被分离,使得代码结构更清晰,更易于理解和维护。

🚦依赖注入类型

✨构造方法注入

在Spring框架中,构造方法注入是一种依赖注入的方式,它通过构造方法将所需的依赖项传递给Bean。这种方式通常被认为是更推荐的做法,因为它可以使Bean的状态更加明确,并且可以确保在创建Bean时所有的必需依赖项都已经准备好。下面通过一个示例来演示:

🍔编写用户类

public class User {private int id;private String username;private String password;public User(int id, String username, String password) {this.id = id;this.username = username;this.password = password;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
 🍔配置Bean信息

在Spring的XML配置文件中,<constructor-arg> 标签用于构造方法注入。在这个例子中,<constructor-arg> 标签定义了传递给 User 类构造方法的参数。每个 <constructor-arg> 标签代表一个参数,并且可以通过 name 属性指定参数的名称,或者省略 name 属性,Spring将根据参数的位置来匹配。

在applicationContext-User.xml文件中编写以下代码:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user1" class="com.haust.pojo.User"><constructor-arg name="id" value="1"/><constructor-arg name="username" value="lili"/><constructor-arg name="password" value="123456"/></bean>
</beans>
🍔编写测试类
public class UserTest {public static void main(String[]args){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext-User.xml");User user=applicationContext.getBean("user1",User.class);System.out.println(user);}
}

✨setter方法注入

在Spring框架中,setter方法注入是一种常用的依赖注入方式,它利用类的setter方法来注入依赖项。这种方式的好处是可以在运行时改变Bean的属性值,从而提供了更大的灵活性。

以下是setter方法注入的一个简单示例:

🍔编写用户类

用户类中必须有setter方法

public class User2 {private int id;private String username;private String password;public void setId(int id) {this.id = id;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User2{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
 🍔配置Bean信息
    <bean id="user2" class="com.haust.pojo.User2"><property name="id" value="2"/><property name="username" value="popo"/><property name="password" value="123"/></bean>
🍔编写测试类
public class User2Test {public static void main(String[]args){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext-User.xml");User2 user=applicationContext.getBean("user2", User2.class);System.out.println(user);}}

🚦依赖注入应用

了解两种注入方式之后,下面通过一个示例,实现一个登录验证。

🍔编写Dao层

在dao包新建接口UserDao并添加login()方法实现登录功能:

public interface UserDao {public boolean login(String name,String password);
}

在impl包中新建UserDaoImpl类用来实现UserDao类中的login()方法:

public class UserDaoImpl implements UserDao {@Overridepublic boolean login(String name, String password) {if(name.equals("lili")&&password.equals("123")){return true;}return false;}
}
🍔编写Service层

在service包中新建接口UserService,UserService作为业务逻辑层接口:

public interface UserService {public boolean login(String name,String password);
}

在impl包中新建UserServiceImpl类用来实现UserService类中的login()方法:

public class UserServiceImpl implements UserService {private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic boolean login(String name, String password) {return userDao.login(name, password);}
}
🍔编写applicationContext.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userDao" class="com.haust.impl.UserDaoImpl"></bean><bean id="UserService" class="com.haust.impl.UserServiceImpl"><property name="userDao" ref="userDao"/></bean>
</beans>
🍔编写测试类
public class LoginTest {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService) applicationContext.getBean("userService");boolean flag = userService.login("lili", "123");if (flag) {System.out.println("登录成功");} else {System.out.println("登录失败");}}
}

 以上就是今天要讲的内容了,主要介绍了Spring入门的控制反转和依赖注入以及相关示例,如果您感兴趣的话,可以订阅我的相关专栏。非常感谢您的阅读,如果这篇文章对您有帮助,那将是我的荣幸。我们下期再见啦🧸!
 

相关文章:

【Spring篇】初识之Spring的入门程序及控制反转与依赖注入

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【计算机网络】&#xff0c;【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 文章目录 &#x1f3af;初始Spring …...

OpenLayers:构建高质量的Web地图应用

OpenLayers&#xff1a;构建高质量的Web地图应用 文章目录 OpenLayers&#xff1a;构建高质量的Web地图应用简介为什么选择 OpenLayers&#xff1f;跨平台兼容性高性能渲染高度可定制化社区支持 安装与设置功能扩展矢量图层地理编码投影转换 交互与事件其他高级特性控制动画数据…...

Java比较两个Excel是否内容一致

领导每天让比较两个Excel中的内容&#xff0c;为了节省工作效率多摸鱼&#xff0c;就写了个java接口&#xff0c;通过上传两个文件 进行代码比较得到详细的比较结果(这个需要自己根据日志二开) 目前只实现了比较功能 话不多说直接上代码&#xff0c;具体看注释 package com.yx…...

UniApp入门教程

UniApp X 是一种用于构建跨平台应用程序的框架&#xff0c;它基于 Vue.js 并通过 UniApp 技术栈支持多种平台&#xff0c;如微信小程序、支付宝小程序、H5、Android 和 iOS。以下是 UniApp X 的一些关键特点和基础知识&#xff1a; UniApp X 的特点 跨平台支持&#xff1a; 可…...

Vue.js中使用Element UI实现动态表单项管理及验证

在Vue.js项目中&#xff0c;表单是与用户交互的重要部分&#xff0c;特别是在需要动态管理表单项的场景下&#xff0c;如何优雅地实现添加、删除、上移、下移及验证功能变得尤为重要。本文将详细介绍如何使用Element UI来实现一个包含动态表单项管理以及验证功能的表单。 效果…...

一插U盘就提示格式化?原因、恢复与预防全攻略

一、现象直击&#xff1a;U盘插入电脑即提示格式化 在日常的工作与生活中&#xff0c;U盘作为重要的数据存储和传输工具&#xff0c;被广泛应用于各类场景。然而&#xff0c;有时当我们满怀期待地将U盘插入电脑时&#xff0c;却会遭遇一个令人头疼的问题——系统弹出提示框&am…...

云电脑使用教程标准版

云电脑&#xff0c;也称为云桌面&#xff0c;是一种通过互联网连接远程服务器&#xff0c;使用虚拟桌面环境来执行计算任务的技术。川翔云电脑通过创建软件镜像&#xff0c;让用户能够快速启动并使用预配置的软件和资料&#xff0c;提供高效且经济的云服务。相较于公有云服务&a…...

浏览器服务端文件下载控制(安全阻止、文件浏览器打开还是下载行为控制)

文章目录 简介Chrome已阻止不安全内容下载PDF直接打开txt、xml、js文件被自动打开了而不是下载阿里OSS设置response header阿里OSS修改metadata 简介 随着浏览器的发展&#xff0c;有很多安全方面的限制&#xff0c;对我们的文件下载行为产生了很大的影响。 在JavaScript下载…...

机器学习——量子机器学习

量子机器学习: 未来的机器学习方法 量子计算和机器学习的结合为计算科学带来了前所未有的前景。量子机器学习(QML)正在迅速发展&#xff0c;目标是利用量子计算的优势来处理传统计算机无法高效解决的问题。本文将深入探讨量子机器学习的基本概念、量子计算的关键技术、具体的量…...

[Linux] 创建可以免密登录的SFTP用户

本文主要包含: 创建新用户创建密钥对用于免密登录新用户将新建用户改造为SFTP用户为SFTP上传数据设置限速 1. 创建新用户 sudo useradd sftp_user sudo passwd sftp_user # 输入密码2. 创建密钥对 参考这篇文章 [Linux] 生成 PEM 密钥对实现服务器的免密登录 3. 将新建用户…...

【部署篇】Redis-03主从模式部署(源码方式安装)

一、准备主机 主从模式只是解决了数据备份容灾并不能解决单点故障问题&#xff0c;生产环境中需要在主从模式基础上增加哨兵&#xff0c;实现主节点宕机时自动将其中一个重节点设置为新的主节点。 主机IP角色说明192.168.128.31master&#xff0c;主节点可读写。192.168.128…...

C/C++语言基础--C++四大类型转换讲解

本专栏目的 更新C/C的基础语法&#xff0c;包括C的一些新特性 前言 通过前面几节课&#xff0c;我们学习了抽象、封装、继承、多态、异常等概念&#xff0c;这一篇我们将继续学习C的类型转换&#xff0c;和C语言还有很大区别的&#xff1b;在本节课最后&#xff0c;也简要说…...

KafKa 集群【docker compose】

文章目录 主机准备部署编辑 docker-compose.ymlcontrollerbroker生成cluster_id 一篇完整的 docker-compose.yml 文件查看集群状态使用 kafka-ui 查看拉取 kafka-ui添加集群查看集群状态 使用命令行查看 配置讲解controllerbroker 主机准备 IPcontroller idbroker id192.168.1…...

【工具篇】MLU运行XInference部署手册

文章目录 前言一、平台环境准备二、代码下载三、安装部署1.正常pip 安装 四、运行结果展示1.如果界面404或没有东西请这样做2.运行效果 前言 Xorbits Inference&#xff08;Xinference&#xff09;是一个功能强大、用途广泛的库&#xff0c;旨在为语言、语音识别和多模态模型提…...

计算机网络:数据链路层 —— 扩展共享式以太网

文章目录 共享式以太网共享式以太网存在的问题在物理层扩展以太网扩展站点与集线器之间的距离扩展共享式以太网的覆盖范围和站点数量 在链路层扩展以太网网桥的主要结构网桥的基本工作原理透明网桥自学习和转发帧生成树协议STP 共享式以太网 共享式以太网是当今局域网中广泛采…...

平安养老险深圳分公司:创新养老服务,深入践行金融为民

党的二十届三中全会《决定》提出&#xff1a;“积极发展科技金融、绿色金融、普惠金融、养老金融、数字金融&#xff0c;加强对重大战略、重点领域、薄弱环节的优质金融服务。” 为经济社会发展提供高质量服务&#xff0c;更好满足人民日益增长的美好生活需要&#xff0c;金融…...

静态站点生成器哪家强?

有一种方法&#xff0c;让你写好文档后&#xff0c;快速地让同事、用户和合作伙伴看到&#xff0c;这就是静态站点生成器。 静态站点生成器是一种软件&#xff0c;用于创建不需要服务器端脚本的网站。这些网站由纯HTML文件组成&#xff0c;可能还包括CSS和JavaScript来增强功…...

从0开始部署优化虚拟机

一&#xff0c;vm workstation 安装 CentOS-7 忽略 二、查看虚拟机IP ip address 得到 192.168.196.128/24 宿主机进行Ping测试 C:\Users\Administrator>ping 192.168.196.128正在 Ping 192.168.196.128 具有 32 字节的数据: 来自 192.168.196.128 的回复: 字节32 时间…...

录屏有道, 四款必备录屏工具推荐!

制作教程视频、游戏直播或是远程会议记录等都需要录屏&#xff0c;那么到底应该怎么录屏呢&#xff1f;接下来就给大家介绍几个好用的录屏工具 Foxit REC 直达链接&#xff1a;www.foxitsoftware.cn/REC/ 操作教程&#xff1a;立即获取 Foxit REC以其强大的功能、简洁的界面…...

5G NR:UE初始接入信令流程浅介

UE初始接入信令流程 流程说明 用户设备&#xff08;UE&#xff09;向gNB-DU发送RRCSetupRequest消息。gNB-DU 包含 RRC 消息&#xff0c;如果 UE 被接纳&#xff0c;则在 INITIAL UL RRC MESSAGE TRANSFER 消息中包括为 UE 分配的低层配置&#xff0c;并将其传输到 gNB-CU。IN…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...