6.Vue3.0使用axios-二次封装

本文介绍了Axios的安装,通过npm install --save axios命令完成。接着说明了在main.js中引入Axios,还对其进行二次封装,在http文件夹新建api.js文件,封装了post、get等请求。封装完成后输出并在main.js中引入注册。最后提及Axios的请求和响应拦截器可进行处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

安装

npm install  --save axios

在mian.js中引入

import axios 'axios' (axios不需要使用vue.use(),我也是不明所以然啊

到这里我都会对axios进行二次封装

在http文件夹中新建api.js 文件

引入axios

import axios 'axios'

对post,get请求进行封装

get请求:

15276316-a3a01508f4225b4d.png
get请求封装


postJson请求:

15276316-383d9fa7e2ced83a.png
postJson请求封装


postForm请求:

15276316-8251e6b359b20840.png
postForm请求封装


文件请求:(这个其实不怎么用到Element有文件上传的插件)

15276316-d0242321dcf1c06f.png
文件请求封装


封装完成了之后对它们进行输出(install 方法将被作为 Vue 的参数调用):

15276316-5cf4b13c0d19b442.png
输出


在mian.js中引入并且注册

import axiosApi from '@/http/api.js'

Vue.use(axiosApi)

axios有两个拦截器请求拦截器,响应拦截器可以进行处理

响应拦截器:

15276316-5d1b74a5c3d13e10.png
15276316-728480d7f030b107.png
响应拦截器


请求拦截器:(上个项目中使用的是token)

15276316-9757d8e439e87b27.png
请求拦截器
<think>我们有一个需求:在Spring Boot后端使用SSE实现文件上传进度推送,并在Vue前端监听上传进度。 步骤: 1. 后端:创建SSE端点,用于前端连接并监听进度。 2. 后端:处理文件上传,将上传进度通过SSE推送到前端。 3. 前端(Vue):建立SSE连接,监听进度事件,并更新进度条。 参考引用[2]和[4]中关于SSE的实现。 具体步骤: 一、Spring Boot后端实现 1. 创建SSE控制器 我们可以创建一个SSE控制器,用于管理SSE连接和发送进度事件。 2. 文件上传控制器 在文件上传的接口中,我们可以获取到文件上传的进度,然后通过SSE将进度推送给前端。 3. 使用一个全局的SSE发射器管理器(这里简化处理,使用一个Map来存储,键可以用用户ID或会话ID) 但是注意:SSE连接是单向的(服务器到客户端),每个客户端需要有一个唯一的标识来关联。 二、Vue前端实现 1. 在文件上传前,先建立SSE连接(指定一个唯一的标识,比如用户ID或者随机生成的UUID) 2. 在上传文件时,将这个标识传给后端(比如作为查询参数) 3. 后端在处理上传时,根据这个标识找到对应的SseEmitter,然后发送进度事件。 4. 前端监听SSE事件,更新进度。 具体代码实现: 后端代码: 1. 添加SSE工具类或控制器: ```java import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class SseController { // 存储SSE发射器,键为客户端ID private static final Map<String, SseEmitter> sseEmitters = new ConcurrentHashMap<>(); // 创建SSE连接 public SseEmitter createSseConnection(String clientId) { // 设置超时时间,0表示永不超时(但实际中建议设置一个合理的超时时间,比如30秒或1分钟,然后通过心跳机制保持连接) SseEmitter emitter = new SseEmitter(0L); // 0表示不超时 // 存储 sseEmitters.put(clientId, emitter); // 移除处理 emitter.onCompletion(() -> sseEmitters.remove(clientId)); emitter.onTimeout(() -> sseEmitters.remove(clientId)); return emitter; } // 发送进度 public void sendProgress(String clientId, int progress) { SseEmitter emitter = sseEmitters.get(clientId); if (emitter != null) { try { // 发送事件,事件名为"progress",数据为进度百分比 emitter.send(SseEmitter.event().name("progress").data(progress)); } catch (Exception e) { // 发送失败,移除该发射器 sseEmitters.remove(clientId); } } } } ``` 2. 在文件上传控制器中,注入上面的SseController,并在上传过程中调用sendProgress方法。 但是,如何获取上传进度?我们可以使用CommonsMultipartResolver或者Servlet3.0的Part来获取上传进度,但更常用的是使用CommonsMultipartResolver。 添加依赖(如果使用Spring Boot): ```xml <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> <!-- 使用最新版本 --> </dependency> ``` 配置MultipartResolver: ```java @Bean public MultipartResolver multipartResolver() { CommonsMultipartResolver resolver = new CommonsMultipartResolver(); resolver.setMaxUploadSize(1000000); // 设置最大上传大小 return resolver; } ``` 然后,在文件上传方法中,我们可以通过监听器来获取上传进度: ```java @RestController public class FileUploadController { @Autowired private SseController sseController; @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("clientId") String clientId) throws Exception { // 这里我们无法直接获取进度,需要自定义一个上传进度监听器 // 但是Spring MVC没有直接提供进度监听,所以我们需要使用CommonsMultipartResolver配合CommonsFileUpload // 另一种做法:在拦截器或AOP中处理,但比较麻烦。 // 简单做法:使用CommonsMultipartFile,并自定义一个ProgressListener // 注意:Spring MVC的MultipartFile接口并没有提供进度监听的方法,所以我们需要使用Servlet API的HttpServletRequest来获取FileItemFactory // 因此,我们可以在控制器中这样写(但需要获取到原生的HttpServletRequest): // 由于比较复杂,这里我们换一种方式:使用拦截器(Interceptor)来监听上传进度,并将进度存储在session或request属性中,然后通过另一个线程定期获取并推送。 // 但是为了简化,我们可以在上传方法内模拟进度(实际生产环境需要更复杂的处理)。 // 这里我们使用一个简单的循环来模拟上传进度,并每10%推送一次 long fileSize = file.getSize(); byte[] bytes = file.getBytes(); // 模拟上传延迟 int chunkSize = (int) (fileSize / 10); // 分成10份 for (int i = 0; i < 10; i++) { // 模拟上传一部分 Thread.sleep(500); // 延迟0.5秒 int progress = (i + 1) * 10; // 推送进度 sseController.sendProgress(clientId, progress); } return "Upload success!"; } } ``` 注意:上面的模拟进度只是示例,实际中我们需要在文件上传过程中获取进度。我们可以通过自定义一个MultipartFile对象,重写transferTo方法,并在其中加入进度监听。但这样比较麻烦。 另一种推荐做法:使用Servlet3.0的Part和上传进度监听(需要Servlet3.0容器,如Tomcat7+)。但是Spring MVC的MultipartFile封装了Part,我们难以直接获取进度。 因此,我们可以使用Apache Commons FileUpload的ProgressListener。但是需要配置一个自定义的MultipartResolver。 具体实现可参考:https://www.baeldung.com/spring-file-upload-progress 由于问题复杂,这里我们给出一个简化的版本,使用模拟进度。实际开发中,请根据上述参考实现。 3. 创建SSE控制器端点: ```java @RestController @RequestMapping("/sse") public class SseControllerAPI { @Autowired private SseController sseController; @GetMapping("/connect") public SseEmitter connect(@RequestParam String clientId) { return sseController.createSseConnection(clientId); } } ``` 前端Vue实现: 1. 在文件上传前,先建立SSE连接(生成一个随机的clientId) 2. 使用这个clientId作为参数,调用上传接口,并同时建立SSE连接。 3. 监听SSE事件,更新进度。 示例代码: ```vue <template> <div> <input type="file" @change="handleFileChange" /> <button @click="uploadFile">上传</button> <div>进度: {{ progress }}%</div> </div> </template> <script> export default { data() { return { file: null, progress: 0, clientId: null, eventSource: null }; }, methods: { handleFileChange(event) { this.file = event.target.files[0]; }, generateClientId() { // 生成一个随机字符串作为clientId return &#39;client_&#39; + Math.random().toString(36).substr(2, 9); }, uploadFile() { if (!this.file) { alert(&#39;请选择文件&#39;); return; } // 生成clientId this.clientId = this.generateClientId(); // 先建立SSE连接 this.setupSSE(); // 然后上传文件 const formData = new FormData(); formData.append(&#39;file&#39;, this.file); formData.append(&#39;clientId&#39;, this.clientId); this.progress = 0; // 重置进度 this.$axios.post(&#39;/upload&#39;, formData, { headers: { &#39;Content-Type&#39;: &#39;multipart/form-data&#39; } }).then(response => { console.log(response.data); // 上传完成,关闭SSE连接 if (this.eventSource) { this.eventSource.close(); } }).catch(error => { console.error(error); if (this.eventSource) { this.eventSource.close(); } }); }, setupSSE() { // 创建EventSource连接 this.eventSource = new EventSource(`/sse/connect?clientId=${this.clientId}`); // 监听进度事件 this.eventSource.addEventListener(&#39;progress&#39;, (event) => { const progress = parseInt(event.data); this.progress = progress; if (progress === 100) { // 完成,可以关闭连接(但这里我们等上传接口返回再关闭,避免提前关闭) } }); // 处理错误 this.eventSource.onerror = (error) => { console.error(&#39;SSE error:&#39;, error); this.eventSource.close(); }; } } }; </script> ``` 注意:上面的代码中,我们假设后端SSE端点是`/sse/connect`,文件上传接口是`/upload`。 但是,实际中,SSE连接建立后,服务器可能会超时关闭。因此,我们需要在后端设置合理的超时时间,并可能需要在客户端进行重连。 另外,由于每个客户端都需要一个唯一的clientId,我们使用随机生成的方式,并确保在每次上传时重新生成。 以上就是一个简单的实现方案。实际生产环境中,还需要考虑并发情况下的SSE发射器管理、错误处理、心跳机制等。 相关问题: 1. 如何在后端准确获取文件上传进度? 2. 如何处理多个文件上传的进度? 3. SSE连接断开后如何重连? 4. 如何保证SSE连接的安全性(比如防止clientId被冒用)? 5. 如何优化SSE的性能,避免内存泄漏?</think>### Spring Boot SSE文件上传进度通知与Vue前端监听实现方案 #### 一、后端实现(Spring Boot) 1. **创建SSE控制器** ```java @RestController @RequestMapping("/sse") public class SseController { // 存储所有活动的SSE连接 private static final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>(); // 创建SSE连接端点 @GetMapping("/connect/{clientId}") public SseEmitter createConnection(@PathVariable String clientId) { SseEmitter emitter = new SseEmitter(60 * 1000L); // 60秒超时 emitters.put(clientId, emitter); emitter.onCompletion(() -> emitters.remove(clientId)); emitter.onTimeout(() -> emitters.remove(clientId)); return emitter; } // 推送进度给指定客户端 public static void sendProgress(String clientId, int progress) { SseEmitter emitter = emitters.get(clientId); if (emitter != null) { try { emitter.send(SseEmitter.event() .name("progress") .data(progress)); } catch (IOException e) { emitters.remove(clientId); } } } } ``` 2. **文件上传控制器(带进度监听)** ```java @RestController @RequestMapping("/upload") public class FileUploadController { @PostMapping public ResponseEntity<String> uploadFile( @RequestParam("file") MultipartFile file, @RequestParam("clientId") String clientId) { try { // 模拟文件处理过程(实际开发中替换为真实处理逻辑) long totalBytes = file.getSize(); long uploadedBytes = 0; byte[] buffer = new byte[1024]; try (InputStream is = file.getInputStream()) { int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { uploadedBytes += bytesRead; // 计算并推送进度 int progress = (int) ((uploadedBytes * 100) / totalBytes); SseController.sendProgress(clientId, progress); // 模拟处理延迟(实际开发中删除) Thread.sleep(50); } } return ResponseEntity.ok("上传成功"); } catch (Exception e) { return ResponseEntity.status(500).body("上传失败"); } } } ``` #### 二、前端实现(Vue 3) 1. **建立SSE连接** ```vue <template> <div> <input type="file" @change="handleFileSelect" /> <button @click="uploadFile">开始上传</button> <div>进度: {{ progress }}%</div> <div v-if="progress === 100">上传完成!</div> </div> </template> <script setup> import { ref } from &#39;vue&#39;; import axios from &#39;axios&#39;; const selectedFile = ref(null); const progress = ref(0); const clientId = ref(null); let eventSource = null; // 生成唯一客户端ID const generateClientId = () => { return &#39;client_&#39; + Date.now() + &#39;_&#39; + Math.random().toString(36).substr(2, 5); }; // 建立SSE连接 const connectSSE = () => { clientId.value = generateClientId(); // 创建SSE连接 eventSource = new EventSource(`http://localhost:8080/sse/connect/${clientId.value}`); eventSource.addEventListener(&#39;progress&#39;, (event) => { progress.value = parseInt(event.data); }); eventSource.onerror = (err) => { console.error(&#39;SSE连接错误:&#39;, err); eventSource.close(); }; }; const handleFileSelect = (event) => { selectedFile.value = event.target.files[0]; }; const uploadFile = async () => { if (!selectedFile.value) return; progress.value = 0; connectSSE(); // 开始上传前建立连接 const formData = new FormData(); formData.append(&#39;file&#39;, selectedFile.value); formData.append(&#39;clientId&#39;, clientId.value); try { await axios.post(&#39;/upload&#39;, formData, { headers: { &#39;Content-Type&#39;: &#39;multipart/form-data&#39; } }); } catch (error) { console.error(&#39;上传失败:&#39;, error); } finally { // 上传完成后关闭连接 setTimeout(() => eventSource.close(), 2000); } }; </script> ``` #### 三、关键配置说明 1. **Spring Boot配置(application.yml)** ```yaml spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB ``` 2. **跨域配置(CORS)** ```java @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:8081") // Vue开发服务器地址 .allowedMethods("*") .allowCredentials(true); } } ``` #### 四、实现原理 1. **工作流程** - 前端生成唯一`clientId`并建立SSE连接 - 文件上传时携带`clientId` - 后端处理文件时按块计算进度 - 通过`SseEmitter`实时推送进度事件 - 前端监听`progress`事件更新界面 2. **技术优势** - 低延迟:SSE基于HTTP长连接,实时性高 - 轻量级:相比WebSocket实现更简单 - 自动重连:浏览器内置SSE重连机制 - 兼容性:主流浏览器均支持[^2][^4] #### 五、注意事项 1. **连接管理** - 每个客户端需使用唯一ID - 上传完成后主动关闭SSE连接 - 设置合理超时时间(建议60-120秒) 2. **错误处理** - 添加SSE连接异常监听 - 处理文件上传中断情况 - 后端需清理无效的SseEmitter引用 3. **性能优化** ```java // 在进度变化>5%时才推送(减少网络开销) int lastSentProgress = 0; if (progress - lastSentProgress >= 5 || progress == 100) { SseController.sendProgress(clientId, progress); lastSentProgress = progress; } ``` --- ### 相关问题 1. SSE和WebSocket在实时通信场景下如何选择?[^4] 2. 如何处理大文件分片上传和断点续传? 3. Spring Boot中如何实现SSE的集群支持? 4. Vue前端如何封装可复用的SSE组件? 5. 如何保障SSE通信的安全性(身份认证与授权)? [^1]: 使用 Spring Boot 和 Vue.js 实现实时通知系统 [^2]: SSE 实践:用 Vue 和 Spring Boot 实现实时数据传输 [^3]: 航班预订管理系统技术选型 [^4]: Spring Boot集成sse实现chatgpt流式交互
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值