小区物业收费管理系统

目录

一、题目要求

二、系统基本功能结构

三、数据库设计

1、综合E-R模型

2、表结构

3、JSP 页面设计

admin_index.jsp:

Charge_item_manage.jsp

index.jsp

payment.jsp

Payment_record_query.jsp

qrcord.jsp

四、Servlet 设计

ChargeItemManageServlet.java

LoginServlet.java

PaymentRecordQueryServlet.java

PaymentServlet.java

RegisterServlet.java

五、运行效果

1.登录

2.管理员页面

3.收费管理页面

4.缴费记录页面查询

5.用户页面

6.用户缴费页面

7.用户缴费记录查询

七、心得体会


一、题目要求

用户分为业主和系统管理员两种,业主可以通过注册页面添加自己的基本信息,包括姓名、楼号、单元号、房号、类型(户主/租户)、车牌号(没有车可以为空)、手机号等,可以在系统中查询水费、电费、物业费、卫生费、暖气费、停车费等收费标准及历史缴费情况。也可以在线自主缴费。自主缴费时选择对应项目并填写缴费数量(如100度电),系统会自动算出缴费总额。收费功能暂用一个二维码图片代替。系统管理员可以对物业收费项目进行增删改查等操作,也可以查询业主的缴费记录。系统采用预交费方式,如某业主电费余额为0后系统自动对其断电。物业费、卫生费等欠费后,管理员电话通知业主缴费,否则,用户无法通过系统交纳水电费。

二、系统基本功能结构

系统总体架构图

项目结构体图(主要的类、JSP页面存放目录结构等

三、数据库设计

1、综合E-R模型

2、表结构

Charge_item 表:存储缴费项目信息,包括缴费编号(item_id,自增主键)、项目名称(item_name)、单价(Charge_standard)。、Charge_item表

字段名称

数据类型

约束

备注

item_id

Int(auto increment)

primary key

缴费编号

item_name

Varchar(255)

名称

Charge_standard

decimal

单价

Payment_record 表:记录物费缴费情况,有物费编号(record_id,主键)、用户编号(user_id)、物费名称(item_id)、缴费金额(payment_amount)、时间(payment_time)。

字段名称

数据类型

约束

备注

record_id

Int

primary key

物费编号

user_id

Int

用户名称

item_id

Int

物费名称

payment_amount

decimal

缴费金额

payment_time

Timestamp

时间

user 表:涵盖用户基本信息,用户编号(User_id,主键)、姓名(name)、楼名(Building_number)、单元名(Unit_number)、房间名(Room_number)、户主类别(type)、车号(Car_number)、电话(Phone_number)、密码(password)、登录类别(role)。

字段名称

数据类型

约束

备注

User_id

int

primary key

用户编号

name

char

用户名称

Building_number

char

楼名

Unit_number

char

单元名

Room_number

char

房间名

type

enum

户主类别

Car_number

char

车号

Phone_number

char

电话

password

char

密码

role

enum

登录类别

3、JSP 页面设计

admin_index.jsp:

管理员首页,提供收费项目管理、缴费记录查询入口及退出按钮,页面样式简洁,通过合理的 CSS 设置增强可读性与操作便捷性。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>

<head>
    <title>管理员首页</title>
    <style>
        /* 全局样式设置 */
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        /* 页面标题样式 */
        h2 {
            text-align: center;
            color: #333;
            margin-bottom: 20px;
        }

        /* 功能链接通用样式 */
        a {
            display: block;
            text-decoration: none;
            color: white;
            background-color: #007bff;
            padding: 10px 20px;
            border-radius: 5px;
            margin-bottom: 10px;
            width: 200px;
            text-align: center;
            transition: background-color 0.3s ease;
        }

        a:hover {
            background-color: #0056b3;
        }

        /* 退出按钮样式 */
        #logout {
            background-color: #f44336;
            margin-top: 20px;
        }

        #logout:hover {
            background-color: #d32f2f;
        }
    </style>
</head>

<body>
<div class="card">
    <h2>欢迎管理员登录</h2>
    <a href="/ChargeItemManageServlet">收费项目管理</a>
    <a href="/PaymentRecordQueryServlet">缴费记录查询</a>
    <a href="<%=request.getContextPath()%>/LoginServlet?action=logout" id="logout">退出到登录界面</a>
