JavaWeb毕业设计实战:社交媒体平台从选型到实现全指南 做JavaWeb方向的毕业设计社交媒体平台是个非常讨巧的选题。它不像“学生管理系统”“图书管理系统”那样答辩时容易被评委追问业务价值也不像纯电商平台那样流程复杂、演示成本高。一套带发布动态、评论、点赞、关注、私信功能的社交媒体平台既能覆盖JavaWeb开发的核心知识面又能在答辩时讲出完整的业务闭环代码量控制在两三千行左右就能有不错的完成度。这篇帖子我会从选题思路、技术选型、数据库设计、调试运行到常见坑位完整过一遍给准备做同类项目的同学一份能直接落地的参考。1. 项目整体设计与思路拆解1.1 为什么社交媒体平台适合当毕设题目先说说选题这件事。毕设题目的核心诉求就三个好做完、好演示、好答辩。社交媒体平台恰好三个都占。好做完体现在功能边界清晰。你可以把它拆成用户、内容、互动、消息四个大模块每个模块再做细分成小功能点。用户模块做注册登录和个人资料内容模块做动态发布和图片上传互动模块做点赞评论和关注消息模块做私信聊和通知。这样做的好处是开发过程中你可以一个模块一个模块地推进不会出现需求蔓延、做到最后收不了尾的情况。好演示体现在交互直观。评委打开你的项目注册账号、发条带图片的动态、给别人点赞评论整个过程不需要任何业务背景就能看懂。这比做一套复杂的进销存系统或者规则引擎演示起来有天然优势因为用户能直接感知你做了什么。好答辩体现在技术点好讲。社交媒体平台天然涉及登录态校验、文件上传、分页查询、一对一多对多关系建模、事务处理这些高频面试考点。评委问你“这个项目有哪些难点”时你随便拎出来一个点都能展开讲三五分钟。1.2 第一版功能范围怎么圈定我见过很多同学一上来就想复刻微博全部功能这是做毕设的大忌。版本规划一定要有优先级概念我建议按这个顺序来做第一版只做闭环核心功能注册登录、发布文字动态、动态列表展示、点赞取消点赞、评论、关注取关、个人主页。这七个功能足以支撑起一个完整可演示的系统。第二版再补体验类功能图片上传、私信、未读消息数、搜索用户、话题标签。这些功能不影响主流程但是能显著提升作品的完整度。第三版才是加分项热门动态排行、用户推荐、在线聊天(WebSocket)、后台数据统计。这类功能做得出来是亮点做不出来也不影响及格。我自己做的时候是按这个节奏来的第一版用了一周第二版用了四天第三版做了一部分。核心经验是——先把主流程跑通再去碰锦上添花的东西。很多人挂在第一版就是因为一开始就陷进了“私信要带表情、评论要带图片、动态要带定位”这种需求泥潭。1.3 这套方案的适用人群与场景这套选题方案特别适合两类人一类是JavaWeb基础过关但项目经验为零的同学做这个能系统性地把SSM或Spring Boot栈走一遍另一类是基础一般但想拿个不错成绩的同学因为这个项目的资料多、社区讨论多、遇到问题好搜答案不会像做冷门题目那样卡住半天找不到解决方案。如果你是对JavaWeb完全不熟的新手我的建议是先别急着动手做花两天把下面这套最小知识链补上HTTP请求处理流程浏览器发请求到Tomcat再到Controller到Service到Mapper再到数据库、Session和Cookie的会话机制、MySQL的建表和关联查询、简单的HTML表单和AJAX传值。这四个点搞清楚做这个项目就不会再有“不知道从哪里下手”的感觉。2. 技术选型的关键权衡2.1 从JSPServlet到Spring BootMyBatis路线JavaWeb方向现在有两条主流技术路线选哪条要看你们学院的要求。如果指导老师不限定技术栈我强烈建议直接用Spring Boot Spring MVC MyBatis MySQL这套组合。很多学校大三是教JSPServlet的但这套技术栈在企业里已经基本退居二线。Spring Boot把配置简化到极致内嵌Tomcat、自动装配、Starter机制能让你的开发效率提升一倍不止。而且现在市面上这套组合的资料是最多的搜索引擎随便一搜就是几百篇教程踩坑之后很容易找到解决方案。如果你的学校硬件要求必须用JSPServlet那也别慌。你可以用Servlet写Controller代码用JSP写视图层用JDBC或者MyBatis访问数据库代码会多一些但项目结构是一样的。我的建议是搞清楚一个原则不管用哪套MVC思想不变变的只是实现工具。理解了这个换技术栈只是语法工作。2.2 前端方案模板引擎还是前后端分离这是很多同学纠结的点。我的判断标准很简单时间紧不紧、前端底子行不行。时间充足且你愿意投入用前后端分离Vue Element UI Axios。前端工程化是现在的行业主流答辩时提一句“前端采用Vue构建通过Axios与后端进行RESTful JSON交互”就很有加分效果。但代价是你得额外维护一套Node.js环境、Vue脚手架工程还要处理跨域问题调试成本明显更高。时间一般或者前端不熟就用模板引擎Spring Boot官方推荐的Thymeleaf或者JSP。用Bootstrap jQuery Thymeleaf的写法能让你把几乎所有精力放在后端逻辑上。我自己做这个项目用的就是Thymeleaf加原生JavaScript页面效果虽然不如前后端分离那么精致但胜在链路短、调试快、出问题好排查。这里给个折中方案核心页面首页动态流、个人主页用模板引擎直接渲染互动操作点赞、评论、关注用AJAX局部刷新技术。这样既保证开发效率页面交互也比整页刷新舒服得多。2.3 版本选型的那些坑技术选型的时候最容易吃暗亏的就是版本兼容问题。我把我实测下来稳定的组合直接列出来给你JDK 8 或 JDK 11Spring Boot 2.7.x对这两个版本支持最好别上来就装JDK 17配Spring Boot 2.x会有兼容问题Spring Boot 2.7.x这个版本稳定且教程多MyBatis Spring Boot Starter 2.3.x要和Spring Boot 2.x配套MySQL 5.7 或 8.08.0要注意驱动类名和连接参数的变化Maven 3.6.3以上IDEA 2022以上Tomcat不用单独装Spring Boot内嵌了注意如果你用了JDK 17还想硬配Spring Boot 2.7启动时会遇到各种反射相关报错网上资料也少别赌这个。要么老老实实JDK 8要么上Spring Boot 3但Spring Boot 3对JDK 17和Jakarta EE要求更高新手不推荐。2.4 数据库设计需要提前规划数据库选MySQL这一点没什么好争议的主要是要不要上Redis的问题。我建议第一版别碰Redis把数据全部放MySQL里靠索引和分页扛住查询压力。答辩时如果被问“性能方面有没有考虑优化”你可以说“当前阶段访问量不大MySQL配合索引已经满足需求后续可以引入Redis做热点缓存和排行榜”。这样既诚实又给自己留了扩展空间。3. 核心功能模块与数据库建模3.1 六大核心表的关系梳理这个项目的数据模型说复杂也复杂说简单其实就是六张表。我先画个整体关系框架然后逐张说设计要点。用户表(user)是核心它和动态表(post)是一对多和评论表(comment)、点赞表(like_record)、关注表(follow)、私信表(message)都有关系。动态表跟评论表、点赞表也是一对多。关注表比较特殊它是一张自关联表存的是用户和用户之间的关注关系。在建表之前建议先花一小时理清关系别急着敲SQL。我当时就是没想清楚关注表怎么写第一版设计成了在用户表里加一个follow_ids的字符串字段用逗号分隔ID。功能跑通之后问题就来了——查某个用户关注了谁只能用like去模糊匹配数据一多必崩。后来改成标准的多对多中间表整个世界清爽了。3.2 用户表和动态表的字段设计用户表在毕设这个场景下不用设计得太臃肿够用就行字段类型说明idbigint主键自增usernamevarchar(50)登录名唯一索引passwordvarchar(100)加密后密文别存明文nicknamevarchar(50)昵称默认和用户名一致avatarvarchar(255)头像图片路径biovarchar(255)个人简介create_timedatetime注册时间动态表是内容的核心载体字段类型说明idbigint主键user_idbigint发布人ID外键索引contentvarchar(1000)文字内容imagesvarchar(1000)图片路径多张用逗号分隔like_countint点赞数冗余字段comment_countint评论数冗余字段create_timedatetime发布时间点赞数和评论数加冗余字段是社交媒体项目的常见做法。如果每次都实时count查询数据量大了性能会很难看。维护方式很简单帖子被点赞成功就把like_count加一取消点赞就减一。这也是个可以讲的亮点说明你考虑了查询性能。3.3 互动与消息模块的设计细节评论表要支持楼中楼的话加一个parent_id字段指向父评论ID父评论ID为0表示是顶层评论。后端查出来之后在Java代码里做分组把子评论挂到父评论下面后再传给页面展示。点赞表用联合唯一索引防止重复点赞是必须的。同一用户对同一条动态只能有记录一条这靠数据库层的唯一约束兜底比单纯在业务代码里判断要可靠得多。关注表同理follower_id和followee_id加上唯一索引防止一个用户对同一个人重复关注。还要在业务代码里校验一下不能自己关注自己。私信表相对简单sender_id、receiver_id、content、is_read、create_time查会话列表时按发送者和接收者的组合分组取最新一条即可。这里给一段核心建表SQL作为参考CREATE TABLE user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码密文, nickname varchar(50) DEFAULT NULL COMMENT 昵称, avatar varchar(255) DEFAULT NULL COMMENT 头像路径, bio varchar(255) DEFAULT NULL COMMENT 个性签名, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE post ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL, content varchar(1000) DEFAULT NULL, images varchar(1000) DEFAULT NULL, like_count int NOT NULL DEFAULT 0, comment_count int NOT NULL DEFAULT 0, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE user_like ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL, target_type tinyint NOT NULL DEFAULT 1 COMMENT 1动态 2评论, target_id bigint NOT NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_user_target (user_id, target_type, target_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE follow ( id bigint NOT NULL AUTO_INCREMENT, follower_id bigint NOT NULL COMMENT 关注者ID, followee_id bigint NOT NULL COMMENT 被关注者ID, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_follow (follower_id, followee_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;工程上细节我会在实际开发中逐一说。表结构设计这块提一句最后的心得字段类型宁可大一点也不要卡着边界。varchar(50)写个二十个字的昵称够用content的varchar(1000)对三百字的动态也绝对够用。但如果你把等级、状态这类字段的类型设计成tinyint过两天需求要加个“置顶级别10级”就得回去改表了。4. 实操过程与核心环节实现4.1 环境准备与工程创建第一步先把环境装好。JDK 8从Oracle官网下载就行Maven 3.6.3从Apache官网下载解压后在IDEA的Settings - Maven里把Maven home directory指过去再把User settings file指向你自己的settings.xml。IDEA里把JDK版本配置到Project Structure的Project SDK。创建工程有一种稳妥的方式去Spring Initializr网页上选Spring Boot 2.7.18、Java 8依赖先勾选Spring Web、MyBatis Framework、MySQL Driver、Lombok生成压缩包后用IDEA打开。比在IDEA内置的Spring Initializr插件里配置要快还不容易出网络问题。工程结构我是这样规划的src/main/java/com/example/social ├── SocialApplication.java // 启动类 ├── controller/ // Controller层接收请求 ├── service/ // Service层业务逻辑 ├── mapper/ // MyBatis的Mapper接口 ├── entity/ // 实体类 ├── interceptor/ // 拦截器登录校验 ├── config/ // 配置类 └── common/ // 工具类、统一返回结果 src/main/resources ├── application.yml // 配置文件 ├── mapper/ // MyBatis的XML文件 └── static/upload/ // 上传图片目录 src/main/webapp └── WEB-INF/templates/ // 页面文件JSP或Thymeleaf4.2 核心配置与项目跑通pom.xml里最关键的是这几组依赖的版本对齐parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version /parent dependencies !-- Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Thymeleaf模板选JSP可替换成spring-boot-starter-tomcat的jsp支持 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-thymeleaf/artifactId /dependency !-- MyBatis -- dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.2/version /dependency !-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependenciesapplication.yml的配置是重头戏几个容易踩坑的地方我先标出来server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/social?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 你的密码 thymeleaf: cache: false servlet: multipart: max-file-size: 10MB max-request-size: 10MB mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.social.entity configuration: map-underscore-to-camel-case: true启动类加一个MapperScan注解扫描Mapper接口SpringBootApplication MapperScan(com.example.social.mapper) public class SocialApplication { public static void main(String[] args) { SpringApplication.run(SocialApplication.class, args); } }配置完了先别急着写业务就写一个最简单的Hello接口测一下链路通不通Controller返回一个字符串浏览器访问localhost:8080/hello能看到输出就算基础环境没问题。4.3 注册登录与登录态校验的实现用户注册的逻辑很简单接收用户名密码校验用户名是否已存在密码做加密处理插入数据库user表。密码加密千万别用MD5。MD5是消息摘要算法不是为密码存储设计的撞库攻击几分钟就能破解常见弱口令。推荐用BCryptSpring Security的crypto包里直接能用// 加密 String encoded BCrypt.hashpw(rawPassword, BCrypt.gensalt()); // 校验 BCrypt.checkpw(inputPassword, storedPassword);如果你不想引Spring Security全家桶单独引spring-security-crypto这个依赖就行代码量很小。登录态我用Session来做。登录成功后把用户对象放进SessionhttpSession.setAttribute(loginUser, user);每个需要登录才能访问的接口在进入Controller之前用拦截器统一校验。写一个LoginInterceptor实现HandlerInterceptorpreHandle方法里判断Session里有没有用户没有就重定向到登录页public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); Object loginUser session.getAttribute(loginUser); if (loginUser null) { response.sendRedirect(/login); return false; } return true; } }然后在WebConfig里注册拦截器并配置放行路径Configuration public class WebConfig implements WebMvcConfigurer { Autowired private LoginInterceptor loginInterceptor; Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns(/**) .excludePathPatterns( /login, /register, /, /post/list, /post/detail/**, /user/public/**, /static/**, /upload/**, /error ); } }放行路径这块要特别小心静态资源JS/CSS/图片如果不放行页面加载会全花用户头像访问接口不放行图片全裂。我第一版就是把/upload/**忘了放行排查了快半小时才找到问题。Controller层拿当前登录用户可以用一个简单的工具方法从Session取值或者用一个CurrentUser注解加HandlerMethodArgumentResolver参数解析器。毕设维度第一种就够用第二种是加分项。4.4 发布动态与图片上传发布动态的接口接收文字内容和图片文件列表。图片上传的核心是把浏览器传来的MultipartFile写到本地磁盘目录然后把访问路径存进数据库对应字段。PostMapping(/post/publish) public String publish(RequestParam(content) String content, RequestParam(value images, required false) MultipartFile[] images, HttpSession session) { User loginUser (User) session.getAttribute(loginUser); Post post new Post(); post.setUserId(loginUser.getId()); post.setContent(content); // 处理图片上传 if (images ! null images.length 0) { ListString paths new ArrayList(); for (MultipartFile file : images) { if (file.isEmpty()) continue; String originalName file.getOriginalFilename(); String ext originalName.substring(originalName.lastIndexOf(.)); String fileName System.currentTimeMillis() _ new Random().nextInt(10000) ext; String savePath UPLOAD_DIR fileName; file.transferTo(new File(savePath)); paths.add(/upload/ fileName); } post.setImages(String.join(,, paths)); } postService.publish(post); return redirect:/; }图片存储路径建议配成绝对路径比如D:/social/upload/然后给这目录做静态资源映射。这需要给网上搜到一个很常见的坑就是文件存到了项目内部目录重新部署就丢。所以把上传目录放到代码目录之外是最稳的做法Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file:D:/social/upload/); }4.5 点赞、关注与事务边界点赞的Service方法值得写一下它涉及两个数据表的写操作user_like表插入记录、post表的like_count加一。这两个操作必须放在一个事务里要么都成功要么都失败。Transactional public void like(Long userId, Long postId) { // 先查是否已点赞防止重复 UserLike existing likeMapper.findByUserAndTarget(userId, 1, postId); if (existing ! null) return; UserLike like new UserLike(); like.setUserId(userId); like.setTargetType(1); like.setTargetId(postId); likeMapper.insert(like); postMapper.increaseLikeCount(postId); }关注和取消关注同理follow表插入或删除记录时注意是不是要维护user表里的关注数粉丝数字段。建议在user表里加follow_count和fans_count冗余字段把count数存起来列表页直接取数避免每个用户都去关联查询。4.6 分页查询的实现方式首页动态流不可能一次查全量数据分页是必须的。MyBatis加PageHelper是毕设里最省事的方案在Maven引入pagehelper-spring-boot-starter然后在查询前直接PageHelper.startPage(pageNum, pageSize)后面跟的查询自动被拦截加分页SQL。// Controller里接收pageNum和pageSize PageHelper.startPage(pageNum, pageSize); ListPostVO postList postMapper.findFeed(userId); PageInfoPostVO pageInfo new PageInfo(postList);页面里用Thymeleaf遍历postList底部做上一页下一页的链接就行。PageInfo里封装了总页数、当前页、总记录数等信息直接用。这套分页方案要注意尽量别在代码里先查了list再翻页那样PageHelper不会生效。查询条件要在startPage之后、第一次查询之前确定好。5. 常见问题与排查技巧实录做这个项目踩坑是必然的我把实际操作中遇到的典型问题整理成一份排查手册按出现频率排序。你把这部分收藏起来出了问题先来这里翻一遍。5.1 启动阶段的问题启动报错Access denied for user rootlocalhost (using password: YES)应用启动直接挂原因十有八九是数据库密码不对或者账号没有远程访问权限。先检查application.yml里用户名密码再进MySQL执行类似于授权语句确保root能本地登录。启动报错Failed to configure a DataSource: url attribute is not specified这个问题常见于没有配置application.yml或者application.properties里的spring.datasource.url。注意Spring Boot启动时如果找不到数据源配置会直接报错不是因为代码写错了就是配置没找到。项目能启动但访问页面404启动成功说明Spring容器没问题404大概率是Controller路径写错或者视图解析不到。先确认你访问的URL和GetMapping路径完全一致再确认Thymeleaf页面文件放在正确目录下。Spring Boot里Thymeleaf默认的页面目录是src/main/resources/templates/放在static下是访问不到的。5.2 数据库层面的问题插入中文乱码中文乱码是JavaWeb的老大难问题。做一个全链路排查数据库连接URL带没带characterEncodingutf8、数据库表的字符集是不是utf8mb4、页面请求的编码是不是UTF-8。有一环不对就会乱码。实测下来最容易漏的是创建数据库时没指定字符集。执行下面的语句确保数据库、表、字段三级都是utf8mb4CREATE DATABASE social DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;如果已经建好库了可以改掉默认字符集ALTER DATABASE social CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; ALTER TABLE post CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;Invalid bound statement (not found): xxxMapper.xxx这个意思是MyBatis找不到Mapper接口对应的SQL语句检查三处XML文件的namespace是不是写成了Mapper接口的全限定名、XML的id和接口方法名是否一致、application.yml里的mapper-locations是不是能匹配到XML文件所在目录。JDBC连接MySQL时报CLIENT.PLUGIN_AUTH错误MySQL 8.0的驱动包和5.7不一样你还在用com.mysql.jdbc.Driver连MySQL 8.0肯定报错。改成com.mysql.cj.jdbc.Driver同时URL里加serverTimezoneAsia/Shanghai。5.3 前端交互与部署的问题图片上传成功但页面加载不出来图片路径对不对、磁盘目录存在不存在、静态资源映射配置了没有这三个问题按顺序排查。文件存储路径建议用绝对路径访问路径用相对路径存库避免IP端口变化导致路径失效。AJAX请求拿到的是401或者重定向到login登录拦截器把AJAX请求给拦了。Session过期或者未登录时拦截器返回重定向AJAX拿到的是login页面的HTML。处理方式拦截器里判断请求头X-Requested-With是不是XMLHttpRequest是的话返回状态码401或者JSON让前端根据状态码跳转登录页。页面样式全丢CSS加载出来是纯文本静态资源没有正确映射检查addResourceHandlers的注册还要确认浏览器控制台的Network里CSS请求的路径常规静态资源放src/main/resources/static/下。5.4 排查思路的经验总结这里分享一个总原则从外往里查。先看浏览器Network里请求有没有发出去、返回状态码是多少再看Controller有没有收到参数、Service打印的日志是什么最后才怀疑Mapper和SQL的问题。不要一上来就翻代码绝大多数问题出在配置和环境上代码逻辑反而简单。另外推荐一个很实用的排查技巧遇到看不懂的异常把完整堆栈信息复制到搜索引擎搜英文原文看前三行。别自己翻译成中文搜或者只看最后一行MyBatis或Spring的异常嵌套很深最开始的Caused by才是根因。用表格快速归类常见问题方便你排查定位异常现象最可能原因快速解决Access denied for user账号密码或权限不对核对连接配置和MySQL授权中文乱码URL或表字符集不对全链路改成utf8mb4Mapper方法找不到namespace或id写错核对XML与接口方法对应页面404Controller路径或页面目录不对核对路径到具体类去看图片加载404静态资源映射漏配检查addResourceHandlers端口被占用本地已有程序占用8080改server.port或kill进程Could not open JDBC ConnectionMySQL服务没启动检查MySQL服务和3306端口6. 给即将动手的你们几句实在话我做完这个项目最大的感受是毕设最难的从来不是技术而是把需求定清楚、把节奏排好。技术上的东西你写代码时自然会遇到遇到的问题越多答辩时越有东西讲。我答辩的时候评委问我“项目里最复杂的部分是什么”我把点赞防重的唯一索引、事务边界、图片上传静态资源映射这几个点一讲气氛一下就对了。做这个项目还有一个额外收获它就是面试时Java后端“项目经验”的一个合格雏形。把这段经历写进简历面试官问业务场景、技术选型、遇到的问题你都能答得上来自家项目里的实际情况比背八股文强得多。如果你现在刚开始框架还没搭先把今天整理的配置部分跑通然后再动手写注册登录。后面真做到功能集成时欢迎来讨论具体问题。这个项目的扩展空间很大等你的第一版跑通之后再谈Redis缓存、WebSocket在线提醒和热门推荐算法也不迟。