资讯详情

资讯详情

Servlet+JSP+JDBC房屋租赁管理系统:从HTTP请求到SQL的完整链路解析

简介这套基于ServletJsp的房屋租赁管理系统面向计算机相关专业正在做毕业设计的学生以及需要项目实战的Java学习者解决从需求分析到系统实现的一站式参考需求。系统功能覆盖会员登录、免费注册、信息检索、新闻中心、留言板、房源发布出售/求租/求购、交易信息管理、统计报表等模块前后端技术栈清晰后端采用Servlet、JavaWeb与JDBC前端采用JSP、jQuery、CSS数据库使用SQL Server运行于JDK8及IDEA或Eclipse环境。压缩包约13.69MB主要文件类型包括Java源码、SQL Server数据库脚本、毕业论文文档、系统详细配置指导以及项目演示PPT便于直接导入开发环境并对照文档启动调试。资源还附带论文和PPT可省去撰写文档的精力适合作为毕业设计参考和JavaWeb综合练习项目。目前已有250人学习下载生态与口碑经过验证对初学与进阶者均有实际价值。1. 别小看这套ServletJSPJDBC房屋租赁管理系统它其实是最适合理解的Web工程如果只听说过Spring Boot第一次打开这种老派JavaWeb项目可能会懵没有自动配置、没有Starter连数据库驱动都要自己放进lib目录。但这套房屋租赁管理系统反而是我见过最适合拿来读“Http请求如何变成SQL”这一过程的毕设项目它把Servlet、JSP、JDBC三者做得非常直白前台有会员注册登录、出租出售求租求购、留言公告和信息检索后台有交易管理、房屋统计和销售租金报表覆盖了一个业务系统从用户操作到管理决策的完整闭环。适合正在做毕设、或想用传统JavaWeb练手的同学你不需要先掌握框架只需要JDK8、IDEA或Eclipse、SQL Server和Navicat就能把它跑起来改起来也没有那么多魔法。2. 技术栈与工程结构把一次请求从JSP页面追踪到SQL Server的完整链路2.1 技术选型为什么这种“老技术”仍是毕设在用的大热门先聊清楚这套东西用什么写的。后端是Servlet和JavaWeb前端是JSP、jQuery和CSS持久层用JDBC直连没有MyBatis没有Spring数据库选了SQL Server开发工具用IDEA或Eclipse加Navicat。这种组合在现在看起来确实不潮但它恰好是JavaWeb课设和毕设的经典样板。原因有三第一Servlet容器由Tomcat管理你只需要写一个类继承HttpServlet并重写doGet/doPost请求如何分发、如何拿到请求参数、如何跳转页面这些底层机制全部暴露在你面前比Spring Boot里一个RestController直白得多。第二JDBC虽然代码冗余但正好能让你理解Connection、PreparedStatement、ResultSet的生命周期后面再学MyBatis时你会知道它在替你做什么。第三这套系统不是单个CRUD demo它有前台发布、后台统计这种业务分层能体现面向对象和分层设计能力。可能有人会问为什么不用Spring Boot对于毕设答辩来说老师更想看的是你如何自己控制请求转发和数据库连接而不是依赖一个黑匣子。这套房屋租赁管理系统的数据表、业务逻辑并不复杂用ServletJSP写反而让每个环节都可调试。前端的jQuery在这里主要用来做异步校验、弹窗和局部刷新CSS负责界面美观整体上不需要node_modules那套构建链路下载下来就能跑。2.2 包结构与源码导航从Controller到Dao的代码地图拿到源码后先别急着点运行。建议先看一眼工程目录确认代码组织方式。这套系统虽然不同版本包名可能不一样但通常遵循下面的结构rent_house ├── src │ ├── com.rent.servlet # Servlet控制器对应MVC中的Controller │ │ ├── LoginServlet.java │ │ ├── RegisterServlet.java │ │ ├── HouseServlet.java │ │ ├── MemberServlet.java │ │ └── StatisticServlet.java │ ├── com.rent.entity # 实体类对应数据库表 │ │ ├── Member.java │ │ ├── House.java │ │ ├── Notice.java │ │ └── Message.java │ ├── com.rent.dao # 数据访问层写JDBC │ │ ├── BaseDao.java │ │ ├── MemberDao.java │ │ └── HouseDao.java │ ├── com.rent.util # 工具类 │ │ ├── DBHelper.java │ │ └── StringUtil.java │ └── com.rent.filter # 过滤器如登录拦截、编码过滤 │ └── EncodingFilter.java ├── WebContent或者webapp │ ├── index.jsp # 前台首页 │ ├── login.jsp # 会员登录 │ ├── register.jsp # 免费注册 │ ├── news.jsp # 新闻中心 │ ├── house_list.jsp # 出租/出售信息列表 │ ├── house_detail.jsp # 房屋详细 │ ├── member # 会员中心页面组 │ ├── admin # 后台管理页面组 │ ├── css │ ├── js │ ├── images │ └── WEB-INF │ ├── web.xml # Servlet映射、欢迎页面、过滤器配置 │ └── lib # 已放入的jar包这个结构很典型Servlet不直接写SQL它先调用Dao层Dao层通过DBHelper获取连接执行SQL后把结果封装成实体类再request.setAttribute(list, list)转发到JSP由JSP用jSTL或Java脚本片段循环输出。记忆时可以把它当作一条流水线JSP发请求 → Servlet接参数 → Dao查数据库 → 回到Servlet → 转发到另一个JSP展示。这里有个容易忽略的地方web.xml里配置了Servlet的url-pattern比如LoginServlet映射到/loginHouseServlet映射到/house/list、/house/add、/house/delete等。如果你想加新功能需要同时在Servlet类上加WebServlet或在web.xml里声明否则访问会404。老项目用web.xml维护路由不像Spring Boot用注解一把梭所以添加新页面时别忘了这一步。2.3 数据库设计会员、房源、交易、留言和公告的实体关系这套系统的业务除了出租信息还包括出售信息、求租信息、求购信息说明它把“发布房源”和“寻找房源”两条线都做了。数据库脚本文件通常以.sql结尾用Navicat执行即可。核心表大致如下。表名关键字段作用t_membermember_id, username, password, phone, email会员登录、个人信息t_househouse_id, member_id, title, type, price, area, description, status出租/出售房源信息type区分租售t_demanddemand_id, member_id, content, min_price, max_price, type求租/求购信息t_noticenotice_id, title, content, create_time站内公告t_messagemessage_id, member_id, content, reply留言板t_orderorder_id, house_id, member_id, deal_price, deal_time交易信息设计要点是会员与房源是一对多关系t_house通过member_id关联会员求租求购信息单独放表避免和房源混在一起统计报表不建表而是通过SQL的GROUP BY按月或按类型汇总这样报表需求变化时不用改表结构。字段命名带前缀外键清晰用Navicat查看表关系时一目了然。房屋状态status的设计也很有讲究。常见约定是0表示未出租/未售出1表示已出租/已售出这样前台列表里只展示status0的房源后台成交后把它改成1求租求购信息和交易记录就能联动起来。类型type字段用来区分出租、出售具体值在代码或数据字典里注释清楚避免混淆。2.4 源码里的隐藏依赖WEB-INF/lib 目录与 JDBC 驱动传统JavaWeb项目不像Maven那样在pom.xml里声明依赖而是把jar包直接放在WebContent/WEB-INF/lib目录下。这个目录里的内容会被Tomcat自动加载。这套系统通常离不开下面这些jar包servlet-api.jarServlet接口和HttpServlet类由Tomcat自带但编译时需要。jstl.jar / standard.jarJSP标准标签库页面里用c:forEach循环靠它。sqljdbc4.jar 或 sqljdbc42.jarSQL Server的JDBC驱动没有它Class.forName直接报错。如果改造成MySQL需要把驱动替换成mysql-connector-java.jar。打开源码后先检查lib目录是否完整如果缺失编译期会大量报红。IDE里还需要把Tomcat添加为运行环境否则Servlet、HttpServletRequest这些类也找不到。这一步看似简单实际是很多第一次导入老项目的人翻车的地方。3. 核心模块拆解从“会员点击登录”到“页面渲染”的完整请求链路3.1 登录与注册一次getParameter到PreparedStatement的完整路径先看用户登录。这是最基础也是最值得读的模块因为它的代码路径极短JSP表单 → Servlet → Dao → SQL → 回跳。!-- login.jsp 片段 -- form actionlogin methodpost input typetext nameusername placeholder用户名 / input typepassword namepassword placeholder密码 / button typesubmit登录/button /form动作提交给“login”对应LoginServlet的doPostWebServlet(/login) public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); MemberDao dao new MemberDao(); Member member dao.findByUsernameAndPassword(username, password); if (member ! null) { request.getSession().setAttribute(loginMember, member); response.sendRedirect(index); // 登录成功回首页 } else { request.setAttribute(error, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } } }注意两个细节sendRedirect是重定向浏览器地址会变成indexforward是转发地址栏不变所以登录失败后页面还是login.jsp但能看到error提示。这是JavaWeb面试常问的区分通过代码位置能直接看出来。MemberDao的查询方法如下public Member findByUsernameAndPassword(String username, String password) { String sql select * from t_member where username ? and password ?; try (Connection conn DBHelper.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { Member m new Member(); m.setId(rs.getInt(member_id)); m.setUsername(rs.getString(username)); m.setPassword(rs.getString(password)); m.setPhone(rs.getString(phone)); return m; } } } catch (Exception e) { e.printStackTrace(); } return null; }这里使用PreparedStatement而不是拼接字符串是为了防止SQL注入。参数通过setString方式绑定即使输入“ or 11”也只会被当成普通字符串。第一次改造时可以把密码明文改成MD5加密但要注意登录时也要用同样方式处理后再去比对。3.2 发布出售和求租信息用HouseDao把表单写进数据库会员登录后可以发布出租、出售信息也可以在求租求购模块发布需求。这里以发布房源为例。WebServlet(/house/add) public class HouseServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String title request.getParameter(title); String type request.getParameter(type); // 1出租 2出售 String price request.getParameter(price); String area request.getParameter(area); String description request.getParameter(description); Member loginMember (Member) request.getSession().getAttribute(loginMember); House house new House(); house.setTitle(title); house.setType(Integer.parseInt(type)); house.setPrice(Double.parseDouble(price)); house.setArea(Double.parseDouble(area)); house.setDescription(description); house.setMemberId(loginMember.getId()); house.setStatus(0); boolean ok new HouseDao().addHouse(house); if (ok) { response.sendRedirect(house/list); } else { request.setAttribute(error, 发布失败); request.getRequestDispatcher(house_add.jsp).forward(request, response); } } }HouseDao的addHouse方法就是对SQL Server执行insertpublic boolean addHouse(House house) { String sql insert into t_house(title, member_id, type, price, area, description, status) values(?,?,?,?,?,?,0); try (Connection conn DBHelper.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, house.getTitle()); ps.setInt(2, house.getMemberId()); ps.setInt(3, house.getType()); ps.setDouble(4, house.getPrice()); ps.setDouble(5, house.getArea()); ps.setString(6, house.getDescription()); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } }type字段作为一个int传入price和area用double类型适配数据库里的decimal。这里可以看到JavaBean JDBC的标准写法实体类只存数据Servlet只做参数解析和页面跳转Dao只负责SQL。如果后面想加“发布后需管理员审核”只需要把status改成2并在后台列表过滤status2的数据业务逻辑保持不动。3.3 信息检索与分页条件拼接最容易写出毛病的部分前台有“信息检索”功能可以按关键字、出租/出售类型过滤房源。分页是每个列表页都需要的常见实现是计算总条数再按页取数据。public ListHouse search(String keyword, String type, int pageIndex, int pageSize) { StringBuilder sql new StringBuilder(select * from t_house where 11 ); ListObject params new ArrayList(); if (keyword ! null !keyword.trim().isEmpty()) { sql.append(and title like ? ); params.add(% keyword.trim() %); } if (type ! null !type.isEmpty()) { sql.append(and type ? ); params.add(type); } // SQL Server 2012 分页写法 sql.append(order by house_id desc ); sql.append(offset ? rows fetch next ? rows only); params.add((pageIndex - 1) * pageSize); params.add(pageSize); // 依次把params放到PreparedStatement中... }这里有两个关键点。第一where 11 是恒等条件只是为了后续拼接and方便不影响性能因为SQL Server会把它优化掉。第二SQL Server的分页与MySQL的limit不同这里用offset...fetch所以数据库方言必须对应若直接改成MySQL要把这段换成limit ?,?。检索结果返回后传到JSP页面用jSTL循环c:forEach varhouse items${page.list} div classhouse-item h3a hrefhouse/detail?id${house.id}${house.title}/a/h3 p价格${house.price} | 面积${house.area}㎡/p /div /c:forEach首页展示的出租详细、出售信息、求租详细、求购信息本质都是同一个List页面按type参数过滤出来的。只要理解了这条查询链路改前端样式、加筛选条件都很快。3.4 统计报表模块用GROUP BY把交易记录变成管理决策数据后台的“房屋统计报表”和“销售租金报表”是这套系统区别于普通CRUD的地方。它的实现思路很直接通过聚合函数把明细表变成汇总表再展示到JSP页面。以销售租金报表为例SQL大致如下select year(deal_time) as deal_year, month(deal_time) as deal_month, sum(deal_price) as month_total, count(*) as deal_count from t_order where status 已成交 group by year(deal_time), month(deal_time) order by deal_year, deal_month;这段SQL对交易时间做年、月分组sum(deal_price)算出月租金或销售额count(*)算出成交笔数。在StatisticServlet中调用Dao查询把结果放到ListMapString, Object里再传给admin/report.jsp输出表格。这里容易踩的坑是聚合函数和GROUP BY的字段必须匹配select里出现的非聚合字段都要在group by中出现否则SQL Server会直接报错。另外如果某个月没有成交这条分组就不会出现报表上对应月份是空的。常见处理是在Java代码里把缺失月份补0或者在JSP里判断null显示为0。4. 从零跑通本地环境配置与部署步骤4.1 环境清单JDK8、Tomcat、SQL Server 的版本搭配这套系统不是Maven工程没有脚手架所以环境匹配很关键。建议按下面这套配置来别一开始就上JDK21老项目容易不兼容。软件推荐版本说明JDK1.8文中写明jdk8稳定Tomcat8/9都支持Tomcat8.5 或 9.0Servlet容器部署war包IDEIDEA 或 EclipseIDEA需配置Tomcat Server数据库SQL Server 2008 R2 / 2012 / 2019脚本基于SQL Server语法数据库管理工具Navicat for SQL Server用于执行.sql脚本和查看数据浏览器Chrome / Edge访问前端页面Tomcat与JDK版本要匹配JDK8配Tomcat8.5或9.0都没问题。如果你机器上装了更高版本JDK建议临时把Project Structure里的SDK切到1.8同时把编译级别也调到1.8避免class版本过高导致Tomcat无法加载。4.2 用IDEA导入源码并补全依赖打开IDEA选择File → Open找到源码目录。如果你打开后看到的是空工程可以按下面步骤调整打开Project Structure确认Project SDK1.8Language Level8。找到Web Content或webapp目录右键选择“Add as Framework Support”添加Web。进入File → Project Structure → Modules → Dependencies把WEB-INF/lib下的所有jar包加进来。在运行配置里添加Tomcat Server → Local选择安装好的Tomcat。Deployment标签里Add项目ArtifactApplication context设为 /rent_house 或直接 /。如果lib里有servlet-api.jar有些同学会把Tomcat自带的servlet-api也加进来导致重复。我的习惯是lib里的servlet-api不参与编译只保留Tomcat提供的如果编译报错再重新添加。启动前最好先Build一下确认没有红色报错。4.3 创建数据库并导入脚本数据库脚本通常是项目根目录下的.sql文件可能叫rent_house.sql或database.sql。在Navicat for SQL Server中新建一个数据库字符集选简体中文常用、排序规则保持默认然后右键数据库选择“运行SQL文件”执行脚本。脚本执行后展开表列表确认出现前文提到的那几张表。如果脚本中有USE database字样注意当前连接是否有权限。接下来要改JDBC连接配置。通常在DBHelper.java或config/db.properties里jdbc.drivercom.microsoft.sqlserver.jdbc.SQLServerDriver jdbc.urljdbc:sqlserver://localhost:1433;DatabaseNamerent_house jdbc.usernamesa jdbc.password123456SQL Server的JDBC URL和MySQL不一样它是分号分隔DatabaseName。如果SQL Server使用的是命名实例例如localhost\SQLEXPRESSURL写法通常要加instanceName参数不过大多数本地环境直接用默认实例加上1433端口即可。改完用户名密码后重启Tomcat生效。4.4 启动Tomcat跑通一条完整业务链路配置好之后点击Tomcat运行按钮控制台出现“Server startup in ... ms”说明启动成功。浏览器访问http://localhost:8080/rent_house/index.jsp如果看到前台首页说明工程能跑。建议按下面顺序验证功能确认不是只有首页能看点击免费注册注册一个测试会员。用刚注册的账号登录进入会员中心。发布一条出租信息。退出后访问首页检索刚才发布的房源关键字能看到结果。用管理员账号登录后台在交易信息管理里把这条房屋标记为已成交。查看销售租金报表确认出现了对应月份的汇总数据。这套流程走完就证明Servlet转发、JDBC写库、检索、报表聚合全部通了。如果中间某一步失败优先看Tomcat日志里的异常栈绝大多数问题都能在控制台直接定位。5. 避坑指南从 SQL Server 驱动到中文乱码的高频踩坑记录5.1 启动报 ClassNotFoundException找不到 SQL Server 驱动现象Tomcat启动或访问页面时报ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver原因缺少JDBC驱动包。驱动jar没有放进WEB-INF/lib目录或者IDE没有把它加入构建路径。很多同学只在文件系统里看到sqljdbc4.jar但Project Structure没加入编译能过运行时找不到。解决把sqljdbc4.jar或sqljdbc42.jar放到WebContent/WEB-INF/lib目录然后IDEA里右键Add as Library。如果已经放了还报错检查是否被Maven或IDE的依赖范围“provided”排除了。我的经验是先把jar复制到lib再执行一次Build → Rebuild Project然后重启Tomcat。5.2 页面中文乱码Tomcat与JSP编码三层不一致现象登录后页面上的中文标题、公告内容全部变成“锟斤拷”或问号。原因典型的编码不统一。请求参数没有设置UTF-8或者JSP页面没有写pageEncoding或者Tomcat 8以下连接器默认URIEncoding是ISO-8859-1。解决第一在doGet/doPost里执行request.setCharacterEncoding(UTF-8); response.setCharacterEncoding(UTF-8);。第二JSP文件头部写% page contentTypetext/html;charsetUTF-8 languagejava pageEncodingUTF-8 %第三如果是GET请求传中文在Tomcat的server.xml连接器上加URIEncodingUTF-8。另外数据库字符集也要匹配SQL Server中一般没问题但如果是从旧库导入检查列排序规则是否为Chinese_PRC_CI_AS。5.3 连接数据库失败端口、实例名与URL写法现象报错Connection refused: connect或者The TCP/IP connection to the host localhost, port 1433 has failed.原因SQL Server默认没有开启TCP/IP协议或者服务实例名不是默认的又或者防火墙拦截了1433端口。SQL Server在开发机上默认实例名可能是MSSQLSERVER但某些安装版是SQLExpress。解决打开SQL Server Configuration Manager启用“TCP/IP”。右键属性在IP地址标签页确认端口是1433。然后重启SQL Server服务。URL写成jdbc:sqlserver://localhost:1433;DatabaseNamerent_house。如果命名实例写成jdbc:sqlserver://localhost\SQLEXPRESS;DatabaseNamerent_house。另外检查登录模式是否选了“混合模式”sa密码是否正确。Navicat能连上不代表Tomcat能连上因为可能用户权限、加密方式不一样。5.4 修改JSP后页面没变化Tomcat缓存和IDE编译问题现象改了index.jsp上的文字或样式刷新页面还是旧内容。原因Tomcat默认对JSP做增量编译但IDEA部署时没有把最新webroot资源同步过去或者项目没有设置为Update resources on update页面没有重新加载。解决IDEA中Tomcat配置里的“On frame deactivation”选Update resources这样每次切回IDE会自动同步静态文件。如果改了Java代码则需要Undeploy再Redeploy。还有种情况是浏览器缓存按CtrlShiftR强制刷新或者清空Tomcat的work/Catalina目录下的临时编译文件。多年的老经验是先看IDE的target或out目录里JSP内容更新没如果没更新直接Clean Project。5.5 报表统计全是0或类型报错SUM和COUNT的返回处理现象后台销售租金报表显示一行数据都是0或者控制台报Cannot convert value 1234.50 from type BigDecimal to type Integer原因sum()函数返回类型通常是BigDecimal或浮点类型如果用rs.getInt()去取就会类型不匹配如果没有交易记录查询结果集为空页面循环不渲染而不是返回一个0行数据。解决在Dao里读取用rs.getBigDecimal(month_total)或rs.getDoublenull情况单独处理。例如BigDecimal total rs.getBigDecimal(month_total); list.add(total null ? BigDecimal.ZERO : total);同时统计页面通常要把“无数据”和“0数据”区分开有时有分组但没成交count是0sum是null页面显示空。可以在JSP中用fmt标签格式化或者Java代码里把total置为0再传页面。这样报表格式统一也方便前端折线图。6. 二次开发建议从毕设项目到简历项目的三个改造点拿到能跑的系统只是第一步真正让它成为你的东西至少要做三处改造。第一把数据库从SQL Server迁移到MySQL。毕设在线演示环境很多用MySQL你可以把驱动换成mysql-connector-java.jarURL改成jdbc:mysql://localhost:3306/rent_house?characterEncodingutf8并把分页、时间函数这两个SQL方言改掉。SQL Server的year(deal_time)在MySQL里是year(deal_time)其实一样但分页要改成limit。改完后跑一遍注册到报表的完整流程确认没有遗漏的Syntax错误。第二给Servlet做一层BaseServlet。现在每加一个功能就要写一个类路由全在web.xml里太散。可以定义一个BaseServlet继承HttpServlet根据参数action调用子类的同名方法把路由集中起来减少类的数量。这种做法在原生JavaWeb项目里非常常见你能在改造过程中理解“约定大于配置”。第三给密码加盐并修复权限漏洞。目前登录校验是明文比对可以引入MD5或SHA-256加盐同时用Filter拦截“/member/”、“/admin/”路径未登录直接跳登录页。这就把系统从“能跑”提升到“有安全意识的项目”。每次改完我习惯按“注册新会员 → 登录 → 发布房源 → 检索 → 后台成交 → 查报表”这条链路从头走一遍再顺手测一个错误密码和非法URL。从那以后我每次拿到老项目都会先看web.xml和lib目录再上手改这个习惯省掉了太多冤枉时间。希望这些踩坑记录和改造思路能帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →