同学录系统JavaWeb期末项目实战:环境搭建、功能复现与避坑指南
发布时间:2026/10/11 3:05:22 锦皓数字建站

简介这份同学录系统Java Web期末项目源码包面向高校计算机专业学生与Java Web初学者用于课程设计参考、项目实战练习与答辩准备。资源包含完整的前后端代码与数据库脚本可帮助读者理解Servlet、JSP、MVC架构及Session权限控制的落地方式。压缩包共48个文件约1021KB以java源文件与class编译文件为主辅以jsp页面、sql建表脚本、css样式、js脚本及properties、xml等配置文件覆盖从视图层到数据访问层的完整结构。目前已有4371人学习下载适合作为期末项目模板或自学案例。读者可从中获取可运行的项目骨架、student与user两张表的SQL初始化脚本、登录与列表展示等核心页面实现以及JDBC连接配置和Tomcat部署所需的工程文件便于对照调试、二次开发与排错练习。1. 同学录系统 JavaWeb 期末项目从零到能跑通我踩过的坑比代码还多每年期末季总有一批人对着“同学录系统 JavaWeb 期末项目.zip”这个压缩包发愁。解压之后看到一堆.java、.jsp、.xml和WEB-INF目录IDEA 打开一片红Tomcat 一启动就报 404 或者 500数据库连不上中文乱码像鬼打墙。这个标题背后其实是一个典型的 JavaWeb 综合实训项目用 JSP/Servlet 或者 SSM 框架实现用户注册登录、同学信息管理、留言板、相册上传这些功能最后打包成 war 丢进 Tomcat 跑起来。它适合正在做课程设计的学生也适合想回头补 JavaWeb 基础、把前后端串起来的初级开发者。我见过太多人卡在环境配置和数据库连接上代码逻辑反而没写几行。这篇笔记就把这个压缩包拆开从环境搭建到功能复现再到部署排错一步步走通。2. 环境搭建与项目结构别急着改代码先把架子搭稳拿到一个 JavaWeb 项目压缩包最忌讳的就是直接双击打开然后乱改。我一般会先做三件事确认 JDK 版本、确认 Tomcat 版本、确认数据库类型。同学录系统这类期末项目常见的技术栈是 JDK 8 Tomcat 8.5/9 MySQL 5.7/8.0前端用 JSP JSTL 原生 JavaScript后端用 Servlet JDBC 或者 Spring MyBatis。版本对不上后面全是玄学问题。2.1 先看目录结构判断项目类型解压之后先看根目录有没有pom.xml。有就是 Maven 项目没有就是传统 Web 项目。再看WEB-INF下面有没有web.xml以及lib目录里有没有 jar 包。这一步决定了你导入 IDEA 的方式。# 查看项目根目录结构Linux/macOS find . -maxdepth 2 -type d | sort # 查看是否有 Maven 构建文件 ls -la pom.xml # 查看 WEB-INF 下的关键文件 ls -la WEB-INF/web.xml ls -la WEB-INF/lib/逻辑说明find命令列出两层目录快速判断项目是 Maven 还是普通 Web 项目。pom.xml存在说明依赖由 Maven 管理不存在则需要手动把lib下的 jar 包加到 classpath。web.xml是传统 Servlet 项目的入口配置如果项目用注解配置这个文件可能很简单甚至没有。参数说明-maxdepth 2限制目录深度避免输出太多。-type d只看目录。ls -la查看隐藏文件和权限。2.2 导入 IDEA 并配置 Tomcat如果是 Maven 项目直接File - Open选择pom.xmlIDEA 会自动下载依赖。如果是普通 Web 项目选择File - New - Project from Existing Sources然后勾选 Web Application。接下来配置 Tomcat# 在 IDEA 中配置 Tomcat 的步骤非命令行但按顺序操作 # 1. Run - Edit Configurations - - Tomcat Server - Local # 2. 在 Server 选项卡中Application server 选择本地 Tomcat 目录 # 3. 在 Deployment 选项卡中点击 - Artifact选择项目对应的 war exploded # 4. Application context 建议设为 /tongxuelu避免根路径冲突逻辑说明war exploded模式支持热部署改 JSP 不用重启。Application context是访问路径前缀设成/tongxuelu后浏览器访问http://localhost:8080/tongxuelu即可。参数说明Tomcat 端口默认 8080如果被占用可以在 Server 选项卡改。On Update action建议选Update classes and resources这样改 Java 代码也能快速生效。2.3 数据库初始化建库建表再连同学录系统的数据库一般叫tongxuelu或者classmate表包括user、message、photo、class_info等。先执行 SQL 脚本再改项目里的数据库连接配置。-- 创建数据库字符集用 utf8mb4 避免中文乱码 CREATE DATABASE IF NOT EXISTS tongxuelu DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE tongxuelu; -- 用户表存储登录账号和基本信息 CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, real_name VARCHAR(50), class_name VARCHAR(50), phone VARCHAR(20), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 留言表关联用户存储留言内容 CREATE TABLE message ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, content TEXT NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;逻辑说明utf8mb4支持 emoji 和生僻字比utf8更稳。ON DELETE CASCADE保证删用户时留言自动清理避免脏数据。create_time默认当前时间插入时不用手动传。参数说明VARCHAR(100)存密码如果项目用 MD5 加密32 位够用如果存明文建议改长一点并提醒用户改密码。TEXT类型存留言内容长度上限 65535 字节。数据库连接配置一般在src/main/resources/db.properties或者src/jdbc.properties# 数据库连接配置根据实际环境修改 jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/tongxuelu?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse jdbc.usernameroot jdbc.password你的密码逻辑说明com.mysql.cj.jdbc.Driver是 MySQL 8.0 的驱动类5.x 用com.mysql.jdbc.Driver。serverTimezoneAsia/Shanghai解决时区报错useSSLfalse去掉安全连接警告。参数说明characterEncodingutf8要和数据库字符集一致。如果项目用连接池如 Druid配置项名称可能不同但核心参数就这几个。3. 核心功能复现登录、留言、文件上传一个不能少环境跑通之后接下来就是把核心功能串起来。同学录系统最常被验收的三个功能是用户登录、留言板、头像/相册上传。这三个功能覆盖了 Servlet 请求处理、Session 管理、JDBC 操作、文件 IO是期末答辩的重点。3.1 登录功能从表单到 Session 的完整链路登录流程是JSP 表单提交 - Servlet 接收 - 查数据库 - 写 Session - 跳转主页。很多人卡在中文乱码和 Session 取不到值上。// LoginServlet.java 核心代码 WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置请求和响应编码必须在获取参数之前 req.setCharacterEncoding(UTF-8); resp.setContentType(text/html;charsetUTF-8); String username req.getParameter(username); String password req.getParameter(password); // 简单校验实际项目建议用 MD5 或 BCrypt if (username null || username.trim().isEmpty() || password null || password.trim().isEmpty()) { req.setAttribute(msg, 用户名或密码不能为空); req.getRequestDispatcher(/login.jsp).forward(req, resp); return; } UserDao userDao new UserDao(); User user userDao.findByUsernameAndPassword(username, password); if (user ! null) { // 登录成功写 Session HttpSession session req.getSession(); session.setAttribute(currentUser, user); session.setMaxInactiveInterval(30 * 60); // 30分钟过期 resp.sendRedirect(req.getContextPath() /index.jsp); } else { req.setAttribute(msg, 用户名或密码错误); req.getRequestDispatcher(/login.jsp).forward(req, resp); } } }逻辑说明setCharacterEncoding必须在getParameter之前调用否则中文参数会乱码。sendRedirect是重定向浏览器地址栏会变forward是转发地址栏不变。登录成功用重定向防止刷新重复提交。参数说明setMaxInactiveInterval(30 * 60)设置 Session 30 分钟无操作过期单位是秒。req.getContextPath()获取项目上下文路径避免硬编码/tongxuelu。对应的 DAO 层// UserDao.java 查询方法 public User findByUsernameAndPassword(String username, String password) { String sql SELECT * FROM user WHERE username ? AND password ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { User user new User(); user.setId(rs.getInt(id)); user.setUsername(rs.getString(username)); user.setRealName(rs.getString(real_name)); user.setClassName(rs.getString(class_name)); return user; } } } catch (SQLException e) { e.printStackTrace(); } return null; }逻辑说明用PreparedStatement防止 SQL 注入这是期末项目最容易丢分的地方。try-with-resources自动关闭连接避免资源泄漏。参数说明?是占位符setString按顺序填充。如果密码用 MD5这里要先对password做加密再传。3.2 留言板分页查询与 XSS 防护留言板功能包括发布留言和展示留言列表。展示时要做分页否则数据一多页面就卡。另外留言内容直接输出到 JSP 会有 XSS 风险需要转义。// MessageDao.java 分页查询 public ListMessage findByPage(int page, int pageSize) { ListMessage list new ArrayList(); String sql SELECT m.*, u.real_name FROM message m JOIN user u ON m.user_id u.id ORDER BY m.create_time DESC LIMIT ?, ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, (page - 1) * pageSize); ps.setInt(2, pageSize); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { Message msg new Message(); msg.setId(rs.getInt(id)); msg.setContent(rs.getString(content)); msg.setRealName(rs.getString(real_name)); msg.setCreateTime(rs.getTimestamp(create_time)); list.add(msg); } } } catch (SQLException e) { e.printStackTrace(); } return list; }逻辑说明LIMIT ?, ?第一个参数是偏移量第二个是每页条数。(page - 1) * pageSize计算偏移。JOIN user拿到留言者的真实姓名避免前端再查一次。参数说明page从 1 开始pageSize建议 10 到 20。如果数据量很大LIMIT偏移量太大性能会下降但期末项目数据量小够用。JSP 输出时用 JSTL 的c:out转义%-- message_list.jsp 片段 --% c:forEach items${messageList} varmsg div classmessage-item span classauthorc:out value${msg.realName}//span span classtimefmt:formatDate value${msg.createTime} patternyyyy-MM-dd HH:mm//span p classcontentc:out value${msg.content}//p /div /c:forEach逻辑说明c:out默认转义 HTML 标签防止script注入。fmt:formatDate格式化时间避免显示2025-01-01 00:00:00.0这种带毫秒的格式。参数说明pattern可以按需改比如yyyy年MM月dd日。3.3 文件上传头像与相册的保存路径文件上传是期末项目里翻车率最高的功能。常见问题包括表单没加enctype、Servlet 没加MultipartConfig、保存路径是相对路径导致文件找不到。// UploadServlet.java 头像上传 WebServlet(/upload) MultipartConfig(maxFileSize 1024 * 1024 * 5, maxRequestSize 1024 * 1024 * 10) public class UploadServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); Part part req.getPart(avatar); // 获取原始文件名 String fileName part.getSubmittedFileName(); if (fileName null || fileName.isEmpty()) { resp.getWriter().write(请选择文件); return; } // 生成唯一文件名避免覆盖 String ext fileName.substring(fileName.lastIndexOf(.)); String newFileName UUID.randomUUID().toString() ext; // 保存到 webapp/uploads 目录 String uploadPath getServletContext().getRealPath(/uploads); File uploadDir new File(uploadPath); if (!uploadDir.exists()) { uploadDir.mkdirs(); } part.write(uploadPath File.separator newFileName); // 把相对路径存到数据库 String relativePath uploads/ newFileName; // ... 更新用户头像字段的代码 resp.sendRedirect(req.getContextPath() /profile.jsp); } }逻辑说明MultipartConfig必须加否则getPart返回 null。UUID生成唯一文件名防止同名覆盖。getRealPath(/uploads)拿到的是部署目录重启 Tomcat 可能丢失生产环境建议存到外部目录。参数说明maxFileSize单文件最大 5MBmaxRequestSize整个请求最大 10MB。part.write直接写文件路径用File.separator兼容 Windows 和 Linux。表单必须加enctypeform action${pageContext.request.contextPath}/upload methodpost enctypemultipart/form-data input typefile nameavatar acceptimage/* button typesubmit上传/button /form逻辑说明enctypemultipart/form-data是文件上传的必要条件少了这个后台拿不到文件流。acceptimage/*限制前端选择图片类型但不是强制后台还要校验。4. 避坑与排查那些让答辩当场翻车的细节这一章记录我见过最多的 5 个坑每个都按「现象 - 原因 - 解决」写。答辩前对照检查一遍能省很多尴尬。4.1 中文乱码从数据库到浏览器的全链路排查现象登录后显示“???”或者“测试”留言内容全是问号。原因乱码可能出现在三个地方——数据库字符集、JDBC 连接编码、JSP 页面编码。任何一处不一致都会乱。解决按顺序检查。数据库用SHOW VARIABLES LIKE character%;确认character_set_server是utf8mb4。JDBC URL 加useUnicodetruecharacterEncodingutf8。JSP 页面顶部加% page contentTypetext/html;charsetUTF-8 languagejava %。Servlet 里req.setCharacterEncoding(UTF-8)和resp.setContentType(text/html;charsetUTF-8)都要写。Tomcat 的server.xml里 Connector 加URIEncodingUTF-8。4.2 404 错误路径对了但就是找不到现象浏览器访问http://localhost:8080/login报 404但代码里明明写了WebServlet(/login)。原因最常见的是 Application context 设错了或者web.xml里metadata-completetrue导致注解不生效。解决先看浏览器地址栏的路径确认项目上下文。如果 context 是/tongxuelu访问地址应该是http://localhost:8080/tongxuelu/login。检查web.xml的web-app标签有没有metadata-completetrue有的话改成false或者删掉。如果是 Maven 项目确认pom.xml里packaging是war并且maven-war-plugin配置正确。4.3 数据库连接失败Public Key Retrieval 和时区报错现象启动时报com.mysql.cj.jdbc.exceptions.CommunicationsException或者The server time zone value ?D1ú±ê×?ê±?? is unrecognized。原因MySQL 8.0 默认要求 SSL 连接并且时区设置和系统不一致。另外allowPublicKeyRetrieval没开也会导致连接被拒。解决JDBC URL 加上useSSLfalseallowPublicKeyRetrievaltrueserverTimezoneAsia/Shanghai。如果还不行检查 MySQL 用户权限确保root用户允许从localhost连接。FLUSH PRIVILEGES;刷新权限。4.4 文件上传后访问 404保存路径和访问路径不一致现象上传成功数据库里也有记录但img srcuploads/xxx.jpg显示裂图。原因文件保存到了getRealPath(/uploads)但 JSP 里的相对路径是相对于当前页面 URL 的不是相对于项目根目录。解决JSP 里用${pageContext.request.contextPath}/uploads/xxx.jpg拼绝对路径。或者把文件保存到webapp/uploads下确保 Tomcat 能直接访问。如果重启后文件丢失说明保存到了临时部署目录需要改到外部目录并在 Tomcat 配置虚拟路径。4.5 Session 失效登录后刷新页面又跳回登录页现象登录成功跳转主页点几个链接后突然跳回登录页Session 里的用户没了。原因可能是 Session 超时时间太短或者浏览器禁用了 Cookie或者项目重启导致 Session 丢失。解决检查setMaxInactiveInterval的值默认 30 分钟够用。如果浏览器禁用 Cookie需要用 URL 重写response.encodeURL()。开发阶段 Tomcat 重启会清空 Session这是正常的答辩前别频繁重启。5. 进阶技巧让期末项目多拿几分的小改动如果基础功能已经跑通想在答辩时多拿几分可以加几个小改动。这些改动工作量不大但能体现你对代码质量的理解。第一个是密码加密。把明文密码改成 MD5 或者 BCrypt。MD5 简单但安全性一般BCrypt 需要引入jbcrypt依赖但更安全。期末项目用 MD5 加盐就够了。// MD5 加密工具类 public class MD5Util { public static String encrypt(String password) { try { MessageDigest md MessageDigest.getInstance(MD5); byte[] digest md.digest(password.getBytes(StandardCharsets.UTF_8)); StringBuilder sb new StringBuilder(); for (byte b : digest) { sb.append(String.format(%02x, b)); } return sb.toString(); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(MD5 加密失败, e); } } }逻辑说明MessageDigest是 JDK 自带的加密类%02x把字节转成两位十六进制。登录时把用户输入的密码加密后再和数据库比对。参数说明MD5 输出固定 32 位十六进制字符串。如果想加盐在password后面拼一个固定字符串再加密。第二个是分页组件封装。把分页逻辑抽成一个PageBean类包含list、totalPage、currentPage等字段JSP 里直接遍历页码。// PageBean.java 分页封装 public class PageBeanT { private ListT list; // 当前页数据 private int totalPage; // 总页数 private int currentPage; // 当前页码 private int pageSize; // 每页条数 private int totalCount; // 总记录数 // 计算总页数 public void setTotalCount(int totalCount) { this.totalCount totalCount; this.totalPage (totalCount pageSize - 1) / pageSize; } // getter/setter 省略 }逻辑说明(totalCount pageSize - 1) / pageSize是向上取整的经典写法避免最后一页数据被截断。JSP 里用c:forEach begin1 end${pageBean.totalPage}生成页码链接。参数说明pageSize建议 10 到 20太小翻页频繁太大页面加载慢。第三个是加一个简单的过滤器统一处理编码和登录拦截。// EncodingFilter.java 统一编码 WebFilter(/*) public class EncodingFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding(UTF-8); resp.setContentType(text/html;charsetUTF-8); chain.doFilter(req, resp); } }逻辑说明WebFilter(/*)拦截所有请求在进入 Servlet 之前统一设置编码省去每个 Servlet 重复写。登录拦截可以再加一个LoginFilter判断 Session 里有没有currentUser没有就跳登录页。参数说明chain.doFilter放行请求必须调用否则请求会被卡住。最后一个技巧是答辩演示前把数据库数据准备充分一点。留言板至少 20 条用户至少 5 个相册至少 3 张图。数据太少分页和列表展示效果出不来老师一看就觉得功能没做完。我一般会写一个init.sql脚本答辩前执行一遍数据全回来。这个习惯帮我省过好几次尴尬希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。