</div>
</body>

</html>

Charge_item_manage.jsp

用于收费项目管理,可添加、修改、删除收费项目,并展示项目列表,借助 JavaScript 实现表单显示与隐藏以及删除确认功能,提升用户交互体验。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="com.tt.entity.ChargeItem" %>
<!DOCTYPE html>
<html>

<head>
    <title>收费项目管理</title>
    <style>
        /* 全局样式设置 */
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        /* 页面容器样式 */
        .page-container {
            background-color: white;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
            border-radius: 5px;
            padding: 20px;
            width: 80%;
            max-width: 1000px;
        }

        h2 {
            text-align: center;
            color: #333;
            margin-bottom: 20px;
        }

        /* 链接通用样式 */
        a {
            display: inline-block;
            text-decoration: none;
            color: white;
            background-color: #007bff;
            padding: 10px 20px;
            border-radius: 5px;
            margin-bottom: 10px;
            margin-right: 10px;
            text-align: center;
            transition: background-color 0.3s ease;
        }

        a:hover {
            background-color: #0056b3;
        }

        /* 返回按钮样式 */
        .back-button {
            background-color: #6c757d;
            margin-top: 20px;
            margin-bottom: 20px;
        }

        .back-button:hover {
            background-color: #5a6268;
        }

        table {
            border-collapse: collapse;
            width: 100%;
            margin-top: 20px;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
        }

        th, td {
            border: 1px solid #dddddd;
            text-align: left;
            padding: 12px;
        }

        tr:nth-child(even) {
            background-color: #f2f2f2;
        }

        /* 表头样式优化 */
        th {
            background-color: #007bff;
            color: white;
            font-weight: bold;
        }

        /* 鼠标悬停行样式 */
        tr:hover {
            background-color: #e0e0e0;
        }

        /* 表单样式 */
        form {
            background-color: white;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
            margin-top: 20px;
        }

        label {
            display: block;
            margin-bottom: 5px;
        }

        input[type="text"] {
            width: 100%;
            padding: 10px;
            margin-bottom: 15px;
            border: 1px solid #ccc;
            border-radius: 3px;
        }

        input[type="submit"] {
            background-color: #007bff;
            color: white;
            padding: 10px 15px;
            border: none;
            border-radius: 3px;
            cursor: pointer;
        }

        input[type="submit"]:hover {
            background-color: #0056b3;
        }
    </style>
</head>

<body>
<div class="page-container">
    <a href="${pageContext.request.contextPath}/admin_index.jsp" class="back-button">返回管理员首页</a>
    <h2>收费项目管理</h2>
    <a href="#" onclick="showAddForm()">添加收费项目</a>
    <div id="addForm" style="display:none;">
        <form action="/ChargeItemManageServlet" method="post">
            <input type="hidden" name="action" value="add">
            <label for="itemName">项目名称:</label><input type="text" id="itemName" name="itemName" required><br>
            <label for="chargeStandard">收费标准:</label><input type="text" id="chargeStandard" name="chargeStandard" required><br>
            <input type="submit" value="添加">
        </form>
    </div>
    <table>
        <thead>
        <tr>
            <th>项目编号</th>
            <th>项目名称</th>
            <th>收费标准</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        <%
            List<ChargeItem> chargeItems = (List<ChargeItem>) request.getAttribute("chargeItems");
            if (chargeItems!= null) {
                for (ChargeItem item : chargeItems) {
        %>
        <tr>
            <td><%= item.getItem_id() %></td>
            <td><%= item.getItem_name() %></td>
            <td><%= item.getCharge_standard() %></td>
            <td>
                <a href="#" onclick="showUpdateForm(<%= item.getItem_id() %>, '<%= item.getItem_name() %>', <%= item.getCharge_standard() %>)">修改</a>
                <a href="#" onclick="confirmDelete(<%= item.getItem_id() %>)">删除</a>
            </td>
        </tr>
        <%
                }
            }
        %>
        </tbody>
    </table>
    <div id="updateForm" style="display:none;">
        <form action="ChargeItemManageServlet" method="post">
            <input type="hidden" name="action" value="update">
            <input type="hidden" id="updateItemId" name="itemId">
            <label for="updateItemName">项目名称:</label><input type="text" id="updateItemName" name="itemName" required><br>
            <label for="updateChargeStandard">收费标准:</label><input type="text" id="updateChargeStandard" name="chargeStandard" required><br>
            <input type="submit" value="更新">
        </form>
    </div>
