Spring Boot图片处理实战:从上传压缩到水印缓存完整方案
在实际项目中我们经常需要处理图片资源的管理和展示问题。无论是个人博客、社交应用还是内容平台图片的存储、压缩、水印、防盗链和缓存策略都是绕不开的技术点。很多开发者只关注功能实现却忽略了图片处理背后的性能、安全和维护成本。本文将以一个常见的图片展示需求为切入点带你从零搭建一套可用的图片处理方案。我们会先理解图片处理的基本流程然后配置必要的依赖和环境接着实现上传、压缩、水印和展示功能最后补充生产环境中常见的性能优化和安全防护措施。学完后你将掌握图片处理的核心技术栈并能根据实际项目需求调整方案。1. 理解图片处理的基本流程和技术选型图片处理不仅仅是把文件存到服务器那么简单。一个完整的图片处理流程包括上传、验证、压缩、存储、元数据管理、访问控制和展示优化等多个环节。1.1 为什么需要专门的图片处理方案直接使用原图会带来几个问题大文件加载慢消耗流量、不同终端需要不同尺寸、原图容易被盗用、存储空间占用大。专业的图片处理方案通过以下方式解决这些问题压缩优化减少文件大小提升加载速度尺寸适配根据设备屏幕生成合适尺寸的图片水印保护防止未授权使用缓存策略减少服务器压力防盗链防止外站直接引用1.2 常见技术方案对比在实际项目中我们可以选择自建方案或使用云服务。自建方案控制力强、成本可控但需要自行维护云服务省心省力但可能有费用和依赖风险。方案类型优势劣势适用场景自建图片服务器完全可控、无额外费用需要维护、扩展性差内部系统、小流量项目云存储CDN高可用、自动扩展按量收费、依赖外部公网项目、大流量场景混合方案平衡控制力和成本架构复杂中型项目、有特殊需求对于学习和小型项目我们建议先从自建方案开始理解底层原理后再考虑云服务。2. 环境准备与依赖配置我们将使用 Spring Boot 作为后端框架配合 Thumbnator 进行图片处理MySQL 存储元数据。前端使用简单的 HTML 和 JavaScript 演示上传和展示功能。2.1 开发环境要求确保你的开发环境满足以下要求JDK 8 或更高版本Maven 3.6MySQL 5.7现代浏览器Chrome、Firefox、Safari2.2 创建 Spring Boot 项目使用 Spring Initializr 创建项目选择以下依赖Spring WebSpring Data JPAMySQL DriverThymeleaf用于简单的前端页面生成的pom.xml需要额外添加图片处理依赖dependency groupIdnet.coobird/groupId artifactIdthumbnailator/artifactId version0.4.14/version /dependency2.3 数据库配置在application.properties中配置数据库连接# 数据库配置 spring.datasource.urljdbc:mysql://localhost:3306/image_demo?useSSLfalseserverTimezoneUTC spring.datasource.usernameyour_username spring.datasource.passwordyour_password # JPA 配置 spring.jpa.hibernate.ddl-autoupdate spring.jpa.show-sqltrue spring.jpa.properties.hibernate.dialectorg.hibernate.dialect.MySQL5Dialect # 文件上传配置 spring.servlet.multipart.max-file-size10MB spring.servlet.multipart.max-request-size10MB # 存储路径配置 image.upload-dir./uploads/2.4 创建存储目录在项目根目录创建上传文件存储目录mkdir -p uploads/original mkdir -p uploads/thumbnail mkdir -p uploads/watermark注意生产环境中这些目录应该放在应用数据区而不是项目代码目录下。3. 实现图片上传和处理功能现在开始实现核心的图片处理功能。我们将创建实体类、Repository、Service 和 Controller完成从上传到展示的完整流程。3.1 定义图片元数据实体首先创建图片信息的实体类用于记录图片的基本信息和处理状态Entity Table(name image_info) public class ImageInfo { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(nullable false) private String originalFilename; Column(nullable false) private String storedFilename; private String filePath; private Long fileSize; private String mimeType; private Integer width; private Integer height; Column(nullable false) private LocalDateTime uploadTime; private String thumbnailPath; private String watermarkPath; // 省略构造函数、getter、setter }3.2 实现图片上传服务创建图片处理服务类负责文件的保存、压缩、水印添加等操作Service public class ImageService { Value(${image.upload-dir}) private String uploadDir; public ImageInfo saveImage(MultipartFile file) throws IOException { // 验证文件类型 if (!isImageFile(file)) { throw new IllegalArgumentException(只支持图片文件); } // 生成唯一文件名 String originalFilename file.getOriginalFilename(); String fileExtension getFileExtension(originalFilename); String storedFilename UUID.randomUUID().toString() fileExtension; // 保存原图 Path originalPath Paths.get(uploadDir, original, storedFilename); Files.createDirectories(originalPath.getParent()); file.transferTo(originalPath.toFile()); // 获取图片信息 BufferedImage image ImageIO.read(originalPath.toFile()); // 创建图片信息记录 ImageInfo imageInfo new ImageInfo(); imageInfo.setOriginalFilename(originalFilename); imageInfo.setStoredFilename(storedFilename); imageInfo.setFilePath(originalPath.toString()); imageInfo.setFileSize(file.getSize()); imageInfo.setMimeType(file.getContentType()); imageInfo.setWidth(image.getWidth()); imageInfo.setHeight(image.getHeight()); imageInfo.setUploadTime(LocalDateTime.now()); return imageInfo; } public void generateThumbnail(ImageInfo imageInfo, int width, int height) throws IOException { Path originalPath Paths.get(imageInfo.getFilePath()); Path thumbnailPath Paths.get(uploadDir, thumbnail, thumb_ imageInfo.getStoredFilename()); Thumbnails.of(originalPath.toFile()) .size(width, height) .outputFormat(jpg) .outputQuality(0.8) .toFile(thumbnailPath.toFile()); imageInfo.setThumbnailPath(thumbnailPath.toString()); } public void addWatermark(ImageInfo imageInfo, String watermarkText) throws IOException { Path originalPath Paths.get(imageInfo.getFilePath()); Path watermarkPath Paths.get(uploadDir, watermark, wm_ imageInfo.getStoredFilename()); Thumbnails.of(originalPath.toFile()) .scale(1) .watermark(Positions.BOTTOM_RIGHT, createTextWatermark(watermarkText), 0.5f) .outputQuality(0.9) .toFile(watermarkPath.toFile()); imageInfo.setWatermarkPath(watermarkPath.toString()); } private boolean isImageFile(MultipartFile file) { String contentType file.getContentType(); return contentType ! null contentType.startsWith(image/); } private String getFileExtension(String filename) { return filename.substring(filename.lastIndexOf(.)); } private BufferedImage createTextWatermark(String text) { BufferedImage watermark new BufferedImage(200, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d watermark.createGraphics(); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f)); g2d.setColor(Color.WHITE); g2d.setFont(new Font(Arial, Font.BOLD, 20)); g2d.drawString(text, 10, 30); g2d.dispose(); return watermark; } }3.3 创建控制器处理请求实现 REST API 控制器提供图片上传和访问接口RestController RequestMapping(/api/images) public class ImageController { Autowired private ImageService imageService; Autowired private ImageRepository imageRepository; PostMapping(/upload) public ResponseEntityMapString, Object uploadImage( RequestParam(file) MultipartFile file, RequestParam(value thumbnail, defaultValue true) boolean generateThumbnail, RequestParam(value watermark, required false) String watermarkText) { MapString, Object response new HashMap(); try { // 保存原图 ImageInfo imageInfo imageService.saveImage(file); // 生成缩略图 if (generateThumbnail) { imageService.generateThumbnail(imageInfo, 300, 200); } // 添加水印 if (watermarkText ! null !watermarkText.trim().isEmpty()) { imageService.addWatermark(imageInfo, watermarkText); } // 保存到数据库 imageRepository.save(imageInfo); response.put(success, true); response.put(imageId, imageInfo.getId()); response.put(message, 图片上传成功); return ResponseEntity.ok(response); } catch (Exception e) { response.put(success, false); response.put(message, 上传失败: e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); } } GetMapping(/{imageId}) public ResponseEntitybyte[] getImage( PathVariable Long imageId, RequestParam(defaultValue original) String type) { OptionalImageInfo imageInfoOpt imageRepository.findById(imageId); if (!imageInfoOpt.isPresent()) { return ResponseEntity.notFound().build(); } ImageInfo imageInfo imageInfoOpt.get(); String filePath null; switch (type) { case thumbnail: filePath imageInfo.getThumbnailPath(); break; case watermark: filePath imageInfo.getWatermarkPath(); break; default: filePath imageInfo.getFilePath(); } if (filePath null) { return ResponseEntity.notFound().build(); } try { Path path Paths.get(filePath); byte[] imageBytes Files.readAllBytes(path); String contentType Files.probeContentType(path); if (contentType null) { contentType image/jpeg; } return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .body(imageBytes); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } }4. 前端页面实现和功能验证为了完整演示功能我们创建一个简单的前端页面用于图片上传和展示。4.1 创建上传页面在src/main/resources/templates目录下创建upload.html!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org head meta charsetUTF-8 title图片上传演示/title style .container { max-width: 800px; margin: 0 auto; padding: 20px; } .upload-area { border: 2px dashed #ccc; padding: 40px; text-align: center; margin: 20px 0; } .preview { display: flex; flex-wrap: wrap; gap: 20px; margin-top: 30px; } .image-card { border: 1px solid #ddd; padding: 10px; border-radius: 5px; } .image-card img { max-width: 300px; max-height: 200px; } /style /head body div classcontainer h1图片上传和处理演示/h1 form iduploadForm enctypemultipart/form-data div classupload-area input typefile idfileInput namefile acceptimage/* required div label input typecheckbox namegenerateThumbnail checked 生成缩略图 /label label stylemargin-left: 20px; 水印文字: input typetext namewatermarkText placeholder可选 /label /div button typesubmit stylemargin-top: 20px;上传图片/button /div /form div idpreviewArea classpreview styledisplay: none; div classimage-card h3原图/h3 img idoriginalImage src alt原图 /div div classimage-card h3缩略图/h3 img idthumbnailImage src alt缩略图 /div div classimage-card h3带水印/h3 img idwatermarkImage src alt带水印 /div /div div idmessage stylemargin-top: 20px;/div /div script document.getElementById(uploadForm).addEventListener(submit, async function(e) { e.preventDefault(); const formData new FormData(); const fileInput document.getElementById(fileInput); const generateThumbnail document.querySelector(input[namegenerateThumbnail]).checked; const watermarkText document.querySelector(input[namewatermarkText]).value; formData.append(file, fileInput.files[0]); formData.append(generateThumbnail, generateThumbnail); if (watermarkText) { formData.append(watermarkText, watermarkText); } try { const response await fetch(/api/images/upload, { method: POST, body: formData }); const result await response.json(); const messageDiv document.getElementById(message); if (result.success) { messageDiv.innerHTML span stylecolor: green;上传成功图片ID: ${result.imageId}/span; // 显示预览 const imageId result.imageId; document.getElementById(originalImage).src /api/images/${imageId}?typeoriginal; document.getElementById(thumbnailImage).src /api/images/${imageId}?typethumbnail; document.getElementById(watermarkImage).src /api/images/${imageId}?typewatermark; document.getElementById(previewArea).style.display flex; } else { messageDiv.innerHTML span stylecolor: red;上传失败: ${result.message}/span; } } catch (error) { document.getElementById(message).innerHTML span stylecolor: red;请求失败: ${error.message}/span; } }); /script /body /html4.2 添加首页控制器创建页面控制器提供访问入口Controller public class PageController { GetMapping(/) public String index() { return upload; } }4.3 启动和测试应用启动 Spring Boot 应用访问http://localhost:8080测试功能选择一张图片文件JPG、PNG 等格式选择是否生成缩略图可选输入水印文字点击上传观察处理结果正常情况应该能看到原图、缩略图和带水印版本的三张图片。检查控制台日志确认没有异常信息。5. 生产环境优化和常见问题排查基础功能跑通后我们需要考虑生产环境中的稳定性、性能和安全性问题。5.1 性能优化建议图片处理是 CPU 和 I/O 密集型操作需要特别注意性能优化异步处理机制对于大图片或高并发场景应该使用异步处理避免阻塞请求线程Service public class AsyncImageService { Async public CompletableFutureVoid processImageAsync(ImageInfo imageInfo) { try { // 生成缩略图 imageService.generateThumbnail(imageInfo, 300, 200); // 添加水印 imageService.addWatermark(imageInfo, 版权保护); // 更新数据库 imageRepository.save(imageInfo); return CompletableFuture.completedFuture(null); } catch (Exception e) { return CompletableFuture.failedFuture(e); } } }图片缓存策略使用 Redis 或内存缓存处理后的图片减少磁盘 I/OService public class ImageCacheService { Autowired private RedisTemplateString, byte[] redisTemplate; public byte[] getCachedImage(String cacheKey) { return redisTemplate.opsForValue().get(cacheKey); } public void cacheImage(String cacheKey, byte[] imageData, Duration ttl) { redisTemplate.opsForValue().set(cacheKey, imageData, ttl); } }5.2 安全防护措施图片上传功能需要严格的安全控制防止恶意文件攻击文件类型验证增强除了检查 MIME 类型还应该验证文件魔数public boolean isSafeImageFile(MultipartFile file) throws IOException { // 检查扩展名 String filename file.getOriginalFilename().toLowerCase(); if (!filename.matches(.*\\.(jpg|jpeg|png|gif)$)) { return false; } // 检查魔数 byte[] magicNumber new byte[8]; file.getInputStream().read(magicNumber); // JPEG: FF D8 FF if (magicNumber[0] (byte)0xFF magicNumber[1] (byte)0xD8 magicNumber[2] (byte)0xFF) { return true; } // PNG: 89 50 4E 47 if (magicNumber[0] (byte)0x89 magicNumber[1] (byte)0x50 magicNumber[2] (byte)0x4E magicNumber[3] (byte)0x47) { return true; } return false; }文件大小和尺寸限制防止超大文件攻击Component public class ImageValidator { private static final long MAX_FILE_SIZE 10 * 1024 * 1024; // 10MB private static final int MAX_IMAGE_WIDTH 4096; private static final int MAX_IMAGE_HEIGHT 4096; public void validateImage(MultipartFile file) throws IOException { if (file.getSize() MAX_FILE_SIZE) { throw new IllegalArgumentException(文件大小不能超过10MB); } BufferedImage image ImageIO.read(file.getInputStream()); if (image null) { throw new IllegalArgumentException(无效的图片文件); } if (image.getWidth() MAX_IMAGE_WIDTH || image.getHeight() MAX_IMAGE_HEIGHT) { throw new IllegalArgumentException(图片尺寸不能超过4096x4096); } } }5.3 常见问题排查表在实际部署中可能会遇到以下问题问题现象可能原因检查方式解决方案上传失败提示文件大小超限Spring Boot 文件大小配置不正确检查application.properties中的配置调整spring.servlet.multipart.max-file-size图片处理速度慢图片太大或服务器配置低查看服务器 CPU 和内存使用情况优化图片尺寸增加服务器资源使用异步处理缩略图生成失败图片格式不支持或损坏检查原图是否能正常打开添加格式验证使用 try-catch 处理异常水印文字显示乱码字体不支持中文检查水印生成代码中的字体设置使用支持中文的字体如 微软雅黑图片访问返回 404文件路径错误或权限不足检查文件是否实际存在权限是否正确确保存储目录有读写权限路径配置正确5.4 监控和日志记录生产环境需要完善的监控和日志记录Aspect Component Slf4j public class ImageServiceMonitor { Around(execution(* com.example.service.ImageService.*(..))) public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable { long startTime System.currentTimeMillis(); String methodName joinPoint.getSignature().getName(); try { Object result joinPoint.proceed(); long duration System.currentTimeMillis() - startTime; log.info(方法 {} 执行耗时: {}ms, methodName, duration); if (duration 5000) { // 超过5秒记录警告 log.warn(方法 {} 执行过慢耗时: {}ms, methodName, duration); } return result; } catch (Exception e) { log.error(方法 {} 执行失败: {}, methodName, e.getMessage(), e); throw e; } } }6. 扩展功能和最佳实践掌握了基础功能后可以根据实际需求扩展更多高级功能。6.1 支持更多图片处理功能图片格式转换添加格式转换支持如 WebP 格式以减小文件大小public void convertToWebP(ImageInfo imageInfo) throws IOException { Path originalPath Paths.get(imageInfo.getFilePath()); Path webpPath Paths.get(uploadDir, webp, imageInfo.getStoredFilename().replaceFirst(\\.[^.]$, .webp)); Thumbnails.of(originalPath.toFile()) .scale(1) .outputFormat(webp) .outputQuality(0.8) .toFile(webpPath.toFile()); }智能裁剪根据图片内容进行智能裁剪public void smartCrop(ImageInfo imageInfo, int targetWidth, int targetHeight) throws IOException { Path originalPath Paths.get(imageInfo.getFilePath()); Path cropPath Paths.get(uploadDir, cropped, crop_ imageInfo.getStoredFilename()); Thumbnails.of(originalPath.toFile()) .size(targetWidth, targetHeight) .keepAspectRatio(false) .toFile(cropPath.toFile()); }6.2 数据库优化建议对于大量图片的场景数据库需要相应优化分表策略按时间或业务维度分表提高查询性能-- 按月分表 CREATE TABLE image_info_202401 LIKE image_info; CREATE TABLE image_info_202402 LIKE image_info;索引优化为常用查询字段添加索引CREATE INDEX idx_upload_time ON image_info(upload_time); CREATE INDEX idx_file_size ON image_info(file_size);6.3 部署架构建议随着业务增长需要考虑更复杂的部署架构微服务架构将图片服务拆分为独立微服务上传服务处理文件上传和验证处理服务负责图片压缩、水印等处理存储服务管理文件存储和访问元数据服务管理图片信息数据库CDN 加速使用 CDN 加速图片访问减少源站压力Service public class CDNService { public String getCDNUrl(String imagePath) { // 根据业务规则生成 CDN URL return https://cdn.yourdomain.com imagePath; } public void purgeCDNCache(String imagePath) { // 清除 CDN 缓存 } }图片处理看似简单但涉及的技术点相当广泛。从基础的文件操作到高性能的异步处理从简单的格式转换到复杂的智能裁剪每个环节都需要仔细设计和优化。实际项目中要根据业务规模、团队技术栈和性能要求选择合适的方案避免过度设计或功能不足。建议在掌握本文基础功能后重点练习异常处理、性能监控和安全防护这三个生产环境最关键的能力。可以先在小项目中实践逐步积累经验后再应用到更复杂的场景中。

