简介:这是一套面向Java Web课程设计场景的完整项目源码,基于JSP与MySQL实现个人与家乡展示管理平台,适合计算机相关专业学生用于课程设计、毕业设计参考或Java Web入门练手。前端涵盖首页照片轮播、个人简介、技能分类下拉管理、家乡简介、美食美景与风土人情特色展示,以及支持回复的游客留言板;后端提供管理员与游客两类角色,实现用户、技能、家乡特色与留言的增删改查管理。压缩包共约2000个文件,以1621个svg图标、108个scss与38个css样式、82个js脚本、48个jsp页面、40个java源码及1个sql数据库脚本为主,整体约29.69MB,前后端结构清晰。目前已有289人学习下载,可帮助读者快速理解JSP+MySQL的MVC分层写法、后台管理模块设计与留言交互逻辑,并直接复用为课设基础框架。
1. 从一份 JSP 老项目说起:个人与家乡展示管理平台能解决什么
如果你手头正好有一门 Java Web 课程设计要交,或者想找一个结构完整、能跑通前后端增删改查的练手项目,这套基于 Java(JSP)+ MySQL 的个人与家乡展示管理平台值得拆开看看。它不是那种只放几张静态页面的“作业模板”,而是把前台展示和后台管理都做全了:首页照片轮播、个人简介、技能分类管理、家乡特色介绍、游客留言与回复,后台则对应一整套用户、技能、特色、留言的增删改查。换句话说,它覆盖了 JSP 时代最典型的 MVC 分层写法,拿来当课程设计能直接交,拿来学 JSP 与 MySQL 的配合也能把请求流转、会话管理、数据库连接这几块摸清楚。适合谁?正在做 Java Web 课设的学生、想复习 JSP 原生开发的老手,以及需要一套可改可扩的管理平台骨架的开发者。
2. 环境搭建与数据库落地:把 JSP 项目跑起来的第一步
这套项目是典型的 JSP + Servlet + MySQL 结构,没有用 Spring Boot 那套自动配置,所以环境得自己一步步配。好处是你能看清每个请求到底走了哪条路,坏处是配错一个地方就起不来。下面按我实际部署的顺序拆开讲。
2.1 JDK、Tomcat 与 MySQL 的版本选择
JDK 建议用 8 或 11,别一上来就上 17 以上。JSP 项目里很多老写法依赖javax.servlet包,JDK 17 之后模块化限制更严,容易在 Tomcat 启动时报类找不到。Tomcat 选 8.5 或 9.0 都行,9.0 对 Servlet 4.0 支持更完整,但如果你拿到的源码里web.xml还是 3.0 的声明,Tomcat 9 也能向下兼容。MySQL 用 5.7 或 8.0 都可以,区别主要在驱动包和连接 URL 上。
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 8 或 11 | 避免模块化导致的类加载问题 |
| Tomcat | 8.5 / 9.0 | 9.0 兼容性更好,8.5 更稳 |
| MySQL | 5.7 / 8.0 | 8.0 需换驱动并改 URL 参数 |
| 驱动包 | mysql-connector-java | 5.7 用 5.1.x,8.0 用 8.0.x |
MySQL 安装时记住 root 密码,字符集选utf8mb4,不然中文留言和家乡介绍会变问号。安装完用命令行验证一下:
mysql -u root -p # 输入密码后执行 SHOW VARIABLES LIKE 'character_set%'; # 确认 character_set_server 是 utf8mb4这一步别跳过。我见过太多人项目跑起来后页面中文全是乱码,回头查半天,最后发现是数据库建库时用了latin1。
2.2 导入 SQL 与修改数据库连接配置
项目一般会带一个.sql文件,里面是建库建表和初始数据。用命令行或 Navicat 导入都行。导入前先建库:
CREATE DATABASE IF NOT EXISTS hometown_db DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; USE hometown_db; SOURCE /path/to/your_project.sql;导入完成后,找到项目里数据库连接的工具类或配置文件。JSP 项目常见两种写法:一种是把连接参数写在db.properties里,另一种是直接硬编码在 Java 工具类中。如果是db.properties,改这几项:
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/hometown_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false jdbc.username=root jdbc.password=你的密码注意serverTimezone这个参数,MySQL 8.0 不写会报时区错误。useSSL=false在本地开发时加上,省得控制台一直刷警告。如果是硬编码在 Java 类里,找到DriverManager.getConnection那一行,按同样格式改。
2.3 部署到 Tomcat 并验证首页轮播
把项目打成 WAR 包或者直接把 WebContent 目录放到 Tomcat 的webapps下。启动 Tomcat:
# Linux/Mac ./startup.sh # Windows startup.bat启动后访问http://localhost:8080/项目名/,应该能看到首页照片轮播。轮播一般是用 JavaScript 定时切换图片,图片路径写在 JSP 或 JS 里。如果图片不显示,先看浏览器控制台的 404 报错,确认图片实际存放路径和引用路径是否一致。常见问题是源码里写的是绝对路径/images/1.jpg,但项目部署后上下文路径变了,得改成${pageContext.request.contextPath}/images/1.jpg。
后台管理入口通常是/admin/login.jsp或类似路径,默认管理员账号密码在 SQL 初始数据里,导入后可以查user表看到。登录进去后逐个点开用户管理、技能管理、特色管理、留言管理,确认列表能加载、新增能提交、删除有确认提示。这一步走完,说明环境基本通了。
3. 前台展示模块拆解:轮播、简介与留言板的实现细节
前台是给游客看的,重点在展示效果和交互流畅度。这套项目的前台分五块:首页轮播、个人简介、个人技能、家乡简介与特色、用户留言。每块背后都对应数据库表和 JSP 页面,理解了这个对应关系,改起来就不容易乱。
3.1 首页轮播与个人简介的数据组织
轮播图一般不是从数据库读的,而是直接在 JSP 里写死图片路径,或者用一个简单的 JS 数组管理。如果你想做成可后台管理的轮播,那就得加一张banner表,存图片路径和排序。项目默认可能没做这么细,但改起来不难。
个人简介页面通常是静态内容为主,从profile表读一条记录展示。表结构大概是这样:
CREATE TABLE profile ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), bio TEXT, avatar VARCHAR(255), update_time DATETIME );JSP 里用 JDBC 查出这条记录,然后嵌到 HTML 里。注意bio字段如果存了 HTML 标签,输出时要用<c:out>或手动转义,不然会有 XSS 风险。课程设计里老师不一定查这个,但养成习惯没坏处。
3.2 技能分类的下拉菜单与增删改查
技能管理是这套项目里比较有代表性的模块。前台展示时按分类下拉菜单切换,后台管理时对每个分类做增删改查。分类一般有:科研情况、学习成绩、开发技能、获奖、其他。数据库设计上,可以用一张skill表加一个category字段区分,也可以每个分类一张表。前者更灵活,后者更简单。
用一张表的写法:
CREATE TABLE skill ( id INT PRIMARY KEY AUTO_INCREMENT, category VARCHAR(50) NOT NULL, title VARCHAR(100), description TEXT, sort_order INT DEFAULT 0 );后台新增时,category用下拉菜单选择,提交到 Servlet 后执行INSERT。前台展示时,先SELECT DISTINCT category拿到所有分类,再按分类查具体技能项。JSP 页面里用 JSTL 的<c:forEach>遍历输出。
// 查询所有分类 String sql = "SELECT DISTINCT category FROM skill ORDER BY category"; // 按分类查询技能 String sql2 = "SELECT * FROM skill WHERE category = ? ORDER BY sort_order";参数说明:sort_order控制同一分类下的显示顺序,值越小越靠前。改的时候注意别把category写死成中文,万一以后要加英文分类,数据库里存英文、页面显示中文更灵活。
3.3 留言板与回复功能的数据表设计
留言板是前台交互最重的一块。游客注册后可以留言,管理员可以回复。表设计上,一条留言和它的回复可以放在同一张表里用parent_id关联,也可以分两张表。同一张表的写法:
CREATE TABLE message ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, content TEXT, parent_id INT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id) );parent_id = 0表示这是一条主留言,否则表示它是对某条留言的回复。前台展示时,先查parent_id = 0的主留言,再对每条主留言查它的回复。回复功能在 JSP 里用一个隐藏的parent_id字段传递。
// 插入留言 String sql = "INSERT INTO message (user_id, content, parent_id) VALUES (?, ?, ?)"; ps.setInt(1, userId); ps.setString(2, content); ps.setInt(3, parentId); // 0 表示主留言注意user_id从 session 里取,别从表单传,不然容易被人伪造身份。回复功能同理,管理员回复时user_id用管理员的 ID,parent_id用被回复留言的 ID。
4. 后台管理模块实战:用户、技能与留言的增删改查
后台是这套项目的骨架,所有前台展示的数据都从这里来。后台模块一般包括:用户管理、技能管理、家乡特色管理、留言管理。每个模块的套路都差不多——列表页、新增页、编辑页、删除接口。把这四个动作吃透,改任何模块都是复制粘贴。
4.1 用户管理与权限区分
用户表里一般有个role字段区分管理员和游客:
CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE, password VARCHAR(100), role VARCHAR(20) DEFAULT 'guest', create_time DATETIME DEFAULT CURRENT_TIMESTAMP );注册时role默认guest,管理员账号在 SQL 初始数据里写死admin。登录时查库比对密码,然后把role存进 session。后台每个管理页面的开头都要判断 session 里的role是不是admin,不是就跳回登录页。
// 权限拦截 String role = (String) session.getAttribute("role"); if (!"admin".equals(role)) { response.sendRedirect("login.jsp"); return; }密码别明文存,用 MD5 或 SHA-256 哈希一下。课程设计里老师可能不查,但这是基本习惯。注册时对用户名做唯一性校验,不然重复注册会报数据库异常。
4.2 技能与家乡特色的后台管理
技能管理和家乡特色管理的逻辑几乎一样,都是对一张表做增删改查。区别在于字段不同:技能有分类、标题、描述;家乡特色有分类(美食、美景、风土人情)、标题、图片、描述。
后台列表页用表格展示,每行后面跟“编辑”和“删除”按钮。删除时弹确认框,确认后跳转到删除 Servlet。编辑时先把数据查出来填到表单里,提交后执行UPDATE。
// 更新技能 String sql = "UPDATE skill SET category=?, title=?, description=?, sort_order=? WHERE id=?"; ps.setString(1, category); ps.setString(2, title); ps.setString(3, description); ps.setInt(4, sortOrder); ps.setInt(5, id);参数说明:id从表单隐藏域传过来,别从 URL 参数取,不然容易被人改 ID 删错数据。图片上传如果要做,用commons-fileupload或 Servlet 3.0 的Part接口,存到服务器目录后在数据库里存相对路径。
4.3 留言管理的审核与回复
留言管理比前两个多一个“回复”动作。后台列表页展示所有主留言,每条后面有“回复”和“删除”按钮。回复时弹出一个输入框,提交后往message表插一条parent_id为主留言 ID 的记录。
// 管理员回复 String sql = "INSERT INTO message (user_id, content, parent_id) VALUES (?, ?, ?)"; ps.setInt(1, adminId); ps.setString(2, replyContent); ps.setInt(3, parentMessageId);删除留言时要注意级联删除回复。如果数据库外键设了ON DELETE CASCADE,删主留言会自动删回复;没设的话得手动先删回复再删主留言。我一般会在删除前先查一下有没有子回复,有就一起删,避免留下孤儿数据。
5. 避坑与排查:JSP + MySQL 项目最容易翻车的五个地方
这套项目跑通不难,但跑稳不容易。下面这五个坑是我在实际部署和帮人调试时遇到频率最高的,每个都按“现象 → 原因 → 解决”写清楚。
5.1 中文乱码:从数据库到页面的全链路排查
现象:页面显示的中文变成问号或乱码,留言内容尤其明显。
原因:乱码可能出现在三个环节——数据库字符集、JDBC 连接字符集、JSP 页面编码。任何一环不是utf8或utf8mb4,中文就会出问题。
解决:先确认数据库和表的字符集是utf8mb4,再检查 JDBC URL 里有没有characterEncoding=utf8,最后在 JSP 页面顶部加<%@ page contentType="text/html;charset=UTF-8" %>。如果是 POST 请求,还要在 Servlet 里加request.setCharacterEncoding("UTF-8")。三处都对了,乱码基本消失。
5.2 数据库连接失败:驱动、URL 与权限的三重检查
现象:启动 Tomcat 后访问页面报java.sql.SQLException,或者后台登录时提示连接不上数据库。
原因:常见三种——驱动包没放到WEB-INF/lib下、URL 里时区或 SSL 参数没写、MySQL 用户权限不够。
解决:先把mysql-connector-java的 jar 包确认放进WEB-INF/lib,然后检查 URL 格式。MySQL 8.0 的 URL 必须带serverTimezone,5.7 可以不写但建议加上。最后用命令行登录 MySQL,确认root用户能从localhost连接。如果报Access denied,检查密码和主机限制。
5.3 图片轮播不显示:路径与上下文的问题
现象:首页轮播区域空白,或者图片位置显示裂图。
原因:图片路径写成了绝对路径,或者图片根本没放到部署目录里。
解决:打开浏览器开发者工具,看 Network 面板里图片请求的 URL 是什么。如果是http://localhost:8080/images/1.jpg而不是http://localhost:8080/项目名/images/1.jpg,说明路径少了上下文。在 JSP 里用${pageContext.request.contextPath}/images/1.jpg拼接。另外确认图片确实在webapps/项目名/images/目录下。
5.4 留言回复层级错乱:parent_id 传参错误
现象:回复留言后,回复内容显示在了错误的主留言下面,或者所有回复都堆在一起。
原因:parent_id在表单里传错了,或者前台展示时没有按parent_id分组。
解决:检查回复表单里隐藏的parent_id是不是当前主留言的 ID。前台展示时,先查parent_id = 0的主留言,再对每条主留言单独查parent_id = 该留言ID的回复。别一次性把所有留言查出来在前端分组,那样容易乱。
5.5 后台权限绕过:直接访问管理页面
现象:不登录直接访问后台管理页面的 URL,居然能打开。
原因:管理页面没有做 session 校验,或者校验逻辑写在了 JSP 里但被注释掉了。
解决:在每个后台 JSP 页面顶部加 session 校验代码,判断role是不是admin。更稳妥的做法是用一个 Filter 统一拦截/admin/*路径,在 Filter 里做校验。这样即使新增了管理页面,也不会漏掉权限检查。
6. 进阶技巧:把 JSP 项目改造成可维护的骨架
这套项目跑通之后,如果你不想只交个作业就扔,可以花点时间把它改造成更顺手的骨架。我一般会做三件事:抽一个统一的数据库工具类、把重复的增删改查逻辑模板化、给关键操作加日志。这三步做完,后面再加模块就是填空。
6.1 抽离数据库工具类与连接池
项目里如果每个 Servlet 都写一遍DriverManager.getConnection,改数据库密码时就得满项目找。抽一个DBUtil类:
public class DBUtil { private static final String URL = "jdbc:mysql://localhost:3306/hometown_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false"; private static final String USER = "root"; private static final String PASSWORD = "你的密码"; static { try { 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) { // 依次关闭,省略 try-catch } }参数说明:URL、USER、PASSWORD可以进一步抽到db.properties里,用Properties类加载。连接池如果要用,加一个c3p0或Druid的 jar 包,把getConnection改成从池里取。课程设计里不一定要上连接池,但知道这个改法,以后换项目不慌。
6.2 用 Filter 统一处理编码与权限
编码和权限是每个请求都要做的事,写在每个 Servlet 里太啰嗦。加一个 Filter:
@WebFilter("/*") public class EncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // 权限校验:非登录状态且访问 /admin/ 路径时跳转 String uri = request.getRequestURI(); if (uri.contains("/admin/") && request.getSession().getAttribute("role") == null) { response.sendRedirect(request.getContextPath() + "/login.jsp"); return; } chain.doFilter(req, resp); } }注意@WebFilter("/*")会拦截所有请求,包括静态资源。如果发现 CSS 或图片加载不了,在 Filter 里放行.css、.js、.jpg等后缀的请求。这个 Filter 一加,编码和权限两件事都不用再操心了。
6.3 验证改造效果与日常维护习惯
改造完之后,按这个顺序验证一遍:先清空浏览器缓存,访问首页看轮播和中文是否正常;然后退出登录,直接访问/admin/userList.jsp,应该被跳回登录页;再登录进去,新增一条技能、一条留言、一条回复,确认数据库里数据正确;最后删掉一条主留言,确认它的回复也一起没了。
从那以后我每次拿到 JSP 老项目,都先做这三步改造再开始写业务。看起来多花了半小时,但后面改需求时省下的时间远不止这点。希望帮到你。
本文还有配套的精品资源,点击获取