</div>
<script>
    function showAddForm() {
        document.getElementById('addForm').style.display = 'block';
    }

    function showUpdateForm(itemId, itemName, chargeStandard) {
        document.getElementById('updateForm').style.display = 'block';
        document.getElementById('updateItemId').value = itemId;
        document.getElementById('updateItemName').value = itemName;
        document.getElementById('updateChargeStandard').value = chargeStandard;
    }

    function confirmDelete(itemId) {
        if (confirm("确定要删除该收费项目吗?")) {
            var form = document.createElement('form');
            form.action = 'ChargeItemManageServlet';
            form.method = 'post';
            form.style.display = 'none';

            var inputAction = document.createElement('input');
            inputAction.type = 'hidden';
            inputAction.name = 'action';
            inputAction.value = 'delete';
            form.appendChild(inputAction);

            var inputItemId = document.createElement('input');
            inputItemId.type = 'hidden';
            inputItemId.name="itemId";
            inputItemId.value = itemId;
            form.appendChild(inputItemId);

            document.body.appendChild(form);
            form.submit();
        }
    }
</script>
</body>

</html>

index.jsp

页面重定向至 login.jsp,引导用户进入登录页面。

<%--
  Created by IntelliJ IDEA.
  User: *****
  Date: 2024/12/15
  Time: 18:04
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <meta http-equiv="refresh" content="0;url=login.jsp">
    <title>$Title$</title>
  </head>
  <body>
  $END$
  </body>
</html>

login.jsp:用户登录页面,包含手机号和密码输入框,对输入错误进行提示,确保用户输入信息的准确性。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>

<head>
    <title>登录</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            padding: 0;
        }

        form {
            background-color: white;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
            width: 300px;
        }

        h2 {
            text-align: center;
            margin-bottom: 20px;
        }

        label {
            display: block;
            margin-bottom: 5px;
        }

        input[type="text"],
        input[type="password"] {
            width: 100%;
            padding: 10px;
            margin-bottom: 15px;
            border: 1px solid #ccc;
            border-radius: 3px;
            margin-right: 10px; /* 添加这行代码,设置右侧外边距为10px */
        }

        input[type="submit"] {
            background-color: #007bff;
            color: white;
            padding: 10px 15px;
            border: none;
            border-radius: 3px;
            cursor: pointer;
        }

        input[type="submit"]:hover {
            background-color: #0056b3;
        }

        p {
            color: red;
            margin-top: 10px;
            text-align: center;
        }
    </style>
</head>

<body>
<form action="/LoginServlet" method="post">
    <h2>用户登录</h2>
    <div>
        <label for="phone">手机号:</label>
        <input type="text" id="phone" name="phone" required>
    </div>
    <div>
        <label for="password">密码:</label>
        <input type="password" id="password" name="password" required>
    </div>
    <input type="submit" value="登录">
    <%
        String errorMessage = (String) request.getAttribute("errorMessage");
        if (errorMessage!= null) {
    %>
    <p><%= errorMessage %></p>
    <%
        }
    %>
</form>
</body>
</html>

owner_index.jsp:业主首页,提供缴费记录查询和进行缴费的功能入口,方便业主操作。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>

<head>
    <title>业主首页</title>
    <style>
        /* 全局样式设置 */
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        /* 页面标题样式 */
        h2 {
            text-align: center;
            color: #333;
            margin-bottom: 20px;
        }

        /* 功能链接通用样式 */
        a {
            display: block;
            text-decoration: none;
            color: white;
            background-color: #007bff;
            padding: 10px 20px;
            border-radius: 5px;
            margin-bottom: 10px;
            width: 200px;
            text-align: center;
            transition: background-color 0.3s ease;
        }

        a:hover {
            background-color: #0056b3;
        }

        /* 退出按钮样式 */
        #logout {
            background-color: #f44336;
            margin-top: 20px;
        }

        #logout:hover {
            background-color: #d32f2f;
        }
    </style>
</head>

<body>
<div class="card">
    <h2>欢迎业主登录</h2>
    <a href="/PaymentRecordQueryServlet">缴费记录查询</a>
    <a href="/PaymentServlet">进行缴费</a>
    <a href="<%=request.getContextPath()%>/LoginServlet?action=logout" id="logout">退出到登录界面</a>
