又到了课题选题的季节。“基于WEB的文学网的设计与实现”这条题目,我在带学生的这几年里反复见到,从课程设计到毕业设计都有它的身影。它不像电商系统那样满大街都是,也不像管理系统那样容易做得枯燥,天然带着内容平台的味道,改一改就能套用到博客、社区、资源共享站等多个方向。这篇文章我就把这个课题从选题逻辑到部署上线完整盘一遍,包括技术选型、数据库设计、核心功能实现、常见坑点,给正在做这个课题的朋友一份可以直接落地的参考。
1. 课题定位与整体设计思路
1.1 国内高校喜欢出这道题的原因
先说为什么这道题经久不衰。文学网本质是一个“内容发布 + 用户互动”的WEB应用,它的功能边界非常清晰:用户注册登录、作品发布编辑、分类浏览、搜索、收藏评论。这些功能几乎覆盖了WEB开发的所有基础知识点。
从教学角度讲,它比纯管理系统多了“内容展示”和“用户行为”两个维度,能训练到页面布局、数据关联、权限控制等更接近真实项目的技能。从答辩角度讲,文学网的需求扩张性很强,你可以做成简洁的阅读平台,也可以加连载管理、排行榜、阅读进度、敏感词过滤等高级功能,可上可下,适合不同水平的学生。
从评委视角看,他们最关心的不是你的界面有多花哨,而是你能否讲清楚“用户提交一个请求之后,数据是怎么流转的”。这条题目恰好能把前端、后端、数据库三者串成一条完整的链路,很容易展示项目深度。
1.2 功能模块怎么划分才合理
我见过太多人一上来就画十几张功能模块图,把后台管理、前台展示、会员体系、支付功能全塞进去,最后代码写不完。合理的划分方式应该是“先做骨架,再填血肉”。
站在实际交付的角度,我建议把系统拆成前台和后台两大块,前台面向普通游客和注册用户,后台面向管理员。
前台部分最核心的功能有四个:
- 用户模块:注册、登录、个人信息维护、密码修改
- 作品模块:作品列表、分类筛选、作品详情、章节阅读、作品搜索
- 互动模块:收藏/书架、评论、评分、点赞,这部分可根据工期选择性实现
- 个人中心:我的书架、我的评论、阅读历史
后台部分相对简单,一个完整的后台需要能管理用户(禁用/启用)、管理作品(审核/下架/删除)、管理分类(增删改查)、管理评论(删除违规内容)。
这里有个经验要分享:优先保证“作者发布作品—读者阅读作品”这条主线的闭环。很多同学把精力耗在后台的花哨图表上,结果前台连最基本的翻页阅读都做得不稳定,这是本末倒置。评委试的是你的系统好不好用,不是你的ECharts图表漂不漂亮。
1.3 技术选型之前想清楚的三件事
在确定用什么框架之前,有三个问题需要你先回答:
第一,这个项目是给谁用的?如果是课程设计结课,选你熟悉的、能讲清楚的技术栈即可;如果是毕业设计,建议选择考察价值更高的技术组合。第二,你手上有多少时间?只有两周的话,老老实实用单体架构 + 模板引擎;有两个月的话,可以考虑前后端分离 + 分布式部署。第三,你自己想从中学到什么?想熟悉后端业务逻辑,就把重心放在Spring Boot的服务层设计上;想积累工程经验,就多在部署、安全、性能优化上下工夫。
这三个问题直接决定了你后面的技术选型,也决定了你答辩的时候能撑住多深的追问。
2. 技术栈选型与项目架构搭建
2.1 不同技术方案的适用场景对比
技术选型环节,很多人的第一反应是“用最流行的”。实际上对于课题类项目,“合适”远比“流行”重要。
| 方案 | 技术构成 | 优点 | 缺点 | 适合人群 |
|---|---|---|---|---|
| 方案A:传统单体 | JSP/Servlet + JSTL + MySQL | 链路清晰,贴近教材 | 开发效率偏低,前后端耦合 | 基础薄、时间紧 |
| 方案B:经典SSM/SSH | Spring MVC + MyBatis + MySQL | 企业主流,简历友好 | 配置繁琐,学习曲线陡 | 想面试加分 |
| 方案C:Spring Boot + Thymeleaf | Spring Boot + MyBatis-Plus + MySQL | 开发快,配置少,资料多 | 模板和前端逻辑耦合 | 大多数首选 |
| 方案D:前后端分离 | Spring Boot + Vue + MySQL | 展示效果强,工程化程度高 | 开发量大,部署稍复杂 | 时间充裕、基础好 |
我带的学生里,90%以上最终选了方案C。原因是Spring Boot把Spring的配置简化到了极致,内嵌Tomcat避免了繁琐的服务器配置,Thymeleaf作为服务端模板引擎又能在页面中直接渲染数据,整个开发周期可以压缩到两到三周。对于以“完成课题”为第一目标的人来说,这是性价比最高的组合。
不过这里要提一句,如果你的目标是求职加分,方案D的前后端分离会让你在面试时有更多谈资,但代价是你要同时掌握Vue的工程化构建和接口联调。鱼和熊掌不可兼得,量力而行。
2.2 为什么推荐Spring Boot作为主框架
Spring Boot这几年几乎成了Java WEB项目的默认起点,市场占有率极高。它的核心优势在于“约定大于配置”的理念——框架帮你做了大量默认设置,你只需要关注业务代码。
对于文学网这个场景,Spring Boot有几个能力是极其对口的:
一是内嵌Tomcat,打包成可执行的JAR,一条java -jar命令就能跑起来,不再需要单独装Tomcat、配server.xml。这对环境配置能力偏弱的学生来说省了很多麻烦。
二是Starter机制,想连数据库就引入spring-boot-starter-jdbc,想处理JSON就引入spring-boot-starter-web,依赖管理由父POM统一锁版本,我见过太多新手因为手动引入不同版本的包导致冲突报错,Spring Boot把这些包袱全卸掉了。
三是Actuator和统一的异常处理,排查问题时能看到更清晰的错误链。文学网的日志排查、接口调试在这些机制的帮助下会高效很多。
当然,Spring Boot不是万能的,它在复杂分布式场景下也不轻松,但对课题项目来说,它绝对是“投入产出比最高”的选择。
提示:如果你的指导老师要求必须用JSP,那就不必强行Spring Boot了。JSP/Servlet依然是很好的教学框架,能让你对HTTP协议和请求分发有更深的理解。技术选型永远为“结课”和“答辩”服务,而不是为“个人偏好”服务。
2.3 数据库表结构设计:核心表与关键字段
文学网的数据模型是整个系统的地基。设计得好,后续功能开发是水到渠成;设计得不好,后期改表结构会让你改到怀疑人生。下面是核心数据表的参考方案。
用户表 design_user
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | BIGINT(20) | 主键,自增 |
| username | VARCHAR(50) | 登录名,唯一索引 |
| password | VARCHAR(100) | 加密后的密码,不要存明文 |
| nickname | VARCHAR(50) | 昵称,用于前端展示 |
| avatar | VARCHAR(255) | 头像路径 |
| role | TINYINT(1) | 角色:0普通用户,1管理员 |
| status | TINYINT(1) | 状态:0正常,1禁用 |
| create_time | DATETIME | 注册时间 |
密码字段务必预留长度。如果使用BCrypt加密,加密后字符串长度是60位,字段设计为20位的同学后期会被迫修改,这种低级错误非常影响答辩印象分。
作品表 design_work
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | BIGINT(20) | 主键 |
| author_id | BIGINT(20) | 作者ID,关联用户表 |
| category_id | BIGINT(20) | 分类ID |
| title | VARCHAR(100) | 作品标题 |
| description | TEXT | 作品简介 |
| cover | VARCHAR(255) | 封面图路径 |
| status | TINYINT(1) | 状态:0草稿,1连载中,2完结,3已下架 |
| view_count | INT(11) | 浏览量 |
| favorite_count | INT(11) | 收藏数 |
| create_time | DATETIME | 发布时间 |
| update_time | DATETIME | 最后更新时间 |
这里有个容易被忽视的点:author_id要建立索引。很多同学做查询时习惯WHERE id = ?,却忘了按作者查作品、按分类查作品这些高频查询场景。索引不是越多越好,但author_id和category_id在这个系统里一定是建议加的。
章节表 design_chapter
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | BIGINT(20) | 主键 |
| work_id | BIGINT(20) | 所属作品ID |
| title | VARCHAR(100) | 章节标题 |
| content | LONGTEXT | 章节正文 |
| chapter_order | INT(11) | 章节序号 |
| create_time | DATETIME | 发布时间 |
正文用LONGTEXT而不是TEXT,是因为小说章节动辄几千字,TEXT类型最多只能存65535字节,很容易超出限制。这个字段类型选错,上线之后就是数据写入静默失败,很阴险。
除了这三张核心表,还有评论表、收藏表、分类表。收藏表建议做成(user_id, work_id)的唯一索引,防止同一用户重复收藏同本书;评论表要存work_id和user_id,方便前台显示评论人和评论内容。
3. 核心功能实现与关键代码细节
3.1 用户注册登录:安全是底线
用户模块是所有WEB应用的入口,写不好后面全是坑。注册登录看似简单,实际涉及三个关键点:密码加密、会话保持、登录拦截。
密码存储一定要用BCrypt加密。Spring Security这样的重型安全框架需要引入大量配置,很多同学劝退。我推荐一个轻量方案:使用spring-security-crypto独立模块,它不强制走整个Security过滤器链,只提供加密工具类。
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-crypto</artifactId> <version>5.7.3</version> </dependency>注册时加密:
String encodedPassword = new BCryptPasswordEncoder().encode(password);登录校验时:
boolean matches = new BCryptPasswordEncoder().matches(rawPassword, encodedPassword);这套方案的好处是:密码即使被拖库,也无法反解出明文;同时BCrypt内部带随机盐,同一密码每次加密结果都不一样,能有效对抗彩虹表攻击。
会话保持我选择用Session而不是JWT。原因很简单:Session是服务端状态,便于随时强制下线某个用户;JWT虽然生来适合前后端分离和无状态服务,但课题项目通常用不到这种能力,反而要处理Token刷新、失效等额外复杂度,属于自我加戏。如果指导老师问“为什么不用JWT”,你可以从“系统规模小、Session足够且逻辑更简单”这个角度作答,这本身就是加分项。
登录拦截用一个HandlerInterceptor实现:
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getSession().getAttribute("loginUser") == null) { response.sendRedirect("/user/login"); return false; } return true; } }然后注册拦截规则,放行静态资源和登录注册接口,拦截其余需要登录的路径。这样就不用每个Controller重复写了,代码结构也清爽。
3.2 作品发布与富文本编辑:内容安全是重点
作品发布是文学网的核心动线。这里有两个实现层次:
基础层次是纯文本框提交,用<textarea>配合换行符转<br/>显示。优点是简单,缺点是不支持格式灵活性,写出来的章节像纯文本文件,阅读体验较差。
进阶层次是引入富文本编辑器。国内用得最多的是UEditor,但官方已停止维护很久了。我个人更推荐开源项目Editor.md(支持Markdown语法,正好适合文字创作者)或者wangEditor(轻量、文档全、集成简单)。
<link rel="stylesheet" href="/static/editor/css/editormd.min.css" /> <div id="editor"> <textarea style="display:none;" th:text="${chapter.content}"></textarea> </div> <script src="/static/editor/editormd.min.js"></script> <script> var editor = editormd("editor", { width: "100%", height: 640, path: "/static/editor/lib/", // 关闭HTML源码模式,防止XSS注入 htmlDecode: false, toolbarIcons: function() { // 只保留基础排版按钮 return ["bold", "italic", "quote", "|", "list-ul", "list-ol", "|", "link", "|", "preview", "fullscreen"]; } }); </script>富文本展示时有个安全细节千万注意:用户提交的内容是HTML或者Markdown,如果直接th:utext输出,等于把你网站的XSS漏洞拱手送人。正确做法是服务端做过滤,只允许白名单标签存在。
我一般会定义一个过滤工具类,把script标签、onclick/onerror等事件属性全部剥掉:
public static String cleanHtml(String content) { if (content == null) return ""; return content.replaceAll("(?i)<script.*?</script>", "") .replaceAll("(?i)on\\w+\\s*=\\s*\"[^\"]*\"", "") .replaceAll("(?i)on\\w+\\s*=\\s*'[^']*'", "") .replaceAll("(?i)javascript:", ""); }这并不是最严谨的防御方案,但对于课题项目来说已经足够体现你的安全意识。如果你能在答辩时主动说出“我对用户输入做了XSS过滤”,评委通常会眼前一亮。
3.3 图书阅读与书架收藏:用好关联查询
阅读页是文学网最核心的展示页面。当用户点击一本作品后,系统要展示作品详情、章节列表、评论区等丰富信息。我建议把“作品详情”和“章节列表”分成两个接口,避免单个页面数据量过大导致加载缓慢。
章节阅读页的实现不复杂:
@GetMapping("/chapter/{id}") public String chapter(@PathVariable Long id, Model model, HttpSession session) { Chapter chapter = chapterService.getById(id); Work work = workService.getById(chapter.getWorkId()); // 作品浏览量+1 workService.incrementViewCount(chapter.getWorkId()); // 查询上一章/下一章,实现翻页 Chapter prev = chapterService.getPrevChapter(chapter.getWorkId(), chapter.getChapterOrder()); Chapter next = chapterService.getNextChapter(chapter.getWorkId(), chapter.getChapterOrder()); model.addAttribute("chapter", chapter); model.addAttribute("work", work); model.addAttribute("prev", prev); model.addAttribute("next", next); return "reader"; }一个容易被忽略的需求是阅读进度。当用户读完第3章退出,下次进来应该还能接着第4章开始。实现方案是在收藏表或单独的表里记录用户和章节的对应关系,每次阅读时判断当前章节是否大于已读章节,如果是就更新。这个小功能在答辩时是很好的加分点,因为它展现了“用户视角”的思考。
书架/收藏功能对应收藏表,核心方法是“先查是否已收藏,再决定插入或删除”:
@PostMapping("/favorite") @ResponseBody public Result toggleFavorite(@RequestParam Long workId, HttpSession session) { User user = (User) session.getAttribute("loginUser"); Favorite existing = favoriteService.findByUserAndWork(user.getId(), workId); if (existing == null) { favoriteService.add(user.getId(), workId); return Result.success("收藏成功"); } else { favoriteService.remove(existing.getId()); return Result.success("已取消收藏"); } }这个接口记得用@PostMapping而不是@GetMapping,因为收藏操作会修改数据,从HTTP语义和安全性上都应该用POST。
3.4 搜索与推荐:看似简单实则巨大的功能
搜索功能在文学网里承担着“用户找书”的重任。最朴素的实现是SQL模糊匹配:
SELECT * FROM design_work WHERE title LIKE CONCAT('%', #{keyword}, '%') OR description LIKE CONCAT('%', #{keyword}, '%')这个写法在数据量小的时候没问题,但一旦作品量过万,LIKE '%关键词%'会全表扫描,响应速度肉眼可见地变慢。更严重的是,模糊匹配对中文分词不友好,搜“红楼梦”搜不到“红楼”。
进阶方案是引入全文检索引擎,比如Elasticsearch。但对课题项目来说,引入ES的运维成本太高,不推荐。
性价比最高的方案是:如果用的是MySQL 5.7及以上版本,可以在作品表上加全文索引:
ALTER TABLE design_work ADD FULLTEXT INDEX ft_title_desc (title, description);然后使用MATCH AGAINST查询:
SELECT * FROM design_work WHERE MATCH(title, description) AGAINST ('#{keyword}' IN NATURAL LANGUAGE MODE)这个优化足够应付答辩。如果你愿意做得更深入一点,还可以实现基于分类的热门推荐——按浏览量倒序取前10本,放到首页。对于课题项目,做到这个程度已经完全足够了。
4. 开发环境配置与部署上线
4.1 本地开发环境准备清单
开发文学网之前,先把开发环境搭好,这一步很多新手折在这里。我建议按下面的清单逐项确认:
- JDK 8或JDK 11:Spring Boot 2.x版本稳定的基础上,JDK 8完全够用,不建议直接上JDK 17,部分老依赖可能存在兼容性问题
- Maven 3.6+:项目依赖管理,IDEA自带Maven也可以
- MySQL 5.7+或8.0:数据库,建议直接在本地装8.0,字符集设置为utf8mb4
- Navicat或DataGrip:数据库可视化工具,不是必需的,但能大幅提升建表和调试效率
- IDEA 2022+:集成开发环境,社区版足够,无需破解旗舰版
- Redis(可选):如果只做基础功能缓存,就不需要;如果要做验证码、会话共享等功能,再考虑引入
提示:MySQL安装时务必勾选“Use Legacy Authentication”,否则默认的caching_sha2_password认证方式会导致某些版本的JDBC驱动连接报错。如果你已经安装了MySQL 8.0,可以在连接串后追加
?allowPublicKeyRetrieval=true&useSSL=false,解决连接被拒绝的问题。
4.2 Tomcat部署与Nginx反向代理
Spring Boot内置Tomcat,开发时可以一键启动。部署到服务器时有两种方式:
方式一:打包成JAR直接运行。在项目根目录执行:
mvn clean package -DskipTests生成的JAR文件在target/目录下,上传到服务器后:
nohup java -jar literary-web-0.0.1-SNAPSHOT.jar --server.port=8080 > app.log 2>&1 &这种方式简单直接,适合课程设计和个人项目。通过nohup可以让进程在SSH断开后继续跑,如果要开机自启,可以写成systemd服务。
方式二:打包成WAR部署到独立Tomcat。需要把Spring Boot的启动类继承SpringBootServletInitializer,并修改打包方式为war:
<packaging>war</packaging>然后把WAR丢到Tomcat的webapps/目录即可。这种方式的好处是可以用Tomcat的管理界面和下方的多个应用部署,但也多了一层维护成本。
对于一台服务器上同时跑多个项目的情况,我更建议用Nginx做反向代理。Nginx监听80端口,将不同域名或路径转发到不同的Spring Boot服务端口:
server { listen 80; server_name literature.example.com; location / { 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; } }这样做的附加好处是:Nginx可以托管静态资源(图片、CSS、JS等),减轻后端压力。在Nginx中配置:
location /static/ { alias /www/literature/static/; expires 7d; }图片资源不会再经过Java后端,访问速度快得多。这也是真实企业项目的常见做法,写进论文和答辩PPT里就是很好的“性能优化”亮点。
4.3 静态资源优化与页面加载提速
文学网的内容属性决定了它图片多、文字多。页面加载速度直接关乎使用体验,三个最有效的优化手段:
图片懒加载是必须的。作品列表页可能会有几十个封面图,用浏览器原生的loading属性实现最简单:
<img src="/cover/xxx.jpg" loading="lazy" alt="封面" />就一行属性,浏览器会自动在图片进入视口前才加载,首屏加载的请求数能减少60%以上。注意要给图片预留占位区域,否则懒加载会导致页面高度跳动。
其次是对CSS和JS做合并压缩。Spring Boot默认提供静态资源位置,把重复的公共样式抽到common.css,压成一行可以显著减少传输体积。现在的带宽普遍不是瓶颈,传输体积影响有限,但减少HTTP请求数量依然有效。
最后是整页缓存。Spring Boot中可以用简单的@Cacheable缓存热点数据:
@Cacheable(cacheNames = "hotWorks", key = "0", unless = "#result == null") public List<Work> getHotWorks() { return workMapper.selectHotWorks(); }首页的一批数据缓存10分钟,数据库的压力会小很多。如果答辩时被问到“数据量大时怎么优化”,能答出这几个点,你的工程素养就体现出来了。
5. 常见问题排查与项目验收避坑指南
5.1 开发中的高频报错与解决方法
这个项目我做过太多遍了,踩过的坑也基本固定。这里整理几个最高频的问题,建议收藏备用。
问题一:数据库乱码。插入中文后查出来是问号或乱码。90%的情况是数据库连接串缺少字符集参数:
spring: datasource: url: jdbc:mysql://localhost:3306/literature?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai同时确认数据库表的字符集是utf8mb4:
ALTER TABLE design_work CONVERT TO CHARACTER SET utf8mb4;问题二:明明登录成功却还是被拦截。这是典型的Session和重定向路径问题。通常是登录成功后把用户写进了Session,但拦截器放行的路径和Controller返回的路径不一致。比如Controller里返回redirect:/work/list,但实际上应该放行/work/list,拦截器却只放行了/index。排查时先在拦截器的preHandle里打印请求路径,直观看到底哪个路径被拦截了。
问题三:文件上传失败或路径不对。封面图上传是文学网常做的功能。Spring Boot默认的单文件大小限制是1MB,封面图很容易超限。需要在配置中调整:
spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB另外注意文件存的路径最好是绝对路径,用System.getProperty("user.dir") + "/upload/"这种形式,不要用相对路径,因为相对路径在不同启动方式下指向的位置不一样。你本地跑可能是项目根目录/upload,打成JAR包放到服务器上再启动,相对路径就可能变成服务器的当前目录,图片就404了。
问题四:页面渲染时报“Neither BindingResult nor plain target object for bean name”。这是Thymeleaf里用了th:object="${work}",但Controller没有往Model里放进work对象。检查Controller的GET请求方法是否把对象添加进了Model。
5.2 答辩前必须做好的安全检查
答辩演示时,最尴尬的就是评委顺手测试一下你的系统安全性,结果当场翻车。三个安全点必须在演示前逐项确认:
SQL注入防护。使用MyBatis的#{}占位符是安全的,它最终会被预编译为?,不会拼接到SQL语句中。但如果你在${}里直接拼接了用户输入,就极有可能被注入。排查所有XML或注解SQL,除了排序字段等极少数场景,一律用#{}。
XSS防护。用户提交的评论、作品简介、昵称,这些内容展示到页面上时,如果用th:utext输出,用户输入的<script>alert(1)</script>就会直接执行。正确做法是全部使用th:text输出,Thymeleaf会自动做HTML转义。如果是富文本内容,必须保留HTML格式,那就用服务端白名单过滤后再输出。
文件上传安全。如果做了头像和封面上传,需要校验文件类型。最好的方式是检查文件的真实内容头(Magic Number),而不是只看后缀名:
// 只允许jpg/png/gif String magicNumber = getFileHeader(file); if (!magicNumber.startsWith("FFD8FF") && !magicNumber.startsWith("89504E47") && !magicNumber.startsWith("47494638")) { throw new BusinessException("不支持的文件格式"); }5.3 从“能跑”到“好用”的提升方向
如果核心功能已经完成,还有余力的话,下面几个方向可以继续打磨,每一个都能在答辩时增加亮点。
方向一是阅读记录同步。当前章节阅读进度存储到服务器而不是浏览器,这样用户换设备也能继续阅读,体现对用户体验的思考。
方向二是数据导出的定时任务。管理员可以按周导出新增作品和新增用户的统计数据。使用Spring的@Scheduled定时任务,配合EasyExcel导出Excel报表,只花半天时间就能完成。
方向三是日志切面。用一个@Aspect拦截所有Controller请求,统一记录访问日志和耗时,既能帮助你定位性能瓶颈,又能在答辩时说“我通过日志埋点对系统进行了监控分析”。
方向四是接口限流,比如防止某个IP频繁刷评论或刷收藏,用简单的拦截器加计数就能实现,这是高并发话题的入场券。
6. 项目亮点提炼与个人经验总结
文学网这个课题做完,你要能在答辩时清晰地回答一个问题:我做的这个系统,和别人的有什么不同?
如果你只做了CRUD,评委可能觉得平淡无奇。但如果你能拿出这三个亮点,整场的氛围会截然不同。
第一,阅读体验上的细节。连续阅读时章节之间的自动翻页、记住上次阅读位置、字体大小调节,这些体验绝不是代码量的堆砌,而是一种“站在用户角度思考”的工程素养。你可以在答辩时打开两个竞品网站,现场对比说明你的交互设计。
第二,性能优化层面的探索。首页数据缓存、静态资源加速、SQL索引优化,这些虽然是小规模的优化手段,但恰恰是评委最爱问的领域。“项目上线后有大量用户访问怎么办”,这个问题的标准答案就在这里。
第三,安全防护意识。密码加密、SQL注入、XSS过滤、上传校验,这些内容让项目从“能用”升格为“安全可靠”。哪怕你只做了最基本的防护,也要在PPT里单独标注出来,因为它代表你有没有形成安全意识。
最后再分享一个实际答辩的小技巧:提前准备三组测试数据,第一组是全新的空系统登录数据,第二组是普通用户的完整操作数据,第三组是管理员的后台管理数据。许多答辩翻车不是功能坏了,而是现场演示时临场找账号密码、临时填数据,显得系统非常不稳定。把所有账号密码和演示路径提前打印在一张纸上,放在鼠标旁边,比什么都管用。
这个系统做完还能怎么扩展?加上Markdown编辑器可以面向技术博客,加上音频文件管理就成了听书平台,加上多租户概念就是可运营的文学SaaS。以文学网为起点,你收获的绝不仅仅是一个能跑的WEB项目,而是一套完整的内容平台设计方法论。这也是它作为课题能持续多年被选用的根本原因。动手去做吧,把每一行代码都写明白,把每一个选择都讲清楚,这会成为你简历里最扎实的一个项目。