相关新闻

Phashion测试策略:如何构建可靠的图片查重测试用例

Phashion测试策略:如何构建可靠的图片查重测试用例

Phashion测试策略:如何构建可靠的图片查重测试用例 【免费下载链接】phashion Ruby wrapper around pHash, the perceptual hash library for detecting duplicate multimedia files 项目地址: https://gitcode.com/gh_mirrors/ph/phashion Phashion是一个基…

2026/10/13 12:42:47 阅读更多 →
Rails邮件模板新选择:Slim-Rails mailer generator使用详解

Rails邮件模板新选择:Slim-Rails mailer generator使用详解

Rails邮件模板新选择:Slim-Rails mailer generator使用详解 【免费下载链接】slim-rails Slim templates generator for Rails 项目地址: https://gitcode.com/gh_mirrors/sl/slim-rails Slim-Rails是一款专为Rails框架设计的模板生成工具,它提供…

2026/10/12 12:11:38 阅读更多 →
Caliburn.Micro与Notifications.Wpf集成教程:MVVM模式下的通知最佳实践

Caliburn.Micro与Notifications.Wpf集成教程:MVVM模式下的通知最佳实践

Caliburn.Micro与Notifications.Wpf集成教程:MVVM模式下的通知最佳实践 【免费下载链接】Notifications.Wpf Toast notifications for WPF 项目地址: https://gitcode.com/gh_mirrors/no/Notifications.Wpf Notifications.Wpf是一款专为WPF应用设计的Toast通…