</div>
</body>

</html>

payment.jsp

业主缴费页面,可选择收费项目并输入缴费金额,页面设计注重用户输入流程的顺畅性。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="com.tt.entity.ChargeItem" %>
<!DOCTYPE html>
<html>

<head>
    <title>进行缴费</title>
    <style>
        /* 全局样式设置 */
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        /* 页面容器样式 */
        .page-container {
            background-color: white;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
            border-radius: 5px;
            padding: 20px;
            width: 80%;
            max-width: 600px;
        }

        h2 {
            text-align: center;
            color: #333;
            margin-bottom: 20px;
        }

        /* 返回按钮样式 */
        .back-button {
            display: inline-block;
            text-decoration: none;
            color: white;
            background-color: #6c757d;
            padding: 10px 20px;
            border-radius: 5px;
            margin-bottom: 20px;
            text-align: center;
            transition: background-color 0.3s ease;
        }

        .back-button:hover {
            background-color: #5a6268;
        }

        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }

        select, input[type="text"] {
            width: 100%;
            padding: 10px;
            margin-bottom: 15px;
            border: 1px solid #ccc;
            border-radius: 3px;
        }

        input[type="submit"] {
            background-color: #007bff;
            color: white;
            padding: 10px 15px;
            border: none;
            border-radius: 3px;
            cursor: pointer;
        }

        input[type="submit"]:hover {
            background-color: #0056b3;
        }
    </style>
</head>

<body>
<div class="page-container">
    <a href="${pageContext.request.contextPath}/owner_index.jsp" class="back-button">返回业主首页</a>
    <h2>进行缴费</h2>
    <form action="/PaymentServlet" method="post">
        <label for="itemId">选择收费项目:</label>
        <select id="itemId" name="itemId" required>
            <%
                List<ChargeItem> chargeItems = (List<ChargeItem>) request.getAttribute("chargeItems");
                if (chargeItems!= null &&!chargeItems.isEmpty()) {
                    for (ChargeItem item : chargeItems) {
            %>
            <option value="<%= item.getItem_id() %>"><%= item.getItem_name() %></option>
            <%
                }
            } else {
            %>
            <option value="" disabled selected>暂无收费项目可选,请联系管理员</option>
            <%
                }
            %>
        </select><br>
        <label for="paymentAmount">缴费金额:</label><input type="text" id="paymentAmount" name="paymentAmount" required><br>
        <input type="submit" value="缴费">
    </form>
</div>
</body>

Payment_record_query.jsp

用于查询缴费记录,以表格形式展示记录详情,提升数据展示的清晰度。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="com.tt.entity.PaymentRecord" %>
<!DOCTYPE html>
<html>

