简介这是一份面向JSP初学者的课程设计小项目——留言本系统采用JSPJavaBeanAccess组合开发适合正在完成Web课程设计或想快速上手JSP开发流程的学生。系统无需配置数据源放入Tomcat即可运行并实现了UBB代码解析、UBB头像、正则表达式过滤、管理登录验证码以及MD5加密管理密码等功能完整展示了JSP基础应用的常见写法。压缩包共194个文件约621KB其中157个gif主要作为表情与头像资源13个jsp为页面主体还包含5个class、5个css、4个db、4个js及1个mdb数据库文件目录按页面、样式、类文件和数据库归置便于快速定位。已有158人学习下载。通过这份资源可以拿到完整可跑的留言本项目既能参考JavaBean封装数据库操作、JSP页面与样式分离的组织方式也能学习验证码、MD5加密、正则替换等实用技巧适合用于课程设计参考和入门练习。1. 把JSP课程设计资源真正跑起来JavaBeanAccess/SQL双数据库登录实战期末课程设计摊在面前JSP登录系统作为经典题目简单却五脏俱全JavaBean、数据库操作、前台页面、会话管理全占了。如果你手里拿到一份jspbook.rar里面是带JavaBean封装、Access与SQL Server双数据库支持的课程设计源码那这篇笔记要帮你解决的是怎么让它在你的笔记本上半个小时内跑起来并且每一口坑都能说清楚原因。适合正在被课程设计追着跑的学生也适合想快速复盘传统JSP项目结构的初学者。这份资源的最大价值不是代码本身而是把一个可演示的登录系统从源码到数据库再到部署的路径完整串了起来跑通它JSP里最经典的几件事你就都见过了。2. 导入与部署先把这套JSP项目在本地跑通并看清目录结构2.1 版本选型JDK、Tomcat与IDE怎么配才不会踩老项目的雷传统JSP课程设计项目大多是2015到2018年生成的代码里全是javax.servletJavaBean也是老写法。给它配环境第一原则是「不要用最新版」。我一般固定三个版本JDK 8、Tomcat 8.5或9.0、IDEA 2021以上的版本都能兼容。JDK 8对老编译参数兼容性好Tomcat 8.5/9还在javax包时代正好匹配项目代码。你要是用Tomcat 10或11启动时ClassNotFoundException找javax.servlet会让你怀疑人生这个后面第5章细说。IDE选择上IDEA Ultimate自带Java Enterprise支持Community版也能跑传统Web项目手动配置Tomcat就行。学校机房如果还在用MyEclipse导入逻辑也差不多只是WebRoot识别方式略有差异。还有一点项目路径不要出现中文和空格。很多老项目在别人的机器上能跑到你这儿就乱码、404、失败仔细一查全是路径问题。这一条放在版本选型里一并解决最划算。2.2 资源包结构rar里到底装了些什么拿到jspbook.rar先不要急着解压到桌面就双击跑。花两分钟看一眼目录结构能省掉后面大量无用功。常见的课程设计资源包基本长这样目录作用src/bean/JavaBean类用户Bean、数据库连接Beansrc/servlet/部分版本有Servlet控制器如果没有就忽略WebRoot/JSP页面、JS、CSS、WEB-INFWebRoot/WEB-INF/lib数据库驱动jar包db/Access数据库文件.mdb或.accdb、SQL脚本.sql课程设计文档.doc/.docx答辩用的设计说明书打开资源包先确认三件事WEB-INF/lib里有没有UCanAccess的jar决定你后面用哪种Access驱动db目录里给的是accdb文件还是mdb文件以及有没有对应的SQL建库脚本WebRoot下有没有web.xml。这三件事直接决定你能不能跑起来以及数据库环节要不要额外处理。如果这个资源包给的是纯SQL Server版那db目录里一般只有一个.sql文件没有Access物理库驱动和连接方式差得比较远第3章会分别给代码。还有个小细节资源包里如果同时出现Access和SQL两个版本的脚本先跑Access版。它不用额外装数据库服务SQL Server版还得先在本机把MSSQL服务装好、建库、导数据链路更长。把容易出错的环节后置能明显提升第一遍跑通的概率。2.3 从RAR到运行IDEA导入与手动配置Tomcat的完整步骤下面以IDEA Community版为例把导入到运行的步骤完整走一遍。第一步是解压到一个全英文路径比如D:\jspbook。# 解压到英文路径避免中文目录导致编译期和运行期双重乱码 mkdir D:\jspbook # 把 jspbook.rar 内容解压到 D:\jspbook 下 # 用 7-Zip 或 WinRAR 均可解压后确认 src 和 WebRoot 在同一个根目录下第二步IDEA新建一个空Project把解压出来的src目录和WebRoot目录直接拖进Project面板。IDEA会弹提示是否把src标记为Sources Root选确认如果识别出Web资源目录也会问是否加到Web Facet里同样确认。第三步是关键Community版不会自动识别传统Web项目的根目录必须手动指定。File - Project Structure - Facets - 添加 Web Web Resource Directory: 选择 WebRoot 目录 Deployment Descriptors: WebRoot/WEB-INF/web.xml这里很多人漏掉第三步就急着重启Tomcat结果页面全部404原因就是Tomcat部署包里根本没把WebRoot下的JSP打进去。第四步配置TomcatRun菜单 - Edit Configurations - 左上角加号 - Tomcat Server - Local。打开Deployment标签点加号选Artifact把项目加进去Application context填 /jspbook。第五步启动浏览器访问http://localhost:8080/jspbook/index.jsp看到登录页就是通了。整个过程中最容易出问题的就是第三步和第五步的路径一致性。Artifact里Output Layout要把WebRoot下的全部资源包含进去否则本地Tomcat能启动、页面却找不到。我一般还会顺手看一眼Tomcat启动日志里有没有Deployment failed提示比盯着浏览器看404靠谱。老项目在IDEA里第一次跑起来靠的就是这几个目录指向不出错。3. JavaBean与数据库连接层Access和SQL Server两套驱动的切换方案3.1 课程设计里为什么选JavaBean评分点与可维护性课程设计答辩时老师最常看的点三层有没有分离、数据库有没有封装、页面里有没有散落SQL代码。JavaBean恰好把「业务逻辑」从页面里抽出来。这个资源包里JavaBean负责两件事拿数据库连接、做登录校验。JSP页面只用jsp:useBean调用页面里看不到一行SQL这是传统JSP项目最标准的写法也是答辩时能随口讲清楚的设计点。很多新手刚拿到源码时第一反应是找「主函数」但Web项目里不存在这种东西。你要先找到bean包里的类再顺着JSP页面的useBean标签找到调用入口。这个资源包如果结构规整核心就两个BeanDBConnection负责递数据库连接LoginBean负责判断账号密码。先把结构在脑子里立起来后面看代码就不乱。3.2 DBConnectionAccess连接与UCanAccess替代ODBC老版课程设计资源里Access连接通常走JDBC-ODBC桥再加ODBC数据源典型代码长这样// 老写法JDK 8以后不推荐 Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); String url jdbc:odbc:userdb;这段代码当年能用现在基本跑不通。原因不复杂JDK 8里这个桥还能将就用JDK 9直接移除了类加上Windows 10/11 64位系统的ODBC数据源管理32位和64位入口很容易配错。所以我默认把连接层换成UCanAccess改动只有连接驱动和URL两处。package bean; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * 数据库连接类UCanAccess 纯Java驱动不依赖ODBC */ public class DBConnection { private static final String DRIVER net.ucanaccess.jdbc.UcanaccessDriver; private static final String URL jdbc:ucanaccess://D:/jspbook/db/userdb.accdb; private static final String USER ; private static final String PASSWORD ; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }逻辑说明驱动类名net.ucanaccess.jdbc.UcanaccessDriver是核心URL前缀jdbc:ucanaccess://后跟Access文件的绝对路径。Access库一般没有用户名密码USER和PASSWORD留空字符串。Class.forName在静态块里执行类第一次加载时完成驱动注册这个顺序在Java里是标准做法。参数说明UCanAccess 5.x要求JDK 8以上依赖jackcess、commons-lang3、hsqldb、commons-io这几个jar必须一起放进WEB-INF/lib只放一个主jar照样报ClassNotFound。数据库文件路径用正斜杠或双反斜杠都行但路径里不要带中文。如果资源包给的是.mdb老格式UCanAccess同样支持代码不用改。如果资源包里恰好是SQL Server版驱动和URL换成另一套其余代码结构一模一样// SQL Server 连接参数 Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); String url jdbc:sqlserver://localhost:1433;DatabaseNamejspbook; String user sa; String password 123456;逻辑说明SQL Server是服务型数据库URL指向服务地址和端口不是文件路径。1433是默认端口DatabaseName对应你手动创建的业务库名。这里有个常见误导sa密码填错会报login failed但服务本身已经连上了报错信息里带的是SQL Server的登录错误码跟Access那类驱动错误完全不是一回事。参数说明SQL Server安装时可以选Windows身份验证或混合模式默认Windows身份验证模式下sa账号处于停用状态需要先在SSMS里把服务器身份验证改为混合模式、启用sa账号并设好密码再改这里的连接串。资源包里的SQL脚本一般是建库和建表语句在SSMS里执行一遍就能把表结构建好。3.3 用配置文件解耦双数据库一套代码切换Access和SQL Server这个资源包的卖点是双数据库支持我在连接层会再加一个配置开关让一套代码能跑两种库。做法是加一个db.properties放classpath根目录# db.properties放到 src 根目录 db.typeaccess access.drivernet.ucanaccess.jdbc.UcanaccessDriver access.urljdbc:ucanaccess://D:/jspbook/db/userdb.accdb access.user access.password sql.drivercom.microsoft.sqlserver.jdbc.SQLServerDriver sql.urljdbc:sqlserver://localhost:1433;DatabaseNamejspbook sql.usersa sql.password123456配套的DBConnection改成读配置文件package bean; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class DBConnection { private static String driver; private static String url; private static String user; private static String password; static { try (InputStream in DBConnection.class.getClassLoader() .getResourceAsStream(db.properties)) { Properties p new Properties(); p.load(in); // db.type 是总开关填 access 走 Access填 sql 走 SQL Server if (access.equals(p.getProperty(db.type))) { driver p.getProperty(access.driver); url p.getProperty(access.url); user p.getProperty(access.user); password p.getProperty(access.password); } else { driver p.getProperty(sql.driver); url p.getProperty(sql.url); user p.getProperty(sql.user); password p.getProperty(sql.password); } Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } }逻辑说明getResourceAsStream(db.properties)从classpath根目录读配置不依赖具体磁盘路径。改库时只改db.type和对应前缀参数Java代码一行不动。这个设计放课程设计文档的「系统设计」章节里讲比直接贴原生连接代码得分高。参数说明try-with-resources会自动关闭InputStream老项目里经常能看到忘记关流的写法自己写的时候别学。Properties读出来的值全是字符串db.type比较用equals配置文件里不要带多余空格。SQL Server的URL里分号在properties文件里不需要转义直接写就行。4. 登录模块完整实现从表单校验到Session管理到SQL注入边界4.1 登录页面前端校验与后端校验的分工登录页是课程设计的第一张脸页面要做到两件事版式干净、校验双保险。前端用JavaScript做快速提醒后端在JavaBean里做最终校验。前端校验可以被绕过这层防的是手误后端校验才是真正的安全边界这个分工在答辩时几乎必问。% page contentTypetext/html;charsetUTF-8 languagejava % html headtitle用户登录/title/head body div stylewidth:360px; margin:80px auto; h3用户登录/h3 form actiondoLogin.jsp methodpost onsubmitreturn checkForm() 用户名input typetext nameusername idusername required/ 密 码input typepassword namepassword idpassword required/ button typesubmit登 录/button /form % if (request.getAttribute(errorMsg) ! null) { % p stylecolor:red;% request.getAttribute(errorMsg) %/p % } % /div script function checkForm() { var u document.getElementById(username).value.trim(); var p document.getElementById(password).value.trim(); if (u || p ) { alert(用户名和密码不能为空); return false; } return true; } /script /body /html逻辑说明onsubmit返回false时表单不提交。错误提示用request.getAttribute(errorMsg)回显登录失败时用户能看到具体原因而不是直接跳到空白页。这里注意一个细节表单字段的name必须和JavaBean属性名一致因为后面要靠jsp:setProperty property*自动装配写成nameuser而Bean属性是username就会装配不上。参数说明methodpost是硬性要求登录请求不能用GET否则密码会明文出现在地址栏。required是HTML5原生非空校验checkForm()里再补一次trim空判断两层前端校验叠加。页面编码用UTF-8与后面乱码排查那章配合着看。4.2 LoginBeanPreparedStatement怎么写才算真正防住了SQL注入登录逻辑最忌讳字符串拼接SQL。一句 OR 11就可以绕过密码直接登录这个现象在Access和SQL Server上同样成立。课程设计里用PreparedStatement是标配代码里也容易讲清楚。// 不安全写法反面教材 String unsafeSql SELECT COUNT(*) FROM users WHERE username username AND password password ; // 安全写法PreparedStatement 参数化查询 public boolean checkLogin() { String sql SELECT COUNT(*) FROM users WHERE username? AND password?; try (Connection conn DBConnection.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); ResultSet rs ps.executeQuery(); if (rs.next() rs.getInt(1) 0) { return true; } rs.close(); } catch (Exception e) { e.printStackTrace(); } return false; }逻辑说明?占位符让PreparedStatement把用户输入当字面量不参与SQL结构解析。传入 OR 11时它只是一段普通字符串不会成为查询条件的一部分。COUNT(*)用rs.getInt(1)取值大于0说明账号密码匹配这个写法比查出所有字段再遍历判断更轻。参数说明setString(1, username)里的下标从1开始不是0。如果查询条件增加一个状态字段就在SQL里再写一个?再按顺序set一次。username和password在Bean的setter里最好先trim()再存去掉首尾空格能省掉一批「我明明输入对了」的排查时间。try-with-resources保证Connection和PreparedStatement自动关闭这条对Access尤其重要第5章会展开。4.3 登录处理页与Session登录态的建立、保持和销毁传统JSP登录处理一般在doLogin.jsp里完成它负责调用Bean、判断结果、跳转。理解这个页面的生命周期整个登录模块就通了。% page contentTypetext/html;charsetUTF-8 languagejava % jsp:useBean idloginBean classbean.LoginBean scopepage/ jsp:setProperty nameloginBean property*/ % if (loginBean.checkLogin()) { // 登录成功写入 session session.setAttribute(loginUser, loginBean.getUsername()); response.sendRedirect(welcome.jsp); } else { // 登录失败回登录页并带错误提示 request.setAttribute(errorMsg, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } %逻辑说明scopepage表示这个Bean只在这个页面实例里存活用完即释放课程设计场景下足够。property*自动从request请求参数里按属性名匹配填充这就是4.1强调字段名必须一致的原因。session里存了loginUser后后续页面靠它识别登录状态。forward是服务器内部跳转地址栏不变request里带的值还能用sendRedirect是浏览器重定向地址栏变化request里的值全丢所以错误提示必须塞进request再forward。受保护页面顶部的守卫代码就三行% Object user session.getAttribute(loginUser); if (user null) { response.sendRedirect(login.jsp); return; } %逻辑说明session里的loginUser不存在就重定向回登录页return必须写否则页面下方代码会继续执行守卫就失效了。登出操作一行session.invalidate()可以完成但不要放在普通链接的href里用GET触发那样会被浏览器预加载误触发应该单独放一个logout.jsp处理。这套逻辑在答辩时按「登录态建立、保持、销毁」三个词讲清晰且加分。5. 避坑JSP课程设计最常见的五个运行问题与排查记录5.1 ODBC数据源报错64位系统下Access驱动翻车现象项目正常启动登录页也能打开一点提交按钮Tomcat控制台报java.sql.SQLException: [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序。原因老资源包用的是JDBC-ODBC桥加手工配置的ODBC数据源。JDK 8里这个桥还能用但不推荐JDK 9直接删掉了sun.jdbc.odbc.JdbcOdbcDriver这个类。再加上Windows 10/11 64位系统下ODBC数据源管理工具有32位和64位两个版本控制面板进错入口就配到了另一个版本里程序根本读不到。解决放弃ODBC换UCanAccess纯Java驱动。把ucanaccess主jar和jackcess、commons-lang3、hsqldb、commons-io几个依赖jar放进WEB-INF/lib驱动类和URL按第3章的方式改。数据库文件路径用绝对路径并且保证全英文。改完记得清缓存重启Tomcat这个坑我见过有人改了代码忘了重启卡了半天。5.2 中文乱码JSP页面、请求、数据库三层编码对不齐现象用户名输入中文登录后welcome.jsp页面上显示一串??或者欢迎语变成乱码刷新几次后有时正常有时乱。原因传统JSP项目三个环节都在影响字符集JSP页面本身的pageEncoding、Tomcat接收请求时的解码方式、数据库表字段的字符集。老项目常把pageEncoding设为GBK而后台按UTF-8解码两边一碰撞就乱。解决统一UTF-8三步走。第一步所有JSP页面头部加% page contentTypetext/html;charsetUTF-8 %。第二步在web.xml里配置Tomcat内置的SetCharacterEncodingFilter把encoding参数设为UTF-8并映射到所有路径这比在代码里手动request.setCharacterEncoding更可靠因为过滤器在Servlet处理前就完成了编码统一。第三步SQL Server版连接URL加;encodingutf-8Access版则确认Windows控制面板里「非Unicode程序的语言」设置的是简体中文。三步做完还乱码就逐页检查是否某个页面漏了pageEncoding。5.3 Access数据库文件被锁多连接同时操作导致无法访问现象连续登录几次后Tomcat控制台报另一个程序正在使用此文件进程无法访问数据库突然打不开重启Tomcat以后又能坚持一阵子。原因Access是文件型数据库不是服务型数据库写操作是独占锁。课程设计代码里如果每个请求都新建连接用完不关多个连接同时碰同一个.accdb文件就会触发锁。这和并发量无关哪怕两个请求同时写也会出问题。解决第一所有获取Connection的地方必须关闭直接在代码里用try-with-resources让Connection、Statement、ResultSet自动关。第二课程设计场景别做连接池连接用完即关连接池反而会让文件长时间被占。第三检查有没有后台定时任务在持续打开数据库。最终防线是换成SQL Server那是答辩级优化先按前两条排查基本能解决。5.4 Tomcat 10启动报ClassNotFoundjavax和jakarta的版本鸿沟现象用Tomcat 10或11部署老项目启动时控制台报ClassNotFoundException: javax.servlet.http.HttpServlet页面全部打不开。原因Servlet规范从5.0开始改命名空间把所有javax.*包迁移到jakarta.*。老课程设计项目全是javax开头Tomcat 10的类加载器里不再提供javax包所以直接找不到类。这不是资源包的锅是环境版本不匹配。解决老项目用Tomcat 8.5或9.0。IDEA里新建Tomcat Server时版本选9部署同一个Artifact问题立刻消失。如果手里只有Tomcat 10把代码里所有import javax.servlet改成import jakarta.servlet也能解决但改完后有些第三方库内部引用的还是javax不一定会完全消停所以换Tomcat版本是更稳的路径。5.5 启动后404Web根目录没被IDE认出来现象Tomcat正常启动控制台也没有报错但浏览器访问http://localhost:8080/jspbook/index.jsp返回404。原因IDEA Community版不会自动识别传统Web项目的WebRoot目录。Facets配置里Web资源目录指错了位置Artifact打包时没有把WebRoot下的JSP文件包含进去部署到Tomcat的包里就只有class文件没有页面。解决打开Project StructureFacets标签里选中Web把Web Resource Directory指向WebRoot目录Deployment Descriptors指向WebRoot/WEB-INF/web.xml再打开Artifacts确认Output Layout里WebRoot下的资源在部署包内。改完重新build再启动然后到Tomcat的webapps目录看解压出来的文件夹里有没有JSP文件。这个坑在MyEclipse导出的老项目上尤其常见因为MyEclipse默认WebRootIDEA默认webapp两个根目录名不一样。6. 打包与验收把课程设计升级成可部署的WAR并扩充加分功能6.1 WAR打包三步走传统JSP项目的交付物是war文件拷到Tomcat的webapps目录就能自动部署不用开IDE。IDEA里打包路径是File - Project Structure - Artifacts - 加号选Web Application Archive然后Build菜单里Build Artifacts执行构建war生成在out目录。把它复制到Tomcat的webapps目录重启Tomcat自动解压访问http://localhost:8080/jspbook/就是完整项目。这里有个几乎必踩的坑war包里WEB-INF/lib下的驱动jar是否齐全。本地能跑是IDEA运行配置自动把lib带进classpath打war时如果Artifacts的Output Layout里没把lib加进去换台机器就报ClassNotFound。打包前手动看一眼war里WEB-INF/lib有没有驱动jar比现场救火强。6.2 三个改动不大但答辩加分的增强点第一密码MD5加密存储注册时用MessageDigest把明文转MD5写库登录时比对MD5值数据库里不再存明文。第二登录页加四字符验证码用Graphics2D画带干扰线的图片字符串存session提交时比对验证码刷新和失效都能讲两句。第三把登录失败次数记进数据库连续三次锁账号十分钟。注意Access对并发写不友好这个功能建议放在SQL Server版本上实现。去年我带学弟调这个项目Access驱动和中文乱码两个坑几乎每台机器都要踩一遍后来养成了一个习惯任何老课程设计项目到手先确认数据库驱动和Tomcat版本再动任何源码。你手里这份jspbook.rar要是还没跑通按这个顺序来一遍很大概率能少熬两晚上。希望帮到你。本文还有配套的精品资源点击获取