
简介这是一套基于 JavaJSP MySQL 实现的个人与家乡展示管理平台课程设计源码包面向 Java Web 初学者、课程设计学生及毕业设计开发者。前端包括欢迎页面照片轮播、个人简介展示、个人技能管理、家乡简介、特色介绍与游客留言板后端提供管理员与游客用户管理、技能信息增删改查、家乡美食美景风土人情管理、留言回复管理等功能覆盖典型注册登录、会话管理与 CRUD 开发流程可帮助理解 JSP 页面与后端 Java 代码的交互方式。压缩包内共 2000 个文件以 svg 图标、scss/css 样式、javascript 交互脚本、jsp 页面和 java 后台代码为主另含 sql 数据库脚本与项目配置文件压缩包整体约 29.69MB文件结构清晰便于按模块对照学习。资源已有 288 人学习可用于课程设计、实训项目或提升 Java Web 综合开发能力是完整可运行的实践参考。1. 这是什么样的 JSP MySQL 课程设计一个能交作业也能练手的平台把 JSP 课程设计项目下载下来第一个动作往往是点运行结果不是 404 就是一连串红色报错。这类项目的坑通常不在代码逻辑而在环境和数据库。这个「个人与家乡展示管理平台」是标准的 JavaJSP MySQL 课程设计前台包含欢迎页照片轮播、个人简介、个人技能管理、家乡简介、特色介绍和用户留言后台提供管理员对技能、家乡特色和留言的增删改查游客注册后可以留言。它适合两类人正在找 JavaWeb 完整案例的学生需要参考建表和分层写法以及想在 JSP 场景里练 Servlet 生命周期和 JDBC 基本功的人。技术栈不花哨但课程设计评分点基本都覆盖了。2. 数据库先行四张核心表的建库脚本与字段设计2.1 建库语句与字符集选择任何 JSP 项目拿到手第一件事都不是点启动而是先把库建出来。这个平台的数据量不大但表之间有关联用户要分管理员和游客技能要分科研、学习成绩、开发技能、获奖家乡特色要分美食、美景、风土人情留言要带回复字段。我习惯先把四张表的设计理清楚再去读代码这样后面排查 SQL 报错时脑子里始终有完整的字段图。CREATE DATABASE IF NOT EXISTS hometown_platform DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; USE hometown_platform;字符集选 utf8mb4 而不是 utf8原因是 MySQL 8 默认就是 utf8mb4而且它能存 emoji 和生僻字。课程设计里留言板内容经常有特殊符号用 utf8 在部分 MySQL 版本下会报 Incorrect string value 的错。字符集在建库时一次性定死后期再 ALTER 改表虽然能改但已经落库的数据要重新转相当折腾。2.2 四张表的字段设计CREATE TABLE t_user ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT 用户ID, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录名, password VARCHAR(64) NOT NULL COMMENT 演示环境明文存储答辩够用, role TINYINT NOT NULL DEFAULT 1 COMMENT 0-管理员 1-游客, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; INSERT INTO t_user (username, password, role) VALUES (admin, 123456, 0); CREATE TABLE t_skill ( id INT AUTO_INCREMENT PRIMARY KEY, category VARCHAR(20) NOT NULL COMMENT 科研情况/学习成绩/开发技能/获奖, title VARCHAR(100) NOT NULL COMMENT 技能或成果标题, content TEXT COMMENT 详细描述, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_hometown ( id INT AUTO_INCREMENT PRIMARY KEY, type VARCHAR(20) NOT NULL COMMENT 美食/美景/风土人情, title VARCHAR(100) NOT NULL, content TEXT, image_url VARCHAR(255) COMMENT 图片相对路径, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_message ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL COMMENT 留言的游客ID, username VARCHAR(50) COMMENT 冗余昵称省一次联查, content VARCHAR(500) NOT NULL COMMENT 留言内容, reply VARCHAR(500) COMMENT 管理员回复内容, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, reply_time DATETIME COMMENT 回复时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;四张表的对应关系很清楚t_user 管登录和权限t_skill 对应技能管理下拉菜单里的四个分类t_hometown 对应家乡特色的三个分类t_message 是留言板。role 字段用 TINYINT 而不是字符串判断权限只需要 0 和 1代码里用 Integer 判断也更直接。表名核心字段对应前端模块t_userusername, password, role登录、注册、权限判断t_skillcategory, title, content个人技能管理下拉菜单t_hometowntype, title, content, image_url家乡特色美食/美景/风土人情t_messageuser_id, username, content, reply游客留言、管理员回复两个设计细节值得说。第一t_message 里冗余了 username留言列表和管理员回复页不用每次 JOIN 一次 t_user以课程设计的数据量冗余比联查直观答辩也好解释。第二t_hometown 的 type 和 t_skill 的 category 都用字符串存固定分类值分类有限JSP 页面直接输出展示不需要再做字典映射。2.3 建表脚本怎么跑Navicat、命令行和 IDEA 三种方式脚本可以在 Navicat 里直接运行也可以命令行导入。我一般用 Navicat for MySQL连接配置好后右键数据库选「运行 SQL 文件」把上面这段脚本一次性导入。没有图形化工具就用命令行mysql -u root -p init.sql命令行方式要注意 mysql 命令目录在不在 PATH 里Windows 装完 MySQL 8 经常遇到 mysql 命令找不到去 MySQL 安装目录的 bin 下执行就能解决。导入完成后执行 SHOW TABLES; 确认四张表都在再回去看代码。数据库层面通了后面的 JSP 调试才不会把 SQL 错误和代码错误混在一起。3. 三层架构怎么落地Servlet JSP JDBC 的代码分工3.1 分层原则为什么课程设计推荐手动 JDBC 而不是直接上框架课程设计阶段我建议不要直接套 Spring Boot倒不是 Spring 不好而是评分老师想看到的是 JSP 里的请求流转、Servlet 的映射逻辑、JDBC 里 PreparedStatement 的参数绑定。JSP 本质是一个被容器编译成 Servlet 的页面浏览器发来 HTTP 请求Servlet 接收参数、调用业务方法、把结果放进 request 域再 forward 到 JSP 渲染这是 JavaWeb 最原始的请求流程也是最常被面试官追问的 MVC 落地方案。这个平台按这个思路拆项目结构src/main/java ├── entity 实体类User、Skill、Hometown、Message ├── dao JDBC 数据访问层 ├── servlet WebServlet 注解映射 URL └── util DBUtil 数据库连接工具 src/main/webapp ├── index.jsp 欢迎页轮播 ├── profile.jsp 个人简介 ├── skill.jsp 技能管理 ├── hometown.jsp 家乡简介 ├── feature.jsp 特色介绍 ├── message.jsp 留言板 └── admin/ 后台管理页面entity 只放字段和 getter/setterdao 只写 SQLservlet 只做参数接收和页面跳转JSP 只负责渲染。这样分工的好处是后面留言板加分页功能时只动 dao 和 servletJSP 模板不用改。这类老结构的 JSP 项目还可能用 web.xml 写一堆 servlet-mapping而这个平台走的是 Servlet 3.0 的 WebServlet 注解类上标注后 Tomcat 启动时自动注册 URL。两种写法效果一样如果项目要跑 Tomcat 7 以下就必须退回 web.xml。我的习惯是优先注解每新增一个 Servlet 不用去翻 XML排查 404 时少一个变量。3.2 一个能直接用的 JDBC 工具类手动 JDBC 的核心是连接工具类整个平台的 DAO 层都从它拿连接。这是最原始也最透明的写法适合课程设计的评分要求package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/hometown_platform?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; 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); } }Class.forName 负责把驱动类加载到 JVMMySQL 8 以上的驱动类名是 com.mysql.cj.jdbc.Driver老教程里的 com.mysql.jdbc.Driver 在 8.x 驱动里已经移除写错了直接 ClassNotFoundException。连接串里三个参数是血泪经验换来的。useSSLfalse 关闭 MySQL 8 默认开启的 SSL 校验不加会在本地连库时抛 SSL 相关异常serverTimezoneAsia/Shanghai 指定时区不加报 The server time zone value 错误characterEncodingutf8 保证 JDBC 层的中文读写编码和建库时的 utf8mb4 对齐。PASSWORD 按本机 MySQL 密码改。DriverManager 每次 getConnection 都新建物理连接高并发撑不住但课程设计访问量完全够。想往工程化靠把 DBUtil 换成 Druid 连接池DAO 里从 dataSource.getConnection() 拿连接其余代码不用改答辩加分的时候用得上。另外注意驱动 jar 必须放在 src/main/webapp/WEB-INF/lib 下IDEA Maven 项目在 pom.xml 引入 mysql-connector-j 依赖后会自动打包传统手工建项目 jar 放错位置会导致运行时报 ClassNotFoundException编译期却不报错。这是 JSP 项目最常见的环境坑。3.3 留言板链路从 JSP 表单到 Servlet 再到 DAO留言是平台里链路最完整的功能走一遍它其他模块的增删改查就都会了。前台 message.jsp 有一个表单游客登录后填内容提交请求交给 /message 这个 ServletServlet 取出会话里的 userId调用 DAO 插入数据库再重定向回留言页。package servlet; import dao.MessageDao; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; WebServlet(/message) public class MessageServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); String action request.getParameter(action); if (add.equals(action)) { Integer userId (Integer) request.getSession().getAttribute(userId); if (userId null) { response.sendRedirect(login.jsp); return; } String content request.getParameter(content); new MessageDao().insert(userId, content); response.sendRedirect(message.jsp); } } }两个设计点。action 参数用来区分同一个 Servlet 里的不同操作后面加 reply 操作只需再增加一个分支不用新建类。session 里存 userId 是最轻量的登录态方案课程设计不需要引入单点登录session 里没有 userId 直接重定向到 login.jsp防止未登录游客通过伪造表单直接留言。对应的 DAO 插入方法用 PreparedStatement 而不是 Statementpublic void insert(Integer userId, String content) { String sql INSERT INTO t_message(user_id, username, content) VALUES(?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, userId); ps.setString(2, getUserNameById(userId)); ps.setString(3, content); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } }PreparedStatement 用 ? 占位setInt/setString 绑定参数。一是防 SQL 注入留言内容里出现单引号不会被拼进 SQL二是重复执行时数据库有预编译缓存课程设计规模体现不明显但这个习惯面试常问。getUserNameById 是 DAO 里另一个查询方法根据 userId 查 t_user 表补全 username 冗余字段。管理员在后台看到的留言列表需要把已回复和未回复的都列出来回复时走同一个 Servlet 的 reply 分支if (reply.equals(action)) { String id request.getParameter(id); String reply request.getParameter(reply); new MessageDao().reply(id, reply); response.sendRedirect(admin/messageList.jsp); }reply 对应的 SQL 是 UPDATE t_message SET reply ?, reply_time NOW() WHERE id ?DAO 里同样用 PreparedStatement 绑定两个参数。到这里留言功能的前台提交、后台回复、页面展示全部闭环剩下的技能管理和家乡特色管理本质就是 t_skill、t_hometown 两张表的增删改查参考同样的模式改表名和字段名即可。4. 前端页面与功能模块轮播、下拉菜单与留言回复4.1 欢迎页照片轮播的实现思路资源里带着 sb-admin-2.css、all.css、fontawesome.css 这些文件说明页面原型基于 SB Admin 2 这类 Bootstrap 管理模板改造Font Awesome 负责图标。欢迎页 index.jsp 的照片轮播是整个平台的入口课程设计通常要求自动轮播加指示器切换常见做法是直接用 Bootstrap 的 Carousel 组件。div idhomeCarousel classcarousel slide>ListString categoryList new SkillDao().listCategories(); request.setAttribute(categoryList, categoryList); request.setAttribute(selectedCategory, skill.getCategory()); request.getRequestDispatcher(skillEdit.jsp).forward(request, response);然后 JSP 用 JSTL 的 c:forEach 渲染下拉框% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % select namecategory classform-control option value请选择分类/option c:forEach items${categoryList} varc option value${c} ${c selectedCategory ? selected : }${c}/option /c:forEach /selectselectedCategory 是当前技能记录已有分类编辑时通过 c selectedCategory 判断命中就输出 selected 属性下拉框能回显到原有值。新建技能时 selectedCategory 为空所有选项都不选中。categoryList 来自 SkillDao 的 SELECT DISTINCT category FROM t_skill用户后台新增分类后下拉框也跟着变。JSTL 标签库要引入 jstl-1.2.jar 和 standard.jar漏了页面上报 java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config。4.3 管理后台回复留言普通用户与管理员的权限边界后台页面放在 admin 目录下访问前要判断登录角色。用 Servlet 过滤器统一拦截比每个页面单独判断更省事WebFilter(/admin/*) public class AdminFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpSession session ((HttpServletRequest) req).getSession(); Object role session.getAttribute(role); if (role ! null Integer.valueOf(0).equals(role)) { chain.doFilter(req, res); } else { ((HttpServletResponse) res).sendRedirect(../login.jsp); } } }这个过滤器只拦 /admin/* 路径管理员 session 里 role0 才放行不然直接跳回登录页。登录 Servlet 在验证通过后要同时往 session 里放 userId 和 role 两个属性role 是后台过滤器判断的依据。留言列表页显示留言内容时如果 reply 字段不为空追加一段带时间的回复块c:if test${not empty msg.reply} div classreply-box管理员回复${msg.reply} span classtext-mutedfmt:formatDate value${msg.replyTime} patternyyyy-MM-dd HH:mm//span /div /c:iffmt:formatDate 需要引入 JSTL 的 fmt 标签库把数据库 datetime 格式化成可读字符串。回复时间没值时 c:if 自动跳过整个 div已回复和未回复在视觉上一眼区分。4.4 照片管理新增家乡特色时上传怎么处理课程设计里最常见的上传方案是把图片存到项目的 upload 目录数据库只存相对路径。写一个 UploadServlet 处理 multipart/form-data 表单WebServlet(/upload) MultipartConfig(maxFileSize 5 * 1024 * 1024) public class UploadServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Part part request.getPart(image); String fileName System.currentTimeMillis() _ part.getSubmittedFileName(); String uploadPath getServletContext().getRealPath(/upload); part.write(uploadPath File.separator fileName); // 相对路径 /upload/fileName 存到 t_hometown.image_url } }MultipartConfig 限制单张图片最大 5MB文件名加时间戳前缀避免不同用户传同名文件互相覆盖。getRealPath(/upload) 拿的是部署目录下的绝对路径war 包方式部署时目录在 Tomcat 的 webapps/项目名/upload 下重新部署会丢所以正规做法是图片落盘到服务器固定目录数据库存完整访问路径课程设计用项目内目录最省事只要答辩演示时不重复部署新包就行。5. 避坑JSP MySQL 从启动到交付的五个真实翻车点5.1 中文乱码三处编码不一致页面全是问号现象留言板提交中文后数据库里存的是问号页面显示也全是乱码。原因JSP 页面、请求参数、数据库连接串和数据库表四处编码只要一处不是 UTF-8中文就保不住。Tomcat 8 之前默认请求编码是 ISO-8859-1表单提交的 UTF-8 中文会被按单字节解析。解决建库用 utf8mb4JSP 页面顶部加 % page contentTypetext/html;charsetUTF-8 %Servlet 入口统一调 request.setCharacterEncoding(UTF-8)。更稳妥的做法是加全局过滤器WebFilter(/*) public class EncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding(UTF-8); res.setContentType(text/html;charsetUTF-8); chain.doFilter(req, res); } }过滤器拦所有请求在进入业务代码前把编码定好。注意 setCharacterEncoding 要在 getParameter 之前执行前面已经读过参数这次设置就失效了。排查顺序也有讲究。先看数据库里存的值是不是问号是问号说明连接串或表字符集有问题不是问号说明页面渲染编码有问题。页面乱码但库正常优先检查 JSP 的 page 指令和 response.setContentType库里就是问号优先检查连接串的 characterEncoding 和建表字符集。两步定位别从头到尾瞎试。5.2 404 页面找不到artifact 没部署还是路径少了项目名现象Tomcat 能启动但访问 http://localhost:8080/ 是白页或 404。原因IDEA 里 Artifact 没部署到 Tomcat 的 Deployment 列表访问路径少了项目名 context pathweb.xml 没配置 welcome-file。解决打开 IDEA 的 Run/Debug Configurations确认 Deployment 标签页里有项目 artifactApplication context 填项目名。访问路径用 http://localhost:8080/项目名/比如项目名是 hometown_platform 就访问 http://localhost:8080/hometown_platform/。如果项目没配主页在 web.xml 里加welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list还有一个隐藏点JSP 文件放错目录。WEB-INF 下的 JSP 外部无法直接 URL 访问如果把 index.jsp 放进了 WEB-INF根路径访问必然 404。IDEA 项目的 src/main/webapp 是根目录页面必须放在根目录或其子目录下WEB-INF 只放 lib、classes 和 web.xml。5.3 JDBC 连接失败驱动缺失与 MySQL 8 认证方式对不上现象启动后点任何需要查库的页面控制台报 ClassNotFoundException 或 SQLNonTransientConnectionException。原因驱动 jar 不在 WEB-INF/lib 下MySQL 8 默认的 caching_sha2_password 认证方式与老驱动不兼容连接串缺 useSSL、serverTimezone、allowPublicKeyRetrieval 参数。解决检查三条。第一mysql-connector-java 或 mysql-connector-j 的 jar 必须放在 src/main/webapp/WEB-INF/libMaven 项目确认依赖已引入第二驱动类名用 com.mysql.cj.jdbc.Driver第三连接串写成 jdbc:mysql://localhost:3306/hometown_platform?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue。allowPublicKeyRetrievaltrue 是 MySQL 8 首次连接报 Public Key Retrieval is not allowed 的关键参数本机 MySQL 8.0 以上基本必加。如果手头不方便升级驱动另一个应急方案是把 MySQL 用户认证方式改回 mysql_native_passwordALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 123456; FLUSH PRIVILEGES;老版本驱动只认识 mysql_native_passwordMySQL 8 默认的 caching_sha2_password 会让老驱动握手失败。注意 MySQL 8.4 开始默认不再支持 mysql_native_password改认证方式只适合应急优先升级驱动。提示ALTER USER 会影响该用户所有连接的认证方式执行前先在 Navicat 里确认当前能连上改完再用新驱动验证。5.4 JSP 编译报错Tomcat 和 JDK 版本不匹配现象JSP 页面访问时控制台报 Unable to compile class for JSP页面里 import 的 javax.servlet 全部标红。原因Tomcat 10 及以上把包名从 javax.servlet 换成了 jakarta.servlet老课程设计代码全是 javax 开头放在新版 Tomcat 上自然编译不过。另外 Tomcat 10 要求 JDK 11本机如果是 JDK 8 也会出问题。解决课程设计项目锁死 Tomcat 8.5 或 Tomcat 9配 JDK 8这是最稳的组合。不要为了追新装 Tomcat 10除非准备好把所有 import 的 javax.servlet 批量替换成 jakarta.servlet。IDEA 里确认 Project Structure 的 SDK 和 Tomcat 的 JRE 设置一致改完重启 Tomcat 再试。5.5 SQL 关键字冲突desc、order 这些字段名别用现象SQL 执行报 You have an error in your SQL syntax反复检查 SQL 语句本身没写错。原因字段名或表名撞了 MySQL 保留字。这个平台里最容易踩的是把技能描述字段命名为 desc但 DESC 是 MySQL 的排序关键字还有留言排序字段用 order。解决建表时避开保留字描述字段用 description 或 content排序字段用 sort_order 或干脆不用。表已建好不想改字段名的话SQL 里用反引号包起来比如 SELECTdescFROM t_skill能跑但不是长久之计答辩时老师看到反引号会追问字段命名规范一次性改名字最省心。6. 部署验证与进阶war 包从 IDEA 到 Tomcat 的收尾技巧项目在 IDEA 里跑通只算完成一半课程设计交付通常要求能部署到独立 Tomcat 的 war 包。我用 IDEA 打包传统 JSP 项目走固定三步File → Project Structure → Artifacts 里选 Web Application: ArchiveName 填项目名Build → Build Artifacts → Rebuild生成到 out/artifacts 目录后扔进 Tomcat 的 webapps 目录启动 Tomcat 会自动解压部署。部署完按下面的清单逐一验证比直接交作业稳验证项操作期望结果首页http://localhost:8080/项目名/轮播自动播放导航可用注册登录首页点注册回登录页登录登录后 session 生效游客留言登录后提交留言刷新后留言出现在列表后台回复admin/123456 进后台回复前台留言出现回复块和时间技能/特色管理新增一条记录再删除列表随操作刷新交付之外三个改进方向按性价比排序时间紧就只做第一个。第一留言分页留言一多列表就长Servlet 里接收 page 参数DAO 用 LIMIT offset, sizeJSP 底部渲染上一页下一页按钮。第二DBUtil 换 Druid 连接池配置文件配最大连接数和等待时间DAO 接口不动。第三留言表单加一层 JS 非空校验后端 Servlet 再校验一遍双保险答辩能多讲两句。从那以后我每次接手 JSP 项目都强制自己先走三件事确认驱动 jar 在 WEB-INF/lib、启动前看一遍控制台日志、所有页面访问前确认字符集。这三件事做完项目基本不会被环境和乱码卡住。希望这份资源里的建库脚本和页面模板能帮你在课程设计这条路上少翻几次车。本文还有配套的精品资源点击获取