学 JavaEE 的人大概都经历过这个阶段:Servlet 会写了,JSP 也认识了,JDBC 连 MySQL 也能跑通了,但真要独立做点什么,又觉得无从下手。这次开一个《JavaEE33-博客系统案例实战》系列,就是想彻底解决这个问题——从零开始撸一个博客系统,第一期先把项目搭起来,再把博客列表这个核心页面做出来,让数据库里的文章真正“晒”到浏览器上。这个项目适合刚学完 JavaEE 基础、准备做完整项目但还不想碰 Spring Boot 的同学,也适合想回顾 Servlet + JSP 经典开发链路的老手。整个系列会往后一直迭代:列表、详情、发布、编辑,最后加一个简单的后台,所以你看不到什么一步到位的炫技,更多的是工程上最稳、最能被复现的做法。
顺带说一句,很多人纠结“学完 Servlet 和 JSP 到底能干什么”,博客系统就是答案。它算不上大项目,但足够完整:列表、详情、分页、搜索、发布、编辑、删除,几乎把 CRUD 应用里会遇到的场景都覆盖了。这篇先把地基打好,后面几期都在这个基础上盖楼。
1. 为什么是博客系统,以及“列表先行”的选型逻辑
1.1 博客系统为什么适合当 JavaEE 练手项目
我在带人入门 JavaEE 的时候,很少推荐学生管理系统、图书馆管理系统这类项目,原因很简单:这些系统太重业务规则,技术点反而单薄。博客系统的业务模型非常直接——文章是核心实体,用户看文章、写文章、改文章,整个过程没有复杂的权限和状态流转,却覆盖了 Web 开发的完整链路。
你可以把它理解成一个“包罗 CRUD 的标准样本”:博客列表是查询,文章详情是单条查询,发布文章是新增,编辑删除是更新和删除。再加上分页、分类筛选、按时间排序、阅读量统计这些周边功能,一个博客系统能把 JavaEE 开发中的高频技能全部串起来。而且博客系统天然是 Web 形态,用户能看到自己的劳动成果——把文章发布出去,刷新页面就能看到效果,这种即时反馈对学习非常有用。
这期的目标是“博客列表”,也就是把数据库里的文章展示到首页。别小看这个功能,从用户视角看,进入博客第一眼看到的就是文章列表,没有列表,详情、发布、后台都无从谈起;从技术视角看,列表背后涉及查询、排序、分页、渲染这几件事,把列表做透了,后续功能就是在这个骨架上做加法。
1.2 先做列表、不做登录,背后的两层原因
我见过很多新手做项目,上来就先把登录注册做完,注册、登录、验证码、改密码折腾一个星期,结果主页还是空的,心态先崩了。博客系统为什么不先做登录?两个原因。
第一,从需求优先级看,博客的第一用户是“读者”,不是“作者”。一个博客系统上线第一天,最需要保证的是用户能打开首页、看到文章。登录注册只是作者写文章时需要的门禁,属于后台功能,优先级天然靠后。先做一个能让内容“被看见”的闭环,比先做一个空壳系统更能验证技术方案是否可行。
第二,从教学节奏看,列表功能涉及的是最核心的“请求→处理→渲染”链路:浏览器发起请求,Servlet 接收参数,调用 Service 查库,拿到数据放进 request 域,转发到 JSP 渲染。这条链路跑通,JavaEE 的骨架你就真正掌握了。登录功能无非是在这条链路前面加一层 Session 判断,本质并没有新增多少技术含量。
说白了一句话:先学会“把数据晒出来”,再考虑“让谁进来写”。
1.3 技术选型:Servlet + JSP + MyBatis + MySQL,为什么不用 Spring Boot
这个系列叫 JavaEE,那技术栈我就尽量贴近经典 JavaEE 路线:Servlet 4.0 + JSP + MyBatis + MySQL + Tomcat 9 + Maven。没有用 Spring Boot,是刻意为之。Spring Boot 的自动配置帮开发者省掉了太多麻烦,但也把底层逻辑藏得太深。你用它写一个 Controller 接收参数、返回数据,十分钟能跑通,可一旦出了问题,你不知道请求是怎么进到容器、Servlet 容器和 Spring 容器是什么关系、过滤器在哪里生效。
用经典 Servlet + JSP,你得自己配置 web.xml,自己处理请求参数,自己决定视图怎么转发。这个过程不是折磨,是在帮你建立 Web 应用的底层心智模型。以后你切到 Spring Boot,会发现框架帮你做的其实就是这些事,只是自动化了。
MyBatis 是我在“纯 JDBC”和“Spring Data JPA”之间做的折中。纯 JDBC 写数据访问太啰嗦,一个查询要写连接、写 PreparedStatement、写 ResultSet 映射,重复代码一大堆;MyBatis 保留了 SQL 的可控性,同时把样板代码收掉,是最适合这个阶段的持久层框架。下面用一张表说明选型思路:
| 组件 | 选择 | 理由 |
|---|---|---|
| Web 容器 | Tomcat 9.0.x | 支持 Servlet 4.0,稳定,报错信息友好 |
| 持久层 | MyBatis 3.5.x | SQL 可控,学习成本低,贴近 JDBC 语义 |
| 数据库 | MySQL 5.7 / 8.0 | 普及率高,环境容易搭 |
| 构建工具 | Maven | 依赖管理和打包标准化,大厂主流 |
| 前端技术 | JSP + JSTL | 服务端渲染,和 Servlet 天然衔接 |
如果你之后想上 Vue3 做前后端分离,这套后端项目也不必推翻:把 JSP 换成返回 JSON 的接口,Servlet 把数据写进 response 的 Writer 里,前端用 axios 去拿,核心的查询、分页逻辑仍然可以复用。到系列后期我会单独讲这个改造思路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 工程骨架搭建:从空目录到能在 Tomcat 里跑起来
2.1 开发环境版本:JDK、Tomcat、MySQL 的匹配关系
很多新手在这个环节就卡住了,原因不是不会写代码,而是版本之间“拧着劲”。先说一个最常见的版本坑:Tomcat 10 和 Tomcat 9 的包名不一样。Tomcat 10 开始把 javax.servlet 换成了 jakarta.servlet,网上流传的老教程大多数写的是 javax.servlet.*,代码照着敲完部署到 Tomcat 10 上直接 ClassNotFoundError。我这个项目用的是 Tomcat 9.0.x + JDK 8 或 11 + MySQL 8.0,这是目前最稳妥也最普及的组合。
JDK 我建议直接用 11,太老的环境会遇到一些新库不支持的问题,太新的 JDK 搭配老 Tomcat 也可能有小毛病。MySQL 用 8.0 没问题,但要注意驱动类名是 com.mysql.cj.jdbc.Driver,不是老版本的 com.mysql.jdbc.Driver,连接 URL 还需要带上时区参数 serverTimezone=Asia/Shanghai,否则会报时区错误。
IDE 这块,有人用 IDEA,有人用 Eclipse,也有人用 VS Code。我这次开发用的是 VS Code,配 Java Extension Pack,插件装好后 Java 的编译、调试、Maven 支持都能用。VS Code 里配 JavaEE 环境,核心是装好 “Extension Pack for Java”,再配合“Tomcat for Java”插件把 war 包部署到 Tomcat。这个组合对内存占用比 IDEA 友好很多,我自己长期在用。
2.2 Maven 工程结构:目录与依赖配置
项目里建的 Maven 工程要打包成 war 包,因为最终要放进 Tomcat 运行。目录结构这样建:
code复制blog/
├── pom.xml
└── src
└── main
├── java
│ └── com/blog
│ ├── dao/
│ ├── entity/
│ ├── servlet/
│ └── util/
├── resources
│ ├── mybatis-config.xml
│ └── mapper/
│ └── ArticleMapper.xml
└── webapp
├── WEB-INF/
│ └── web.xml
├── css/
└── list.jsp
明确一下各层职责:entity 放数据库表对应的实体类,dao 放数据访问接口,util 放常量、日期工具之类的工具类,servlet 放控制层。新手最常犯的错误是啥都往 Servlet 里塞——查数据库的代码写在 Servlet 里,封装数据的代码也写在 Servlet 里,一个类几百行。分层不是形式主义,分开之后你会发现每个类的职责清晰了,排查问题也容易了。
pom.xml 里的依赖是另一个重灾区。贴一下核心依赖配置:
xml复制<dependencies>
<!-- Servlet API,Tomcat 提供,打包时不需要包含 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<