2026/10/7 3:57:41 阅读更多 →

最新新闻

Unity2D弹球游戏可运行完整项目:物理引擎+碰撞+UI闭环实现

Unity2D弹球游戏可运行完整项目:物理引擎+碰撞+UI闭环实现

简介:这是一份面向Unity初学者与2D游戏开发入门者的可运行完整项目,聚焦弹球游戏核心逻辑实现,帮助开发者掌握不依赖物理引擎的2D运动控制、碰撞检测、挡板交互、得分系统及UI状态管理等关键技能。资源包含432个文件,以128个info配…

2026/10/14 14:38:54 阅读更多 →
零基础网页制作入门:HTML与CSS实战指南

零基础网页制作入门:HTML与CSS实战指南

1. 项目概述与核心思路拆解 1.1 这个项目到底在解决什么问题 先说结论:创建简单网页教学这个方向,本质上是帮那些完全不了解前端的人,用最短的时间建立起对网页制作的基本认知和动手能力。很多人觉得做网页是程序员的专属技能,一…

2026/10/14 14:38:54 阅读更多 →
Kubernetes CronJob执行延迟排查:从控制器到节点侧的关键链路与优化

Kubernetes CronJob执行延迟排查:从控制器到节点侧的关键链路与优化

告警一夜之间刷了十几条:原本应该准点 1:00 执行的 CronJob,实际跑到 1:37 才从 Pod 里打出第一批日志。我盯着“执行延迟”三个字想了很久,最初以为是容器时间不同步,后来才发现问题根本不在 CronJob 控制器,而在调度…