<head>
    <title>缴费记录查询</title>
    <style>
        /* 全局样式设置 */
        body {
            font-family: 'Roboto', sans-serif; /* 使用更现代大气的字体 */
            background-color: #f0f2f5; /* 柔和的背景色 */
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        /* 页面容器样式 */
        .page-container {
            background-color: white;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 增加立体感的阴影 */
            border-radius: 8px;
            padding: 30px;
            width: 80%;
            max-width: 1200px; /* 限制最大宽度,适应不同屏幕 */
        }

        h2 {
            text-align: center;
            color: #333;
            margin-bottom: 30px;
            font-size: 28px; /* 加大标题字体 */
        }

        table {
            border-collapse: collapse;
            width: 100%;
            margin-top: 20px;
        }

        th, td {
            border: 1px solid #e0e0e0; /* 更淡的边框色 */
            text-align: left;
            padding: 15px 20px; /* 加大内边距 */
            font-size: 16px;
        }

        tr:nth-child(even) {
            background-color: #f8f8f8;
        }

        /* 表头样式优化 */
        th {
            background-color: #007bff;
            color: white;
            font-weight: bold;
        }

        /* 鼠标悬停行样式 */
        tr:hover {
            background-color: #e8e8e8;
        }

        /* 返回按钮样式 */
        .back-button {
            display: inline-block;
            text-decoration: none;
            color: white;
            background-color: #6c757d;
            padding: 12px 25px; /* 加大按钮尺寸 */
            border-radius: 6px;
            margin-bottom: 20px;
            font-size: 16px;
            transition: background-color 0.3s ease;
        }

        .back-button:hover {
            background-color: #5a6268;
        }
    </style>
</head>

<body>
<div class="page-container">
    <a href="${pageContext.request.contextPath}/owner_index.jsp" class="back-button">返回管理员首页</a>
    <h2>缴费记录查询</h2>
    <table>
        <thead>
        <tr>
            <th>记录编号</th>
            <th>用户编号</th>
            <th>项目编号</th>
            <th>缴费金额</th>
            <th>缴费时间</th>
        </tr>
        </thead>
        <tbody>
        <%
            List<PaymentRecord> paymentRecords = (List<PaymentRecord>) request.getAttribute("paymentRecords");
            if (paymentRecords!= null) {
                for (PaymentRecord record : paymentRecords) {
        %>
        <tr>
            <td><%= record.getRecord_id() %></td>
            <td><%= record.getUser_id() %></td>
            <td><%= record.getItem_id() %></td>
            <td><%= record.getPayment_amount() %></td>
            <td><%= record.getPayment_time() %></td>
        </tr>
        <%
                }
            }
        %>
        </tbody>
    </table>
</div>
</body>

</html>

qrcord.jsp

显示缴费二维码页面,提示缴费成功并展示缴费金额,虽二维码为占位,但整体页面设计符合业务流程。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <title>缴费二维码</title>
    <style>
        /* 全局样式设置 */
        body {
            font-family: Arial, sans-serif;
            background-color: #f8f9fa; /* 更柔和的背景色 */
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        .page-container {
            background-color: white;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* 增强阴影效果 */
            border-radius: 10px; /* 更圆润的边框 */
            padding: 30px;
            width: 80%;
            max-width: 600px;
            text-align: center;
        }

        h2 {
            color: #007bff; /* 标题颜色改为主题色,更醒目 */
            margin-bottom: 20px;
            font-size: 24px; /* 增大标题字体大小 */
        }

        p {
            color: #6c757d; /* 正文内容颜色稍作调整 */
            margin-bottom: 15px;
            font-size: 16px;
        }

        img {
            max-width: 300px;
            max-height: 300px;
            margin-bottom: 20px;
            border-radius: 5px; /* 给二维码图片添加圆角 */
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); /* 给图片添加阴影 */
        }

        .back-button {
            display: inline-block;
            padding: 10px 20px;
            background-color: #007bff; /* 按钮背景色为主题色 */
            color: white; /* 按钮文字颜色为白色 */
            text-decoration: none; /* 去除下划线 */
            border-radius: 5px; /* 按钮圆角 */
            transition: background-color 0.3s ease; /* 过渡效果 */
        }

        .back-button:hover {
            background-color: #0056b3; /* 鼠标悬停时按钮颜色加深 */
        }
    </style>
</head>

<body>
<div class="page-container">
    <h2>缴费成功</h2>
    <!-- 获取并显示缴费金额 -->
    <p>缴费金额:<%= request.getParameter("paymentAmount") %> 元</p>
    <!-- 这里使用img标签占位,实际需替换为生成二维码的代码 -->
    <img src="img/zhifu.png" alt="缴费二维码">
    <a href="owner_index.jsp" class="back-button">返回业主首页</a>
</div>
</body>

</html>

四、Servlet 设计

ChargeItemManageServlet.java

处理收费项目管理请求,支持添加、修改、删除操作,操作结果反馈给用户,并重新展示收费项目列表。

package com.tt.servlet;

import com.tt.dao.ChargeItemDAO;
import com.tt.dao.ChargeItemDAOImpl;
import com.tt.entity.ChargeItem;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/ChargeItemManageServlet")
public class ChargeItemManageServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ChargeItemDAO chargeItemDAO = new ChargeItemDAOImpl();
        List<ChargeItem> chargeItems = chargeItemDAO.getAllChargeItems();
        request.setAttribute("chargeItems", chargeItems);
        request.getRequestDispatcher(request.getContextPath() + "charge_item_manage.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String action = request.getParameter("action");
        ChargeItemDAO chargeItemDAO = new ChargeItemDAOImpl();
        try {
            if ("add".equals(action)) {
                String itemName = request.getParameter("itemName");
                double chargeStandard = Double.parseDouble(request.getParameter("chargeStandard"));
                ChargeItem chargeItem = new ChargeItem();
                chargeItem.setItem_name(itemName);
                chargeItem.setCharge_standard(chargeStandard);
                int result = chargeItemDAO.addChargeItem(chargeItem);
                if (result > 0) {
                    request.setAttribute("successMessage", "收费项目添加成功!");
                } else {
                    request.setAttribute("errorMessage", "收费项目添加失败,请稍后再试!");
                }
            } else if ("update".equals(action)) {
                int itemId = Integer.parseInt(request.getParameter("itemId"));
                String itemName = request.getParameter("itemName");
                double chargeStandard = Double.parseDouble(request.getParameter("chargeStandard"));
                ChargeItem chargeItem = new ChargeItem();
                chargeItem.setItem_id(itemId);
                chargeItem.setItem_name(itemName);
                chargeItem.setCharge_standard(chargeStandard);
                int result = chargeItemDAO.updateChargeItem(chargeItem);
                if (result > 0) {
                    request.setAttribute("successMessage", "收费项目更新成功!");
                } else {
                    request.setAttribute("errorMessage", "收费项目更新失败,请稍后再试!");
                }
            } else if ("delete".equals(action)) {
                int itemId = Integer.parseInt(request.getParameter("itemId"));
                int result = chargeItemDAO.deleteChargeItem(itemId);
                if (result > 0) {
                    request.setAttribute("successMessage", "收费项目删除成功!");
                } else {
                    request.setAttribute("errorMessage", "收费项目删除失败,请稍后再试!");
                }
            }
            doGet(request, response);
        } catch (NumberFormatException e) {
            request.setAttribute("errorMessage", "参数格式错误,请检查输入的数字格式是否正确!");
            doGet(request, response);
        }

    }
}

