Java个人博客系统毕业设计全解析:架构、代码与避坑指南
简介:一套基于Java的个人博客系统毕业设计完整交付包,面向计算机相关专业毕业生及Java Web初学者,针对性解决毕业设计从选题、系统开发到论文答辩的全流程资料缺失问题。资源涵盖项目报告、答辩PPT、源代码、数据库文件与部署教程视频,压缩包整体约178.52MB。项目采用Servlet、JSP、JavaBean等后端技术,按MVC模式拆分业务逻辑、数据处理与界面展示,配合MySQL等关系型数据库及JDBC交互,并辅以HTML、CSS、JavaScript和Bootstrap、jQuery等前端框架;报告部分包含需求分析、系统设计、模块划分等内容,源码中可查看控制器、服务层、持久层与前端视图的具体实现,部署视频则引导完成环境配置、数据库导入与服务器启动。此外还提供答辩PPT和系统界面截图,便于演示与复盘。目前已有1347人学习下载,适合需要完整项目参照、快速上手Java Web实操训练的读者。
1. 基于Java的个人博客系统毕业设计:源码包里不只有代码
很多同学拿到这种 zip 的第一反应是解压、扔进 IDEA、按 F5,结果花掉三个晚上都起不来。这套基于 Java 的个人博客系统毕业设计,捆绑了项目报告、答辩 PPT、源代码、数据库脚本和部署视频,本质上不是要你读代码,而是要你在一周内凑齐“能演示、能答辩、能交差”的完整交付物。它适合两类人:一类是 Java 基础还不稳、需要现成骨架做二次开发的,另一类是系统已经写完但缺报告和答辩材料、急着补齐交付物的。搞清楚包里每样东西怎么配合,比急着启动更重要。
2. 技术栈与核心设计:再老的代码也要先盘明白架构
2.1 前台展示与后台管理:一条业务线分两半
个人博客系统不等于“一个博客页面”。几乎所有基于 Java 的毕设博客都拆成前台和后台两条线:前台是访客看的东西——文章列表、文章详情、分类导航、评论;后台是博主自己用的东西——登录、写文章、管理分类、审核评论。判定一套博客源码靠不靠谱,先看 Controller 里是不是把/admin/开头的路径单独拎出来。拎出来了,说明作者在设计时真的考虑过权限问题;没拎出来,那八成是几个页面堆在一起,答辩时老师问一句“怎么防止普通用户删文章”你就卡住。
前台和后台的代码规模也不一样。前台页面看着多,但逻辑薄,大部分是查询和分页;后台页面看着少,但逻辑重,涉及登录校验、数据校验、状态流转。看源码时不要按文件数量判断工作量,报告里项目功能模块划分应该按“前台展示 + 后台管理 + 数据库设计”三段去写,这是答辩 PPT 最常用的页数结构。理解了这条分界线,你再打开项目报告看目录,会发现它的功能概述、需求分析、系统设计三章,讲的就是这套划分逻辑。
2.2 五张表撑起一个系统:表结构设计与建表 SQL
这种规模的毕设项目,数据库表一般四到六张,五张是标配:用户表、文章表、分类表、评论表,再加一张标签表。很多老代码里文章和标签是多对多关系,需要中间表,但绝大多数毕设为了控制答辩复杂度,要么砍掉标签功能,要么只用分类不用标签,所以你会发现源码里的表可能比预期少,这不算缩水,是“够用就好”的设计取舍。我在给学弟改这类项目时,一般先删掉用不到的字段,让表和代码一一对应,而不是留着字段不写逻辑,答辩时一问一个准。
打开数据库脚本文件,你会看到类似下面的建表语句,注意字符集要选utf8mb4,不是utf8:
-- 用户表:只存登录凭证和角色,个人资料字段可后续扩展 CREATE TABLE `user` ( `id` INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键', `username` VARCHAR(50) NOT NULL UNIQUE COMMENT '登录名', `password` VARCHAR(64) NOT NULL COMMENT '密码,MD5加盐后的密文', `nickname` VARCHAR(50) DEFAULT '' COMMENT '前台显示昵称', `role` TINYINT DEFAULT 1 COMMENT '1=普通用户 2=管理员', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; -- 文章表:正文用 LONGTEXT,标题加普通索引即可 CREATE TABLE `article` ( `id` INT AUTO_INCREMENT PRIMARY KEY COMMENT '文章主键', `user_id` INT NOT NULL COMMENT '作者ID,关联user.id', `category_id` INT DEFAULT NULL COMMENT '分类ID,关联category.id', `title` VARCHAR(200) NOT NULL COMMENT '文章标题', `content` LONGTEXT NOT NULL COMMENT 'Markdown或HTML正文', `status` TINYINT DEFAULT 1 COMMENT '1=已发布 0=草稿', `view_count` INT DEFAULT 0 COMMENT '浏览量', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY `idx_user_id` (`user_id`), KEY `idx_category_id` (`category_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章表'; -- 分类表:字段少,但排序字段很重要 CREATE TABLE `category` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(50) NOT NULL COMMENT '分类名', `sort` INT DEFAULT 0 COMMENT '排序权重,数字越小越靠前' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分类表'; -- 评论表:设计 is_approved 字段,后台审核就靠它 CREATE TABLE `comment` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `article_id` INT NOT NULL COMMENT '被评论的文章ID', `user_id` INT NOT NULL COMMENT '评论人ID', `content` VARCHAR(500) NOT NULL COMMENT '评论内容', `is_approved` TINYINT DEFAULT 0 COMMENT '0=待审核 1=已通过', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, KEY `idx_article_id` (`article_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论表';这段 SQL 里有几个设计点答辩时会用到:一是role字段区分管理员和普通用户,比单独建一张权限表简单且够用;二是comment表用is_approved做审核标记,前台列表只查is_approved = 1的记录;三是表之间不建物理外键,只在应用层维护关联关系,这样写起来省事,删除文章时也不用担心外键约束挡路。如果用的是 MyBatis-Plus 这类工具,它可以根据实体类自动生成类似的建表 SQL,但毕设项目我建议直接用现成的.sql脚本,少一层工具依赖就少一个翻车点。
2.3 为什么选 Spring Boot + MyBatis:答辩老师只问三件事
技术选型是项目报告里最容易被挑毛病的部分,但也是最好准备的。现在的 Java 毕设博客系统,八成以上是 Spring Boot + MyBatis(或 MyBatis-Plus)+ MySQL,少数老项目用 SSM 甚至 SSH。答辩老师问技术选型,翻来覆去就三个问题:为什么不用 SSH、为什么用 MyBatis 不用 JPA、Spring Boot 相比 Spring MVC 省了什么配置。回答思路很固定:SSH 的 Struts 配置繁琐、拦截器体系复杂,Spring Boot 的自动配置和内置 Tomcat 能把部署成本降到最低;MyBatis 手写 SQL 可控性强,分页和连表查询的优化空间比 JPA 大;至于 JPA 的 Hibernate,学习曲线陡,不适合课程设计周期。
这套组合还有一个隐性好处:招 Java 工程师的岗位需求里写的基本都是 Spring Boot + MyBatis,答辩时顺势说一句“这套技术栈贴近企业实际开发”,比单纯吹自己功能多要有说服力。不过 java 基础薄的同学要注意,别在 PPT 里写“微服务”“分布式”这类词,一旦老师追问你负载均衡和缓存一致性,你会当场露馅。技术上守住“单体应用 + 标准三层架构”就够了,报告里的技术可行性分析也从这三层展开:表现层用 Thymeleaf 或 JSP,业务层用 Service 接口隔离,持久层用 MyBatis 映射 SQL。
3. 从解压到跑通:环境版本、数据库导入和配置三件套
3.1 环境版本先对齐:JDK 8、Maven 3.6、MySQL 8 别乱升
很多人在这一步就把时间耗光了,原因不是代码有问题,而是环境版本不匹配。这套老项目最常见的技术组合是 JDK 1.8 + Maven 3.6.x + MySQL 5.7 或 8.0 + IDEA 2020 以上版本,Tomcat 直接用 Spring Boot 内置的即可,不需要单独安装。有个血泪经验:JDK 17 虽然能跑大部分 Spring Boot 2.x 项目,但很多老代码里的javax.servlet依赖需要额外加--add-opens参数才能启动,对不懂 JVM 参数的新手来说就是灾难。老老实实装 JDK 8,配置JAVA_HOME和MAVEN_HOME环境变量,比什么技巧都管用。
IDEA 导入项目时,选Import Project而不是直接 Open,Maven 会自动读取pom.xml并下载依赖。如果你的 Maven 是 IDEA 自带的,注意settings.xml里的本地仓库路径,默认会在 C 盘堆出一大堆.jar文件,空间紧张会导致下载到一半失败。我一般会把本地仓库改到 D 盘或专用数据盘,然后在settings.xml里配阿里云镜像,这两个改动能让依赖下载时间缩短一大半。Maven 第一次构建时,右下角会有进度条,别急着写代码,等 BUILD SUCCESS 出现再继续。
3.2 初始化数据库:拿到 sql 文件后先做这三步
打开数据库脚本后不要直接双击运行,先用记事本或 IDEA 看一眼文件头部,重点确认三件事:字符集声明是不是utf8mb4、开头有没有CREATE DATABASE语句、里面有没有DROP TABLE IF EXISTS。如果脚本里没有建库语句,就自己先在 Navicat 或命令行里建一个库,库名要和后面application.yml里的连接串保持一致。常见的做法是建库叫blog_db,然后执行导入。
命令行导入是最不容易出错的,Windows 和 Linux 通用:
# 先登录 MySQL,密码输入时不会显示 mysql -u root -p # 在 MySQL 内部执行建库,库名按脚本要求来 CREATE DATABASE IF NOT EXISTS blog_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 退出后用 mysql 命令直接导入整个 SQL 文件 mysql -u root -p blog_db < /path/to/blog_db.sql导入完成后,用 Navicat 随便打开一张表,执行几条最基础的增删改查语句,确认引擎没毛病。这一步能试出两件事:一是.sql文件是否和你手里的数据库版本兼容,二是确认 root 账号密码是否足够复杂。MySQL 8 默认的密码认证插件是caching_sha2_password,老项目主流的 MySQL 驱动版本很可能只支持mysql_native_password,这就是为什么很多人在最后一步报错Public Key Retrieval is not allowed的原因,后面避坑章节再细说。
3.3 三个必改配置参数:端口、时区和密码
数据库导入了,代码也打开了,启动前先打开src/main/resources/application.yml(或application.properties),把参数核对一遍。老项目的配置文件里经常藏着上一任学生改到一半的残留值,你不改它,它就让你在晚上十一点的宿舍里对着一堆红字发呆。我一般会先全局搜localhost、3306、password这三个词,把所有可能改漏的地方找齐。
server: port: 8080 servlet: context-path: /blog # 访问路径带 /blog,部署后前端资源要对应改 spring: datasource: url: jdbc:mysql://localhost:3306/blog_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true username: root password: 改成你自己的密码 driver-class-name: com.mysql.cj.jdbc.Driver mvc: view: prefix: /WEB-INF/jsp/ # 老项目用 JSP 时配这个 suffix: .jsp mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.blog.entity configuration: map-underscore-to-camel-case: true # 数据库下划线自动映射为驼峰属性 logging: level: com.blog.mapper: debug # 打印 SQL 有助于排错,部署时改成 info配置里最容易被忽略的是serverTimezone=Asia/Shanghai,没有这个参数,MySQL 8 会报时区错误;其次是allowPublicKeyRetrieval=true,没有它,连接可能直接失败或被安全策略拦下。context-path决定了浏览器地址栏里的路径,如果你访问不到页面,第一反应不应该是改代码,而是看看这个前缀是不是和你输入的一致。logging.level.com.blog.mapper=debug是救命配置,它能让你在控制台看到每条 SQL 的执行情况,排查“查不到数据”“数据没更新”这类问题时特别好用。
4. 核心代码怎么改:登录、CRUD、拦截器和分页查询
4.1 Controller 层:先分清返回视图和重定向
打开源码后不要急着搜“bug”,先把包结构过一遍。标准的 Java Web 三层架构表现层会有controller或web包,业务层叫service,持久层叫mapper或dao。这个分层就是项目报告里“系统架构设计”那一章的素材,也是答辩时老师看代码最先扫的地方。Controller 层的代码风格在老项目里通常长这样:方法返回字符串,配合 ModelAndView 或 Model 传参。
@Controller @RequestMapping("/user") public class UserController { @Resource private UserService userService; @PostMapping("/login") public String login(String username, String password, HttpSession session, Model model) { User user = userService.login(username, password); if (user == null) { // 登录失败,回到登录页并携带错误标记 model.addAttribute("error", "用户名或密码错误"); return "login"; } session.setAttribute("loginUser", user); if (user.getRole() == 2) { // 管理员跳后台首页 return "redirect:/admin/index"; } return "redirect:/"; } }这段代码的逻辑核心是userService.login()返回的 User 对象是否为 null,而不是直接拿密码做字符串比较,密码校验被封装在 Service 层。返回"redirect:/admin/index"是让浏览器发第二次请求,地址栏会变化;返回"login"则是服务端直接渲染视图文件。新手最容易改错的地方是分不清这两个返回方式,导致表单提交后刷新页面又重复提交一次。改成前后端分离的同学要注意,这里没有返回 JSON,答辩老师如果问“接口和页面怎么分离的”,你要能说清楚当前这套是服务端渲染的老方案。
4.2 Service 层:事务注解与状态字段的配合
Service 层是这套系统里最值得抄作业的地方,因为增删改查的模板就这么几种,看会了就能套用到所有模块。文章发布的流程比较典型:前台草稿箱可以存未发布内容,后台点发布才把status字段从 0 改成 1。评论审核也一样,前台提交的评论默认is_approved=0,后台审核通过才置为 1。这两个业务场景都是靠状态字段流转,而不是删数据或加数据,答辩时这属于业务逻辑设计的亮点。
@Service public class ArticleServiceImpl implements ArticleService { @Resource private ArticleMapper articleMapper; @Override @Transactional(rollbackFor = Exception.class) public boolean createArticle(Article article, List<Integer> tagIds) { if (article.getStatus() == null) { article.setStatus(0); // 默认草稿 } int rows = articleMapper.insert(article); // 如果还要保存文章和标签的关联关系,在这里批量插入 return rows > 0; } @Override public IPage<Article> pageArticles(long current, long size, Integer categoryId) { Page<Article> page = new Page<>(current, size); QueryWrapper<Article> wrapper = new QueryWrapper<>(); wrapper.eq("status", 1); // 前台只展示已发布 if (categoryId != null) { wrapper.eq("category_id", categoryId); } wrapper.orderByDesc("create_time"); return articleMapper.selectPage(page, wrapper); } }@Transactional注解是最容易被忽略的,加了它,方法内任何一步抛出异常,前面的插入操作都会回滚,避免出现“文章正文没插进去,标签关联却多了一堆脏数据”的情况。QueryWrapper是 MyBatis-Plus 的构造器,用wrapper.eq("status", 1)替代手写 if 拼 SQL,能有效防止 SQL 注入,答辩时主动提这一点,老师会认为你有安全意识。注意wrapper.eq里的字符串是数据库字段名,不是实体类属性名,如果你把category_id写成categoryId,运行时不报错但查询结果为空,这种问题最坑。
4.3 登录拦截器:答辩老师最爱追问的权限控制
权限控制是个人博客系统毕设里少有的“非增删改查”功能,也最容易成为答辩的加分项。前台部分页面需要登录才能评论,后台所有管理页面必须管理员才能访问,如果把权限判断写在每个 Controller 方法里,代码会非常啰嗦。标准做法是写一个 HandlerInterceptor,在请求进入 Controller 之前做统一检查,这也是 Spring Boot 拦截器的经典用法。
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); User loginUser = (User) session.getAttribute("loginUser"); if (loginUser == null) { // 未登录,重定向到登录页,带来源路径便于登录后跳回 String contextPath = request.getContextPath(); response.sendRedirect(contextPath + "/user/login"); return false; } return true; } }光有拦截器还不够,要让 Spring Boot 认识它,需要一个配置类来注册。注意路径匹配的粒度:后台的登录页本身不能拦,否则任何人都进不去;但后台的其它功能页面全部要拦。
@Configuration public class WebConfig implements WebMvcConfigurer { @Resource private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns("/admin/**") .excludePathPatterns("/user/login", "/user/logout"); } }这里有个隐藏很深的坑:如果你把后台静态资源也放在/admin/static/**下,拦截器会把 CSS 和 JS 请求一起拦住,页面样式全丢。我一般建议把静态资源放在/static/**全局路径下,后台页面模板单独走/admin/templates/**,这样拦截器的路径配置一眼就能看懂。答辩时老师常问“拦截器和过滤器有什么区别”,一句话回答:过滤器是 Servlet 规范里的,拦截器是 Spring MVC 里的,拦截器能拿到 Handler 对象,能做更细粒度的方法级别控制。
4.4 分页查询:一套 Page 模板所有列表通用
博客列表、后台文章管理、评论管理,全都需要分页。老项目有手写 LIMIT 加计算总页数的,工作量大且容易算错。用 MyBatis-Plus 的 Page 对象加 IPage 返回值,是目前最常见的做法。上面 4.2 里的pageArticles已经展示了查询侧的分页,这里补充一个后台列表的写法:查询条件多一个status可选参数,用来筛草稿和已发布文章。
@RequestMapping("/admin/article/list") public String list(@RequestParam(defaultValue = "1") long pageNum, @RequestParam(defaultValue = "10") long pageSize, @RequestParam(required = false) Integer status, Model model) { Page<Article> page = new Page<>(pageNum, pageSize); QueryWrapper<Article> wrapper = new QueryWrapper<>(); wrapper.orderByDesc("create_time"); if (status != null) { wrapper.eq("status", status); } IPage<Article> pageResult = articleMapper.selectPage(page, wrapper); model.addAttribute("pageResult", pageResult); return "admin/article_list"; }要记得在 MyBatis-Plus 配置里加分页插件,否则selectPage返回的数据总数永远是 0 或者直接翻车。配置方式是在 MyBatis 配置类或配置文件中注册PaginationInnerInterceptor。新来的同学经常忘掉这一步,然后对着“明明查出来了但总页数不对”的现象怀疑人生。分页插件的原理是拦截 SQL,自动拼接LIMIT并执行一条COUNT(*)查询,所以你的 Mapper 接口方法返回类型必须是IPage,不能是List。
5. 避坑排查:从导入到部署最容易翻车的 5 个坑
5.1 启动即报 Invalid bound statement:Mapper.xml 没被打进包
现象:IDEA 启动时报Invalid bound statement (not found): com.blog.mapper.UserMapper.selectLogin,但 Mapper 接口里方法和 XML 里看起来都没问题。
原因:Maven 构建时没有把src/main/resources/mapper/*.xml文件打包进去,或者mybatis.mapper-locations路径配错。IDE 在编译时只处理 Java 文件,XML 不在默认处理范围内,所以报错的是运行时而不是编译时。
解决:先在pom.xml的<build>节点确认有没有配置 resources 资源过滤;再把application.yml里的mapper-locations: classpath:mapper/*.xml核对一遍。最笨但有效的验证方法:在项目编译后的target/classes目录里翻一下,mapper文件夹是否存在。不存在就把 XML 文件手动复制进去再启动,能跑就说明是构建配置问题。常见做法是修改 pom 的 resources 配置,让 Maven 把 XML 一起打包。
5.2 数据库连接报时区错误:MySQL 8 的 UTC 不买账
现象:启动报The server time zone value '�й���ʱ��' is unrecognized,或者The server time zone value 'CST' is unrecognized。
原因:MySQL 8 默认时区未显式配置,JDBC 驱动拿不到合法时区。MySQL 5.7 时代不查时区也能连,升级到 8.0 后这事就成了硬性要求。
解决:改application.yml中 jdbc url,末尾加serverTimezone=Asia/Shanghai。如果你连的是自己的本地库,也可以在 MySQL 命令行执行SET GLOBAL time_zone = '+8:00'。两个方法二选一,我一般改配置文件,因为部署到服务器时数据库环境你控制不了。注意 URL 里的中文参数不要用非标准字符,Asia/Shanghai是标准写法,别写成GMT+8,有的驱动版本不认。
5.3 JSP 页面 404:Spring Boot 内置 Tomcat 的经典翻车点
现象:项目能启动,首页也能访问,但点进任意一个用户中心页面就 404,日志里没有异常堆栈。
原因:老项目用 JSP 做视图层,但 Spring Boot 用spring-boot-starter-web时默认内置 Tomcat 的 JSP 支持路径和你预期的WEB-INF/jsp不一致。如果打成 jar 包运行,JSP 文件在 jar 内部,Tomcat 默认不解析这个路径。
解决:本地 IDEA 调试时,确认application.yml里spring.mvc.view.prefix和suffix配置正确,且src/main/webapp/WEB-INF/jsp目录存在。如果要打包部署,把 Spring Boot 应用改成 war 包,放到外部 Tomcat 的webapps目录下,JSP 才能正常解析。答辩演示时尽量用 IDEA 直接跑,不要现场演示 jar 包启动,这个坑不好解释。
5.4 Maven 依赖下载到一半卡死:镜像和本地仓库换掉再谈其他
现象:IDEA 底部 Maven 面板一直转圈,jar 包列表里很多依赖显示红色,BUILD FAILURE提示无法解析spring-boot-starter-web:jar:2.x.x。
原因:默认 Maven 中央仓库在海外,下载速度取决于网络状况,而且断点续传能力很差,一卡就整个任务重来。这不是代码的问题,是环境的问题。
解决:在 Maven 的settings.xml配置阿里云镜像,把<mirror>指向https://maven.aliyun.com/repository/public。同时检查本地仓库路径,如果 C 盘空间不足,把<localRepository>改到 D 盘指定目录。改完配置后,IDEA 里执行mvn clean compile,耐心等一次全量下载。以后新建仓库或切换分支,就不会再被这种破事折磨。
5.5 端口被占用:8080 被别的进程占了
现象:启动日志最后一行显示Web server failed to start. Port 8080 was already in use.,但项目代码没毛病。
原因:本机跑过别的 Spring Boot 项目、Skype、或者某个不知名后台进程占用了 8080。
解决:最快的方法是把application.yml里的server.port改成 8090 或 8081,改完刷新页面就行。第二个方法是在命令行执行netstat -ano | findstr :8080,查到 PID 后去任务管理器结束进程。我一般建议直接改端口,而不是跟占用进程硬刚,因为有些系统进程的端口你是杀不掉的,为了毕设去动系统进程不值得。
6. 部署与答辩验证:让系统在别人电脑上也能跑
6.1 Maven 打包:jar 和 war 怎么选
打包之前先看pom.xml里<packaging>节点。如果是war,打包结果放到 Tomcat 的webapps目录,访问路径是http://服务器IP:8080/包名;如果是jar,直接java -jar启动,访问路径是ip:8080。JSP 项目尽量走 war,省去一堆视图解析的麻烦。
mvn clean package -DskipTests # 产物在 target 目录下,部署时用 nohup 挂后台 nohup java -jar blog-system.jar > blog.log 2>&1 &-DskipTests是跳过单元测试,普通毕设项目没有测试用例,不跳过也没事,但留着这个参数能少一次编译时间。启动后立刻看blog.log,日志只输出到文件,控制台看不到调试信息。
6.2 云服务器部署:宝塔面板加 Nginx 三步走
第一次部署到云服务器的人,别直接在裸 Linux 上敲命令,用宝塔面板能省一大半时间。安装 Java、MySQL、Nginx 三个软件后,把 war 包传进 Tomcat 的 webapps 目录,或者把 jar 包放到任意目录用 nohup 启动。Nginx 配置一个反向代理,把 80 端口转发到后端接口地址,让用户不用输入端口号就能访问。后端【接口打不开】99% 是安全组没放行端口,去云服务商控制台检查,这个和代码无关。
6.3 答辩前两天的自检清单
最后两天不要加新功能,专心做回归验证。我给自己列了一张表,按顺序过一遍:前台列表能否正常分页、文章详情能否正确渲染、登录后会话能否保持、后台新增文章能否出现在前台、评论能否审核通过、修改密码后旧 session 是否失效。每一项都是演示时会被老师点到的基础功能,有一项不过关,整个系统的完成度评价都会受影响。
我过去带过的一个学弟,答辩展示到一半,后台新增文章按钮点了没反应,老师当场皱眉。下来一查,是评论区和文章列表共用了同一个数据库连接池,连接数被耗尽。从那以后,我养成了一个习惯:答辩前一周,关闭所有断点调试,只保留logging.level.com.blog.mapper=debug,把每个功能从浏览器里完整点一遍。这个习惯救过我很多次,也希望帮到你。
本文还有配套的精品资源,点击获取