简介:这是一套基于Servlet的房屋租赁管理信息系统完整源码,采用Java+Servlet+JSP+MySQL技术栈,运行于Tomcat7及以上环境,适合Java Web初学者与课程设计、毕业设计开发者参考学习。系统分为管理员与普通用户两种角色,前台涵盖会员注册登录、密码找回、新闻中心、出租求租、出售求购、信息检索、留言板等模块,后台则提供新闻资讯、会员、留言、滚动公告、出租出售求租信息、预定定金合同、收付款、房屋统计报表、销售租金报表及登录日志等管理功能,业务链条较为完整。压缩包共681个文件,约2.6MB,以gif图片、js脚本、jsp页面、html静态页、java源码与class文件、css样式为主,另含sql建库脚本与登录说明,便于快速部署与二次开发。目前已有262人学习下载,可作为掌握Servlet分层开发、JSP页面交互与数据库操作的实战范本。
1. 从一份“老派”Servlet房屋租赁系统说起:为什么它仍是JavaWeb练手的好靶子
如果你正在搜“javaweb项目完整案例mysql”,大概率已经翻过一堆 Spring Boot 的商城源码,配置一堆 starter 之后发现业务逻辑全被框架封装了,改个查询都要先理解自动配置链路。这套基于 Servlet + JSP + MySQL 的房屋租赁管理信息系统恰好相反——它把请求怎么进来、参数怎么取、SQL 怎么拼、页面怎么渲染全部摊在你面前。系统分管理员和普通用户两种角色,前台覆盖会员登录注册、新闻中心、出租求租出售求购四类信息发布与检索、留言板、会员中心,后台则把新闻资讯、注册会员、滚动公告、出租出售求租信息、预定定金合同收付款、房屋统计报表、销售租金报表、管理员设置和后台登录日志全部管起来。技术栈是 JDK1.8 + Tomcat7 及以上 + MySQL,前端用 JSP、CSS、JavaScript、JQuery、Ajax 加轮播图,后端纯 Servlet,开发环境 Eclipse 或 IntelliJ IDEA 都能跑。它适合谁?适合刚学完 Java 基础、想找一个能跑通完整增删改查和角色权限、又不想被框架黑盒挡住视线的人。下面我按“资源是什么 → 怎么用 → 坑在哪”的顺序,把这份源码拆开讲透。
2. 环境搭建与数据库落地:从 JDK1.8 到 Tomcat 的第一条请求
这套系统对版本比较敏感,JDK 必须 1.8,Tomcat 7 及以上,MySQL 用 5.7 或 8.0 都行但驱动包要对应。很多人卡在第一步不是代码问题,而是环境版本对不上导致 JSP 编译报错或者数据库连不上。这一章把环境配置、数据库导入、项目部署三件事按顺序走一遍,每一步都给出可抄的命令和配置。
2.1 JDK 与 Tomcat 的版本对齐
先确认 JDK 版本,命令行执行:
java -version输出必须是1.8.0_xxx。如果是 11 或 17,Servlet 的javax.servlet包名在 Tomcat 9 之后虽然还在,但部分老代码用的 API 会有兼容问题,最稳妥就是 1.8。Tomcat 下载解压后,把JAVA_HOME指向 JDK 目录,CATALINA_HOME指向 Tomcat 目录。Windows 下在setclasspath.bat里确认JAVA_HOME被正确读取,Linux 下在catalina.sh开头加一行export JAVA_HOME=/your/jdk/path。
提示:Tomcat 7 和 Tomcat 8 对 JSP 的默认编码处理不同,如果页面中文乱码,先检查
server.xml的 Connector 有没有加URIEncoding="UTF-8"。
2.2 MySQL 建库与数据导入
数据库名一般叫house或rent,源码包里通常带一个.sql文件。导入命令:
mysql -u root -p -e "CREATE DATABASE house DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" mysql -u root -p house < house.sql导入后验证表是否齐全:
USE house; SHOW TABLES; SELECT COUNT(*) FROM admin;admin表里存的是后台管理员账号,常见默认是admin/123456或admin/admin,具体看 SQL 文件里的 INSERT 语句。如果SHOW TABLES出来只有几张表,说明 SQL 文件没导完,检查文件里有没有DELIMITER或存储过程导致中途报错。
2.3 项目导入与数据库连接配置
Eclipse 导入 Existing Projects into Workspace,IDEA 用 Open 选项目根目录。找到数据库配置文件,通常是src/db.properties或src/com/util/DBUtil.java里的硬编码。如果是 properties 文件:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/house?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=yourpasswordMySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver,URL 要加serverTimezone=Asia/Shanghai,否则启动报时区错误。改完配置后,把mysql-connector-java的 jar 放进WEB-INF/lib,在 Eclipse 里还要右键 Build Path 确认 jar 被加入 Web App Libraries。
部署到 Tomcat 后访问http://localhost:8080/项目名/,如果看到首页轮播图和新闻列表,说明数据库连通了。如果报 500 且堆栈指向ClassNotFoundException,九成是驱动 jar 没进WEB-INF/lib或者 Build Path 没刷新。
3. 前后台功能拆解:Servlet 如何接住 JSP 的每一次请求
环境跑通之后,真正要理解的是这套系统怎么组织代码。它没有用任何 MVC 框架,所有请求都靠web.xml或注解映射到 Servlet,Servlet 里调 DAO,DAO 里写 JDBC,最后request.getRequestDispatcher().forward()回 JSP。这一章把前台会员流程和后台管理流程各挑一条主线走通,让你看清数据从页面到数据库再回页面的完整链路。
3.1 前台会员注册登录与密码找回
注册页register.jsp提交到RegisterServlet,核心代码结构:
// RegisterServlet.java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); String question = request.getParameter("question"); String answer = request.getParameter("answer"); Member member = new Member(); member.setUsername(username); member.setPassword(MD5Util.encode(password)); // 密码做MD5 member.setQuestion(question); member.setAnswer(answer); MemberDao dao = new MemberDao(); boolean ok = dao.insert(member); if (ok) { response.sendRedirect("login.jsp"); } else { request.setAttribute("msg", "注册失败,用户名可能已存在"); request.getRequestDispatcher("register.jsp").forward(request, response); } }这里有几个关键点。request.setCharacterEncoding("UTF-8")必须放在取参数之前,否则中文用户名入库变问号。密码用 MD5 存储,找回密码时通过question和answer校验身份,校验通过后允许重置。MemberDao里就是标准的PreparedStatement插入,注意PreparedStatement的占位符顺序和setString的索引要一一对应,错一个就报SQLException。
登录流程类似,LoginServlet查库比对 MD5 后的密码,成功则session.setAttribute("member", member),后续页面用session.getAttribute("member")判断是否登录。如果没登录就访问会员中心,常见做法是在 JSP 顶部加一段判断跳转,或者在 Servlet 里做过滤器。
3.2 后台信息管理与统计报表
后台的出租信息管理是典型的“列表 + 增删改查”模式。admin/rent_list.jsp用 JQuery 的$.ajax请求RentListServlet,Servlet 返回 JSON 数组,页面动态渲染表格。核心 Servlet 代码:
// RentListServlet.java protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json;charset=UTF-8"); List<Rent> list = new RentDao().findAll(); JSONArray jsonArray = JSONArray.fromObject(list); PrintWriter out = response.getWriter(); out.print(jsonArray.toString()); out.flush(); out.close(); }这里用的是json-lib或fastjson把 List 转 JSON,具体看源码里 import 的是哪个包。前端收到后遍历生成<tr>,每行带编辑和删除按钮,删除走RentDeleteServlet?id=xxx。统计报表部分通常是SELECT COUNT(*)和GROUP BY的组合,比如按房屋类型统计出租数量:
SELECT type, COUNT(*) AS num FROM rent_info GROUP BY type;结果在report.jsp里用 JSTL 的<c:forEach>渲染成表格。如果报表页面空白,先看 SQL 在数据库里能不能查出数据,再看 Servlet 有没有把 List 放进 request 域。
注意:后台登录日志表一般只增不删,如果发现日志页面加载越来越慢,检查有没有给
login_time字段建索引。
4. 避坑与排查:这套老代码最容易翻车的五个地方
这套系统代码量不小,加上年代较早,很多写法在今天看来有隐患。下面五条是我实际部署和调试时反复遇到的,每条按现象、原因、解决来说,你照着排查能省不少时间。
4.1 中文乱码:POST 和 GET 处理方式不一样
现象是注册时输入中文用户名,数据库里存进去变成???或者页面显示乱码。原因是 POST 请求默认用 ISO-8859-1 解码,GET 请求在 Tomcat 7 里默认也是 ISO-8859-1。解决分两步:POST 在 Servlet 第一行加request.setCharacterEncoding("UTF-8");GET 要么改server.xml的 Connector 加URIEncoding="UTF-8",要么在代码里用new String(request.getParameter("name").getBytes("ISO-8859-1"), "UTF-8")手动转。数据库连接 URL 里也要带characterEncoding=utf8,建库时用utf8mb4。
4.2 数据库连接池未关闭导致 Tomcat 启动越来越慢
现象是反复重启 Tomcat 后,MySQL 里SHOW PROCESSLIST看到大量 Sleep 连接,最终报Too many connections。原因是 DAO 里Connection、PreparedStatement、ResultSet没有在 finally 里关闭。解决是把关闭操作统一写进DBUtil.close(rs, ps, conn)静态方法,每个 DAO 方法 finally 里调用。如果源码里用的是DriverManager.getConnection每次新建连接,建议改成DataSource或至少加一个简单的连接池,否则并发一上来就崩。
4.3 JSP 页面报javax.servlet.jsp.JspException找不到标签库
现象是访问某个 JSP 报 500,堆栈里说找不到http://java.sun.com/jsp/jstl/core的标签。原因是项目用了 JSTL 但WEB-INF/lib下缺jstl.jar和standard.jar。解决是把这两个 jar 补进去,并且在 JSP 顶部确认<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>写对。Tomcat 7 以上有时还需要在web.xml里把 servlet 版本声明改成 3.0 以上,否则 EL 表达式不生效。
4.4 文件上传路径写死导致换机器就失效
现象是后台发布新闻时上传图片,本机测试正常,换一台电脑或者部署到服务器后图片不显示。原因是上传代码里把保存路径写成了D:/upload/或C:/tomcat/webapps/...。解决是改成相对路径,用request.getServletContext().getRealPath("/upload")获取实际部署路径,或者把上传目录配置到项目外并映射虚拟路径。同时检查form标签有没有加enctype="multipart/form-data",Servlet 有没有用@MultipartConfig注解或commons-fileupload解析。
4.5 后台权限绕过:直接访问 admin 目录下的 JSP
现象是普通用户不登录,直接在浏览器输入http://localhost:8080/项目名/admin/index.jsp就能进后台。原因是权限校验只写在登录 Servlet 里,没有对后台每个页面做拦截。解决是加一个AdminFilter,在doFilter里判断session.getAttribute("admin")是否为空,为空就重定向到后台登录页。web.xml里配置 filter 拦截/admin/*。这个坑最危险,因为数据可能被任意篡改。
5. 进阶技巧:用 SQL 统计和 JSTL 把报表页做成可复用组件
后台的房屋统计报表和销售租金报表是这套系统里最值得深挖的部分,因为它涉及多表关联和动态条件查询。很多人把报表页写成一个大 JSP 里塞满 Java 代码,改一个字段要翻半天。我一般会把统计逻辑收进一个ReportServlet,用参数控制统计维度,JSP 只负责渲染。下面给一个可复用的写法。
先看统计 SQL 的参数化设计。假设要按月份统计租金收入,表结构里contract表有rent和sign_date:
SELECT DATE_FORMAT(sign_date, '%Y-%m') AS month, SUM(rent) AS total FROM contract WHERE sign_date BETWEEN ? AND ? GROUP BY DATE_FORMAT(sign_date, '%Y-%m') ORDER BY month;Servlet 里接收startDate和endDate两个参数,默认查最近六个月:
// ReportServlet.java protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String start = request.getParameter("startDate"); String end = request.getParameter("endDate"); if (start == null || start.isEmpty()) { Calendar cal = Calendar.getInstance(); cal.add(Calendar.MONTH, -6); start = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()); } if (end == null || end.isEmpty()) { end = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); } List<Map<String, Object>> data = new ReportDao().sumRentByMonth(start, end); request.setAttribute("reportData", data); request.getRequestDispatcher("/admin/report.jsp").forward(request, response); }JSP 里用 JSTL 遍历,不再写<% %>脚本片段:
<table border="1"> <tr><th>月份</th><th>租金收入</th></tr> <c:forEach items="${reportData}" var="row"> <tr> <td>${row.month}</td> <td>${row.total}</td> </tr> </c:forEach> </table>这样改统计维度只需要改 SQL 和 Servlet 里的参数名,JSP 完全不用动。参数说明:startDate和endDate格式是yyyy-MM-dd,传空则走默认最近六个月;ReportDao里用PreparedStatement设置两个日期参数,注意setDate要用java.sql.Date而不是java.util.Date,否则报类型转换错误。
还有一个技巧是给报表加导出功能。不用引入 POI 那么重,先用最简单的 CSV 导出:
response.setContentType("text/csv;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=report.csv"); PrintWriter out = response.getWriter(); out.println("月份,租金收入"); for (Map<String, Object> row : data) { out.println(row.get("month") + "," + row.get("total")); } out.flush();前端在报表页加一个<a href="ReportExportServlet?startDate=...&endDate=...">导出CSV</a>就能用。Excel 打开 CSV 如果中文乱码,在输出前先写\uFEFF这个 BOM 头。
从那以后我每次接手这种老 Servlet 项目,都强制先把数据库连接关闭检查一遍、把后台权限过滤器加上、把报表 SQL 单独在客户端跑通再写进代码。这三步走完,后面基本不会出大问题。希望帮到你。
本文还有配套的精品资源,点击获取