LoginServlet.java

处理用户登录请求,验证手机号和密码,根据用户角色(admin 或 owner)重定向到相应首页,同时支持退出登录功能。

package com.tt.servlet;


import jakarta.servlet.annotation.WebServlet;
import com.tt.dao.UserDAO;
import com.tt.dao.UserDAOImpl;
import com.tt.entity.User;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.util.logging.Logger;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    private static final Logger logger = Logger.getLogger(LoginServlet.class.getName());
    private static final long serialVersionUID = 1L;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String phone = request.getParameter("phone");
        String password = request.getParameter("password");
        System.out.println(phone+" " +password);

        logger.info("用户尝试登录,手机号:" + phone);

        UserDAO userDAO = new UserDAOImpl();
        User user = userDAO.getUserByPhoneAndPassword(phone, password);

        if (user!= null) {
            logger.info("用户登录成功,用户信息:" + user);
            HttpSession session = request.getSession(true);
            session.setAttribute("user", user);
            if ("admin".equals(user.getRole())) {
                response.sendRedirect(request.getContextPath() + "admin_index.jsp");
            } else {
                response.sendRedirect(request.getContextPath() + "owner_index.jsp");
            }
        } else {
            logger.warning("用户登录失败,手机号或密码错误,手机号:" + phone);
            request.setAttribute("errorMessage", "手机号或密码错误,请重新登录!");
            request.getRequestDispatcher(request.getContextPath() + "/login.jsp").forward(request, response);
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 处理退出登录逻辑,获取当前会话
        HttpSession session = request.getSession(false);
        if (session!= null) {
            // 移除用户相关信息(这里以移除名为 "user" 的属性为例)
            session.removeAttribute("user");
            // 使会话失效
            session.invalidate();
        }
        // 重定向到登录页面,假设登录页面路径为 /login.jsp,根据实际情况修改
        response.sendRedirect(request.getContextPath() + "/login.jsp");
    }
}

PaymentRecordQueryServlet.java

查询缴费记录,管理员可查看所有记录,业主只能查看自己的记录,确保数据访问的安全性与合理性。

package com.tt.servlet;

