资讯动态

Java课程设计实战:Servlet+JSP+JDBC实现记事簿记账本通讯录系统

发布时间:2026/10/9 11:02:27 来源:尧图企业网站定制
简介这是一份基于Java开发的综合型个人信息管理源码包将记事簿、备忘录、通讯录和记账本整合为一体可作为Java Web学习者的实战练习项目、课程设计或毕业设计的参考蓝本。压缩包共101个文件大小约2.75MB其中包含41个JSP页面用于动态界面展示配套Java类与Class文件处理后台逻辑CSS/JS/GIF/PNG等资源完善前端样式与交互SQL文件提供数据库表结构与初始数据DOC/PDF文档则对系统设计思路和实现细节做了说明整体目录划分明确便于按模块查阅。项目典型地采用MVC分层架构涉及Servlet/JSP请求处理、JDBC数据库访问、用户认证与权限控制、附件上传下载等关键功能数据库端涵盖联系人、备忘录、财务记录等业务表设计能帮助开发者理解从数据建模到前后端联调的全流程。目前已有311人学习下载结合源码与文档读者可以快速掌握Java Web开发常见技巧并在此基础上扩展提醒服务、云同步等实用功能。1. 为什么这个「记事簿记账本通讯录」Java 项目值得拆开看如果你是带着「找一份能跑起来的 Java Web 课程设计源码」的目的点进来的我直接说结论这个名为“java记事簿管理系统_备忘录管理系统_通讯录_记账本-源码数据库论文or文档.zip”的压缩包是典型的 Java 全栈课程设计级项目Servlet JSP JDBC 的技术栈一个工程里同时实现了记事簿、备忘录、通讯录和记账本四块功能。对于正在做毕设、准备实训答辩、或者想补一遍 Java Web 基础链路的人来说它的价值在于「麻雀虽小但整条数据流是完整的」——从前端页面到 Servlet 控制层再到 JDBC 落库你能在几百个文件里看到一套传统 Java Web 项目真实的样子。我拆这类压缩包的习惯是先把 class 文件名过一遍这个包里upBean.class、db.class、Request.class、files.class后缀已经透露了包结构Bean 封装数据、db 管连接、Request 处理请求转发加上CssAdmin.css、myweb.css、down.css三套样式说明后台管理界面和前台展示界面是分开做的。这类资源适合两类人一是刚学完 Java 基础、想见识 Servlet JSP 数据库三者怎么协作的初学者二是手里项目缺数据库脚本、缺论文文档、想快速凑齐一套可演示系统的毕业生。下文我会从技术栈拆解开始给你一条能照着复现的完整路线连坑都替你标好。2. 技术栈先立住从 class 文件名反推 MVC 分层与 JDBC 数据流2.1 这套工程怎么对应上 MVCBean、db、Request 各自的职责打开压缩包看字节码文件upBean.class、db.class、Request.class这几个名字几乎是把 MVC 结构写在脸上了。很多初学者第一次看 Java Web 项目会懵不知道哪个文件管什么实际上你可以按「谁在存数据、谁在取数据、谁在转发页面」来归类upBean是 Model 层里面封装的是记事、联系人、账目记录的字段和 getter/setterdb.class是数据访问层负责拿 JDBC 跟 MySQL 打交道Request.class是 Controller 层的入口接收浏览器发来的请求调 db 层的方法最后把结果转发给 JSP 渲染。这里有个容易被忽略的细节class 文件是编译后的产物源码包里通常还保留着.java源文件和.classpath。.classpath是 Eclipse 工程文件说明这个项目原本是在 Eclipse 里建的 Java Web 工程而不是 Maven 结构。这意味着你导入 IDE 时不要按 Maven 标准去找pom.xml得走 Eclipse Dynamic Web Project 的导入路径类库依赖也是通过WEB-INF/lib目录下的 jar 包来管理的。我们后面讲启动步骤时会再展开。2.2 JDBC 连接层手写 DBUtil 的关键代码与参数说明整个系统能不能跑起来第一位看的是数据库连接这一层。传统 Java Web 项目最常见的就是自己写一个 DBUtil 工具类里面封装驱动加载、获取连接、关闭资源三个动作。我拆过的这类包里十有八九是这种写法Class.forName(com.mysql.jdbc.Driver)加载驱动然后用DriverManager.getConnection(url, user, password)建立连接。这里有一个非常容易被搞崩的点MySQL 5.7 和 MySQL 8.0 的驱动类名不一样前者是com.mysql.jdbc.Driver后者是com.mysql.cj.jdbc.Driver并且 8.0 的 URL 必须带serverTimezone参数。如果你拿到源码后发现db.class对应的源文件里写的是老驱动名而你本机装的是 MySQL 8.0运行时会直接抛ClassNotFoundException。我一般会直接改成兼容性写法// 放在项目源码的 com.xxx.util 包下 package com.demo.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DBUtil { // 根据你本机 MySQL 情况改5.7 用 33068.0 同样 3306但驱动名和 URL 参数不同 private static final String URL jdbc:mysql://localhost:3306/notebook_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456; static { try { // MySQL 8.0 用 com.mysql.cj.jdbc.DriverMySQL 5.7 用 com.mysql.jdbc.Driver Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps ! null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }这段代码的决定性参数有两个一个是serverTimezoneMySQL 8.0 不写它会报时区相关的 SQLException另一个是useUnicodetruecharacterEncodingutf8它决定你写入中文会不会变成???。连接关闭顺序也值得留意ResultSet → PreparedStatement → Connection 从里往外关否则长连接池场景下容易把连接占满。2.3 前端交互层JSP 配合 CSS 实现请求转发与页面渲染这套工程的前端由 JSP 页面和三个 CSS 文件构成myweb.css对应前台展示CssAdmin.css对应后台管理界面down.css可能是列表下载或文件上传相关页面。JSP 的逻辑是请求到达 Servlet 后通过request.getRequestDispatcher(xxx.jsp).forward()把数据塞进 request 域再转发给页面渲染。与前后端分离的 Spring Boot Vue 不同这种模式下 JSP 里可以直接写% %或 JSTL 标签输出 Java 变量。实际运行中常见的一个问题是表单提交的编码格式。JSP 页面顶部通常有pageEncodingUTF-8但 Servlet 里request.getParameter()拿到的中文仍然乱码。这不是页面问题而是 Tomcat 8 以上默认对 POST 请求体按 UTF-8 解码对 GET 请求参数按 ISO-8859-1 解码导致的。解决办法是在 Servlet 里加一行过滤或写一个编码 Filter这个我们放到「避坑章节」细说。前端的 css 文件命名字段很直白你顺着文件名就能定位到对应功能页这是拆老项目的优势——变量命名和文件名往往比现在的框架工程更直白。3. 环境配置与启动路线从 JDK 版本到 Tomcat 部署一次跑通3.1 软件环境选型JDK 1.8 Tomcat 8.5 MySQL 5.7 的兼容性理由拿到这种老项目第一件事不是打开 IDE而是先把运行环境搭对。这个工程基于传统 Servlet JSP编译级别不会高到哪里去JDK 1.8 是最稳的选择。你用 JDK 17 去跑 Tomcat 8.5 反而会出一堆模块访问报错比如IllegalAccessError那是 JDK 模块化系统对反射的访问限制导致的。Tomcat 版本我建议 8.5.x它在 JDK 1.8 下对 JSP 的编译兼容性最好。数据库优先 MySQL 5.7如果你的机器装的是 MySQL 8.0 也不是不能跑但要记得改驱动名和 URL 时区参数上一节已经给了代码。这里有一本账得算清楚项目自带的数据库脚本可能是十年前生成的表引擎、默认字符集、字段类型都可能跟现在的 MySQL 默认配置有出入。最典型的是数据库脚本里没写DEFAULT CHARSETutf8导入后整库变 latin1查询中文直接乱码。下面列一组我实际搭环境时的版本组合按这个走坑最少。软件推荐版本关键配置JDK1.88u202 及之前不需要额外模块配置Tomcat8.5.xHTTP 端口 8080UTF-8 编码默认开启MySQL5.7.x字符集 utf8排序规则 utf8_general_ciEclipse IDE2020-06 之后任意版本以 Eclipse 工程方式导入JDBC 驱动mysql-connector-java-5.1.49对应 5.7 库放在 WEB-INF/lib 下3.2 从 zip 到可运行导入 IDE、修 jar 包、改数据库连接的完整步骤把 zip 解压后不要直接双击.classpath文件那只会打开文本编辑器。正确做法是打开 Eclipse选择File → Import → Existing Projects into Workspace再定位到解压目录。如果导入后发现红色的错误标记优先检查WEB-INF/lib下有没有 mysql 驱动 jar。很多课程设计包里会把 jar 也压缩进去但也有只给源码的这时你需要自己去下注意别把 8.0 的 jar 配 5.7 的驱动名反过来也一样。Eclipse 导入完成之后在Project Facets里确认 Dynamic Web Module 版本是 3.0 或 3.1对应的 Tomcat 运行时也要选好。接下来改数据库连接打开db.java或DBUtil.java把用户名密码改成你本机的库名保持跟导入的 SQL 脚本一致。我一般习惯把 SQL 脚本先过目一遍确认里面有没有CREATE DATABASE语句如果有你新建连接时就不用手动建库直接source整个脚本即可。# 假设 SQL 脚本名是 notebook_db.sql位于解压目录的 database 文件夹下 # 先登录本地 MySQLroot 用户 mysql -u root -p # 登录后执行脚本导入 mysql source /your/path/notebook_db.sql; # 验证表是否生成 mysql SHOW TABLES;source命令会把脚本里的建库、建表、插初始化数据全执行一遍比在 Navicat 里手动逐条贴 SQL 省事得多。导入完成后用SHOW TABLES确认至少有记事表、用户表、联系人表、账目表这几类如果只有一两张表说明脚本可能只是部分表结构后面查询数据时会报Table doesnt exist。3.3 启动顺序与验证Tomcat 部署后先看哪个页面一切就绪后把项目 Add 到 Tomcat 的 Server 里server.xml不用动默认的 8080 端口即可。启动控制台后注意看有没有红色报错重点找两类异常一类是ClassNotFoundException: com.mysql.jdbc.Driver这表示驱动 jar 缺失或驱动名跟数据库版本不匹配另一类是CommunicationsException: Communications link failure这通常是 MySQL 服务没启动或端口不对。验证入场页时别急着乱点功能先访问登录页或注册页确认页面样式加载正常CSS 没 404然后注册一个新账号再登录进主界面随手新增一条记事去数据库里SELECT看一眼这条记录是否落库。跑完这三个动作整条链路就是通的。如果页面是空白但没报错多半是web.xml里的welcome-file没配置对直接通过http://localhost:8080/项目名/login.jsp进入即可绕过去。4. 数据库设计与增删改查四张核心表的建表语句和业务落库4.1 四块功能对应的表结构拆解与字段选择理由这个系统叫「记事簿 备忘录 通讯录 记账本」但底层实际就是四类业务数据在同一个库里共存。我在拆解源码时发现这类课程设计的表设计通常非常直白一张业务表对应一个功能模块表名常见命名业务模块核心字段t_user用户认证id, username, password, realnamet_note记事簿id, user_id, title, content, create_timet_memo备忘录id, user_id, memo_content, memo_time, remind_flagt_contact通讯录id, user_id, name, phone, email, addresst_account记账本id, user_id, income_expense, amount, category, record_date字段设计的核心是每条记录都要挂user_id这是多用户系统的底线。如果这个项目里只有记事功能那主键自增就够了但它集成了四个模块不同模块间的数据必须能按用户隔离否则一个用户登录后能看到所有人的账目记录这在答辩演示时非常尴尬。实际拆包时留意看脚本里有没有user_id字段以及有没有建外键索引有的课程设计为简化操作会故意不建外键而是靠应用层逻辑去保证归属这个不算错但答辩时问「不同用户之间怎么隔离数据」容易卡壳。-- 用户表系统登录的主体 CREATE TABLE t_user ( id INT(11) NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL COMMENT 登录名, password VARCHAR(50) NOT NULL COMMENT 登录密码, realname VARCHAR(50) DEFAULT NULL COMMENT 显示昵称, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8 COMMENT系统用户表; -- 记事表功能模块核心user_id 做归属隔离 CREATE TABLE t_note ( id INT(11) NOT NULL AUTO_INCREMENT, user_id INT(11) NOT NULL COMMENT 外键指向用户表主键, title VARCHAR(100) NOT NULL COMMENT 记事标题, content TEXT COMMENT 正文内容, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8 COMMENT记事簿;注意两个细节用户名做了唯一索引uk_username注册时重名直接报错省了一层应用层校验外键没有用CONSTRAINT FOREIGN KEY强制约束而是只加了普通索引idx_user_id。这种做法在课程设计中很常见理由是删除用户时不用处理级联关系但代价是数据一致性得靠代码保证。如果你打算拿它做毕设我建议在答辩前补上外键或至少在数据库里演示一次跨表查询。4.2 数据库增删改查的基线操作PreparedStatement 是底线JDBC 操作里有一个新手很容易翻车的点用Statement拼 SQL。项目源码里如果看到这种写法我建议你直接改成PreparedStatement这不只是性能问题更是防 SQL 注入的安全底线。以记事表为例新增和查询两条 SQL 是必须会写的// 新增记事使用 PreparedStatement 占位符避免拼接注入 String insertSql INSERT INTO t_note (user_id, title, content) VALUES (?, ?, ?); PreparedStatement ps conn.prepareStatement(insertSql); ps.setInt(1, userId); // 参数1 - user_id ps.setString(2, title); // 参数2 - title ps.setString(3, content); // 参数3 - content int rows ps.executeUpdate(); // 影响行数 0 表示成功查询侧要小心的误区是使用SELECT *后靠列序号取值。项目若在后续扩展中给表加了字段列序号就会错位。更稳妥的方式是显式列出需要的列名并且用rs.getString(title)而不是rs.getString(2)取值。修改和删除操作与新增套路相同只是 SQL 里要记得带上WHERE id ? AND user_id ?双重条件否则 A 用户改了 B 用户的记事就是安全事故了。这是四个模块共通的底线逻辑放进哪张表都一样适用。4.3 记事模块的数据流串讲从页面点击到数据库落库的完整路径把一次「新增记事」的操作从头串一遍你能看到架构上的三个角色各干了什么。用户在add_note.jsp填写标题和正文点提交后表单以 POST 请求发到Request这个总入口总入口根据action或method参数分发到记事的处理方法在该方法里创建upBean对象接收页面参数再调用 db 层的addNote(bean)方法方法内部通过 JDBC 执行刚才那条 INSERT 语句。// db 层的一个典型方法新增记事并返回是否成功 public boolean addNote(NoteBean note) { Connection conn null; PreparedStatement ps null; boolean flag false; try { conn DBUtil.getConnection(); String sql INSERT INTO t_note (user_id, title, content) VALUES (?, ?, ?); ps conn.prepareStatement(sql); ps.setInt(1, note.getUserId()); ps.setString(2, note.getTitle()); ps.setString(3, note.getContent()); flag ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); // 生产环境应换成日志输出 } finally { DBUtil.close(conn, ps, null); } return flag; }注意finally块里的连接关闭不能省。很多跑着跑着连接耗尽的项目翻代码一看全是try完不关连接或者只关了ResultSet没关Connection。MySQL 默认的连接数只有 151你不关闭连接几十个人用完就卡死。这一层是整套代码里最容易扣分也最容易修好的点答辩时老师问你「资源管理怎么做的」你把关闭顺序说对就已经赢了。5. 避坑与常见问题排查老 Java Web 项目跑起来的五个拦路虎5.1 页面中文全部变成「???」字符集从 JSP 到数据库三层不一致现象注册新用户时输入中文昵称存进数据库后显示成???或者从数据库查出来在页面上显示为乱码符号。原因这条链路的编码坑是层层传递的。第一层是 JSP 页面pageEncoding没设 UTF-8第二层是 Servlet 没对request和response设置统一编码第三层是数据库连接 URL 里少了characterEncodingutf8第四层是建表时表的默认字符集不是 utf8。这四层只要有一层不一致中文数据就会在你意想不到的位置变形。解决先改数据库连接 URL在DBUtil的 URL 末尾加上useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai然后去web.xml里注册一个编码过滤器强制所有请求和响应按 UTF-8 处理。编码过滤器不用自己发明轮子配置方式如下!-- web.xml 中配置编码过滤器解决 POST 请求参数乱码 -- filter filter-nameencodingFilter/filter-name filter-classcom.demo.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping配置完成后重启 Tomcat重新插入一条中文数据测试。如果库里还是乱码用ALTER TABLE t_note CONVERT TO CHARACTER SET utf8;把存量表转换一遍再测就正常了。5.2 ClassNotFoundException 与驱动加载失败MySQL 版本和驱动名不匹配现象Tomcat 启动时控制台报ClassNotFoundException: com.mysql.jdbc.Driver或者运行时报No suitable driver found for jdbc:mysql.原因源码里写死了老驱动名com.mysql.jdbc.Driver但你引入的驱动 jar 是 MySQL 8.0 的mysql-connector-java-8.0.x.jar8.0 的驱动主类是com.mysql.cj.jdbc.Driver当然找不到类。解决两个方案二选一。如果库是 5.7下载mysql-connector-java-5.1.49.jar放回WEB-INF/lib源码驱动名不用动如果库是 8.0把DBUtil里的Class.forName改成com.mysql.cj.jdbc.Driver同时确认 URL 里带serverTimezone。改完后重启 Tomcat看到控制台不再报错就过了。5.3 Tomcat 端口被占用导致启动失败查找进程与换端口现象启动 Tomcat 时几秒后弹窗提示Port 8080 already in use服务起不来。原因宿主机上有其他程序占用了 8080 端口常见的有 Nginx、另一个 Tomcat 实例或开发工具的调试端口。这是 Java Web 初学者第一天就会遇到的坑。解决命令行执行netstat -ano | findstr 8080查看占用端口的进程 PID然后去任务管理器定位进程。如果确认是残留的 Java 进程直接结束任务如果是别的业务程序改 Tomcat 的server.xml里Connector port8080改为 8081 或 8090再用http://localhost:8081/项目名访问。5.4 运行时 SQLExceptionUnknown column 或 Table doesnt exist现象功能页面正常显示点了「新增」「查询」按钮后页面或控制台报Unknown column xxx或Table xxx doesnt exist。原因源码里的 SQL 语句中字段名或表名跟数据库脚本导入后的实体不一致。常见于脚本只导入了部分表或源码中的字段名比脚本多了一个版本迭代中改掉的列。解决对照SHOW TABLES和DESC t_note;的返回结果把源码 SQL 里的字段名逐一核对。如果是表缺失补执行建表语句如果是字段缺失用ALTER TABLE t_note ADD COLUMN xxx VARCHAR(50);补列。这类问题没有捷径只能逐个对好在四张表的字段数量有限十分钟能排完。5.5 登录后没有跳转或页面 404web.xml 欢迎页与 Servlet 映射问题现象登录成功后应该跳到主界面实际却一直停在原页或者访问http://localhost:8080/项目名/时出现 404。原因web.xml里welcome-file没配对或登录 Servlet 的url-pattern与表单action提交的地址不一致。老项目里经常出现 Servlet 映射写的是/login表单提交写到/LoginServlet大小写或路径对不上就跳转失败。解决打开web.xml检查servlet-mapping标签里的url-pattern再去 JSP 页面的 form 标签里看action的值是否完全一致包括大小写。Tomcat 9 之后的版本对大小写敏感路径对不上直接 404。同时检查welcome-file是否配置了login.jsp或index.jsp没有的话把入口文件补进去。6. 二次开发的三个落点给这套课程设计加点加分项老项目的价值不在于直接交付而在于你可以低成本地往上加东西加完之后它就成了「你的」项目。我在拿到这套源码后通常不会急着改功能先把代码结构读一遍确认哪些类是核心入口、哪些是工具类然后从三个方向选一个动手按投入产出比排序依次是登录校验、过期提醒、记账统计。登录校验这个点性价比最高。很多课程设计只在登录成功后把用户名放进 Session但没做拦截器用户跳过登录页直接访问main.jsp也能打开主界面这在答辩演示时是个显而易见的硬伤。你可以用一个简单的 Filter 拦一下判断 Session 里有没有登录标志没有就重定向回登录页。这个改动大概二十行代码但整体完成度立刻上一个台阶。// 登录拦截过滤器在 web.xml 里注册后所有 .jsp 请求必须先验证 Session public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; Object user request.getSession().getAttribute(userId); if (user null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, res); // 放行已登录用户 } }过期提醒这个功能建议加在备忘录模块上。给t_memo表加一个remind_time字段然后在登录后的主页面加载时查一次SELECT * FROM t_memo WHERE user_id ? AND remind_time BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 1 DAY)把即将到期的备忘循环输出到一个提醒块里。这个功能听起来高级实现起来就是一条带时间范围的 SQL 加一个前端展示循环但它能把「备忘录」从纯文本记录变成带提醒价值的工具答辩时老师通常会追问这个点。记账统计可以顺带做用一条SELECT category, SUM(amount) FROM t_account WHERE user_id ? AND income_expense expense GROUP BY category拉出支出分类汇总再画一个简单的柱状图或饼图。不会用 ECharts 的话输出一个无样式的表格标题也行重点是「统计」这个动作本身。从那以后我每次拿到这类课程设计源码都会固定走一遍「拦截校验 → 时间提醒 → 数据统计」的三步加固既不动原有核心逻辑又能在答辩时拿出能描述清楚的功能亮点。这套源码的完整落地过程从读包、配环境、导数据到排坑整套流程走下来大概需要半天时间但走完这一遍你对 Servlet JSP JDBC 这套传统链路就有了具象的体感。之后再看 Spring MVC 或 Spring Boot你就能意识到框架究竟帮你省掉了哪些重复劳动。希望这篇文章帮到你动手拆包时每一步都走稳一点。这套资源我已整理成完整笔记包含上述所有源码片段、数据库脚本和部署说明文档需要的朋友可以访问我的个人主页自取。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