使用html+Servlet+数据库的方式完成一个简单的酒店管理系统。
项目整体分为客户端那u和管理员端。
客户端:
1.用户登录功能:用户登录功能
2.入住房间:在可以入住的房间之上进行操作,进行入住。
管理员端:
管理员可以直接根据系统默认的用户名密码登录,进行房间和旅客的信息管理。
信息展示和操作:
- 旅客信息展示:展示全部的旅客信息并配合操作
-
房间信息展示:展示全部的房间信息并配合操作
工作日志:
日期:4月3日
任务:数据库的构建以及用户登陆功能的实现
数据库:
考虑到项目仅实现了,用户的登陆和入住功能以及管理员对用户和房间的增删改查功能。决定使用两张表,分别是users、rooms。代码如下:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8mb4_bin NOT NULL,
`password` varchar(50) COLLATE utf8mb4_bin NOT NULL,
`phone` varchar(20) COLLATE utf8mb4_bin NOT NULL,
`id_card` varchar(20) COLLATE utf8mb4_bin NOT NULL,
`status` enum('入住','未入住') COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `phone` (`phone`),
UNIQUE KEY `id_card` (`id_card`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
CREATE TABLE `rooms` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`room_number` varchar(10) COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
用户表字段分别是 用户id、用户姓名、用户密码、用户手机号、用户id_card。(管理员的id为1)
房间表字段分别是 房间id、房间号码。
前端页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>客户端登录</title>
<script src='js/jquery-3.7.1.min.js'></script>
<script src="js/jquery.cookie.min.js"></script>
<script src='js/login.js' defer></script>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
#loginForm {
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
width: 300px;
}
h1 {
text-align: center;
color: #4CAF50;
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
input[type="button"] {
width: 100%;
background-color: #4CAF50;
color: white;
padding: 12px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
input[type="button"]:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<form id="loginForm">
<h1>客户端登录</h1>
<label for="phone">手机号:</label>
<input type="text" class="phone" id="phone"><br>
<label for="password">密码:</label>
<input type="password" class="password" id="password"><br>
<input type="button" value="登录" class='login'>
</form>
</body>
</html>
login.js代码如下:
$(".login").click(function(){
var phone=$(".phone").val().trim();
var password=$(".password").val().trim();
if (phone === "") {
alert("姓名不能为空");
return;
}
if (password === "") {
alert("性别不能为空");
return;
}
$.ajax({
url: "login",
type: "post",
data: { phone,password },
success: function (value) {
if (value.data.length != 0) {
console.log(value.data[0].id)
if (value.data[0].id==1){
window.location.href = 'users.html';
}
else {
window.location.href = 'check_in.html';}
} else {
alert('登录失败');
}
},
error: function () {
alert("出错啦");
}
});
});
用户输入手机号和密码后经校验进入入住页面。为区分管理员和用户的进入的页面,对返回的value.data[0].id进行判断。
时间:4月4日
任务:新增check_in表。用户入住页面。数据的展示。入住按钮的绑定以及对入住情况的判断。
因为要考虑用户的入住之后不能再入住,以及其他用户不能入住已经入住的房间。添加check_in表来做记录。
CREATE TABLE `check_ins` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`room_id` int(11) NOT NULL,
`check_in_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`check_out_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `room_id` (`room_id`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
CREATE DEFINER=`skip-grants user`@`skip-grants host` TRIGGER before_insert_check_in
BEFORE INSERT ON check_ins
FOR EACH ROW
BEGIN
-- 检查用户是否已有未退房记录
IF EXISTS (
SELECT 1 FROM check_ins
WHERE user_id = NEW.user_id
AND check_out_time IS NULL
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '用户已入住,不可重复入住';
END IF;
END;
对与入住页面会展示房间id、房间号以及房间此时的状态还有入住和退房的操作。
对于数据的查询,在入住页面的回显。
html代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>入住管理</title>
<script src='js/jquery-3.7.1.min.js'></script>
<script src="js/jquery.cookie.min.js"></script>
<script src='js/client.js' defer></script>
<script>
function checkOut() {
var userId = $.cookie("user_id");
if (!userId) {
alert("请先登录");
return;
}
$.ajax({
url: "CheckOutServlet",
type: "post",
data: { user_id: userId },
success: function(response) {
console.log(response.status)
if (response.status === "success") {
alert("退房成功");
location.reload();
} else {
alert("退房失败");
}
},
error: function() {
alert("请求失败");
}
});
}
</script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
th, td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #4CAF50;
color: white;
}
tr:hover {
background-color: #f5f5f5;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<table>
<thead></thead>
<tbody>
<tr>
<th>id</th>
<th>房间号</th>
<th>状态</th>
<th>操作</th>
</tr>
</tbody>
</table>
<button onclick="checkOut()">退房</button>
</body>
</html>
client.js代码如下:
$.ajax({
url:"ClientCheckInServlet",
type:"get",
success:function(value){
// alert(value);
// alert('成功');
console.log(value)
var arr=value.data
for(var i=0;i<arr.length;i++){
$("tbody").append("<tr>"+
"<td>"+arr[i].id+"</td>"+
"<td>"+arr[i].room_number+"</td>"+
"<td>"+arr[i].status+"</td>"+
"<td><input type='button' value='入住' class='checkin' index='"+arr[i].id+"' index1='"+arr[i].status+"' > </td>"
+"</tr>")
}
// window.location.href = 'check_in.html';
//点修改小模块展现 未来元素不能直接帮事件,要邦最近的在html已有的上一层元素
$("tbody").on("click",".checkin",function(){
var id= $(this).attr("index")
var status =$(this).attr("index1")
$.ajax({
url: "UpdateServlet",
type: "post",
data:{id},
success: function (value) {
if (status=="occupied"){alert('房间已满');}
else{console.log(value);
alert(value);}
},
error: function () {
alert("出错啦");
}
})
})
},
error:function(){
alert('登录失败');
},
})
ClientCheckInServlet代码实现了对房间信息的查询如下:
package com.qcby.servlet;
import java.io.IOException;
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 com.qcby.db.MysqlUtil;
/**
* Servlet implementation class ClientCheckInServlet
*/
@WebServlet("/ClientCheckInServlet")
public class ClientCheckInServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ClientCheckInServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("get");
String sql="select * from rooms";
String[] columns= {"id","room_number","status"};
String[] columns = {"id", "room_number", "status", "resident_name"};
String res=MysqlUtil.getJsonBySql(sql, columns);
System.out.println(res);
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(res);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
入住按钮的绑定
package com.qcby.servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
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 com.qcby.db.MysqlUtil;
/**
* Servlet implementation class CheckInServlet
*/
@WebServlet("/CheckInServlet")
public class CheckInServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CheckInServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Connection conn = null;
try {
conn = MysqlUtil.getConnection();
conn.setAutoCommit(false); // 开启事务
// 获取参数
String roomId = request.getParameter("room_id");
String userId = request.getParameter("user_id");
// 检查用户是否已有未退房的记录
String checkSql = "SELECT COUNT(*) FROM check_ins WHERE user_id = ? AND check_out_time IS NULL";
try (PreparedStatement psCheck = conn.prepareStatement(checkSql)) {
psCheck.setInt(1, Integer.parseInt(userId));
ResultSet rs = psCheck.executeQuery();
if (rs.next() && rs.getInt(1) > 0) {
response.getWriter().write("{\"status\":\"error\",\"message\":\"您已入住其他房间,请先退房\"}");
return;
}
}
// 更新房间状态
String updateRoomSql = "UPDATE rooms SET status = 'occupied' WHERE id = ?";
try (PreparedStatement psRoom = conn.prepareStatement(updateRoomSql)) {
psRoom.setInt(1, Integer.parseInt(roomId));
psRoom.executeUpdate();
}
// 插入入住记录
String insertCheckInSql = "INSERT INTO check_ins (user_id, room_id) VALUES (?, ?)";
try (PreparedStatement psCheckIn = conn.prepareStatement(insertCheckInSql)) {
psCheckIn.setInt(1, Integer.parseInt(userId));
psCheckIn.setInt(2, Integer.parseInt(roomId));
psCheckIn.executeUpdate();
}
conn.commit(); // 提交事务
response.getWriter().write("{\"status\":\"success\"}");
} catch (Exception e) {
if (conn != null) {
try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); }
}
response.getWriter().write("{\"status\":\"error\",\"message\":\"" + e.getMessage() + "\"}");
} finally {
if (conn != null) {
try { conn.close(); } catch (SQLException e) { e.printStackTrace(); }
}
}
}
}
检查用户是否已有未退房记录
String checkSql = "SELECT COUNT(*) FROM check_ins WHERE user_id = ? AND check_out_time IS NULL";
try (PreparedStatement psCheck = conn.prepareStatement(checkSql)) {
psCheck.setInt(1, Integer.parseInt(userId));
ResultSet rs = psCheck.executeQuery();
if (rs.next() && rs.getInt(1) > 0) {
response.getWriter().write("{\"status\":\"error\",\"message\":\"您已入住其他房间,请先退房\"}");
return; // 终止请求处理
}
}
业务规则:不允许用户同时入住多个房间。
逻辑:
- 查询
check_ins
表中该用户是否存在check_out_time
为NULL
的记录(即未退房)。 - 若存在,返回错误信息,阻止本次入住。
更新房间状态为 “已占用”
String updateRoomSql = "UPDATE rooms SET status = 'occupied' WHERE id = ?";
try (PreparedStatement psRoom = conn.prepareStatement(updateRoomSql)) {
psRoom.setInt(1, Integer.parseInt(roomId));
psRoom.executeUpdate(); // 执行更新
}
操作:将目标房间的状态从 available
(可用)改为 occupied
(已占用)。
做用:确保其他用户无法同时入住同一房间。
插入入住记录
String insertCheckInSql = "INSERT INTO check_ins (user_id, room_id) VALUES (?, ?)";
try (PreparedStatement psCheckIn = conn.prepareStatement(insertCheckInSql)) {
psCheckIn.setInt(1, Integer.parseInt(userId));
psCheckIn.setInt(2, Integer.parseInt(roomId));
psCheckIn.executeUpdate(); // 插入记录
}
退房操作:
package com.qcby.servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
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 com.qcby.db.MysqlUtil;
@WebServlet("/CheckOutServlet")
public class CheckOutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Connection conn = null;
try {
conn = MysqlUtil.getConnection();
conn.setAutoCommit(false); // 开启事务
String userId = request.getParameter("user_id");
if (userId == null || userId.isEmpty()) {
sendError(response, "用户ID不能为空");
return;
}
// 1. 查询用户当前入住的房间ID
String getRoomSql = "SELECT room_id FROM check_ins WHERE user_id = ? AND check_out_time IS NULL ORDER BY check_in_time DESC LIMIT 1";
int roomId = -1;
try (PreparedStatement ps = conn.prepareStatement(getRoomSql)) {
ps.setInt(1, Integer.parseInt(userId));
ResultSet rs = ps.executeQuery();
if (rs.next()) {
roomId = rs.getInt("room_id");
} else {
sendError(response, "未找到有效入住记录");
return;
}
}
// 2. 更新入住记录的退房时间
String updateCheckInSql = "UPDATE check_ins SET check_out_time = NOW() WHERE user_id = ? AND check_out_time IS NULL";
try (PreparedStatement ps = conn.prepareStatement(updateCheckInSql)) {
ps.setInt(1, Integer.parseInt(userId));
int affectedRows = ps.executeUpdate();
if (affectedRows == 0) {
sendError(response, "退房失败:未更新入住记录");
return;
}
}
// 3. 更新房间状态为可用
String updateRoomSql = "UPDATE rooms SET status = 'available' WHERE id = ?";
try (PreparedStatement ps = conn.prepareStatement(updateRoomSql)) {
ps.setInt(1, roomId);
ps.executeUpdate();
}
conn.commit(); // 提交事务
sendSuccess(response, "退房成功");
} catch (Exception e) {
rollback(conn);
sendError(response, "系统错误: " + e.getMessage());
} finally {
closeConnection(conn);
}
}
// -------------------------------- 工具方法 --------------------------------
private void sendSuccess(HttpServletResponse response, String message) throws IOException {
response.setContentType("application/json");
response.getWriter().write("{\"status\":\"success\",\"message\":\"" + message + "\"}");
}
private void sendError(HttpServletResponse response, String message) throws IOException {
response.setContentType("application/json");
response.getWriter().write("{\"status\":\"error\",\"message\":\"" + message + "\"}");
}
private void rollback(Connection conn) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private void closeConnection(Connection conn) {
if (conn != null) {
try {
conn.setAutoCommit(true); // 恢复自动提交模式
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
日期:4月5日
任务:管理端的用户管理和房间管理,入住代码的优化
用户管理有数据库数据的回显,以及删除修改功能的实现。
前端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户管理</title>
<script src='js/jquery-3.7.1.min.js'></script>
<script src="js/jquery.cookie.min.js"></script>
<script src='js/users.js' defer></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
th, td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #4CAF50;
color: white;
}
tr:hover {
background-color: #f5f5f5;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
button, input[type="button"] {
background-color: #4CAF50;
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
margin-bottom: 20px;
}
button:hover, input[type="button"]:hover {
background-color: #45a049;
}
.addModel, .deleteModel, .updateModel {
width: 300px;
padding: 20px;
margin-top: 20px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: white;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
display: none;
}
input[type="text"] {
width: 100%;
padding: 8px;
margin: 8px 0;
box-sizing: border-box;
border: 1px solid #ddd;
border-radius: 4px;
}
.back {
background-color: #f44336;
}
.back:hover {
background-color: #d32f2f;
}
</style>
</head>
<body>
<button onclick="window.location.href='room.html'">房间管理</button>
<table>
<thead></thead>
<tbody>
<tr>
<th>id</th>
<th>姓名</th>
<th>密码</th>
<th>电话</th>
<th>身份证</th>
<th>状态</th>
<th>操作</th>
</tr>
</tbody>
</table>
<div class="updateModel">
姓名:<input type='text' class='upname'><br>
密码:<input type='text' class='uppassword'><br>
电话:<input type='text' class='upphone'><br>
身份证:<input type='text' class='upidcard'><br>
状态:<input type='text' class='upstatus' list="optionList"><br>
<datalist id="optionList">
<option value="入住">入住</option>
<option value="未入住">未入住</option>
</datalist>
<input type='button' value='更新' class='upBtn'>
<input type='button' value='取消' class='back'>
</div>
<div class="deleteModel">
姓名:<input type='text' class='delname'><br>
密码:<input type='text' class='delpassword'><br>
电话:<input type='text' class='delphone'><br>
身份证:<input type='text' class='delidcard'><br>
状态:<input type='text' class='delstatus'><br>
<input type='button' value='删除' class='delBtn'>
<input type='button' value='取消' class='back'>
</div>
</body>
</html>
users.js代码如下:
$.ajax({
url:"users",
type:"get",
success:function(value){
// alert(value);
// alert('成功');
console.log(value)
var arr=value.data
for(var i=0;i<arr.length;i++){
$("tbody").append("<tr>"+
"<td>"+arr[i].id+"</td>"+
"<td>"+arr[i].name+"</td>"+
"<td>"+arr[i].password+"</td>"+
"<td>"+arr[i].phone+"</td>"+
"<td>"+arr[i].id_card+"</td>"+
"<td>"+arr[i].status+"</td>"+
"<td><input type='button' value='修改' class='update' index='"+arr[i].id+"'> <input type='button' value='删除' class='delete' index='"+arr[i].id+"'> </td>"
+"</tr>")
}
},
error:function(){
alert('登录失败');
}
})
//修改
$("tbody").on("click",".update",function(){
// 设置cookie
// $.cookie("id", $(this).attr("index"))
// location.href="update.html"
$(".updateModel").css("display","block")
var id= $(this).attr("index")
$.ajax({
url: "SearchById?id="+id,
type: "get",
success: function (value) {
// alert("1111");
console.log(value);
var obj=value.data[0];
$(".upname").val(obj.name)
$(".uppassword").val(obj.password)
$(".upphone").val(obj.phone)
$(".upidcard").val(obj.id_card)
$(".upstatus").val(obj.status)
$(".upBtn").attr("index",obj.id)
},
error: function () {
alert("出错啦");
}
});
})
//更新
$(".upBtn").click(function(){
var id= $(this).attr("index")
var name = $(".upname").val().trim();
var password = $(".uppassword").val().trim();
var phone = $(".upphone").val().trim();
var id_card = $(".upidcard").val().trim();
var status = $(".upstatus").val().trim();
$.ajax({
url: "userUpdate",
type: "post",
data:{id, name, password, phone,id_card,status},
success: function (value) {
alert("修改成功")
// alert("1111");
console.log(value);
location.reload();
},
error: function () {
alert("出错啦");
}
});
})
// 删除
//点修改小模块展现 未来元素不能直接帮事件,要邦最近的在html已有的上一层元素
$("tbody").on("click",".delete",function(){
$(".deleteModel").css("display","block")
var id= $(this).attr("index")
$.ajax({
url: "SearchById?id="+id,
type: "get",
success: function (value) {
// alert("1111");
console.log(value);
var obj=value.data[0];
$(".delname").val(obj.name)
$(".delpassword").val(obj.password)
$(".delphone").val(obj.phone)
$(".delidcard").val(obj.id_card)
$(".delstatus").val(obj.status)
$(".delBtn").attr("index",obj.id)
},
error: function () {
alert("出错啦");
}
});
})
//删除
$(".delBtn").click(function(){
var id= $(this).attr("index")
console.log(id)
$.ajax({
url: "DeleteServlet",
type: "post",
data: {id},
success: function (value) {
alert(value);
location.reload();
},
error: function () {
alert("出错啦");
}
});
})
//点取消小模块隐藏
$(".back").click(function(){
$(".addModel").css("display","none")
$(".updateModel").css("display","none")
$(".deleteModel").css("display","none")
})
searchbyid代码如下:
package com.qcby.servlet;
import java.io.IOException;
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 com.qcby.db.MysqlUtil;
/**
* Servlet implementation class SearchById
*/
@WebServlet("/SearchById")
public class SearchById extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public SearchById() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id=request.getParameter("id");
// String sql="select *from room where id="+id;
String sql="select *from users where id="+id;
String[] colums= {"id","name","password","phone","id_card","status"};
// String[] colums= {"id","room_number","status"};
String res=MysqlUtil.getJsonBySql(sql, colums);
System.out.println(res);
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(res);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
DeleteServlet代码如下:
package com.qcby.servlet;
import java.io.IOException;
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 com.qcby.db.MysqlUtil;
import com.sun.xml.internal.bind.v2.runtime.Name;
/**
* Servlet implementation class UpdateServlet
*/
@WebServlet("/DeleteServlet")
public class DeleteServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public DeleteServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("post成功!!");
String id = request.getParameter("id");
String sql="DELETE from users where id="+id+";";
int num=MysqlUtil.del(sql);
String res="worng";
if(num>0) {
res="删除成功";
}
response.setCharacterEncoding("utf-8");
response.getWriter().write(res);
}
}
房间管理实现的功能包括数据的回显,数据的修改、删除以及添加。
前端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>房间管理</title>
<script src='js/jquery-3.7.1.min.js'></script>
<script src="js/jquery.cookie.min.js"></script>
<script src='js/room.js' defer></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
th, td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #4CAF50;
color: white;
}
tr:hover {
background-color: #f5f5f5;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
button, input[type="button"] {
background-color: #4CAF50;
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
margin-bottom: 20px;
}
button:hover, input[type="button"]:hover {
background-color: #45a049;
}
.addModel, .deleteModel, .updateModel {
width: 300px;
padding: 20px;
margin-top: 20px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: white;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
display: none;
}
input[type="text"] {
width: 100%;
padding: 8px;
margin: 8px 0;
box-sizing: border-box;
border: 1px solid #ddd;
border-radius: 4px;
}
.back {
background-color: #f44336;
}
.back:hover {
background-color: #d32f2f;
}
</style>
</head>
<body>
<button onclick="window.location.href='users.html'">用户管理</button>
<input type="button" value='添加' class='add'>
<table>
<thead></thead>
<tbody>
<tr>
<th>id</th>
<th>房间号</th>
<th>状态</th>
<th>操作</th>
<th>住户</th>
</tr>
</tbody>
</table>
<div class="updateModel">
房间号:<input type='text' class='uproomnumber'><br>
状态:<input type='text' class='upstatus' list="optionList"><br>
<datalist id="optionList">
<option value="available">available</option>
<option value="occupied">occupied</option>
</datalist>
<input type='button' value='更新' class='upBtn'>
<input type='button' value='取消' class='back'>
</div>
<div class="deleteModel">
房间号:<input type='text' class='delroomnumber'><br>
状态:<input type='text' class='delstatus'><br>
<input type='button' value='删除' class='delBtn'>
<input type='button' value='取消' class='back'>
</div>
<div class='addModel'>
房间号:<input type='text' class='addroomnumber'><br>
状态:<input type='text' class='addstatus' list="optionList"><br>
<datalist id="optionList">
<option value="available">available</option>
<option value="occupied">occupied</option>
</datalist>
<input type='button' value='添加' class='addBtn'>
<input type='button' value='取消' class='back'>
</div>
</body>
</html>
room.js代码:
$.ajax({
url:"ClientCheckInServlet",
type:"get",
success:function(value){
// alert(value);
// alert('成功');
console.log(value)
var arr=value.data
for(var i=0;i<arr.length;i++){
// ---------------------------
var residentName = arr[i].resident_name || "空"; // 处理空值情况
// ---------------------------
$("tbody").append("<tr>"+
"<td>"+arr[i].id+"</td>"+
"<td>"+arr[i].room_number+"</td>"+
"<td>"+arr[i].status+"</td>"+
"<td><input type='button' value='修改' class='update' index='"+arr[i].id+"'> <input type='button' value='删除' class='delete' index='"+arr[i].id+"'> </td>"
// ------------------------------------
+
"<td>"+residentName+"</td>"+ // 新增住户列
// -------------------------------------2
+"</tr>")
}
},
error:function(){
alert('登录失败');
}
})
//修改
$("tbody").on("click",".update",function(){
// 设置cookie
// $.cookie("id", $(this).attr("index"))
// location.href="update.html"
$(".updateModel").css("display","block")
var id= $(this).attr("index")
$.ajax({
url: "RoomSearchById?id="+id,
type: "get",
success: function (value) {
// alert("1111");
console.log(value);
var obj=value.data[0];
$(".uproomnumber").val(obj.room_number)
$(".upstatus").val(obj.status)
$(".upBtn").attr("index",obj.id)
},
error: function () {
alert("出错啦");
}
});
})
//更新
$(".upBtn").click(function(){
var id= $(this).attr("index")
var room_number = $(".uproomnumber").val().trim();
var status = $(".upstatus").val().trim();
$.ajax({
url: "roomUpdate",
type: "post",
data:{id, room_number,status},
success: function (value) {
alert("修改成功")
// alert("1111");
console.log(value);
location.reload();
},
error: function () {
alert("出错啦");
}
});
})
// 删除
//点修改小模块展现 未来元素不能直接帮事件,要邦最近的在html已有的上一层元素
$("tbody").on("click",".delete",function(){
$(".deleteModel").css("display","block")
var id= $(this).attr("index")
$.ajax({
url: "RoomSearchById?id="+id,
type: "get",
success: function (value) {
// alert("1111");
console.log(value);
var obj=value.data[0];
$(".delroomnumber").val(obj.room_number)
$(".delstatus").val(obj.status)
$(".delBtn").attr("index",obj.id)
},
error: function () {
alert("出错啦");
}
});
})
//删除
$(".delBtn").click(function(){
var id= $(this).attr("index")
console.log(id)
$.ajax({
url: "RoomDeleteServlet",
type: "post",
data: {id},
success: function (value) {
alert(value);
location.reload();
},
error: function () {
alert("出错啦");
}
});
})
//点添加小模块展现
$(".add").click(function(){
$(".addModel").css("display","block")
})
//添加
$(".addBtn").click(function(){
var room_number = $(".addroomnumber").val().trim();
var status = $(".addstatus").val().trim();
if (room_number === "") {
alert("房间号不能为空");
return;
}
if (status === "") {
alert("状态不能为空");
return;
}
$.ajax({
url: "AddServlet",
type: "post",
data: { room_number, status },
success: function (value) {
alert(value);
location.href="room.html"
},
error: function () {
alert("出错啦");
}
});
})
//点取消小模块隐藏
$(".back").click(function(){
$(".addModel").css("display","none")
$(".updateModel").css("display","none")
$(".deleteModel").css("display","none")
})
RoomDeleteServlet代码如下:
package com.qcby.servlet;
import java.io.IOException;
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 com.qcby.db.MysqlUtil;
/**
* Servlet implementation class RoomDeleteServlet
*/
@WebServlet("/RoomDeleteServlet")
public class RoomDeleteServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public RoomDeleteServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("post成功!!");
String id = request.getParameter("id");
String sql="DELETE from rooms where id="+id+";";
int num=MysqlUtil.del(sql);
String res="worng";
if(num>0) {
res="删除成功";
}
response.setCharacterEncoding("utf-8");
response.getWriter().write(res);
}
}
RoomSearchById代码如下:
package com.qcby.servlet;
import java.io.IOException;
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 com.qcby.db.MysqlUtil;
/**
* Servlet implementation class RoomSearchById
*/
@WebServlet("/RoomSearchById")
public class RoomSearchById extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public RoomSearchById() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id=request.getParameter("id");
String sql="select *from rooms where id="+id;
// String sql="select *from users where id="+id;
// String[] colums= {"id","name","password","phone","id_card","status"};
String[] colums= {"id","room_number","status"};
String res=MysqlUtil.getJsonBySql(sql, colums);
System.out.println(res);
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(res);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
roomUpdate代码如下:
package com.qcby.servlet;
import java.io.IOException;
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 com.qcby.db.MysqlUtil;
/**
* Servlet implementation class roomUpdate
*/
@WebServlet("/roomUpdate")
public class roomUpdate extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public roomUpdate() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// System.out.println("update post成功");
String id = request.getParameter("id");
String room_number = request.getParameter("room_number");
String status = request.getParameter("status");
if (!"available".equals(status) && !"occupied".equals(status)) {
status = "available"; // 设置默认值或抛出异常
}
String sql = "UPDATE rooms set room_number=\""+room_number+"\",status=\""+status+"\" where id="+id+";";
int num=MysqlUtil.update(sql);
String res="worng";
if(num>0) {
res="修改成功";
}
response.setCharacterEncoding("utf-8");
response.getWriter().write(res);
}
}
check_in代码的优化:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>入住管理</title>
<script src="js/jquery-3.7.1.min.js"></script>
<script src="js/jquery.cookie.min.js"></script>
<script>
function checkUserOccupied(userId) {
return new Promise((resolve) => {
$.ajax({
url: "CheckUserOccupancyServlet",
type: "post",
data: { user_id: userId },
async: false,
success: function(response) {
resolve(response.occupied);
}
});
});
}
function checkOut() {
var userId = $.cookie("user_id");
if (!userId) {
alert("请先登录");
return;
}
$.ajax({
url: "CheckOutServlet",
type: "post",
data: { user_id: userId },
success: function(response) {
if (response.status === "success") {
alert("退房成功");
location.reload(); // 退房后刷新页面,重新启用按钮
} else {
alert("退房失败:" + response.message);
}
}
});
}
$(document).ready(function() {
var userId = $.cookie("user_id");
window.userIsOccupied = false; // 新增全局标记
// 页面加载时检查用户状态并禁用按钮
if (userId) {
checkUserOccupied(userId).then(occupied => {
if (occupied) {
$(".checkin").prop("disabled", true); // 禁用所有入住按钮
window.userIsOccupied = true; // 设置已入住标记
}
});
}
// 加载房间列表(唯一的 AJAX 入口)
$.ajax({
url: "ClientCheckInServlet",
type: "get",
success: function(value) {
var rooms = value.data || [];
$("tbody").empty();
$("thead").html(`
<tr>
<th>房间ID</th>
<th>房间号</th>
<th>状态</th>
<th>操作</th>
</tr>
`);
rooms.forEach(room => {
$("tbody").append(`
<tr>
<td>${room.id}</td>
<td>${room.room_number}</td>
<td>${room.status === "available" ? "可用" : "已占用"}</td>
<td><input type='button' value='入住' class='checkin'
index='${room.id}'
index1='${room.status}'
></td>
</tr>
`);
});
// 入住按钮点击事件(唯一的事件绑定)
$("tbody").on("click", ".checkin", async function() {
var roomId = $(this).attr("index");
var userId = $.cookie("user_id");
var $thisBtn = $(this); // 缓存当前按钮
if (!userId) {
alert("请先登录");
return;
}
// 强校验:用户已入住时直接阻止(优先级高于后端)
if (window.userIsOccupied) {
alert("您已入住,不可选择其他房间");
return;
}
// 前端校验:用户是否已入住(防止按钮未禁用时的非法操作)
if (await checkUserOccupied(userId)) {
alert("您已入住,不可选择其他房间");
return;
}
// 发送入住请求(严格处理后端响应)
$.ajax({
url: "CheckInServlet",
type: "post",
data: { room_id: roomId, user_id: userId },
success: function(response) {
var result = JSON.parse(response);
if (result.status === "success") {
alert("入住成功!");
window.userIsOccupied = true; // 标记已入住
$(".checkin").prop("disabled", true); // 禁用所有按钮
location.reload(); // 刷新页面更新房间状态
} else {
// 关键:处理后端错误(如房间已占用、用户已入住)
alert("入住失败:" + result.message);
// 若房间状态变化,可单独更新当前房间按钮(非必须)
// if (result.message === "房间已被占用") $thisBtn.prop("disabled", true);
}
},
error: function() {
alert("请求失败,请稍后再试");
}
});
});
}
});
});
</script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
th, td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #4CAF50;
color: white;
}
tr:hover {
background-color: #f5f5f5;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
input[type="button"] {
padding: 6px 12px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type="button"]:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.checkout-btn {
margin-top: 20px;
display: block;
padding: 10px 20px;
background-color: #f44336;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<h2>房间入住管理</h2>
<table>
<thead></thead>
<tbody>
<!-- 动态生成的房间列表 -->
</tbody>
</table>
<button class="checkout-btn" onclick="checkOut()">退房</button>
</body>
</html>
CheckUserOccupancyServlet代码如下:
package com.qcby.servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
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 com.qcby.db.MysqlUtil;
/**
* Servlet implementation class CheckUserOccupancyServlet
*/
@WebServlet("/CheckUserOccupancyServlet")
public class CheckUserOccupancyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CheckUserOccupancyServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json;charset=utf-8");
int userId = Integer.parseInt(req.getParameter("user_id"));
try (Connection conn = MysqlUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(
"SELECT COUNT(*) FROM check_ins WHERE user_id = ? AND check_out_time IS NULL"
)) {
ps.setInt(1, userId);
ResultSet rs = ps.executeQuery();
boolean occupied = false;
if (rs.next()) occupied = rs.getInt(1) > 0;
resp.getWriter().print("{\"occupied\":" + occupied + "}");
} catch (Exception e) {
resp.getWriter().print("{\"occupied\":false}");
}
}
}