import com.tt.dao.PaymentRecordDAO;
import com.tt.dao.PaymentRecordDAOImpl;
import com.tt.entity.PaymentRecord;
import com.tt.entity.User;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
@WebServlet("/PaymentRecordQueryServlet")
public class PaymentRecordQueryServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession(false);
        if (session!= null) {
            try {
                User user = (User) session.getAttribute("user");
                PaymentRecordDAO paymentRecordDAO = new PaymentRecordDAOImpl();
                List<PaymentRecord> paymentRecords;
                if ("admin".equals(user.getRole())) {
                    paymentRecords = paymentRecordDAO.getAllPaymentRecords();
                } else {
                    paymentRecords = paymentRecordDAO.getPaymentRecordsByUserId(user.getUser_id());
                }
                request.setAttribute("paymentRecords", paymentRecords);
                request.getRequestDispatcher(request.getContextPath() + "payment_record_query.jsp").forward(request, response);
            } catch (ClassCastException e) {
                request.setAttribute("errorMessage", "用户信息获取出现异常,请重新登录!");
                response.sendRedirect(request.getContextPath() + "/login.jsp");
            }
        } else {
            response.sendRedirect(request.getContextPath() + "/login.jsp");
        }
    }
}

PaymentServlet.java

处理缴费请求,获取收费项目和缴费金额,校验参数后添加缴费记录,成功则跳转到缴费二维码页面,失败给出错误提示。

package com.tt.servlet;

import com.tt.dao.ChargeItemDAOImpl;
import com.tt.dao.PaymentRecordDAO;
import com.tt.dao.PaymentRecordDAOImpl;
import com.tt.entity.ChargeItem;
import com.tt.entity.PaymentRecord;
import com.tt.entity.User;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@WebServlet("/PaymentServlet")
public class PaymentServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置请求字符编码为 UTF-8
        request.setCharacterEncoding("UTF-8");
        // 设置响应字符编码为 UTF-8
        response.setContentType("text/html; charset=UTF-8");

        try {
            // 获取收费项目列表(此处可添加日志记录查看查询操作是否执行)
            System.out.println("开始查询收费项目列表...");
            ChargeItemDAOImpl chargeItemDAO = new ChargeItemDAOImpl();
            List<ChargeItem> chargeItems = chargeItemDAO.getAllChargeItems();
            request.setAttribute("chargeItems", chargeItems);
            System.out.println("成功获取收费项目列表,数量:" + chargeItems.size());

            // 获取缴费相关参数,进行格式校验(增加更详细的异常处理)
            String itemIdStr = request.getParameter("itemId");
            String paymentAmountStr = request.getParameter("paymentAmount");
            if (itemIdStr == null || paymentAmountStr == null || itemIdStr.isEmpty() || paymentAmountStr.isEmpty()) {
                throw new IllegalArgumentException("缴费参数不能为空,请检查输入!");
            }
            int itemId;
            double paymentAmount;
            try {
                itemId = Integer.parseInt(itemIdStr);
                paymentAmount = Double.parseDouble(paymentAmountStr);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("缴费参数格式错误,请检查输入的参数格式是否正确!", e);
            }

            HttpSession session = request.getSession(false);
            if (session!= null) {
                User user = (User) session.getAttribute("user");
                if (user == null) {
                    // 用户信息不存在,可能是会话异常等情况,重定向到登录页
                    System.out.println("用户信息在会话中不存在,重定向到登录页");
                    response.sendRedirect(request.getContextPath() + "/login.jsp");
                    return;
                }

                PaymentRecord paymentRecord = new PaymentRecord();
                paymentRecord.setUser_id(user.getUser_id());
                paymentRecord.setItem_id(itemId);
                paymentRecord.setPayment_amount(paymentAmount);
                paymentRecord.setPayment_time(new Date());

                PaymentRecordDAO paymentRecordDAO = new PaymentRecordDAOImpl();
                int result = paymentRecordDAO.addPaymentRecord(paymentRecord);
                if (result > 0) {
                    // 缴费成功后,将缴费金额作为参数添加到重定向的URL中,同时格式化日期时间方便展示(可根据需求调整日期格式)
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String formattedPaymentTime = sdf.format(paymentRecord.getPayment_time());
                    System.out.println("缴费成功,用户:" + user.getUser_id() + ",缴费项目:" + itemId + ",金额:" + paymentAmount + ",时间:" + formattedPaymentTime);
                    response.sendRedirect(request.getContextPath() + "/qrcode.jsp?paymentAmount=" + paymentAmount);
                } else {
                    request.setAttribute("errorMessage", "缴费失败,请稍后再试!");
                    request.getRequestDispatcher(request.getContextPath() + "/payment.jsp").forward(request, response);
                    System.out.println("缴费记录插入数据库失败,可能是数据库操作异常等原因");
                }
            } else {
                System.out.println("未获取到有效的会话,重定向到登录页");
                response.sendRedirect(request.getContextPath() + "/login.jsp");
            }
        } catch (IllegalArgumentException e) {
            // 捕获参数相关异常,记录错误信息并转发到缴费页面提示用户
            System.out.println("参数异常:" + e.getMessage());
            request.setAttribute("errorMessage", e.getMessage());
            request.getRequestDispatcher(request.getContextPath() + "/payment.jsp").forward(request, response);
        } catch (ServletException | IOException e) {
            // 捕获其他Servlet相关异常,记录详细错误信息(可考虑更完善的错误页面展示给用户)
            System.out.println("Servlet执行出现严重错误:" + e.getMessage());
            e.printStackTrace();
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "服务器内部出现错误,请联系管理员!");
        } catch (Exception e) {
            // 捕获其他未预期的异常,记录并返回通用错误信息给用户(可根据实际完善错误处理逻辑)
            System.out.println("出现未知异常:" + e.getMessage());
            e.printStackTrace();
            request.setAttribute("errorMessage", "系统出现未知错误,请联系管理员!");
            request.getRequestDispatcher(request.getContextPath() + "/payment.jsp").forward(request, response);
        }
    }
}