2026/10/14 14:38:54 阅读更多 →
MySQL SELECT与SHOW实战:从基础查询到性能排查的完整指南

MySQL SELECT与SHOW实战:从基础查询到性能排查的完整指南

从接触数据库开始,大多数人的第一条SQL都是SELECT,而SHOW往往是那个“我知道它存在,但很少深入研究”的兄弟命令。这个主题虽然叫“简单检索”,但SELECT和SHOW几乎撑起了日常数据库操作的半边天:前者负责从一张或多张表…

2026/10/14 14:38:54 阅读更多 →
主成分分析PCA从原理到实战:高维数据降维的核心技术解析

主成分分析PCA从原理到实战:高维数据降维的核心技术解析

很多人在刚开始接触数据分析时,面对几十个甚至上百个特征,第一反应往往是茫然。画出来的散点图矩阵密密麻麻,算出来的相关系数表让人眼花缭乱,跑出来的模型又总被多重共线性拖后腿。这时候,主成分分析(PCA&…

2026/10/14 14:38:54 阅读更多 →
Pandas线性插值实战:空气质量数据异常值与缺失值处理

Pandas线性插值实战:空气质量数据异常值与缺失值处理

这段时间帮某个环境监测项目处理城市空气质量数据,遇到最多的不是模型效果差,而是数据本身的问题。一套PM2.5、PM10、NO2、SO2浓度数据拿过来,缺失值、异常值、重复记录混在一起,直接建模结果根本没法看。把这些数据清洗干净&…

2026/10/14 14:37:53 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →