
做毕业设计这些年我见过太多同学一上来就问“有没有现成系统”结果拿到的代码跑都跑不起来更别说讲清楚自己做了什么。今天我想认真拆一个非常适合计算机专业学生参考的题目基于SpringBoot的农村综合风貌展示平台。这个项目听起来不复杂但它把乡村数字化、内容展示、后台管理、小程序端全部串在一起知识覆盖面非常广拿来当毕设、课程设计或者简历里的项目都很能打。这个平台到底能做什么简单说就是把一个村庄的景点、文化、产业、村容村貌等内容通过网页和小程序统一展示出来。村民可以发动态游客可以浏览、点赞、评论管理员在后台维护信息。从技术角度看它既要解决数据管理问题也要解决多端展示问题还要考虑权限控制、图片存储、搜索筛选这些日常开发里一定会遇到的细节。对于想搞明白SpringBoot全家桶怎么落地的人来说这就是一个缩小版的企业级应用。我下面会按我自己做这类项目的习惯把整个项目从需求分析、技术选型、数据库设计到核心代码、踩坑记录全部过一遍。内容偏实操前后端都有如果你打算自己写一遍可以直接照着做。1. 项目到底在解决什么问题1.1 农村风貌展示的尴尬现状先聊点实际的。你去搜“农村风采展示”绝大多数地方还停留在公众号推文、宣传册、政府网站静态栏目这些形式。信息更新慢、内容零散、游客想找个村子的特色景点得翻好几层网页村民想发个自家农产品动态也没有入口。这个毕设题目看准的正是这个缺口做一个能让村里内容自主更新、游客可以交互、管理员统一管控的展示平台。所以它不是一个普通的“网页展示”而是“内容管理系统 公众端展示 移动端适配”的组合体。用户端看到的是干净美观的风貌页管理端做的是内容录入、审核、分类、排序。这种结构正好对应了互联网产品里最常见的B端和C端分离模式做完这个项目你对权限设计、数据隔离、接口设计都会有实感。1.2 这个项目适合谁来做如果你还在纠结毕设选什么方向这个题目很适合。第一需求明确但不复杂工作量可控一个人做完不会觉得空第二技术栈主流SpringBoot MyBatis/MyBatis-Plus MySQL Vue/小程序面试时可以拿去聊的东西很多第三扩展空间大后面想加地图导航、VR全景、农产品商城、留言板都可以在原有架构上加。如果你是电子信息或者嵌入式方向的同学想掺一些单片机元素也可以把项目延伸成“环境数据展示平台”用传感器采集温度、湿度、空气质量再通过接口把数据上传到这个SpringBoot后端前端用图表展示。这样就把Java后端和硬件串起来了答辩时更有亮点。2. 技术选型为什么是SpringBoot而不是别的2.1 后端为什么选SpringBoot很多人第一个问题就是能不能用Servlet/JSP做能做但我不建议。纯Servlet写一个带用户、评论、分类、多表查询的项目代码量会爆炸而且你处理JSON、事务、文件上传都要自己封装调试成本很高。SpringBoot的核心理念是“自动配置 约定大于配置”你只要引入依赖写少量配置就能把Web应用跑起来把精力放在业务上。我自己的标配是SpringBoot 2.7.x MyBatis-Plus MySQL 8.0 Redis非必须。SpringBoot 2.7已经很成熟网上资料多Java 8或Java 11都兼容完全够毕业设计用。MyBatis-Plus帮我省掉大量单表CRUD的重复代码比如分页查询、条件构造器写起来很爽。提示不建议一上来就上SpringBoot 3.x JDK 17除非你对新特性很熟。毕设重点是跑通业务不是追逐最新版本。官方文档虽然好但很多第三方教程还停留在2.x时代遇到版本坑会耽误时间。2.2 前端展示端怎么选在这个项目里公众端至少有两个我们需要考虑一个是PC网页另一个是移动端。PC端用Vue 2或Vue 3都可以如果你的基础一般直接使用服务端渲染的Thymeleaf模板也能做出来。但考虑到现在评委老师都喜欢看到“前后端分离”我会用Vue 3 Element Plus做一个管理后台再单独做一个微信小程序用于移动端浏览。微信小程序这块最大的好处是省去App的安装分发流程用户扫码就能看。小程序端不用做得特别重重点是展示风貌列表、详情、评论入口和个人登录。通过uni-app开发的话还能打包成H5和各个小程序平台代码复用率很高对毕设来说性价比极高。2.3 数据存储与工具链数据库选择MySQL理由不多说主流、免费、资料多。如果是并发要求不高的毕设系统单库单表就够。缓存看个人情况建议加一个Redis存热门景点点击量如果不想折腾环境也可以先不加用数据库字段累加。文件这块风貌平台跑不了要上传图片本地目录上传是最简单的做一个upload目录映射成静态资源访问路径就行。如果你想让项目显得更专业可以用MinIO自建对象存储或者用云存储的SDK接入。注意毕设阶段别为了“高级”把架构做复杂上传本地磁盘加上数据库记录相对路径已经能说明你掌握了文件处理逻辑。3. 数据库设计先把表结构想清楚3.1 核心实体拆解做这个项目之前我建议先画一个简单的业务流程图把“谁在什么角色下做什么事”理清楚。常见的角色有游客、注册用户、内容管理员、超级管理员。核心实体大概有用户表user注册用户、管理员都放这里通过role字段区分。风貌分类表category比如自然风光、历史人文、特色产业、村容村貌。风貌信息表scenery平台上展示的核心内容标题、封面图、正文、作者、状态、浏览量。评论表comment用户对风貌内容的评论。点赞表like_record记录谁给哪个内容点了赞防止重复点赞。动态公告表notice平台通知、公告信息。轮播图表banner首页轮播图维护。3.2 表结构设计要点我拿scenery表举个例子字段不能乱写。CREATE TABLE scenery ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 主键, title VARCHAR(100) NOT NULL COMMENT 标题, category_id BIGINT NOT NULL COMMENT 分类ID, cover_image VARCHAR(255) COMMENT 封面图URL, images TEXT COMMENT 多图可用JSON数组存, content LONGTEXT COMMENT 详细介绍, author_id BIGINT COMMENT 发布人ID, status TINYINT DEFAULT 0 COMMENT 状态:0草稿,1已发布,2下架, view_count INT DEFAULT 0 COMMENT 浏览量, like_count INT DEFAULT 0 COMMENT 点赞数, sort INT DEFAULT 0 COMMENT 排序权重, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;几个比较容易忽略的点charset要选utf8mb4因为用户评论和正文里很可能有表情符号utf8mb4才能正确存储。status字段一定要有发布/下架是最基础的内容管控逻辑。sort字段很多人会漏但它能实现管理员在后台拖拽排序不管前端是否展示先留着。images用TEXT存JSON数组是最省事的方案虽然不符合严格的范式但对这种展示类项目完全够用也能减少多表关联。点赞表要保证用户和内容不能重复点赞最原始的做法是unique keyCREATE TABLE like_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, target_id BIGINT NOT NULL, target_type TINYINT DEFAULT 0 COMMENT 0表示点赞风貌, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_user_target (user_id, target_id, target_type) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这样数据库层面就挡住了重复点赞。业务逻辑虽然要判断但数据库约束是底线。4. 核心功能拆解与代码落地4.1 后端项目分层与接口设计项目包结构我习惯这样分controller接收请求、返回结果service业务逻辑mapper数据库操作entity实体类dto前端传参对象和返回对象config配置类common统一返回结果、异常处理、工具类为什么要分层不是为了好看是为了可维护。比如评论功能controller里只做参数校验和调用service真正的业务逻辑放在service里这样后面加“评论需要审核”这个需求只需要改service不用动controller。统一返回结果非常重要。我通常定义一个Result类{ code: 200, message: success, data: {...} }前端不管是Vue还是小程序都按这个格式解析。只要能保证code为200就是成功其他都是失败前端可以减少大量判断。接口设计上先列一份清晰的API清单再写代码。比如POST /api/auth/login 用户登录POST /api/auth/register 注册GET /api/scenery/list 分页获取风貌列表GET /api/scenery/detail/{id} 获取详情POST /api/comment/add 发表评论GET /api/comment/list 查看评论POST /api/like/toggle 点赞/取消点赞GET /api/category/list 获取分类列表POST /api/admin/scenery/save 管理员保存风貌POST /api/admin/user/disable 禁用用户接口地址命名尽量用资源名不要用动词堆砌比如不要写/getAllScenery而是用GET /scenery/list。这种REST风格虽然不完全严格但已经足够毕设展示。4.2 风貌列表接口怎么写风貌列表是平台的首页核心必须做分页和条件筛选。用MyBatis-Plus会很简单public IPageSceneryVO getSceneryPage(SceneryQuery query) { PageScenery page new Page(query.getPageNum(), query.getPageSize()); LambdaQueryWrapperScenery wrapper new LambdaQueryWrapper(); wrapper.eq(Scenery::getStatus, 1) .eq(query.getCategoryId() ! null, Scenery::getCategoryId, query.getCategoryId()) .like(StringUtils.hasText(query.getKeyword()), Scenery::getTitle, query.getKeyword()) .orderByDesc(Scenery::getSort) .orderByDesc(Scenery::getCreateTime); return sceneryMapper.selectPage(page, wrapper); }这里有两点要注意。第一状态必须过滤。用户端不能看到未发布的草稿这是基础安全规则。第二条件构造器里eq的condition参数传一个boolean表达式MyBatis-Plus会在条件不成立时自动忽略这个条件避免了拼SQL的if地狱。这个写法到真实项目里也常见评委听了会觉得你有工程意识。视图对象VO不要直接把entity返回给前端。比如scenery表里可能有status、create_time这些字段用户端不一定需要而且字段多了响应体也臃肿。我会创建SceneryVO只保留id、title、coverImage、categoryName、viewCount、likeCount、createTime这些展示字段。4.3 登录与权限控制登录是绕不开的功能。毕业设计最常见的是JWT方案流程是用户提交用户名密码 - 后端校验 - 生成Token返回前端 - 前端后续请求带上Token - 后端拦截器解析Token并拿到用户信息。实现上我一般用jjwt库生成一个带过期时间的Token密码通过BCrypt加密存储。这里必须强调密码不能明文存数据库这是安全问题也是加分项。权限控制上我用自定义拦截器把需要登录的接口放到一个路径下比如/admin/然后在拦截器里判断是否存在合法Token。简单做法public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); // 解析token失败则返回401 // 成功则把userId放入request attribute return true; }如果是学生项目不一定要引入Spring Security它虽然强大但是配置复杂度高很容易把时间耗在过滤链配置上。用拦截器的方式你能讲清楚“认证”和“鉴权”两个概念就够了。真正需要做角色判断时再在方法上判断user.getRole()比如只有管理员才能访问后台接口。4.4 管理后台文件上传与富文本风采展示平台绕不开图片上传。我在后台提供一个上传接口接收MultipartFile保存到本地目录然后把访问路径返回给前端String fileName UUID.randomUUID().toString().replace(-, ) getExtension(file.getOriginalFilename()); String fileDir upload/images/; String realPath resourceProperties.getUploadPath() fileDir; File dest new File(realPath, fileName); file.transferTo(dest);这里我习惯自己生成文件名不要用用户上传的原始文件名避免路径穿越和中文乱码问题。原始文件名只能取扩展名这个是安全习惯。富文本编辑器后台可以集成wangEditor或者TinyMCE。注意富文本里的图片是base64还是URL如果图片多建议编辑器配置成上传图片返回URL不要把base64整段存进数据库否则数据库会迅速膨胀页面加载也会卡。4.5 小程序端从接口到页面小程序端我建议按“首页风采列表 - 分类切换 - 详情页 - 评论区 - 个人中心”来做。首页用scroll-view做滚动加载触底时调用下一页接口。这个分页交互几乎是所有内容类小程序的标准玩法必须熟练掌握。接口请求封装也简单就是uni.request或者wx.request封装一层const BASE_URL http://localhost:8080/api; function request(path, method, data) { return new Promise((resolve, reject) { uni.request({ url: BASE_URL path, method, data, header: { Authorization: uni.getStorageSync(token) || }, success: (res) { if (res.data.code 200) { resolve(res.data.data); } else { uni.showToast({ title: res.data.message, icon: none }); } }, fail: reject }); }); }登录在小程序里一般用微信登录但毕设场景里也需要让用户能模拟登录。最简单的方式是做一个“微信授权登录”和“用户名密码登录”都支持的方案。如果不想在小程序端做注册可以让小程序用户首次打开时创建游客身份操作评论或点赞前再引导登录。有一点我特别想提醒本地调试小程序时域名必须在小程序后台配置request合法域名。如果只是毕设演示可以在开发者工具里勾选“不校验合法域名”但如果要部署上线一定要配HTTPS域名。5. 实操过程中最容易踩的坑5.1 环境配置的坑很多项目跑不起来不是代码问题是环境问题。Java环境变量、Maven仓库、MySQL版本、端口占用每一环都能卡半天。我建议按这个顺序排查java -version 看Java版本如果是17却说用的SpringBoot 2.7兼容性没问题但如果用到某些低版本Java库可能会报错。mvn -v 看Maven配置确认settings.xml里的本地仓库路径是不是自己想要的。MySQL数据库启动后注意字符集如果创建表时没指定utf8mb4后续插入中文可能报错。端口8080被占用是本地开发最常见问题。Windows下用netstat -ano | findstr 8080找到进程或者在SpringBoot配置里改端口解决。5.2 前后端联调遇到跨域前后端分离后前端地址是localhost:8081后端是localhost:8080跨域问题跑不掉。SpringBoot里加一个跨域配置类就能解决Configuration public class CorsConfig { Bean public CorsFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); config.addAllowedOriginPattern(*); config.addAllowedMethod(*); config.addAllowedHeader(*); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); } }毕设阶段可以允许全部来源但你要能说清楚生产环境不会这么配置需要指定具体的域名白名单。这个细节都说出来评委就会觉得你不是只会调包。5.3 图片上传后前端访问不到这是最常见的问题。上传成功后你保存的可能是“upload/images/xxx.jpg”但前端访问的路径是“http://localhost:8080/upload/images/xxx.jpg”如果后端没有把本地目录映射成静态资源就会404。解决方式是在SpringBoot里配置资源映射Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath /); }同时注意Windows路径和Linux路径差异不要硬编码盘符。用配置文件把上传目录和对外访问前缀写成可配置项这样换环境时不用改代码。5.4 小程序里图片请求http报错小程序对网络环境限制很严格生产环境要求HTTPS本地调试如果没有关掉域名校验请求图片地址会出现“image is not allowed in current environment”之类的问题。处理办法是开发阶段在开发者工具工具栏勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”发布会话则必须让后端接口支持HTTPS。如果图片也存在本地需要后端配置HTTPS证书或反向代理。6. 常见问题速查答辩前必看6.1 老师常问的几个点为什么用SpringBoot和SSM有什么区别SpringBoot算是Spring生态的进一步封装内置Tomcat自动配置依赖让开发者更快起步。SSM需要自己配一大堆XMLSpringBoot把常见配置变成约定开发效率更高。MyBatis-Plus好还是MyBatis好毕设场景我推荐MyBatis-Plus它的BaseMapper提供了大量单表CRUD复杂查询自己写XML既能保证效率又能展示你写得来SQL。权限怎么做的用JWT 拦截器Token里带用户id和角色后台接口校验角色。遇到需要更细粒度的数据权限再按用户id过滤数据。图片存在哪里毕设通常放本地磁盘数据库只存相对路径对外通过静态资源映射访问。如果要考虑部署扩展可以换对象存储但核心流程不变。6.2 优化方向可以怎么做系统做完之后如果你想让项目更有区分度可以做这几个扩展接入ECharts在后台做“近7天访问趋势”和“各分类内容占比”图表。增加搜索历史、热点词汇统计。用Redis缓存热门列表减少数据库压力。在小程序端增加地图组件接入高德/腾讯地图展示乡村位置。如果和单片机方向结合可以加物联网模块把传感器数据接入后台展示。这些扩展不需要全部做挑一个你讲得最清楚、代码能跑通的加上去就比单纯完成CRUD要有辨识度。6.3 答辩时的项目讲解框架讲项目不要从开机页面开始讲太流水账。我建议按这个顺序一句话说明平台服务对象和核心价值给农村提供统一数字化风貌展示入口让游客和村民能高效获取内容。画模块图说清楚用户端、后台管理端、数据层之间的关系。挑一个最能体现核心难点的功能深入讲比如动态权限校验、分页查询、图片上传。展示能跑通的核心接口和数据库表。总结遇到的问题和怎么排查。7. 我的几点实操体会做这类项目最忌讳的是“背代码”而不是“懂设计”。如果你是自己从零写的那知识点肯定扎实如果你确实时间紧拿到参考代码也要把每个模块的调用关系说出来。我见过太多同学把代码跑通就以为完了结果答辩时一眼代码都不看PPT上放几个截图老师随便问一句“评论功能怎么实现防刷”就答不上来。这个项目我自己做的时候最大的感受是“内容展示类系统的核心不是功能多而是数据流清晰”。一个风貌从录入、审核、发布到被浏览、点赞、评论每一步都有状态和时间记录。把这条链理顺了你的系统就成功了一大半。最后分享一个小技巧在开发过程中每写完一个接口就用Postman或者Apifox测试一遍把请求参数、返回结果截图保存。这些文档不只是调试记录也是最后写论文和做答辩PPT的素材。真到了写论文阶段你会发现这些资料比看十篇模板都有用。