RegisterServlet.java

处理业主注册请求,校验手机号格式,添加业主信息到数据库,注册成功跳转至登录页,失败提示错误。

package com.tt.servlet;

import com.tt.dao.UserDAO;
import com.tt.dao.UserDAOImpl;
import com.tt.entity.User;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.regex.Pattern;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        String buildingNumber = request.getParameter("buildingNumber");
        String unitNumber = request.getParameter("unitNumber");
        String roomNumber = request.getParameter("roomNumber");
        String houseType = request.getParameter("houseType");
        String carNumber = request.getParameter("carNumber");
        String phone = request.getParameter("phone");
        String password = request.getParameter("password");
        String role = "owner";  // 这里默认注册为普通业主角色,可根据需求调整

        // 简单校验手机号格式,这里只是简单判断是否是11位数字,实际应用中可使用更严格的校验规则
        if (!Pattern.matches("\\d{11}", phone)) {
            request.setAttribute("errorMessage", "手机号格式不正确,请重新输入!");
            request.getRequestDispatcher(request.getContextPath() + "/register.jsp").forward(request, response);
            return;
        }

        User user = new User();
        user.setName(name);
        user.setBuilding_number(buildingNumber);
        user.setUnit_number(unitNumber);
        user.setRoom_number(roomNumber);
        user.setHouse_type(houseType);
        user.setCar_number(carNumber);
        user.setPhone(phone);
        user.setPassword(password);
        user.setRole(role);

        UserDAO userDAO = new UserDAOImpl();
        int result = userDAO.addUser(user);
        if (result > 0) {
            response.sendRedirect(request.getContextPath() + "/login.jsp");
        } else {
            request.setAttribute("errorMessage", "注册失败,请稍后再试!");
            request.getRequestDispatcher(request.getContextPath() + "/register.jsp").forward(request, response);
        }
    }
}


五、运行效果

1.登录

2.管理员页面

3.收费管理页面

4.缴费记录页面查询

5.用户页面

6.用户缴费页面

7.用户缴费记录查询

七、心得体会

在完成本项目的过程中,不仅对 Java Web 开发技术有了更深入的理解和掌握,包括 JSP、Servlet、JDBC 等技术的实际应用,还提高了自己对复杂系统的设计和开发能力。从需求分析、技术选型到功能模块设计和数据库设计,每一个环节都需要严谨对待,任何一个小的疏忽都可能导致后续开发的困难。同时,在解决实际工程问题时,学会了运用所学知识设计多种解决方案,并通过查阅文献等方式寻求更好的替代方案,这对于提升自己的技术素养和解决问题的能力有很大帮助。此外,在开发环境的搭建和配置以及页面设计方面,也积累了宝贵的经验,明白了良好的用户体验和系统稳定性的重要性。总之,通过这个项目的实践,收获颇丰,也认识到自己在技术领域还有很多需要学习和提高的地方,将继续努力提升自己的专业能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值