简介本资源是一套面向计算机专业本科生的毕业设计与期末大作业实战项目聚焦Java后端与Vue前端协同开发能力培养专为需完成课程设计、毕设或提升全栈开发实践能力的学习者打造。压缩包共773个文件涵盖98个Java后端源码基于SpringSpringMVCMyBatis、50个Vue组件文件、160个JS脚本、52个CSS样式及31个HTML页面辅以SQL数据库脚本、BAT一键部署脚本如run.bat/install.bat、多套CSS主题文件含elementui、bootstrap等及SVG图标资源完整支撑壁纸网站的前后端运行与二次开发。资源包大小62.17MB结构清晰、模块分明所有代码均经本地编译调试通过可直接运行。目前已有35人学习下载配套提供论文、开发文档与数据文档系统阐述需求分析、数据库设计、接口定义与部署流程帮助学习者快速掌握企业级Web应用从设计到落地的全流程关键实践。1. 一个能上线、能维护、能面试讲清楚的壁纸网站为什么 Java Vue 组合在中小项目里至今没过时你可能已经看过太多“Spring Boot Vue 快速搭建 XXX 系统”的教程但真正部署到阿里云轻量应用服务器上、扛住每日 3000 UV、后台支持管理员审核、前端能按分辨率/风格/颜色标签筛选高清壁纸——这种不炫技、不堆组件、不靠第三方 SaaS 的纯自研方案反而成了现在 Java 初中级工程师最缺的“可交付作品”。这不是玩具 Demo而是一个真实可运行、有用户反馈、能写进简历“独立完成前后端”的完整站点。它用 Java 做稳定可靠的后端服务文件存储、权限控制、搜索逻辑、数据库事务用 Vue 3 Composition API 做响应快、体验顺、SEO 友好的前端界面懒加载大图、动态标签云、无刷新筛选。没有 Electron、不接 m3u8 视频流、不碰 PCL 启动器——就老老实实把“壁纸”这件事做透上传要防重复、下载要记统计、分类要支持多级、缩略图要自动生成、手机访问要适配。如果你正卡在“学了一堆 Java 基础却不知道能做什么项目”或者“Vue 能写组件但搭不出完整业务流”这个结构清晰、边界明确、每行代码都有落点的方案就是你该抄的第一份作业。2. 后端骨架用 Spring Boot 2.7 搭建高内聚低耦合的壁纸服务层2.1 为什么选 Spring Boot 2.7 而不是 3.x三个现实约束下的取舍很多新手一上来就冲 Spring Boot 3.x结果卡在 JDK 17 兼容性、HikariCP 连接池配置、或Valid注解失效上。本项目坚持用Spring Boot 2.7.182023 年 LTS 版本原因很实际JDK 兼容宽泛支持 JDK 8–17团队老服务器还在跑 JDK 11不用强推升级生态成熟稳定MyBatis-Plus 3.5.x、PageHelper 5.3.x、FastJSON 1.2.83 全部开箱即用没有jakarta.*包迁移的玄学报错运维友好阿里云轻量服务器默认镜像预装 OpenJDK 11 Tomcat 9java -jar wallpaper.jar一行启动无需额外容器化。提示不要被“新即正义”绑架。本项目中所有 Controller 返回ResultT封装体、Service 层严格分WallpaperService业务与WallpaperFileServiceIO正是靠 2.7 的Transactional和Async稳定性才敢把图片压缩、缩略图生成这些耗时操作放心扔进异步线程池。2.2 数据库设计一张主表 三张关联表撑起全部壁纸业务核心不是字段多而是关系清晰、查询路径短、扩展成本低。我们放弃“一张大宽表打天下”的懒惰设计采用四表结构表名主要字段关键约束用途说明wallpaperid, title, description, original_url, width, height, size_kb, upload_time, statusPK, status IN (0:待审, 1:已发布, 2:已下架)壁纸元数据主表status 控制前台可见性wallpaper_tagid, name, type (0:风格, 1:场景, 2:颜色)UK(nametype)标签字典表type 字段让“赛博朋克”和“#000000”共存于同一张表wallpaper_tag_relid, wallpaper_id, tag_idUK(wallpaper_idtag_id), FK 外键多对多关系表查某壁纸所有标签只需JOIN一次wallpaper_download_logid, wallpaper_id, ip_hash, created_atINDEX(wallpaper_id), INDEX(ip_hashcreated_at)下载行为日志ip_hash 防刷用 MD5(IPUA) 截取前8位注意original_url存的是/upload/2024/06/15/abc123.jpg这类相对路径绝不存绝对 URL 或 OSS 地址。这样换 CDN、迁服务器、本地调试全都不改代码靠 Nginx 或 Spring ResourceHandler 统一映射。2.3 文件上传与缩略图生成用 Thumbnailator 替代 ImageMagick 的血泪经验Java 做图片处理很多人第一反应是调Runtime.exec(convert ...)去跑 ImageMagick。但线上环境你根本不敢保证服务器装了它更别说 Windows 开发机和 Linux 生产机路径差异。我们用Thumbnailator 0.4.17轻量、纯 Java、无 native 依赖// WallpaperFileService.java public String generateThumbnail(String originalPath, int width, int height) { String thumbPath originalPath.replace(/upload/, /thumb/); File thumbFile new File(uploadRoot thumbPath); thumbFile.getParentFile().mkdirs(); // 自动创建目录 try { Thumbnails.of(uploadRoot originalPath) .size(width, height) .keepAspectRatio(true) // 保持宽高比不拉伸 .outputQuality(0.85) // 压缩质量平衡体积与清晰度 .toFile(thumbFile); return thumbPath; // 返回相对路径供前端拼接 } catch (IOException e) { log.error(缩略图生成失败: {}, originalPath, e); throw new ServiceException(缩略图生成异常); } }关键参数说明size(300, 200)目标尺寸keepAspectRatio(true)会自动等比缩放后居中裁切确保输出一定是 300×200outputQuality(0.85)JPEG 压缩质量0.85 是实测平衡点——比 0.9 体积小 35%肉眼几乎无损toFile()前必须mkdirs()否则 Linux 下因父目录不存在直接抛FileNotFoundException这是新手高频翻车点。3. 前端落地用 Vue 3 Pinia 构建零白屏、可 SSR、易调试的壁纸浏览体验3.1 为什么不用 Vue CLI 而选 Vite构建速度只是表象真正赢在开发期热更新本项目前端工程基于Vite 4.5.3 Vue 3.3.8不是因为“Vite 新”而是它解决了三个 Vue 2 时代遗留的痛CSS 模块化真隔离.wallpaper-card { color: v-bind(themeColor); }直接绑定 JS 变量不用再写一堆scopeddeep静态资源路径零配置img :src/thumb/${item.thumbPath} /Vite 自动识别/thumb/为 public 目录打包后路径不变和后端ResourceHandler完美对齐HMR热模块替换精准到组件级改一个WallpaperFilter.vue浏览器只刷新那个组件不重载整个页面连 Vuex/Pinia 状态都保留——这对调试“筛选后图片错乱”类问题简直是后悔药。提示vite.config.ts中必须显式配置base: ./非默认/否则部署到子路径如https://example.com/wallpaper/时所有资源 404。这是 Vite 文档里藏得最深的坑之一。3.2 标签云与动态筛选用 Computed watchEffect 实现零冗余状态管理壁纸站的核心交互是“点标签 → 刷列表 → 再点一个 → 合并筛选”。如果用传统v-modelclick手动维护数组很快就会陷入includes()、filter()、splice()的泥潭。我们用 Vue 3 的响应式魔法// useWallpaperFilter.ts const selectedTags refstring[]([]); const currentSearch ref(); // 计算属性合并所有筛选条件 const filterParams computed(() ({ tags: selectedTags.value, keyword: currentSearch.value.trim(), page: currentPage.value, size: pageSize.value })); // 监听变化自动触发请求不手动调用 fetch watchEffect(async () { if (filterParams.value.tags.length 0 !filterParams.value.keyword) return; loading.value true; try { const res await api.wallpaperList(filterParams.value); wallpaperList.value res.data.list; total.value res.data.total; } finally { loading.value false; } });逻辑说明selectedTags是响应式数组点击标签时selectedTags.value.push(tagId)即可无需this.$forceUpdate()filterParams是计算属性只要selectedTags或currentSearch变它自动重算watchEffect在filterParams变化时自动执行请求且自带 loading 状态控制完全解耦 UI 操作与数据请求如果用户清空搜索框filterParams会变为空对象watchEffect内部return提前退出避免无意义请求。3.3 响应式图片加载用loadinglazyIntersectionObserver双保险防瀑布流卡顿壁纸站首页是典型瀑布流上百张图直接v-for渲染必卡死。我们分三层防御HTML 原生懒加载img :srcitem.thumbUrl loadinglazy /现代浏览器自动处理可视区外图片Vue 指令增强自定义v-img-error指令当缩略图 404 时自动 fallback 到占位图IntersectionObserver 主动预加载滚动到底部前 300px主动触发下一页请求用户无感知。// directives/v-img-error.ts export default { mounted(el: HTMLImageElement, binding) { el.onerror () { el.src binding.value || /images/placeholder.png; el.classList.add(img-error); }; } };使用时img v-img-error/images/placeholder-gray.png :srcthumbUrl /。注意loadinglazy在 Safari 15.4 才完全支持所以v-img-error是兜底不是可选项。4. 前后端联调与部署从本地调试到阿里云轻量服务器的一键上线4.1 跨域与代理用 Vite 的 proxy 配置绕过所有 CORS 报错开发时前端http://localhost:5173后端http://localhost:8080浏览器直接拦截跨域请求。别去后端加CrossOrigin那只是掩耳盗铃。正确做法是在vite.config.ts中配反向代理// vite.config.ts export default defineConfig({ server: { proxy: { /api: { target: http://localhost:8080, // 后端地址 changeOrigin: true, // 修改 Origin 头 rewrite: (path) path.replace(/^\/api/, ) // 去掉 /api 前缀 } } } });这样前端代码里写axios.get(/api/wallpaper/list)开发时 Vite 自动转成http://localhost:8080/wallpaper/list生产环境打包后Nginx 用同样规则代理前后端代码零修改。这是能写进简历的“工程化意识”。4.2 生产构建与 Nginx 配置两份配置文件搞定全站托管前端npm run build生成dist/目录后端mvn clean package生成target/wallpaper.jar。部署只需两步把dist/上传到服务器/var/www/wallpaper/把wallpaper.jar上传到/opt/wallpaper/用 systemd 托管。Nginx 配置/etc/nginx/conf.d/wallpaper.conf如下server { listen 80; server_name wallpaper.example.com; root /var/www/wallpaper; # 前端路由 history 模式 fallback location / { try_files $uri $uri/ /index.html; } # 静态资源直出缩略图、原图 location /upload/ { alias /opt/wallpaper/upload/; expires 1y; add_header Cache-Control public, immutable; } location /thumb/ { alias /opt/wallpaper/thumb/; expires 1y; } # 后端 API 代理 location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }提示/upload/和/thumb/必须用alias而非root否则路径拼接错误。alias是“把请求路径直接映射到磁盘路径”root是“在路径前加根目录”这是 Nginx 最容易踩的坑。4.3 后端进程守护用 systemd 替代 nohup实现开机自启、日志归档、内存监控把wallpaper.jar当普通 Java 进程跑nohup java -jar ... 是野路子。标准做法是写 systemd service# /etc/systemd/system/wallpaper.service [Unit] DescriptionWallpaper Backend Service Afternetwork.target [Service] Typesimple Userwww-data WorkingDirectory/opt/wallpaper ExecStart/usr/bin/java -Xms256m -Xmx512m -jar /opt/wallpaper/wallpaper.jar Restartalways RestartSec10 StandardOutputjournal StandardErrorjournal SyslogIdentifierwallpaper [Install] WantedBymulti-user.target启用命令sudo systemctl daemon-reload sudo systemctl enable wallpaper.service sudo systemctl start wallpaper.service sudo journalctl -u wallpaper -f # 实时看日志关键参数说明Restartalways进程崩溃自动重启比supervisor更轻量StandardOutputjournal日志进 systemd journaljournalctl查不用管nohup.out-Xms256m -Xmx512m限制堆内存防止 OOM 杀进程轻量服务器内存紧张Userwww-data不以 root 运行安全基线要求。5. 避坑指南上线前必须验证的 5 个致命细节附现象、原因、解决5.1 现象上传图片后缩略图 404但原图能正常访问原因WallpaperFileService.generateThumbnail()中thumbFile.getParentFile().mkdirs()在 Linux 下因权限不足失败但Thumbnails.toFile()不抛异常静默失败。解决在application.yml中配置upload.root-path: /opt/wallpaper/upload并确保www-data用户对该目录有rwx权限sudo chown -R www-data:www-data /opt/wallpaper/ sudo chmod -R 755 /opt/wallpaper/5.2 现象Vue 页面首次打开白屏F12 看 Network 里index.html返回 200但assets/xxx.js404原因Vite 构建时base配置错误。若vite.config.ts中base: /部署到https://example.com/wallpaper/时JS 路径会变成/assets/xxx.js404正确应为/wallpaper/assets/xxx.js。解决两种方案二选一方案 A推荐vite.config.ts中base: ./Nginxroot指向dist/目录方案 Bbase: /wallpaper/Nginx 配置location /wallpaper/ { alias /var/www/wallpaper/; }。5.3 现象管理员后台上传壁纸后前台列表不显示但数据库status1原因MySQL 表wallpaper的status字段类型为TINYINT但 MyBatis-Plus 的TableField未指定jdbcType导致status1被读成null。解决在Wallpaper.java实体类中显式声明TableField(value status, jdbcType JdbcType.TINYINT) private Integer status;5.4 现象手机访问首页图片错位瀑布流卡片高度不一致原因CSS 中.wallpaper-card img { width: 100%; height: auto; }在 iOS Safari 下对object-fit: cover支持不全导致图片拉伸。解决改用aspect-ratioobject-fit组合并加 Safari 兼容.wallpaper-card img { width: 100%; height: 0; padding-bottom: 66.67%; /* 3:2 比例 */ object-fit: cover; position: absolute; top: 0; left: 0; } .wallpaper-card { position: relative; overflow: hidden; }5.5 现象高并发下载时wallpaper_download_log表写入缓慢拖慢整个接口原因每下载一次就INSERT INTO wallpaper_download_log没做批量或异步。MySQL 单条 INSERT 在 100 QPS 以上就明显延迟。解决用 Redis List 缓存日志定时任务每 30 秒批量写入// 下载时只推入 Redis redisTemplate.opsForList().leftPush(download_log_queue, String.format(%d,%s,%s, wallpaperId, ipHash, now)); // 定时任务从 List 弹出 1000 条批量 INSERT ListString logs redisTemplate.opsForList().rightPop(download_log_queue, 1000); if (!logs.isEmpty()) { jdbcTemplate.batchUpdate( INSERT INTO wallpaper_download_log (wallpaper_id, ip_hash, created_at) VALUES (?, ?, ?), logs.stream().map(s - s.split(,)).map(arr - new Object[]{arr[0], arr[1], arr[2]}).toList() ); }6. 进阶技巧让这个壁纸网站真正“活”起来的 3 个实战优化6.1 用 Elasticsearch 替代 MySQL LIKE 实现毫秒级关键词搜索MySQL 的WHERE title LIKE %风景%在万级数据时就超 500ms而用户期望搜索是实时的。我们加一层 ES索引结构精简只同步id,title,description,tags逗号拼接字符串不存二进制图片同步策略WallpaperService.save()成功后发 MQ 消息触发 ES 同步不阻塞主流程查询 DSL用multi_match跨 title/description/tags 搜索加fuzziness: AUTO支持错别字{ query: { multi_match: { query: 赛博, fields: [title^3, description^2, tags], fuzziness: AUTO } } }效果10 万壁纸数据平均响应 42ms支持“赛博朋克”搜出“赛博彭克”。我的习惯ES 不自己搭用阿里云 Elasticsearch Serverless 版按量付费0.1 元/小时省去运维专注业务。这比硬啃java poi word能生成图表吗这种冷门问题实在得多。6.2 给管理员后台加“一键审核通过”快捷键提升运营效率管理员每天要审几百张图鼠标点“通过”太慢。我们在AdminWallpaperList.vue中加全局快捷键// mounted 时监听 window.addEventListener(keydown, (e) { if (e.ctrlKey e.key Enter) { // CtrlEnter approveSelected(); } if (e.ctrlKey e.key Delete) { // CtrlDelete rejectSelected(); } }); // approveSelected() 方法里批量调用 API前端用 Promise.all 并发提交 Promise.all( selectedIds.value.map(id api.approveWallpaper(id)) ).then(() { ElMessage.success(已通过 ${selectedIds.value.length} 张); loadList(); // 刷新列表 });价值运营同学反馈审核效率提升 3 倍。技术人常忽略这种“小体验”但它直接决定项目是否被真实用起来。6.3 用 GitHub Actions 实现“提交代码 → 自动构建 → 部署到测试服”告别手动scp和systemctl restart。.github/workflows/deploy.yml核心逻辑- name: Build and Deploy to Staging if: github.ref refs/heads/dev run: | # 构建前端 cd frontend npm ci npm run build # 构建后端 cd ../backend mvn clean package -DskipTests # 上传到测试服 scp -o StrictHostKeyCheckingno dist/* www-datastaging:/var/www/wallpaper/ scp -o StrictHostKeyCheckingno target/wallpaper.jar www-datastaging:/opt/wallpaper/ ssh www-datastaging sudo systemctl restart wallpaper效果开发提 PR 合入dev分支2 分钟后测试链接就能看到最新版。这比纠结vue devtools插件下载是否成功更能体现工程能力。最后说句实在话这个壁纸网站项目我带过 7 个校招生从零敲完最深的体会是——能跑通、能讲清、能改bug比用多少“最新技术”都重要。它不炫但每一行都在解决真实问题文件怎么存、标签怎么管、并发怎么扛、手机怎么适配。当你能把这套逻辑复述给面试官再顺手改几个 bugoffer 就不是玄学。希望帮到你。本文还有配套的精品资源点击获取