国外做调查问卷的网站/东莞互联网公司排名
前言
文件上传和下载是 Web 开发中的重要环节,但它们往往不那么容易实现。幸运的是,Spring MVC 提供了一套简单而又强大的解决方案,让我们可以专注于业务逻辑,而不必过多关注底层的文件处理细节。
在本篇博客中,我们将学习如何利用 Spring MVC 实现文件上传和下载功能。首先,我们将了解文件上传的过程以及必要的配置。随后,我们将介绍如何在控制器中处理上传的文件,并对其进行存储或处理。最后,我们将学习如何实现文件下载的功能,使用户能够方便地获取指定的文件。
一、前期准备
1、新建项目,结构如下
2、导入依赖
<dependencies><!-- springmvc 依赖,会将spring的核心包一并添加进来 --><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.23</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.5</version></dependency><!-- 上传组件 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency></dependencies>
使用Apache Commons FileUpload库的上传组件,你可以轻松地处理HTTP请求中的文件上传部分。它提供了一些方便的类和方法,使文件上传变得简单和可靠。
3、配置 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>
用于配置 Servlet 的映射和加载。在 Spring MVC 中,它用于配置 DispatcherServlet 的初始化和请求映射。
具体来说,这段配置的作用如下:
- 定义了一个名为 "dispatcher" 的 Servlet,并指定了 org.springframework.web.servlet.DispatcherServlet 作为其处理类。
- 设置了 load-on-startup 属性为 1,表示在应用启动时就加载该 Servlet。
- 使用 <servlet-mapping> 元素将 "dispatcher" Servlet 映射到所有的请求路径上(即 <url-pattern>/</url-pattern>),意味着所有的请求都会经过该 Servlet 进行处理。
这段配置的作用是将所有的请求交给 DispatcherServlet 处理,并让它成为应用的核心控制器。DispatcherServlet 将根据请求的 URL 和其他配置信息,将请求分发给相应的处理器方法进行处理,然后返回响应结果。
4、编写 ResultVO 类
@Data
public class ResultVO<T> {private Integer code = HttpStatus.OK.value();private String message;private T data;}
这段代码定义了一个名为
ResultVO
的泛型类。它使用了Lombok注解@Data
,该注解用于自动生成类的常用方法,如构造函数、Getter和Setter等。这个
ResultVO
类有以下几个字段:
code
:表示响应的状态码,默认值为HttpStatus.OK.value()
,即200。message
:表示响应的消息,可以是任意字符串。data
:表示响应的数据,使用了泛型T
,可以是任意类型。通过使用
@Data
注解,Lombok将会自动生成以下方法:
- 无参构造函数:用于创建
ResultVO
对象。- 全参构造函数:用于根据提供的参数创建
ResultVO
对象。- Getter和Setter方法:用于获取和设置
code
、message
和data
字段的值。equals
和hashCode
方法:用于比较两个ResultVO
对象的相等性。toString
方法:用于返回ResultVO
对象的字符串表示。通过使用这个通用的
ResultVO
类,你可以在应用程序中统一封装响应结果,包括状态码、消息和数据。它可以帮助你更方便地构建和处理API的响应,并且具有灵活性和可扩展性,适用于各种不同类型的响应数据。
5、编写 ProductVO 类
/*** @Date 2023-10-24* @Author qiu* 商品 VO 对象,用于保存页面提交的数据* 后续将这个 vo 拷贝到 entity 中*/
@Data
public class ProductVO {/*** 商品名称*/private String productName;/*** 商品图片*/private MultipartFile[] file;}
这段代码定义了一个名为
ProductVO
的类,用于保存页面提交的商品数据。它使用了Lombok注解@Data
,该注解用于自动生成类的常用方法。
ProductVO
类有以下几个字段:
productName
:表示商品名称,使用了private
访问修饰符,类型为字符串。file
:表示商品图片,使用了private
访问修饰符,类型为MultipartFile[]
,即文件数组。通过使用
@Data
注解,Lombok将会自动生成以下方法:
- 无参构造函数:用于创建
ProductVO
对象。- 全参构造函数:用于根据提供的参数创建
ProductVO
对象。- Getter和Setter方法:用于获取和设置
productName
和file
字段的值。equals
和hashCode
方法:用于比较两个ProductVO
对象的相等性。toString
方法:用于返回ProductVO
对象的字符串表示。
ProductVO
类主要用于接收前端页面提交的商品数据。在后续的操作中,可以将这个ProductVO
对象的数据拷贝到实体类(entity)中进行进一步处理和持久化。其中,
MultipartFile
是Spring框架提供的一个接口,用于处理文件上传。MultipartFile[]
表示多个文件的数组,可以用于接收前端上传的多个商品图片文件。通过使用这个
ProductVO
类,你可以方便地接收和保存页面提交的商品数据,其中包括商品名称和商品图片。这样可以更好地组织和管理商品相关的信息,并将其传递给后续的业务逻辑处理。
二、 实现文件上传
1、文件上传
@RestController
@Slf4j
public class ProductContoroler {/*** 添加商品,同时带有上传的附件* @param productVO* @return*/@PostMapping("/add")public ResultVO add(ProductVO productVO) throws IOException {ResultVO resultVO = new ResultVO();// 获取上传的路径(绝对路径)String uploadPath = "d://file/";// 拼接完整的上传路径
// uploadPath += filename;log.info(uploadPath);// 根据路径构建一个上传的文件对象File uploadFile = new File(uploadPath);// 判断路径中的文件夹是否存在,不存在则创建if (!uploadFile.exists()) {// 将文件夹创建出来uploadFile.mkdirs();}// 获取上传的文件名MultipartFile[] file = productVO.getFile();for (MultipartFile multipartFile : file) {// 获取文件名String filename = multipartFile.getOriginalFilename();// 执行上传Path path = FileSystems.getDefault().getPath(uploadFile.getAbsolutePath(),filename);multipartFile.transferTo(path);}return resultVO;}}
add
的方法,使用了@PostMapping("/add")
注解,表示当接收到POST请求时,会调用这个方法来处理。该方法的参数是一个
ProductVO
对象,用于接收前端提交的商品数据。方法内部首先创建了一个
ResultVO
对象,用于封装响应结果。然后,指定了一个上传文件的路径
uploadPath
(这里设置为"d://file/")。接着,通过日志记录工具
log
,将uploadPath
输出到日志中,方便查看。在
uploadPath
路径下创建一个文件夹uploadFile
,如果该文件夹不存在的话。接下来,从
productVO
对象中获取上传的商品图片文件数组file
。然后,使用循环遍历
file
数组,对每个文件进行处理。对于每个文件,首先获取其原始文件名
filename
。然后,使用
FileSystems.getDefault().getPath()
方法构建一个文件路径path
,指定了文件的保存位置。最后,调用
multipartFile.transferTo()
方法将文件保存到指定路径path
。最后,返回
resultVO
对象作为响应结果。这个
add
方法实现了接收商品信息以及商品图片的上传功能。它将商品图片保存到指定路径,并返回一个结果对象作为响应。
2、编写 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"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 扫描 --><context:component-scan base-package="edu.nf.ch08"/><!-- mvc注解驱动--><mvc:annotation-driven/><!-- 静态资源处理器--><mvc:default-servlet-handler/><!-- 装配上传附件解析器--><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 限制文件上传的总大小(单位:字节),不配置此属性默认不限制 --><property name="maxUploadSize" value="104857600"/><!-- 设置文件上传的默认编码--><property name="defaultEncoding" value="utf-8"/></bean></beans>
在该配置文件中,首先声明了XML命名空间
xmlns
,以及XML命名空间的映射关系xsi:schemaLocation
。这些声明用于引入和定义XML模式(XSD)。然后,使用
<context:component-scan>
指定要扫描的基础包,以便自动注册Spring的组件。接下来,通过
<mvc:annotation-driven/>
启用Spring MVC的注解驱动,以支持处理器映射和处理器适配器。使用
<mvc:default-servlet-handler/>
配置静态资源处理器,以便将静态资源(如CSS、JavaScript等)映射到默认的Servlet上。通过
<bean>
配置上传附件解析器,这里使用的是CommonsMultipartResolver
,用于处理文件上传功能。可以通过设置maxUploadSize
属性限制文件上传的总大小,并设置defaultEncoding
属性指定文件上传的默认编码。
3、编写页面实现上传
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/JQuery文件.txt.js"></script>
</head>
<body><form id="f1" enctype="multipart/form-data">Name:<input type="text" name="productName"/><br>Image:<input type="file" name="file" multiple/><br><input type="button" value="提交"/><br></form><script>$(function () {$(':button').on('click',function () {// 构建 formData 对象let formData = new FormData($('#f1')[0]);$.ajax({url:'../add',type:'post',data:formData,processData:false, // 告诉 jquery 不要处理发送的数据类型contentType:false, // 告诉 jquery 不要设置请求头的 contentTypesuccess:function ( result ) {if ( result.code === 200 ){alert("上传成功");} else {alert("上传失败");}}})})})
</script></body>
</html>
在页面中,定义了一个带有id为"f1"的form元素,使用了
enctype="multipart/form-data"
属性来支持文件上传。在表单中,有两个输入字段:
- Name:一个文本输入框,用于输入商品名称,其name属性为"productName"。
- Image:一个文件选择框,用于选择商品图片,其name属性为"file",并且设置了multiple属性,表示可以选择多个图片文件。
接着,定义了一个JavaScript脚本,在页面加载完成后执行。
脚本中,通过选择器$(':button')选中所有按钮元素,并绑定了一个点击事件处理函数。当按钮被点击时,会执行该函数。
在函数内部,首先创建一个FormData对象formData,并将表单f1的数据添加到formData中。
然后,使用jQuery的ajax方法,发送一个POST请求到服务器的"../add"路径。
请求的数据为formData,同时设置了processData为false,告诉jQuery不要处理发送的数据类型;contentType也设置为false,告诉jQuery不要设置请求头的contentType。
在请求成功后的回调函数中,根据服务器返回的结果result,判断上传是否成功。如果返回的code为200,则弹出上传成功的提示框;否则,弹出上传失败的提示框。
该HTML页面实现了一个简单的图片上传功能,通过选择商品名称和图片文件,点击提交按钮后,将数据发送到服务器进行处理,并根据返回的结果给出相应的提示。
4、运行效果
1)单个文件
2)多个文件
三、实现文件下载
1、文件下载
/*** 文件下载* @param fileName* @return*/@GetMapping("/download/{fileName}")public ResponseEntity<InputStreamResource> download(@PathVariable("fileName") String fileName) throws Exception {// 文件下载目录(也就是上传路径)String downloadPath = "d://file/" + fileName;// 构建一个文件输入流读取服务器上的文件FileInputStream fis = new FileInputStream(downloadPath);// 设置响应头,告诉浏览器响应流程HttpHeaders headers = new HttpHeaders();// 对文件名进行编码,防止响应头中出现乱码fileName = URLEncoder.encode(fileName,"UTF-8");// 设置头信息,将响应内容处理的方式设置为附件下载headers.setContentDispositionFormData("attachment",fileName);// 设置响应类型为流类型headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);// 创建 InputStreamResource 对象封装输入流,用于读取服务器文件InputStreamResource isr = new InputStreamResource(fis);// 创建 ResponseEntity 对象(封装 InputStreamResource,响应头,以及响应状态码)ResponseEntity<InputStreamResource> entity = new ResponseEntity<>(isr, headers,HttpStatus.CREATED);return entity;}
这段代码实现了一个文件下载的功能。具体来说,当访问URL为"/download/{fileName}"时,该方法会被执行。
方法接收一个文件名参数fileName,并根据该文件名构建文件下载路径downloadPath。
然后,通过FileInputStream读取指定路径上的文件。
接下来,创建一个HttpHeaders对象,用于设置响应头信息。
在响应头中,使用URLEncoder对文件名进行编码,以防止出现乱码。
然后,设置响应内容处理方式为附件下载,并将响应类型设置为流类型。
接着,使用InputStreamResource对象封装文件输入流,以便于读取服务器上的文件。
最后,创建一个ResponseEntity对象,将封装好的InputStreamResource、响应头和响应状态码封装到其中,并将其返回给客户端进行下载。
2、运行效果
四、总结
本次案例只是简单的文件上传和下载,都是上传在本地,那可不可以上传到远程的服务器上呢?也是可以的,后面会出一个案例讲解怎么上传文件到远程服务器 minion 上。
五、gitee 案例
地址:ch08 · qiuqiu/SpringMVC - 码云 - 开源中国 (gitee.com)
相关文章:

SpringMVC Day 08 : 文件上传下载
前言 文件上传和下载是 Web 开发中的重要环节,但它们往往不那么容易实现。幸运的是,Spring MVC 提供了一套简单而又强大的解决方案,让我们可以专注于业务逻辑,而不必过多关注底层的文件处理细节。 在本篇博客中,我们…...

【热带气旋】基本介绍:定义、标准、结构等
热带气旋基本介绍 热带气旋(Tropical Cyclone, TC)1 热带气旋定义2 热带气旋标准2.1 热带低压(Tropical Depression)2.2 热带风暴(Tropical storm)2.3 强热带风暴(Severe tropical storm&#x…...

ue5 右击.uproject generator vs project file 错误
出现如下错误 Unable to find valid 14.31.31103 C toolchain for VisualStudio2022 x64 就算你升级了你的 vs installer 也不好使 那是因为 在C:\Users\{YourUserName}\AppData\Roaming\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml 这个缓存配置文件中写死了 14…...

0X01
打开题目 点了几下跳出一个新的页面 点击secret 在上一个页面查看源代码,出现action.php然后点击之后就会在地址栏里面出现end.php 抓包看看,出现secr3t.php huidao开始的页面,访问看看 这是一个PHP脚本,以HTML标签开头。该脚本包…...

centos7 配置搭建 wordpress 博客
环境配置 系统:centos7 CPU:2核 内存:4G 硬盘:40G 一、登录云服务器器 1.单击实例--实例名称 2. 选择安全组页签,单击安全组操作列的管理规则, 3.在入方向添加需要放行的端口。本教程中,在安全组入方向…...

掌握Android自定义View与独家优化技巧
在Android应用开发中,自定义View是一种强大的工具,可以帮助你创建独特的用户界面元素。本文将详细介绍如何创建自定义View,并提供优化技巧,以确保你的自定义View在性能和用户体验方面表现出色。 什么是自定义View 自定义View是A…...

【T3】彻底关闭服宝
【问题描述】 畅捷通T3登录后, 右下角会出现服宝窗口,需要手工退出。 但是每次重新登录账套后都会出现,非常烦;并且界面空白。 【解决方法】 在软件的安装目录下\UFSMART\Portal,找到【url.ini】文件。 用记事本打开…...

P2359 三素数数 , 线性dp
题目背景 蛟川书院的一道练习题QAQ 题目描述 如果一个数的所有连续三位数字都是大于100的素数,则该数称为三素数数。比如113797是一个6位的三素数数。 输入格式 一个整数n(3 ≤ n ≤ 10000),表示三素数数的位数。 输出格式 …...

【c语言】用C语言设计一个环形缓冲区。当环形缓冲区有一半占用未处理时,提示使用了50%.
InsCode AI创作助手 #include <stdio.h> #include <stdlib.h>#define BUFFER_SIZE 10int buffer[BUFFER_SIZE]; // 环形缓冲区数组 int readIndex 0; // 缓冲区读取索引 int writeIndex 0; // 缓冲区写入索引 int count 0; // 缓冲区占用计数器void enqueue(in…...

Python的web自动化学习(四)Selenium的显性等待(元素定位)
引言: Selenium的显性等待,其常用的定位方法介绍,后面持续更细具体用法 示例如下: <input type"text" class"s_ipt" name"wd" id"kw" maxlength"100" autocomplete"…...

X3DAudio1_7.dll是什么,解决计算机找不到X3DAudio1_7.dll文件的方法
作为一位程序员,我深知x3daudio1_7.dll丢失对电脑用户的影响。这个文件是DirectX的一个组件,它负责处理音频输出和输入。当这个文件丢失时,可能会导致电脑无法正常播放音频,甚至出现蓝屏等问题。那么,面对这个问题&…...

【Python】海龟图turtle.color() 方法有关RGB颜色设置详解
在Turtle模块中,turtle.color()函数用于设置画笔和填充颜色,你可以使用RGB颜色码作为参数。RGB颜色码由三个数字组成,分别代表红色(R),绿色(G)和蓝色(B)的分量…...

中科院上高院,协鑫,和数“能源数字化智能管控”合作项目开启
10月27日,上海和数软件有限公司与协鑫综合能源服务有限公司、中国科学院上海高等研究院签署了《关于“能源数字化智能管控”开发与应用框架合作协议》。 这也标志着新疆协鑫智慧能源有限公司数字化智能提升项目——数字孪生项目正式启动。 根据协议,三方…...

在Mac上安装MongoDB 5.0
MongoDB 5.0安装 1、环境描述 操作系统:macOS 14.0 (23A344) 2、安装MongoDB 2.1、tar解压包安装 下载地址:Download MongoDB Community Server | MongoDB 创建一个目录,以便数据库将文件放入其中。(默认情况下,数据…...

手把手教你如何实现TNAS与云盘之间的无缝同步技巧
嘿,铁粉们! 云盘的下载速度总是让我们抓耳挠腮 数据安全隐私问题让人担心不已 但在购入NAS之前 众多数据存放在云盘里 同时也想把NAS的数据备份在云盘里 实现备份321法则? 不用烦恼 铁威马来帮忙 无需其他多余操作 只要下载CloudSyn…...

【约会云栖】从初中至大学,我见证了科技变革的历程。
前言 提起阿里云开发者大会, 你一定会觉得陌生;但提起云栖大会,你又会耳熟能详。实际上,云栖大会的前身就是阿里云开发者大会,2015年,它永久落户在杭州市西湖区云栖小镇。 2023年10月31日至11月2日…...

【MySQL索引与优化篇】索引优化与查询优化
索引优化与查询优化 文章目录 索引优化与查询优化1. 概述2. 索引失效案例3. 关联查询优化3.1 Join语句原理3.2 Simple Nested-Loop Join(简单嵌套循环连接)3.3 Index Nested-Loop Join(索引嵌套循环连接)3.4 Block Nested-Loop Jo…...

DevChat:VSCode中基于大模型的AI智能编程助手
#AI编程助手哪家好?DevChat“真”好用# 文章目录 1. 前言2. 安装2.1 注册新用户2.2 在VSCode中安装DevChat插件2.3 设置Access Key 3. 实战使用4. 总结 1. 前言 DevChat是由Merico公司精心打造的AI智能编程助手。它利用了最先进的大语言模型技术,像人类…...

Scrum master的职责
首先,Scrum master负责建立Scrum团队。同时Scrum master要帮助团队(甚至大到公司)中的每个成员理解Scrum理论和实践。 Scrum master还需要有很强的软技能,用于指导Scrum团队。Scrum master要对Scrum团队的成功负责任,…...

数据结构:算法(特性,时间复杂度,空间复杂度)
目录 1.算法的概念2.算法的特性1.有穷性2.确定性3.可行性4.输入5.输出 3.好算法的特质1.正确性2.可读性3.健壮性4.高效率与低存储需求 4.算法的时间复杂度1.事后统计的问题2.复杂度表示的计算1.加法规则2.乘法规则3.常见函数数量级比较 5.算法的空间复杂度1.程序的内存需求2.例…...

SaaS 出海,如何搭建国际化服务体系?(一)
防噎指南:这可能是你看到的干货含量最高的 SaaS 出海经验分享,请准备好水杯,放肆食用(XD。 当越来越多中国 SaaS 企业选择开启「国际化」副本,出海便俨然成为国内 SaaS 的新角斗场。 LigaAI 观察到,出海浪…...

数据结构与算法-(7)---栈的应用拓展-前缀表达式转换+求值
🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如…...

泛型的使用
泛型是一种Java编程语法,它允许我们编写支持多种数据类型的通用类、方法和接口。使用泛型可以使代码更通用、更灵活、更健壮,并提高代码的重用性。 在Java中,泛型的语法使用尖括号<>和类型参数来定义。例如,我们可以定义一…...

docker导致远程主机无法访问,docker网段冲突导致主机网络异常无法访问
背景: 公司分配的虚拟机是172网段的,在上面部署了docker、docker-compose、mysql、redis,程序用docker-compose管理,也平稳运行了一个多周,某天用FinalShell连主机重启docker容器,忽然断开连接,然后虚拟机就…...

Python的web自动化学习(三)Selenium的显性、隐形等待
引言: WebDriver的显性等待和隐形等待是用于在测试过程中等待元素加载或操作完成的两种等待方式。了解此两种方式是为后面自动化找到适合的方法去运用 显性等待(Explicit Wait) 显性等待是通过使用WebDriverWait类和ExpectedConditions类来…...

Linux--文件操作
1.什么是文件 对于文件来说,文件文件内容文件属性;对于文件来说,只有两种操作,对内容的修改和对文件属性的修改,这就是文件的范畴。 对于存放在磁盘上的文件,我们需要通过进程来进行访问,访问文…...

硬件知识积累 RS422接口
1. RS422 基本介绍 EIA-422(过去称为RS-422)是一系列的规定采用4线,全双工,差分传输,多点通信的数据传输协议。它采用平衡传输采用单向/非可逆,有使能端或没有使能端的传输线。和RS-485不同的是EIA-422不允…...

项目经验分享|openGauss 陈贤文:受益于开源,回馈于开源
开源之夏 项目经验分享 2023 #08 # 关于 openGauss 社区 openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核深度融合华为在数据库领域多年的经验,结合企业级场景需求,持续构建竞争力特性。同时openGauss也是…...

实时检测并识别视频中的汽车车牌
对于基于摄像头监控的安全系统来说,识别汽车牌照是一项非常重要的任务。我们可以使用一些计算机视觉技术从图像中提取车牌,然后我们可以使用光学字符识别来识别车牌号码。在这里,我将引导您完成此任务的整个过程。 要求: import cv2import numpy as npfrom skimage impor…...

使用 pyspark 进行 Clustering 的简单例子 -- KMeans
K-means算法适合于简单的聚类问题,但可能不适用于复杂的聚类问题。此外,在使用K-means算法之前,需要对数据进行预处理和缩放,以避免偏差。 K-means是一种聚类算法,它将数据点分为不同的簇或组。Pyspark实现的K-means算法基本遵循以下步骤: 随机选择K个点作为初始质心。根…...