Java Web 大文件上传优化:从困境到高效
文章目录
- Java Web 大文件上传优化:从困境到高效
- 一、优化前的困境
- (一)内存占用问题
- (二)上传速度缓慢
- (三)稳定性欠佳
- 二、优化后的实现方案
- (一)客户端(Vue)优化
- (二)服务端(Java)优化
- 三、优化后的提升点
- (一)性能大幅提升
- (二)内存高效利用
- (三)稳定性增强
Java Web 大文件上传优化:从困境到高效
在当今数字化时代,文件处理成为众多 Java Web 应用不可或缺的部分。其中,大文件上传是一项极具挑战性的任务,尤其当客户端采用 Vue,服务端使用 Java 时。接下来,让我们深入探讨大文件上传在优化前后的差异以及优化所带来的显著提升。
一、优化前的困境
(一)内存占用问题
在传统的 Java Web 大文件上传模式下,服务端通常会将整个文件一次性读入内存进行处理。当面对几百 MB 甚至 GB 级别的大文件时,这种方式极易导致内存溢出错误。例如,在一个简单的 Spring MVC 项目中,使用标准的MultipartFile
来接收文件,代码类似这样:
@RequestMapping("/upload")public String uploadFile(@RequestParam("file") MultipartFile file) {// 处理文件逻辑byte\[] bytes = file.getBytes();//...}
这里file.getBytes()
会将整个文件读入内存,如果文件过大,服务器内存很快就会被耗尽,导致应用崩溃。
(二)上传速度缓慢
网络传输本身就存在一定的瓶颈,大文件上传时这个问题更加突出。在客户端,Vue 应用通过 HTTP 请求将文件发送到服务端。由于大文件数据量庞大,传输过程需要耗费大量时间。同时,服务端在处理上传时,若采用单线程模式,同一时间只能处理一个上传请求,进一步延长了整体上传时间。例如,一个 1GB 的文件在普通网络环境下,可能需要数分钟甚至更长时间才能完成上传,严重影响用户体验。
(三)稳定性欠佳
大文件上传过程中,网络波动、服务器负载过高等意外情况时有发生。一旦出现这些问题,传统的上传方式往往无法有效应对,导致上传失败。比如,在上传过程中网络突然中断,由于没有断点续传机制,用户不得不重新开始整个上传流程,这对于用户来说是非常糟糕的体验。
二、优化后的实现方案
(一)客户端(Vue)优化
分片上传
Vue 端可以利用axios
库结合相关插件实现分片上传。首先,将大文件分割成多个较小的分片,然后依次上传这些分片。例如,使用vue - upload - component
插件,代码实现如下:
<template><upload :url="uploadUrl" :file - list="fileList" :on - change="handleChange"><button>选择文件上传</button></upload>
</template>
<script>
import Upload from 'vue - upload - component';
import axios from 'axios';
export default {components: {Upload},data() {return {uploadUrl: '/api/upload',fileList: []};},methods: {handleChange(file) {const chunkSize = 1024 * 1024; // 每片1MBconst chunks = [];for (let i = 0; i < file.size; i += chunkSize) {const chunk = file.slice(i, i + chunkSize);chunks.push(chunk);}chunks.forEach((chunk, index) => {const formData = new FormData();formData.append('file', chunk);formData.append('chunkIndex', index);formData.append('totalChunks', chunks.length);axios.post('/api/uploadChunk', formData).then(response => {// 处理响应}).catch(error => {// 处理错误});});}}
};
</script>
<template><upload :url="uploadUrl" :file - list="fileList" :on - change="handleChange"><button>选择文件上传</button></upload>
</template>
<script>
import Upload from 'vue - upload - component';
import axios from 'axios';
export default {components: {Upload},data() {return {uploadUrl: '/api/upload',fileList: []};},methods: {handleChange(file) {const chunkSize = 1024 * 1024; // 每片1MBconst chunks = [];for (let i = 0; i < file.size; i += chunkSize) {const chunk = file.slice(i, i + chunkSize);chunks.push(chunk);}chunks.forEach((chunk, index) => {const formData = new FormData();formData.append('file', chunk);formData.append('chunkIndex', index);formData.append('totalChunks', chunks.length);axios.post('/api/uploadChunk', formData).then(response => {// 处理响应}).catch(error => {// 处理错误});});}}
};
</script>
<template><upload :url="uploadUrl" :file - list="fileList" :on - change="handleChange"><button>选择文件上传</button></upload>
</template>
<script>
import Upload from 'vue - upload - component';
import axios from 'axios';
export default {components: {Upload},data() {return {uploadUrl: '/api/upload',fileList: []};},methods: {handleChange(file) {const chunkSize = 1024 * 1024; // 每片1MBconst chunks = [];for (let i = 0; i < file.size; i += chunkSize) {const chunk = file.slice(i, i + chunkSize);chunks.push(chunk);}chunks.forEach((chunk, index) => {const formData = new FormData();formData.append('file', chunk);formData.append('chunkIndex', index);formData.append('totalChunks', chunks.length);axios.post('/api/uploadChunk', formData).then(response => {// 处理响应}).catch(error => {// 处理错误});});}}
};
</script>
这样,即使某个分片上传失败,也只需重新上传该分片,大大提高了上传的稳定性。
多线程并发上传
借助Web Workers
技术,Vue 可以实现多线程并发上传分片,进一步提升上传速度。通过创建多个Worker
实例,每个实例负责上传一个分片,从而充分利用客户端的多核处理器资源。例如:
// main.jsconst workerScripts = \[];const chunks = \[]; // 假设已分割好的文件分片数组for (let i = 0; i < chunks.length; i++) {const worker = new Worker('uploadWorker.js');workerScripts.push(worker);worker.postMessage({ chunk: chunks\[i], index: i });worker.onmessage = function (e) {if (e.data.status ==='success') {// 处理成功响应} else {// 处理失败响应}};}
// uploadWorker.jsself.onmessage = function (e) {const { chunk, index } = e.data;const formData = new FormData();formData.append('file', chunk);formData.append('chunkIndex', index);fetch('/api/uploadChunk', {method: 'POST',body: formData}).then(response => {self.postMessage({ status:'success' });}).catch(error => {self.postMessage({ status: 'error' });});};
(二)服务端(Java)优化
流式处理
Java 服务端采用 Servlet 3.1 及以上版本提供的Part
接口进行流式处理,避免一次性将文件读入内存。例如,在 Spring Boot 项目中:
@PostMapping("/uploadChunk")
public ResponseEntity<String> uploadChunk(@RequestParam("file") MultipartFile file,@RequestParam("chunkIndex") int chunkIndex,@RequestParam("totalChunks") int totalChunks) {try (InputStream inputStream = file.getInputStream()) {// 处理文件分片,例如写入临时文件Path tempDir = Files.createTempDirectory("uploadChunks");Path tempFile = Paths.get(tempDir.toString(), chunkIndex + ".tmp");Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);return ResponseEntity.ok("Chunk uploaded successfully");} catch (IOException e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error uploading chunk");}
}
@PostMapping("/uploadChunk")
public ResponseEntity<String> uploadChunk(@RequestParam("file") MultipartFile file,@RequestParam("chunkIndex") int chunkIndex,@RequestParam("totalChunks") int totalChunks) {try (InputStream inputStream = file.getInputStream()) {// 处理文件分片,例如写入临时文件Path tempDir = Files.createTempDirectory("uploadChunks");Path tempFile = Paths.get(tempDir.toString(), chunkIndex + ".tmp");Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);return ResponseEntity.ok("Chunk uploaded successfully");} catch (IOException e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error uploading chunk");}
}
@PostMapping("/uploadChunk")
public ResponseEntity<String> uploadChunk(@RequestParam("file") MultipartFile file,@RequestParam("chunkIndex") int chunkIndex,@RequestParam("totalChunks") int totalChunks) {try (InputStream inputStream = file.getInputStream()) {// 处理文件分片,例如写入临时文件Path tempDir = Files.createTempDirectory("uploadChunks");Path tempFile = Paths.get(tempDir.toString(), chunkIndex + ".tmp");Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);return ResponseEntity.ok("Chunk uploaded successfully");} catch (IOException e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error uploading chunk");}
}
使用 Java NIO
Java NIO(New I/O)提供了更高效的非阻塞 I/O 操作。通过FileChannel
和ByteBuffer
,可以实现更高效的文件读写。例如,在合并分片文件时:
@PostMapping("/mergeChunks")
public ResponseEntity<String> mergeChunks(@RequestParam("totalChunks") int totalChunks) {try {Path outputFile = Paths.get("mergedFile.tmp");try (FileChannel outputChannel = FileChannel.open(outputFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {for (int i = 0; i < totalChunks; i++) {Path tempFile = Paths.get("uploadChunks/" + i + ".tmp");try (FileChannel inputChannel = FileChannel.open(tempFile, StandardOpenOption.READ)) {ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); // 1MB缓冲区while (inputChannel.read(buffer) != -1) {buffer.flip();outputChannel.write(buffer);buffer.clear();}}}}return ResponseEntity.ok("Files merged successfully");} catch (IOException e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error merging files");}
}
@PostMapping("/mergeChunks")
public ResponseEntity<String> mergeChunks(@RequestParam("totalChunks") int totalChunks) {try {Path outputFile = Paths.get("mergedFile.tmp");try (FileChannel outputChannel = FileChannel.open(outputFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {for (int i = 0; i < totalChunks; i++) {Path tempFile = Paths.get("uploadChunks/" + i + ".tmp");try (FileChannel inputChannel = FileChannel.open(tempFile, StandardOpenOption.READ)) {ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); // 1MB缓冲区while (inputChannel.read(buffer) != -1) {buffer.flip();outputChannel.write(buffer);buffer.clear();}}}}return ResponseEntity.ok("Files merged successfully");} catch (IOException e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error merging files");}
}
@PostMapping("/mergeChunks")
public ResponseEntity<String> mergeChunks(@RequestParam("totalChunks") int totalChunks) {try {Path outputFile = Paths.get("mergedFile.tmp");try (FileChannel outputChannel = FileChannel.open(outputFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {for (int i = 0; i < totalChunks; i++) {Path tempFile = Paths.get("uploadChunks/" + i + ".tmp");try (FileChannel inputChannel = FileChannel.open(tempFile, StandardOpenOption.READ)) {ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); // 1MB缓冲区while (inputChannel.read(buffer) != -1) {buffer.flip();outputChannel.write(buffer);buffer.clear();}}}}return ResponseEntity.ok("Files merged successfully");} catch (IOException e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error merging files");}
}
消息队列异步处理
引入消息队列(如 RabbitMQ 或 Kafka),将上传任务异步化。当客户端上传分片时,服务端将分片信息发送到消息队列,由专门的消费者进行后续处理。例如,使用 Spring Boot 集成 RabbitMQ:
// 生产者
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping("/uploadChunk")
public ResponseEntity<String> uploadChunk(@RequestParam("file") MultipartFile file,@RequestParam("chunkIndex") int chunkIndex,@RequestParam("totalChunks") int totalChunks) {try {UploadChunkMessage message = new UploadChunkMessage(file, chunkIndex, totalChunks);rabbitTemplate.convertAndSend("uploadQueue", message);return ResponseEntity.ok("Chunk uploaded successfully");} catch (Exception e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error uploading chunk");}
}
@Component
@RabbitListener(queues = "uploadQueue")
public class UploadChunkConsumer {@RabbitHandlerpublic void handle(UploadChunkMessage message) {// 处理文件分片逻辑}
}
三、优化后的提升点
(一)性能大幅提升
通过分片上传、多线程并发处理以及服务端的优化措施,上传速度得到了显著提升。例如,原本上传一个 1GB 的文件可能需要 5 分钟,优化后可能缩短至 1 分钟以内,大大提高了用户操作的效率。
(二)内存高效利用
服务端的流式处理和 Java NIO 技术避免了大文件一次性读入内存,使得内存占用大幅降低。即使面对多个大文件同时上传的情况,服务器也能稳定运行,避免了内存溢出错误,提升了系统的可靠性。
(三)稳定性增强
分片上传和断点续传机制使得上传过程更加稳定。当遇到网络波动或其他意外情况时,客户端只需重新上传失败的分片,而无需重新上传整个文件。消息队列异步处理也减轻了服务端的压力,提高了系统的容错能力,降低了上传失败的概率。
综上所述,通过对 Java Web 大文件上传在客户端(Vue)和服务端(Java)的优化,我们成功克服了传统上传方式的诸多弊端,实现了高效、稳定的大文件上传功能,为用户带来了更好的体验。
文章对你的博客创作有所帮助。如果你还想补充更多关于某些技术细节的解释,或者加入实际项目案例,都可以告诉我。
相关文章:
Java Web 大文件上传优化:从困境到高效
文章目录 Java Web 大文件上传优化:从困境到高效一、优化前的困境(一)内存占用问题(二)上传速度缓慢(三)稳定性欠佳 二、优化后的实现方案(一)客户端(Vue&…...
C++——STL 常用的查找算法
算法简介: find //查找元素find_if //按条件查找元素adjacent_find //查找相邻重复元素binary_search //二分查找法count //统计元素个数count_if //按条件统计元素个数 1. find 功能描述: 查找指定元素,找到返回指定元素的迭…...
【一次成功】Win10本地化单机部署k8s v1.31.2版本及可视化看板
【一次成功】Win10本地化单机部署k8s v1.31.2版本及可视化看板 零、安装清单一、安装Docker Desktop软件1.1 安装前<启用或关闭Windows功能> 中的描红的三项1.2 查看软件版本1.3 配置Docker镜像 二、更新装Docker Desktop三、安装 k8s3.1 点击启动安装3.2 查看状态3.3 查…...
Vulkan视频解码decode显示display之同步
在ReleaseDisplayedPicture函数中消耗图片资源并且显示display完成,设置两个标志m_hasConsummerSignalFence true 和m_hasConsummerSignalSemaphore true virtual int32_t ReleaseDisplayedPicture(DecodedFrameRelease** pDecodedFramesRelease, uint32_t nu…...
专题|Python梯度提升实例合集:GBM、XGBoost、SMOTE重采样、贝叶斯、逻辑回归、随机森林分析信贷、破产数据...
全文链接:https://tecdat.cn/?p41051 分析师:Jiajie Shi,Yimeng Li 在当今数据驱动的时代,数据分析师和数据建模师面临着各式各样复杂且极具挑战性的任务。本专题合集便是围绕这些挑战展开的宝贵知识盛宴(点击文末“阅…...
4.0 相机引导XY轴控制螺丝枪打螺丝
假如一个产品的同一水平上要打6个螺钉,是通过伺服XY轴移动带动相机以及螺丝枪,由相机拍照,根据拍照后螺丝孔位置来引导伺服进行移动以对准螺丝孔位置的。步骤如下: 一、9点标定,即把相机与伺服的实际位置关联起来。步骤…...
【ElasticSearch】学习笔记
一、lucene的组成 segment是一个具备完整搜索功能的最小单元。 多个segment组成了一个单机文本检索库lucene。 inverted index:倒排索引,用于快速根据关键词找到对应的文章term index: 构建出关键词的目录树,解决了term dictionary数据量过大ÿ…...
Spring Boot整合RabbitMQ极简教程
一、消息队列能解决什么问题? 异步处理:解耦耗时操作(如发短信、日志记录)流量削峰:应对突发请求,避免系统过载应用解耦:服务间通过消息通信,降低依赖 二、快速整合RabbitMQ 1. 环…...
代码随想录-04-字符串-03.替换数字
替换数字 题目 给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anum…...
Tailwindcss开启黑夜模式
本篇讲述如何使用tailwindcss切换白天黑夜主题 tailwindcss自带的暗夜切换会比css自带的theme主体切换来得方便很多,学习成本也很低,只要求会用tailiwndcss 1,tailwindcss.config有两种暗夜模式切换,媒体查询和手动类切换。手动控…...
AI与人的智能,改变一生的思维模型【7】易得性偏差
目录 **易得性偏差思维模型:大脑的「热搜算法」与反操纵指南****病毒式定义:你的大脑正在被「热搜」劫持****四大核心攻击路径与史诗级案例****1. 信息过载时代的「认知短路」****2. 媒体放大器的「恐怖滤镜」****3. 个人经验的「数据暴政」****4. 社交茧…...
有序表--跳表
实现一种结构,支持如下操作,要求单次调用的时间复杂度O(log n) 1,增加x,重复加入算多个词频 2,删除x,如果有多个,只删掉一个 3,查询x的排名,x的排名为,比x小的…...
双指针---字符串替换数字(数字替换为“number“)
题目链接:替换数字 要求:时间复杂度为O(n) 思路: 1、先将字符串扩容到要输出串的长度。 2、从后向前替换数字字符,也就是双指针法,newIndex指向新长度的末尾,i指向旧长度的末尾。 #include<iostream&g…...
外星人入侵-Python-三
武装飞船 开发一个名为《外星人入侵》的游戏吧!为此将使用 Pygame,这是一组功能强大而有趣的模块,可用于管理图形、动画乃至声音, 让你能够更轻松地开发复杂的游戏。通过使用Pygame来处理在屏幕上绘制图像 等任务,可将…...
JavaScript相关面试题
以下是150道JavaScript相关面试题及详细答案: JavaScript基础 1.JavaScript是什么? JavaScript是一种直译式脚本语言,主要用于网页开发,也可用于服务器端开发(如Node.js)。它是一种动态类型、弱类型、基于原…...
常见的数学模型
数学模型的基本原理 简单来说,数学模型就是用数学语言来描述现实世界中的现象或规律。它就像一个“翻译器”,把复杂的现实问题转化成我们可以用数学方法解决的问题。 核心思想: 简化现实:现实世界太复杂,模型会抓住最…...
计算机四级 - 数据库原理 - 第3章 「关系数据库系统概述」
3.1 关系数据库系统概述 关系数据模型的三大要素:关系数据结构、关系操作集合(一次一个集合)和关系完整性约束 1. 关系语言的特点是高度非过程化的, DBMS会自动帮用户选择存取路径,用户不需要依靠循环和递归完成数据的重复操作。…...
使用PHP进行自动化测试:工具与策略的全面分析
使用PHP进行自动化测试:工具与策略的全面分析 引言 随着软件开发的复杂性不断增加,自动化测试已成为确保软件质量的关键环节。PHP作为一种广泛使用的服务器端脚本语言,拥有丰富的生态系统和工具支持,使其成为自动化测试的理想选…...
discuz门户文章允许游客评论
discuz开启游客评论 1、进入后台,用户--用户组--系统用户组--游客--编辑 2、论坛相关 设置未允许发表回复 3、门户相关--文章评论字数(设置此用户组发表文章评论字数限制,设置为0将禁止此用户组发表评论) 4、验证游客回复 测试站 http://jinzhu.zhaowo.…...
AtCoder Beginner Contest 003(A - 社の給料、B -トランプ、C -プログラミング講座、D - 社の冬 )题目讲解
前言 又更新AtCoder Beginner Contes 的题目讲解啦!! 希望能给诸位带来帮助。 话不多说,开始讲解: A - 社の給料←题目翻译 为了解决这个问题,我们需要计算青木每月完成正好N个任务时的平均工资。通过分析,我们可以发现这个问题可以通过数学公式直接求解,而不需要复…...
代码随想录二刷|图论11
图论 一、基础知识 1 无向图 (1)度:一个顶点连n条边就度为n (2)权 加权无向图:有边长的无向图 (3)通道:两个顶点之间有一些边和点,并且没有重复的边 路…...
农资出入库登记本,农药化肥库存出入库软件,佳易王农资管理庄稼医院开单管理系统操作教程
一、概述 本实例以佳易王农资管理庄稼医院开单管理系统为例说明,其他版本可参考本实例。试用版软件资源可到文章最后了解,下载的文件为压缩包文件,请使用免费版的解压工具解压即可试用。 软件特点: 1、功能实用,操作简…...
串的KMP算法详解
KMP算法深度解析 一、从暴力匹配到智能跳转: 在文本编辑器的搜索功能中,当我们在百万字的文档中查找特定关键词时,传统暴力匹配算法的时间复杂度高达O(mn)。KMP算法通过独创的部分匹配表(Partial Match Table)&#x…...
软件测试之测试分类
1. 为什么要对软件测试进行分类 软件测试是软件⽣命周期中的⼀个重要环节,具有较⾼的复杂性,对于软件测试,可以从不同的⻆度 加以分类,使开发者在软件开发过程中的不同层次、不同阶段对测试⼯作进⾏更好的执⾏和管理测试 的分类⽅…...
机器学习 : 训练过程
文章目录 概要流程1 . 前向传播2 . 计算损失3 . 后向传播4 . 梯度下降 技术名词解释小结 【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 概要 主要思想拟合数据 流程 1 . 前向传播 y func * (wxb) 2 . 计算损失 y - Y 3 . 后向传播 根据链式法…...
六十天前端强化训练之第二十天React Router 基础详解
欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗,谢谢大佬! 目录 一、核心概念 1.1 核心组件 1.2 路由模式对比 二、核心代码示例 2.1 基础路由配置 2.2 动态路由示例 2.3 嵌套路由实现 2.4 完整示例代码 三、关键功能实现效果 四、…...
如何在AVL树中高效插入并保持平衡:一步步掌握旋转与平衡因子 —— 旋转篇
文章目录 AVL树种旋转的规则右单旋右单旋代码左单旋左单旋代码左右双旋左右单旋的代码右左单旋右左单旋的代码 AVL树种旋转的规则 在AVL树中,旋转是为了保持树的平衡性。AVL树是一种自平衡的二叉搜索树,它要求每个节点的左右子树的高度差不能超过1。当插…...
C++Primer学习(7.1 定义抽象数据类型)
类的基本思想是数据抽象(data abstraction)和封装(encapsulation)。数据抽象是种依赖于接口(interface)和实现(implementation)分离的编程(以及设计)技术。类的接口包括用户所能执行的操作:类的实现则包括类的数据成员、负责接口实现的函数体以及定义类所需的各种私有函数。 封…...
Vue 3 Diff 算法深度解析:与 Vue 2 双端比对对比
文章目录 1. 核心算法概述1.1 Vue 2 双端比对算法1.2 Vue 3 快速 Diff 算法 2. 算法复杂度分析2.1 时间复杂度对比2.2 空间复杂度对比 3. 核心实现解析3.1 Vue 2 双端比对代码3.2 Vue 3 快速 Diff 代码 4. 性能优化分析4.1 性能测试数据4.2 内存使用对比 5. 使用场景分析5.1 Vu…...
启动桌面Docker提示虚拟服务未启动
在启动 Docker Desktop 时,可能会遇到以下提示: Docker Desktop - Virtual Machine Platform not enabled Virtual Machine Platform not enabled该错误通常是由于 Windows 未启用 “Virtual Machine Platform” 功能导致的,这是运行 Docker…...
【SpringBoot】实现登录功能
在上一篇博客中,我们讲解了注册页面的实现。在此基础上会跳转到登录页面,今天给大家带来的是使用 SpringBoot,MyBatis,Html,CSS,JavaScript,前后端交互实现一个登录功能。 目录 一、效果 二、…...
DataWhale 速通AI编程开发:(进阶篇)第3章 提示词(Prompts)配置项
学习网址:Datawhale-学用 AI,从此开始 3.1 Roo Code提示词配置了什么 众所周知,提示词(Prompt)是用户向大语言模型输入的一段文本,用于指导大语言模型生成符合用户要求的输出。在ai编程领域更是如此,提示…...
VUE中VNode(虚拟节点)是个啥?
用 JavaScript 生成 Virtual DOM(VNode) 在 Vue 中,Virtual DOM(虚拟 DOM)是一个用 JavaScript 对象表示真实 DOM 结构的抽象层。通过这种方式,Vue 可以通过比较 Virtual DOM 与真实 DOM 的差异来最小化更…...
力扣:3. 无重复字符的最长子串(滑动窗口)
3. 无重复字符的最长子串 - 力扣(LeetCode)3. 无重复字符的最长子串 - 给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。 示例 1:输入: s "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc"…...
注解+AOP实现权限控制
注解与AOP实战:实现权限控制 在现代Java开发中,注解(Annotation)和面向切面编程(AOP)是两种强大的技术,它们能够帮助我们实现代码的解耦,提高代码的可读性和可维护性。本文将通过一…...
2.5 python接口编程
在现代软件开发的复杂生态系统中,不同系统、模块之间的交互协作至关重要。接口编程作为一种关键机制,定义了组件之间的通信规范与交互方式。Python 凭借其卓越的灵活性、丰富的库资源以及简洁易读的语法,在接口编程领域占据了重要地位&#x…...
睡不着运动锻炼贴士
在快节奏的现代生活中,失眠似乎已成为许多人的“夜间伴侣”。夜晚辗转反侧,白天精神不振,这样的恶性循环让许多人苦不堪言。其实,除了调整作息和饮食习惯,适当的运动也是改善睡眠的一剂良药。今天,就让我们…...
【Python入门】一篇掌握Python中的字典(创建、访问、修改、字典方法)【详细版】
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀《Python/PyTorch极简课》_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目…...
深入理解 HTML 表单与输入
在网页开发的广袤领域中,HTML 表单如同搭建用户与服务器沟通桥梁的基石。它是收集用户输入信息的关键渠道,承载着交互的重任。今天,就让我们一同深入探索 HTML 表单与输入的奥秘。 HTML 表单在文档中划定出一片独特的区域,这片…...
宝塔docker切换存储目录
1、 停止 Docker 服务 sudo systemctl stop docker2、迁移 Docker 数据目录 sudo mkdir -p /newpath/docker sudo rsync -avz /var/lib/docker/ /newpath/docker/3、修改 Docker 配置文件 vi /etc/docker/daemon.json 内容 {"data-root": "/newpath/docker&q…...
IPoIB驱动中RSS与TSS技术的深度解析:多队列机制与性能优化
在高速网络通信中,IP over InfiniBand(IPoIB) 是实现低延迟、高吞吐的关键技术之一。为了充分发挥多核处理器的性能潜力,IPoIB驱动通过 接收侧扩展(RSS) 和 发送侧扩展(TSS) 技术,实现了数据包处理的多队列并行化。本文结合源码实现与性能优化策略,深入解析其核心机制…...
目前人工智能的发展,判断10年、20年后的人工智能发展的主要方向,或者带动的主要产业
根据2025年的最新行业研究和技术演进趋势,结合历史发展轨迹,未来10-20年人工智能发展的主要方向及带动的产业将呈现以下六大核心趋势: 一、算力革命与底层架构优化 核心地位:算力将成为类似“新能源电池”的基础设施,…...
DeepSeek-prompt指令-当DeepSeek答非所问,应该如何准确的表达我们的诉求?
当DeepSeek答非所问,应该如何准确的表达我们的诉求?不同使用场景如何向DeepSeek发问?是否有指令公式? 目录 1、 扮演专家型指令2、 知识蒸馏型指令3、 颗粒度调节型指令4、 时间轴推演型指令5、 极端测试型6、 逆向思维型指令7、…...
并发编程面试题二
1、java线程常见的基本状态有哪些,这些状态分别是做什么的 (1)创建(New):new Thread(),生成线程对象。 (2)就绪(Runnable):当调用线程对象的sta…...
【NLP】 8. 处理常见词(Stopwords)的不同策略
处理常见词(Stopwords)的不同策略 在自然语言处理 (NLP) 和信息检索 (IR) 任务中,常见词(Stopwords) 是指在文本中频繁出现但通常对主要任务贡献较小的词,例如 “the”、“is”、“in”、“and” 等。这些…...
【Java基础】java中的lambda表达式
Java Lambda表达式深度解析:语法、简化规则与实战 前言 Java 8的Lambda表达式通过简化匿名内部类和引入函数式编程,极大提升了代码的简洁性和可读性。 一、Lambda表达式的核心语法 Lambda表达式由参数列表、->符号和表达式主体组成,其基…...
【RS】OneRec快手-生成式推荐模型
note 本文提出了一种名为 OneRec 的统一生成式推荐框架,旨在替代传统的多阶段排序策略,通过一个端到端的生成模型直接生成推荐结果。OneRec 的主要贡献包括: 编码器-解码器结构:采用稀疏混合专家(MoE)架构…...
DQN 玩 2048 实战|第一期!搭建游戏环境(附 PyGame 可视化源码)
视频讲解: DQN 玩 2048 实战|第一期!搭建游戏环境(附 PyGame 可视化源码) 代码仓库:GitHub - LitchiCheng/DRL-learning: 深度强化学习 2048游戏介绍,引用维基百科 《2048》在44的网格上进行。…...
练习题:87
目录 Python题目 题目 题目分析 代码实现 代码解释 列表推导式部分: 变量赋值和输出: 运行思路 结束语 Python题目 题目 使用列表推导式生成一个包含 1 到 100 中所有偶数的列表。 题目分析 本题要求使用 Python 的列表推导式生成一个包含 …...
二叉树的层序遍历(102)
102. 二叉树的层序遍历 - 力扣(LeetCode) 解法: /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* …...