You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Library/RManager注释.md

3052 lines
122 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
filter 包Java Web 中 Filter 用于过滤请求处理编码、权限验证、XSS 防护等。比如图中的 AdminFilter、XSSFilter分别做权限和防攻击。
javabean 包:存放实体类,封装数据,对应数据库表或业务数据。像 Admin、Manager 这些类,用于存储属性,遵循 JavaBean 规范,有 getter/setter 等。
servlet 包:处理客户端请求,接收参数,调用业务逻辑,返回响应。比如 ManagerLogin 处理登录请求Announcement 相关的处理公告操作。
现在组织这些内容,分三个部分解释每个包的作用,确保清晰准确。
*/
///
// * * * CharacterEncondingFilter.java
/**
* 字符编码过滤器用于统一设置请求与响应的字符编码为UTF-8解决文本乱码问题
*/
public class CharacterEncodingFilter implements Filter {
/**
* 过滤器初始化方法,由容器调用,用于获取过滤器配置参数等初始化操作
* @param filterConfig 过滤器配置对象,可从中读取初始化参数
* @throws ServletException 初始化过程中发生异常时抛出
*/
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 执行过滤逻辑的核心方法,处理请求响应的编码设置
* @param servletRequest 客户端发送的请求对象
* @param servletResponse 服务器返回的响应对象
* @param filterChain 过滤链,用于将请求响应传递给后续处理组件
* @throws IOException 输入输出操作异常
* @throws ServletException Servlet处理过程异常
*/
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 设置请求编码为UTF-8确保接收参数时字符编码统一
servletRequest.setCharacterEncoding("UTF-8");
// 设置响应编码为UTF-8确保返回数据的字符编码统一
servletResponse.setCharacterEncoding("UTF-8");
// 将请求和响应传递给过滤链中的下一个组件如其他过滤器或Servlet
filterChain.doFilter(servletRequest, servletResponse);
}
/**
* 过滤器销毁方法,由容器调用,用于释放过滤器占用的资源
* 当前过滤器无需要释放的资源,方法体为空
*/
public void destroy() {
}
}
// * * * ManagerFilter.java
package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
// * 图书管理员过滤类,用于拦截请求并校验用户是否为登录状态的图书管理员* 实现Filter接口完成请求过滤逻辑
public class ManagerFilter implements Filter {
// * 过滤器销毁方法,用于释放资源* 在过滤器生命周期结束时调用,此处暂无资源释放操作
public void destroy() {
}
/**
* 核心过滤方法,处理请求过滤逻辑
* @param request 客户端发送的请求对象
* @param response 服务器返回的响应对象
* @param chain 过滤器链,用于传递请求和响应
* @throws IOException IO异常
* @throws ServletException Servlet处理异常
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 将通用请求对象转换为Http请求对象
HttpServletRequest req = (HttpServletRequest) request;
// 获取请求对应的HttpSession
HttpSession session = req.getSession();
// 检查session是否存在以及session中是否存在标识管理员登录的"manager"属性
if (session == null || session.getAttribute("manager") == null) {
// 将通用响应对象转换为Http响应对象
HttpServletResponse rep = (HttpServletResponse) response;
// 重定向到管理员登录页面,阻止未登录用户访问受保护资源
rep.sendRedirect(req.getContextPath() + "/loginManager.html");
return; // 终止后续过滤逻辑
}
// 将请求和响应传递给过滤器链中的下一个组件如其他过滤器或Servlet
chain.doFilter(request, response);
}
// * 过滤器初始化方法,用于获取配置参数等初始化操作* @param fConfig 过滤器配置对象* @throws ServletException Servlet初始化异常
public void init(FilterConfig fConfig) throws ServletException {
}
}
// * XSS过滤器用于过滤请求参数中的跨站脚本攻击代码如 script、style 标签等),保护应用免受 XSS 攻击
public class XSSFilter implements Filter {
/**
* 过滤输入字符串中的 XSS 相关代码
* @param htmlStr 待过滤的字符串
* @return 过滤后的字符串,移除了 script、style、HTML 标签内容
*/
public String filter(String htmlStr) {
if (htmlStr == null) {
return null;
}
// 定义匹配 script 标签的正则表达式,不区分大小写
String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>";
// 定义匹配 style 标签的正则表达式,不区分大小写
String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>";
// 定义匹配 HTML 标签的正则表达式,不区分大小写
String regEx_html = "<[^>]+>";
// 编译 script 正则表达式为 Pattern 对象
Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
Matcher m_script = p_script.matcher(htmlStr);
// 替换所有匹配的 script 标签内容为空,即过滤掉 script 标签
htmlStr = m_script.replaceAll("");
// 编译 style 正则表达式为 Pattern 对象
Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
Matcher m_style = p_style.matcher(htmlStr);
// 替换所有匹配的 style 标签内容为空,即过滤掉 style 标签
htmlStr = m_style.replaceAll("");
// 编译 HTML 标签正则表达式为 Pattern 对象
Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
Matcher m_html = p_html.matcher(htmlStr);
// 替换所有匹配的 HTML 标签内容为空,即过滤掉 HTML 标签
htmlStr = m_html.replaceAll("");
return htmlStr.trim(); // 返回处理后去除首尾空白的字符串
}
//自定义请求包装类,重写参数获取方法以实现 XSS 过滤 继承 HttpServletRequestWrapper包装 HttpServletRequest 对象
class Request extends HttpServletRequestWrapper {
public Request(HttpServletRequest request) {
super(request);
}
//重写获取多个参数值的方法,对每个参数值进行 XSS 过滤 ,@param name 参数名 ,@return 过滤后的参数值数组
@Override
public String getParameter(String name) {
// 获取原始参数值并进行过滤
return filter(super.getRequest().getParameter(name));
}
// * * * XSSFilter.java
//重写获取多个参数值的方法,对每个参数值进行 XSS 过滤 ,@param name 参数名 ,@return 过滤后的参数值数组
@Override
public String[] getParameterValues(String name) {
// 获取原始参数值数组
String[] values = super.getRequest().getParameterValues(name);
// 遍历数组,对每个参数值进行过滤
for (int i = 0; i < values.length; i++) {
values[i] = filter(values[i]);
}
return values;
}
}
/**
* 执行过滤逻辑的核心方法
* @param request 客户端请求对象
* @param response 服务器响应对象
* @param chain 过滤链,用于传递请求和响应
* @throws IOException IO 异常
* @throws ServletException Servlet 处理异常
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 使用自定义的 Request 包装请求,实现参数过滤
request = new Request((HttpServletRequest) request);
// 将过滤后的请求传递给过滤链后续组件
chain.doFilter(request, response);
}
//过滤器销毁方法,用于释放资源(当前无资源释放操作)
@Override
public void destroy() {
}
}
// * * * src/main/java/javabean/base.java
package javabean;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 数据库操作基础类,封装数据库连接、查询、更新和资源释放的通用方法
* 依赖DBConstants类获取数据库连接配置
*/
public class Base {
// 数据库连接配置(从DBConstants类获取)
private static final String driver = DBConstants.driver;
private static final String url = DBConstants.url;
private static final String username = DBConstants.username;
private static final String password = DBConstants.password;
/**
* 获取数据库连接
* @return 数据库连接对象
* @throws ClassNotFoundException 数据库驱动未找到异常
*/
public static Connection getConnection() throws ClassNotFoundException {
Connection connection = null;
try {
// 加载数据库驱动
Class.forName(driver);
// 建立数据库连接
connection = (Connection) DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace(); // 打印异常堆栈(实际项目建议日志记录)
}
return connection;
}
/**
* 执行数据库查询操作
* @param connection 数据库连接(可复用)
* @param preparedStatement 预编译语句(可复用)
* @param resultSet 结果集(可复用)
* @param sql SQL语句
* @param params 参数数组(用于预编译语句的占位符)
* @return 查询结果集
* @throws SQLException SQL执行异常
*/
public static ResultSet executequery(Connection connection, PreparedStatement preparedStatement,
ResultSet resultSet, String sql, Object[] params) throws SQLException {
// 如果预编译语句为空,则创建新实例
if (preparedStatement == null) {
preparedStatement = (PreparedStatement) connection.prepareStatement(sql);
}
// 设置预编译语句参数
for (int i = 0; params != null && i < params.length; i++) {
preparedStatement.setObject(i + 1, params[i]);
}
// 执行查询并返回结果集
resultSet = preparedStatement.executeQuery();
return resultSet;
}
/**
* 执行数据库更新操作(INSERT/UPDATE/DELETE
* @param connection 数据库连接(可复用)
* @param preparedStatement 预编译语句(可复用)
* @param sql SQL语句
* @param params 参数数组(用于预编译语句的占位符)
* @return 受影响的行数
* @throws SQLException SQL执行异常
*/
public static int executeUpdate(Connection connection, PreparedStatement preparedStatement, String sql,
Object[] params) throws SQLException {
// 如果预编译语句为空,则创建新实例
if (preparedStatement == null) {
preparedStatement = (PreparedStatement) connection.prepareStatement(sql);
}
// 设置预编译语句参数
for (int i = 0; params != null && i < params.length; i++) {
preparedStatement.setObject(i + 1, params[i]);
}
// 执行更新并返回受影响的行数
int updateRows = preparedStatement.executeUpdate();
return updateRows;
}
/**
* 释放数据库资源(结果集、预编译语句、连接)
* @param connection 数据库连接(可选)
* @param preparedStatement 预编译语句(可选)
* @param resultSet 结果集(可选)
* @return 资源释放成功标志
* @throws SQLException 资源释放异常
*/
public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet)
throws SQLException {
boolean flag = true;
// 按顺序关闭资源:结果集 预编译语句 连接
if (resultSet != null) {
try {
resultSet.close();
resultSet = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
preparedStatement = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (connection != null) {
try {
connection.close();
connection = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
return flag;
}
}
// * * * src/main/java/javabean/DBConstants.java
package javabean;
/**
* 数据库连接配置类,存储数据库连接所需的常量参数
* 注意:实际项目中应避免硬编码密码,建议使用配置文件或环境变量
*/
public class DBConstants {
// MySQL JDBC驱动类(适用于MySQL Connector/J 8.0+版本)
public static final String driver = "com.mysql.cj.jdbc.Driver";
// 数据库连接URL
// 格式:jdbc:mysql://<主机>:<端口>/<数据库名>?参数
// 示例说明:
// - localhost:3306本地MySQL服务默认端口
// - library数据库名称
// - useSSL=false禁用SSL连接生产环境建议启用
// - serverTimezone=UTC设置时区为UTC与数据库保持一致
// - useUnicode=true&characterEncoding=UTF-8启用Unicode编码字符集UTF-8
public static final String url = "jdbc:mysql://localhost:3306/library?&useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
// 数据库用户名通常为root或具有适当权限的用户
public static final String username = "root";
// 数据库密码(注意:硬编码密码存在安全风险,建议使用配置文件或环境变量)
public static final String password = "123456";
}
// * * * src/main/java/javabean/JDBCBean.java
package javabean;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* 数据库操作工具类封装基本的JDBC操作存在安全风险和性能问题建议改进
* 注意直接使用Statement存在SQL注入风险建议改用PreparedStatement
*/
public class JDBCBean {
// 数据库连接配置从DBConstants类获取
private static final String driver = DBConstants.driver;
private static final String url = DBConstants.url;
private static final String username = DBConstants.username;
private static final String password = DBConstants.password;
// 数据库连接和操作对象
private Connection conn = null;
private Statement stmt = null;
/**
* 构造方法初始化数据库连接和Statement对象
* 注意:直接抛出异常到调用者,避免在构造方法中吞掉异常
* 潜在问题:每次实例化都会创建新连接,未使用连接池,影响性能
*/
public JDBCBean() {
try {
Class.forName(driver); // 加载数据库驱动
conn = DriverManager.getConnection(url, username, password); // 建立连接
stmt = conn.createStatement(); // 创建Statement对象存在SQL注入风险
System.out.println("成功与数据库建立连接!");
} catch (ClassNotFoundException | SQLException e) {
System.out.println("无法与数据库建立连接!");
e.printStackTrace(); // 打印异常堆栈(生产环境应使用日志记录)
}
}
/**
* 执行数据库更新操作INSERT/UPDATE/DELETE
* @param s SQL语句存在SQL注入风险
* @return 受影响的行数
*/
public int executeUpdate(String s) {
int result = 0;
try {
System.out.println("执行SQL" + s); // 调试输出,生产环境应移除
result = stmt.executeUpdate(s);
} catch (SQLException e) {
System.out.println("执行更新错误!");
e.printStackTrace();
}
return result;
}
/**
* 执行数据库查询操作
* @param s SQL语句存在SQL注入风险
* @return 查询结果集(需要手动关闭)
*/
public ResultSet executeQuery(String s) {
ResultSet rs = null;
try {
rs = stmt.executeQuery(s);
} catch (SQLException e) {
System.out.println("执行查询错误!" + e.getMessage());
e.printStackTrace();
}
return rs;
}
/**
* 关闭数据库资源Statement和Connection
* 注意:未正确处理异常,可能导致资源泄漏
* 建议使用try-with-resources或在finally块中调用
*/
public void close() {
try {
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// * * * src/main/java/javabean/Common.java
package javabean;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.TreeMap;
/**
* 通用数据库操作工具类,提供表行数统计和图书馆信息映射等功能
*/
public class Common {
/**
* 获取指定表的总记录数
* @param table 表名(不能为空)
* @return 记录总数若表不存在或查询失败返回0
* @throws ClassNotFoundException 数据库驱动未找到异常
* @throws SQLException SQL执行异常
*/
public static int getCount(String table) throws SQLException, ClassNotFoundException {
if (table == null || table.equals("")) {
return 0; // 表名为空直接返回0
}
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try {
connection = Base.getConnection(); // 获取数据库连接
// 构建查询总行数的SQL语句
pstmt = connection.prepareStatement("SELECT COUNT(*) AS count FROM " + table);
resultSet = pstmt.executeQuery(); // 执行查询
resultSet.next(); // 移动到结果集第一条记录
return resultSet.getInt("count"); // 返回总记录数
} catch (SQLException e) {
e.printStackTrace(); // 打印异常堆栈(实际项目建议日志记录)
return 0; // 查询失败返回0
} finally {
// 释放数据库资源
Base.closeResource(connection, pstmt, resultSet);
}
}
/**
* 获取所有图书馆的ID-名称映射按ID升序排列
* @return TreeMap<图书馆ID, 图书馆名称>若查询失败返回null
* @throws SQLException SQL执行异常
*/
public static TreeMap<String, String> getLibraryMap() throws SQLException {
Connection connection = null;
PreparedStatement libraryPstmt = null;
ResultSet librarySet = null;
String librarySql = "SELECT id, name FROM library"; // 查询图书馆的SQL语句
TreeMap<String, String> map = new TreeMap<>(); // 使用TreeMap自动按键ID排序
try {
connection = Base.getConnection(); // 获取数据库连接
libraryPstmt = connection.prepareStatement(librarySql); // 创建预编译语句
librarySet = libraryPstmt.executeQuery(); // 执行查询
// 遍历结果集填充TreeMap
while (librarySet.next()) {
String id = librarySet.getString("id");
String name = librarySet.getString("name");
map.put(id, name); // 键为ID值为名称
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null; // 驱动未找到返回null
} catch (SQLException e) {
e.printStackTrace();
return null; // SQL执行失败返回null
} finally {
// 释放数据库资源
Base.closeResource(connection, libraryPstmt, librarySet);
}
return map;
}
/**
* 测试方法(实际项目建议删除)
* @param args 命令行参数
* @throws SQLException SQL执行异常
*/
public static void main(String[] args) throws SQLException {
System.out.println(Common.getLibraryMap()); // 打印图书馆映射
}
}
// * * * src/main/java/javabean/CompareDate.java
package javabean;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期比较工具类,提供计算两个日期字符串时间差的功能
*/
public class CompareDate {
/**
* 计算两个日期字符串之间的天数差(结束日期 - 开始日期)
* @param Str1 开始日期字符串格式yyyy-MM-dd HH:mm:ss
* @param Str2 结束日期字符串格式yyyy-MM-dd HH:mm:ss
* @return 相差的天数(可能为负数,表示结束日期早于开始日期)
* @throws ParseException 日期格式不正确时抛出(当前方法未处理,直接打印堆栈)
* @implNote 使用SimpleDateFormat进行日期解析存在线程不安全问题
* @implNote 时间差计算为毫秒差除以一天的毫秒数24*60*60*1000结果为整数天数
*/
public static long show(String Str1, String Str2) {
long between = 0;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date1 = format.parse(Str1); // 解析开始日期
Date date2 = format.parse(Str2); // 解析结束日期
between = date2.getTime() - date1.getTime(); // 计算时间差(毫秒)
} catch (ParseException e) {
e.printStackTrace(); // 打印异常堆栈(实际项目应处理异常)
}
// 转换为天数(注意:直接除以一天的毫秒数可能导致精度丢失)
long days = between / (24 * 60 * 60 * 1000);
return days;
}
// 示例用法
public static void main(String[] args) {
long days = CompareDate.show("2023-01-01 00:00:00", "2023-01-03 23:59:59");
System.out.println("相差天数:" + days); // 输出2
}
}
// * * * Manager.java
package javabean;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 管理员业务逻辑处理类,封装管理员登录验证功能
*/
public class Manager {
/**
* 管理员登录验证方法
* @param user 管理员账号
* @param psw 管理员密码
* @return 验证结果:"1"表示成功,其他字符串表示失败原因
* @throws ClassNotFoundException 数据库驱动未找到异常
* @throws SQLException 数据库操作异常
*/
@SuppressWarnings("null") // 抑制空指针警告resultSet在finally中已关闭
public String login(String user, String psw) throws ClassNotFoundException, SQLException {
// 参数校验
if (user == null || user.trim().equals("")) {
return "账号不能为空";
} else if (psw == null || psw.trim().equals("")) {
return "密码不能为空";
}
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
String sql = "select * from manager where ACCOUNT=? and PASSWORD=?";
try {
connection = Base.getConnection(); // 获取数据库连接
pstmt = connection.prepareStatement(sql); // 预编译SQL
pstmt.setString(1, user); // 绑定账号参数
pstmt.setString(2, psw); // 绑定密码参数
resultSet = pstmt.executeQuery(); // 执行查询
if (resultSet.next()) { // 若存在匹配记录
return "1"; // 返回成功标识
}
return "账号或密码错误"; // 查询无结果时返回错误信息
} finally {
// 释放数据库资源
Base.closeResource(connection, pstmt, resultSet);
}
}
}
// * * * java/servlet/announcement.java
package servlet.manager;
import java.io.IOException;
import java.io.PrintWriter;
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 javabean.Base;
import javabean.Util;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* 公告管理Servlet处理公告查询请求
* 映射路径:/manager/announcement
* 仅响应GET请求返回公告列表的JSON数据
*/
@WebServlet("/manager/announcement")
public class Announcement extends HttpServlet {
/**
* 处理GET请求查询公告列表并返回JSON数据
* @param req HTTP请求对象
* @param resp HTTP响应对象
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应格式为JSON字符集UTF-8
resp.setContentType("application/json; charset=utf8");
// 数据库操作变量
Connection connection = null;
PreparedStatement pstmt = null;
String sql = "";
ResultSet resultSet = null;
// 响应数据
int code = 1; // 状态码1=失败0=成功
String msg = "无数据"; // 状态描述
JSONObject jsonObject = new JSONObject(); // 单条公告JSON对象
JSONArray jsonArray = new JSONArray(); // 公告列表JSON数组
try {
// 获取数据库连接
connection = Base.getConnection();
// 查询所有公告的SQL语句
sql = "select * from announcement";
pstmt = connection.prepareStatement(sql);
resultSet = pstmt.executeQuery();
// 遍历结果集封装为JSON格式
while (resultSet.next()) {
jsonObject.put("id", resultSet.getString("id")); // 公告ID
jsonObject.put("title", resultSet.getString("title")); // 公告标题
jsonObject.put("detail", resultSet.getString("detail")); // 公告详情
jsonObject.put("publish_date", resultSet.getString("publish_date")); // 发布日期
jsonArray.add(jsonObject); // 添加到公告列表
}
// 根据查询结果设置响应状态
if (!jsonArray.isEmpty()) {
code = 0;
msg = "查询成功";
} else {
msg = "数据为空";
}
} catch (ClassNotFoundException e) {
msg = "数据库驱动未找到";
} catch (SQLException e) {
msg = "SQL执行错误";
} finally {
// 释放数据库资源
try {
Base.closeResource(connection, pstmt, resultSet);
} catch (SQLException e) {
msg = "资源释放失败";
}
}
// 生成最终响应JSON
PrintWriter out = resp.getWriter();
out.print(Util.jsonResponse(code, msg, jsonArray.toString()));
}
}
// * * * java/servlet/announcementAdd.java
package servlet.manager;
import java.io.IOException;
import java.io.PrintWriter;
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 javabean.Base;
import javabean.DateTime;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* 公告添加Servlet处理公告发布请求
* 映射路径:/manager/announcementAdd
* 仅响应POST请求接收公告标题、内容并保存到数据库
*/
@WebServlet("/manager/announcementAdd")
public class AnnouncementAdd extends HttpServlet {
/**
* 处理POST请求接收公告信息并插入数据库
* @param req HTTP请求对象包含公告标题、内容参数
* @param resp HTTP响应对象返回操作结果JSON
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应格式为JSON字符集UTF-8
resp.setContentType("application/json; charset=utf8");
// 接收客户端提交的参数
String id = req.getParameter("id"); // 未使用的参数(可能为测试保留)
String tit = req.getParameter("title"); // 公告标题
String det = req.getParameter("detail"); // 公告内容
DateTime date = new DateTime(); // 获取当前时间
String time = date.show(); // 格式化时间字符串
// 数据库操作变量
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
int result = 0; // 数据库操作影响的行数
int count = 0; // 未使用的计数器(可能为测试保留)
// 响应数据
int code = 1; // 状态码1=失败0=成功
String msg = ""; // 状态描述
JSONArray jsonArray = new JSONArray(); // 未使用的JSON数组可能为测试保留
JSONObject json = new JSONObject(); // 响应结果JSON对象
// SQL语句插入公告信息注意id字段未包含由数据库自增
String sql = "insert into announcement(title, detail, publish_date) values(?,?,?)";
System.out.println(sql); // 控制台打印SQL语句生产环境建议移除
PrintWriter out = resp.getWriter(); // 获取响应输出流
try {
// 获取数据库连接
connection = Base.getConnection();
// 预编译SQL语句
pstmt = connection.prepareStatement(sql);
// 绑定参数:标题、内容、发布时间
pstmt.setString(1, tit);
pstmt.setString(2, det);
pstmt.setString(3, time);
// 执行插入操作
result = pstmt.executeUpdate();
} catch (SQLException e) {
// 捕获SQL异常未处理具体错误信息建议添加日志
} catch (ClassNotFoundException e) {
e.printStackTrace(); // 打印驱动未找到异常堆栈
} finally {
// 释放数据库资源结果集为null无需关闭
try {
Base.closeResource(connection, pstmt, null);
} catch (SQLException e) {
e.printStackTrace(); // 打印资源释放异常堆栈
}
}
// 根据操作结果生成响应JSON
if (result == 1) {
json.put("code", "0");
json.put("msg", "success");
} else {
json.put("code", "1");
json.put("msg", "error");
}
out.write(json.toString()); // 输出响应结果
}
}
// * * * java/servlet/announcementDel.java
package servlet.manager;
import java.io.IOException;
import java.io.PrintWriter;
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 javabean.Base;
import javabean.Util;
/**
* 公告删除Servlet处理公告删除请求
* 映射路径:/manager/announcementDel
* 仅响应GET请求根据公告ID执行删除操作
*/
@WebServlet("/manager/announcementDel")
public class AnnouncementDel extends HttpServlet {
/**
* 处理GET请求根据ID删除公告并返回JSON响应
* @param req HTTP请求对象包含公告ID参数id
* @param resp HTTP响应对象返回删除结果JSON
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数公告ID
String id = req.getParameter("id");
// 数据库操作变量
String sql = ""; // SQL语句
Connection connection = null; // 数据库连接
PreparedStatement pstmt = null; // 预编译语句
ResultSet resultSet = null; // 结果集(未使用)
int result = 0; // 数据库操作影响的行数
// 响应数据
int code = 1; // 状态码1=失败0=成功
String msg = ""; // 状态描述
PrintWriter out = resp.getWriter(); // 响应输出流
try {
// 获取数据库连接
connection = Base.getConnection();
// 预编译删除SQL使用占位符?防止SQL注入
sql = "delete from announcement where id=?";
pstmt = connection.prepareStatement(sql);
// 绑定参数公告ID
pstmt.setString(1, id);
// 执行删除操作
result = pstmt.executeUpdate();
// 根据影响的行数判断操作结果
if (result == 1) {
code = 0;
msg = "删除成功";
} else {
msg = "删除失败ID不存在或操作异常";
}
} catch (ClassNotFoundException e) {
msg = "数据库驱动未找到";
} catch (SQLException e) {
msg = "SQL执行错误" + e.getMessage(); // 建议记录详细错误日志
} finally {
// 释放数据库资源
try {
Base.closeResource(connection, pstmt, resultSet);
} catch (SQLException e) {
e.printStackTrace(); // 打印资源释放异常堆栈
}
}
// 生成JSON响应状态码、消息、空数据
out.print(Util.jsonResponse(code, msg, null));
}
}
// * * * java/servlet/announcementEdit.java
package servlet.manager;
import java.io.IOException;
import java.io.PrintWriter;
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 javabean.Base;
import javabean.Util;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* 公告编辑Servlet处理公告内容修改请求
* 映射路径:/manager/announcementEdit
* 仅响应POST请求接收公告ID、新标题和内容并更新数据库
*/
@WebServlet("/manager/announcementEdit")
public class AnnouncementEdit extends HttpServlet {
/**
* 处理POST请求执行公告内容修改并返回JSON响应
* @param req HTTP请求对象包含公告ID、新标题和内容参数
* @param resp HTTP响应对象返回操作结果JSON
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应格式为JSON字符集UTF-8
resp.setContentType("application/json; charset=utf8");
// 接收客户端提交的参数
String id = req.getParameter("id"); // 公告ID未校验非空
String tit = req.getParameter("title"); // 新公告标题
String det = req.getParameter("detail"); // 新公告内容
// 数据库操作变量
String sql = ""; // SQL语句
Connection connection = null; // 数据库连接
PreparedStatement pstmt = null; // 预编译语句
ResultSet resultSet = null; // 结果集(未使用)
int result = 0; // 数据库操作影响的行数
// 响应数据
int code = 1; // 状态码1=失败0=成功
String msg = ""; // 状态描述
PrintWriter out = resp.getWriter(); // 响应输出流
JSONArray jsonArray = new JSONArray(); // 未使用的JSON数组建议删除
JSONObject jsonObject = new JSONObject(); // 未使用的JSON对象建议删除
// 参数校验:标题和内容不能为空
if (tit == null || tit.equals("") || det == null || det.equals("")) {
msg = "参数不能为空";
out.print(Util.jsonResponse(code, msg, null));
return; // 终止后续处理
}
try {
// 获取数据库连接
connection = Base.getConnection();
// 预编译更新SQL使用占位符?防止SQL注入
sql = "update announcement set title=?, detail=? where id=?";
pstmt = connection.prepareStatement(sql);
// 绑定参数新标题、新内容、公告ID
pstmt.setString(1, tit);
pstmt.setString(2, det);
pstmt.setString(3, id);
// 执行更新操作
result = pstmt.executeUpdate();
// 根据影响的行数判断操作结果
if (result == 1) {
code = 0;
msg = "修改成功";
} else {
msg = "修改失败ID不存在或操作异常";
}
} catch (ClassNotFoundException e) {
msg = "数据库驱动未找到";
} catch (SQLException e) {
msg = "SQL执行错误" + e.getMessage(); // 建议记录详细错误日志
} finally {
// 释放数据库资源
try {
Base.closeResource(connection, pstmt, resultSet);
} catch (SQLException e) {
e.printStackTrace(); // 打印资源释放异常堆栈
}
}
// 生成JSON响应状态码、消息、空数据
out.print(Util.jsonResponse(code, msg, null));
}
}
// * * * java/servlet/BorrowTable.java
package servlet.manager;
import java.io.IOException;
import java.io.PrintWriter;
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 javabean.Base;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* 借阅记录管理Servlet处理分页查询和条件过滤请求
* 映射路径:/manager/borrowTable
* 仅响应GET请求返回符合条件的借阅记录列表JSON格式
*/
@WebServlet("/manager/borrowTable")
public class BorrowTable extends HttpServlet {
/**
* 处理GET请求执行分页查询并返回JSON数据
* @param req HTTP请求对象包含分页参数和过滤条件
* @param resp HTTP响应对象返回查询结果JSON
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应格式为JSON字符集UTF-8
resp.setContentType("application/json; charset=utf8");
// 接收客户端参数
String limit = req.getParameter("limit"); // 每页显示数量
String page = req.getParameter("page"); // 当前页码
String condition = req.getParameter("condition"); // 过滤字段如card_id
String conditionValue = req.getParameter("conditionValue"); // 过滤值
// 初始化查询条件
String where = ""; // 无限制条件
if (page == null) page = "1"; // 默认页码1
if (limit == null) limit = "10"; // 默认每页10条
// 数据库操作变量
Connection connection = null;
PreparedStatement pstmt = null; // 数据查询语句
PreparedStatement countPstmt = null; // 总数查询语句
ResultSet resultSet = null;
ResultSet countSet = null;
String sql = "";
String countSql = "";
// 响应数据
int code = 1; // 状态码1=失败0=成功
String msg = "无数据"; // 状态描述
int count = 0; // 总记录数
JSONObject jsonData = new JSONObject(); // 单条记录JSON对象
JSONArray jsonArray = new JSONArray(); // 记录列表JSON数组
JSONObject jsonResult = new JSONObject(); // 最终响应JSON
try {
// 获取数据库连接
connection = Base.getConnection();
// 构建基础查询SQL过滤manager_id不为null的记录
sql = "select * from borrow_books where manager_id is not null";
// 拼接条件查询注意直接拼接字符串存在SQL注入风险
if (condition != null && conditionValue != null
&& !condition.equals("") && !conditionValue.equals("")) {
where = " and " + condition + " like '%" + conditionValue + "%' ";
sql += where;
}
// 拼接分页参数(使用预编译占位符)
sql += " limit ?,?";
System.out.println("查询SQL" + sql); // 调试用,生产环境建议移除
// 执行数据查询
pstmt = connection.prepareStatement(sql);
// 计算分页偏移量:(当前页-1)*每页数量
pstmt.setInt(1, (Integer.parseInt(page) - 1) * Integer.parseInt(limit));
pstmt.setInt(2, Integer.parseInt(limit));
resultSet = pstmt.executeQuery();
// 封装查询结果为JSON
while (resultSet.next()) {
jsonData.put("id", resultSet.getString("id")); // 记录ID
jsonData.put("card_id", resultSet.getString("card_id")); // 读者卡号
jsonData.put("book_id", resultSet.getString("book_id")); // 图书ID
jsonData.put("borrow_date", resultSet.getString("borrow_date")); // 借阅日期
jsonData.put("end_date", resultSet.getString("end_date")); // 应还日期
jsonData.put("return_date", resultSet.getString("return_date")); // 归还日期
jsonData.put("illegal", resultSet.getString("illegal")); // 违规状态
jsonData.put("manager_id", resultSet.getString("manager_id")); // 管理员ID
jsonArray.add(jsonData); // 添加到记录列表
}
// 执行总记录数查询
countSql = "select count(*) as count from borrow_books where manager_id is not null" + where;
countPstmt = connection.prepareStatement(countSql);
countSet = countPstmt.executeQuery();
if (countSet.next()) {
count = countSet.getInt("count"); // 获取总记录数
}
// 设置响应状态
if (!jsonArray.isEmpty()) {
code = 0;
msg = "查询成功";
}
} catch (ClassNotFoundException e) {
msg = "数据库驱动未找到";
} catch (SQLException e) {
msg = "SQL执行错误" + e.getMessage();
} finally {
// 分批次释放资源
try {
Base.closeResource(null, pstmt, resultSet); // 关闭数据查询资源
Base.closeResource(connection, countPstmt, countSet); // 关闭总数查询资源
} catch (SQLException e) {
msg = "资源释放失败";
}
}
// 构建最终响应JSON
jsonResult.put("code", code);
jsonResult.put("count", count);
jsonResult.put("msg", msg);
jsonResult.put("data", jsonArray.toArray()); // 转换为JSON数组
// 输出响应
PrintWriter out = resp.getWriter();
out.print(jsonResult.toString());
}
}
// * * * java/servlet/ManagerLogin.java
package servlet.manager;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.HashMap;
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 javax.servlet.http.HttpSession;
import javabean.Manager;
import net.sf.json.JSONObject;
/**
* 管理员登录Servlet处理管理员登录请求
* 映射路径:/managerLogin
* 仅响应POST请求验证账号密码并返回登录结果
*/
@WebServlet("/managerLogin")
public class ManagerLogin extends HttpServlet {
/**
* 处理GET请求未使用返回简单提示
* @param request HTTP请求对象
* @param response HTTP响应对象
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* 处理POST请求执行管理员登录验证
* @param request HTTP请求对象包含user和psw参数
* @param response HTTP响应对象返回JSON格式的登录结果
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应格式为JSON字符集UTF-8
response.setContentType("application/json; charset=utf8");
PrintWriter out = response.getWriter();
// 获取客户端提交的账号和密码
String user = request.getParameter("user"); // 管理员账号
String psw = request.getParameter("psw"); // 管理员密码
// 响应数据容器
HashMap<String, Object> hashMap = new HashMap<>();
// 调用业务逻辑层验证登录
Manager manager = new Manager();
String result = null;
try {
result = manager.login(user, psw); // 调用Manager类的登录方法
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace(); // 打印数据库相关异常堆栈(生产环境建议日志记录)
}
// 根据验证结果生成响应
if (result.equals("1")) { // 登录成功
HttpSession session = request.getSession();
session.setAttribute("manager", user); // 记录登录用户
session.setAttribute("manager_first", "1"); // 标记首次登录状态
hashMap.put("code", 0);
hashMap.put("msg", "登录成功");
// 返回跳转URL前端根据此字段进行页面跳转
hashMap.put("url", request.getContextPath() + "/manager/01nav.jsp");
} else { // 登录失败
hashMap.put("code", 1);
hashMap.put("msg", result); // 错误信息直接来自业务层
}
// 将响应数据转换为JSON并输出
JSONObject json = JSONObject.fromObject(hashMap);
out.write(json.toString());
}
}
// * * * java/servlet/Quit.java
package servlet.manager;
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 javax.servlet.http.HttpSession;
/**
* 管理员退出Servlet处理管理员注销请求
* 映射路径:/manager/quit
* 仅响应GET请求销毁用户会话并重定向到登录页面
*/
@WebServlet("/manager/quit")
public class Quit extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* 处理GET请求执行管理员退出逻辑
* @param req HTTP请求对象
* @param resp HTTP响应对象
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取当前会话
HttpSession session = req.getSession();
// 检查会话中是否存在管理员登录标识
if (session.getAttribute("manager") != null) {
// 移除登录状态,终止会话
session.removeAttribute("manager");
}
// 重定向到管理员登录页面
resp.sendRedirect(req.getContextPath() + "/loginManager.html");
}
}
// * * * java/servlet/ReturnTable.java
package servlet.manager;
import java.io.IOException;
import java.io.PrintWriter;
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 javabean.Base;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* 待归还图书管理Servlet处理分页查询和条件过滤请求
* 映射路径:/manager/returnTable
* 仅响应GET请求返回未处理的借阅记录列表JSON格式
*/
@WebServlet("/manager/returnTable")
public class ReturnTable extends HttpServlet {
/**
* 处理GET请求执行分页查询并返回JSON数据
* @param req HTTP请求对象包含分页参数和过滤条件
* @param resp HTTP响应对象返回查询结果JSON
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应格式为JSON字符集UTF-8
resp.setContentType("application/json; charset=utf8");
// 接收客户端参数
String limit = req.getParameter("limit"); // 每页显示数量
String page = req.getParameter("page"); // 当前页码
String condition = req.getParameter("condition"); // 过滤字段如card_id
String conditionValue = req.getParameter("conditionValue"); // 过滤值
// 初始化查询条件
String where = ""; // 无限制条件
if (page == null) page = "1"; // 默认页码1
if (limit == null) limit = "10"; // 默认每页10条
// 数据库操作变量
Connection connection = null;
PreparedStatement pstmt = null; // 数据查询语句
PreparedStatement countPstmt = null; // 总数查询语句
ResultSet resultSet = null;
ResultSet countSet = null;
String sql = "";
String countSql = "";
// 响应数据
int code = 1; // 状态码1=失败0=成功
String msg = "无数据"; // 状态描述
int count = 0; // 总记录数
JSONObject jsonData = new JSONObject(); // 单条记录JSON对象
JSONArray jsonArray = new JSONArray(); // 记录列表JSON数组
JSONObject jsonResult = new JSONObject(); // 最终响应JSON
try {
// 获取数据库连接
connection = Base.getConnection();
// 构建基础查询SQL过滤manager_id为null的记录
sql = "select * from borrow_books where manager_id is null";
// 拼接条件查询注意直接拼接字符串存在SQL注入风险
if (condition != null && conditionValue != null
&& !condition.equals("") && !conditionValue.equals("")) {
where = " and " + condition + " like '%" + conditionValue + "%' ";
sql += where;
}
// 拼接分页参数(使用预编译占位符)
sql += " limit ?,?";
System.out.println("查询SQL" + sql); // 调试用,生产环境建议移除
// 执行数据查询
pstmt = connection.prepareStatement(sql);
// 计算分页偏移量:(当前页-1)*每页数量
pstmt.setInt(1, (Integer.parseInt(page) - 1) * Integer.parseInt(limit));
pstmt.setInt(2, Integer.parseInt(limit));
resultSet = pstmt.executeQuery();
// 封装查询结果为JSON
while (resultSet.next()) {
jsonData.put("id", resultSet.getString("id")); // 记录ID
jsonData.put("card_id", resultSet.getString("card_id")); // 读者卡号
jsonData.put("book_id", resultSet.getString("book_id")); // 图书ID
jsonData.put("borrow_date", resultSet.getString("borrow_date")); // 借阅日期
jsonData.put("end_date", resultSet.getString("end_date")); // 应还日期
jsonArray.add(jsonData); // 添加到记录列表
}
// 执行总记录数查询
countSql = "select count(*) as count from borrow_books where manager_id is null" + where;
countPstmt = connection.prepareStatement(countSql);
countSet = countPstmt.executeQuery();
if (countSet.next()) {
count = countSet.getInt("count"); // 获取总记录数
}
// 设置响应状态
if (!jsonArray.isEmpty()) {
code = 0;
msg = "查询成功";
}
} catch (ClassNotFoundException e) {
msg = "数据库驱动未找到";
} catch (SQLException e) {
msg = "SQL执行错误" + e.getMessage();
} finally {
// 分批次释放资源
try {
Base.closeResource(null, pstmt, resultSet); // 关闭数据查询资源
Base.closeResource(connection, countPstmt, countSet); // 关闭总数查询资源
} catch (SQLException e) {
msg = "资源释放失败";
}
}
// 构建最终响应JSON
jsonResult.put("code", code);
jsonResult.put("count", count);
jsonResult.put("msg", msg);
jsonResult.put("data", jsonArray.toArray()); // 转换为JSON数组
// 输出响应
PrintWriter out = resp.getWriter();
out.print(jsonResult.toString());
}
/**
* 处理POST请求未使用
* @param request HTTP请求对象
* @param response HTTP响应对象
* @throws ServletException Servlet处理异常
* @throws IOException IO异常
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 未实现POST逻辑
}
}
// * * * 前端页面 jsp
// * * * 01nav.jsp
<body class="layui-layout-body">
<!-- 整体布局容器 -->
<div class="layui-layout layui-layout-admin">
<!-- 头部导航区域 -->
<div class="layui-header">
<div class="layui-logo">图书馆管理人员页面</div>
<!-- 左侧导航菜单 -->
<ul class="layui-nav layui-layout-left">
<li class="layui-nav-item">
<a href="javascript:;">其它系统</a>
<dl class="layui-nav-child">
<!-- 跳转到读者系统首页 -->
<dd><a href="../reader/04readerFrame.jsp" target="parent">图书馆首页</a></dd>
<!-- 跳转到系统管理员登录页面 -->
<dd><a href="../adminLogin.html" target="parent">系统管理员</a></dd>
</dl>
</li>
</ul>
<!-- 右侧用户信息和退出 -->
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item">
<a href="javascript:;">
<!-- 显示当前登录管理员用户名 -->
<%=session.getAttribute("manager") %>
</a>
<dl class="layui-nav-child">
<!-- 跳转到管理员个人资料页面 -->
<dd><a href="09managerSelf.jsp" target="content">基本资料</a></dd>
</dl>
</li>
<!-- 退出系统 -->
<li class="layui-nav-item"><a href="./quit" target="_parent">退出</a></li>
</ul>
</div>
<!-- 左侧功能菜单 -->
<div class="layui-side layui-bg-black">
<div class="layui-side-scroll">
<ul class="layui-nav layui-nav-tree" lay-filter="test">
<!-- 图书管理模块 -->
<li class="layui-nav-item layui-nav-itemed">
<a href="javascript:;">
<i class="layui-icon layui-icon-read" style="font-size: 20px; color: lightblue;"></i>
&nbsp;图书管理
</a>
<dl class="layui-nav-child">
<!-- 借阅图书页面 -->
<dd><a href="02borrow.jsp" target="content">借阅图书</a></dd>
<!-- 归还图书页面 -->
<dd><a href="04judge.jsp;" target="content">归还图书</a></dd>
</dl>
</li>
<!-- 报表管理模块 -->
<li class="layui-nav-item">
<a href="javascript:;">
<i class="layui-icon layui-icon-form" style="font-size: 20px; color: orange;"></i>
&nbsp;报表管理
</a>
<dl class="layui-nav-child">
<!-- 借书报表页面 -->
<dd><a href="06borrowTable.jsp" target="content">借书报表</a></dd>
<!-- 还书报表页面 -->
<dd><a href="07returnTable.jsp" target="content">还书报表</a></dd>
</dl>
</li>
<!-- 公告发布模块 -->
<li class="layui-nav-item">
<a href="08announcement.jsp" target="content">
<i class="layui-icon layui-icon-release" style="font-size: 20px; color: yellow;"></i>
&nbsp;发布公告
</a>
</li>
</ul>
</div>
</div>
<!-- 主体内容区域通过iframe加载子页面 -->
<div class="layui-body">
<iframe src="02borrow.jsp" name="content" height="100%" width="100%" frameborder="0"></iframe>
</div>
<!-- 底部版权信息 -->
<div class="layui-footer">
© 图书管理系统
</div>
</div>
<!-- 初始化LayUI元素模块 -->
<script>
layui.use('element', function() {
var element = layui.element;
});
</script>
</body>
// * * 02borrow.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>借阅图书</title>
<!-- 引入LayUI CSS样式 -->
<link rel="stylesheet" href="../public/layui/css/layui.css" media="all">
<!-- 引入LayUI核心JS库 -->
<script src="../public/layui/layui.js"></script>
<!-- 自定义样式:调整表单标签左边距 -->
<style>
.layui-form-label {
margin-left: 20%;
}
</style>
</head>
<body>
<!-- 页面标题 -->
<div align="center" style="margin-top: 2%;">
<h1>借阅图书</h1>
</div>
<!-- 主表单容器 -->
<div align="center" style="margin-left: 30%; margin-top: 5%; width: 40%;">
<!-- LayUI表单 -->
<form class="layui-form layui-form-pane" action="03borrowSus.jsp">
<!-- 借阅证号输入 -->
<div class="layui-form-item">
<label class="layui-form-label">借阅证号</label>
<div class="layui-input-inline">
<input type="text" name="userid" lay-verify="required"
placeholder="请输入借阅证号" autocomplete="off" class="layui-input">
</div>
</div>
<!-- 图书编号输入 -->
<div class="layui-form-item">
<label class="layui-form-label">图书编号</label>
<div class="layui-input-inline">
<input type="text" name="bookid" lay-verify="required"
placeholder="请输入图书编号" autocomplete="off" class="layui-input">
</div>
</div>
<!-- 借阅日期选择 -->
<div class="layui-form-item">
<label class="layui-form-label">借阅日期</label>
<div class="layui-input-inline">
<input type="text" name="date1" id="date1" autocomplete="off" class="layui-input">
</div>
</div>
<!-- 提交按钮 -->
<div class="layui-form-item" align="center">
<button class="layui-btn" lay-submit lay-filter="demo2">借阅</button>
</div>
</form>
<!-- LayUI初始化脚本 -->
<script>
layui.use(['form', 'laydate'], function() {
var form = layui.form,
laydate = layui.laydate;
// 初始化日期选择器(借阅日期)
laydate.render({
elem: '#date1', // 绑定输入框ID
type: 'datetime', // 日期时间模式
format: 'yyyy-M-d H:m:s',// 日期格式
value: new Date() // 默认值为当前时间
});
// 监听表单提交
form.on('submit(demo2)', function(data) {
// 实际项目中应移除alert改为异步提交
layer.alert(JSON.stringify(data.field), { title: '提交数据' });
return false; // 阻止表单自动提交
});
});
</script>
</div>
</body>
// * * * 03borrowSus.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>借阅图书处理</title>
</head>
<body>
<!-- 使用JDBCBean处理数据库操作 -->
<jsp:useBean id="borrow" scope="session" class="javabean.JDBCBean"></jsp:useBean>
<%
// 获取表单提交参数
String user = request.getParameter("userid"); // 借阅证号
String book = request.getParameter("bookid"); // 图书编号
String date1 = request.getParameter("date1"); // 借阅日期
// 查询借阅证信息
String sql1 = "select * from borrow_card where ID =" + user;
ResultSet rs1 = borrow.executeQuery(sql1);
// 管理员登录验证
if (session.getAttribute("manager") != null) {
if (rs1.next()) {
// 获取借阅证状态和规则ID
String rule = rs1.getString("rule_id");
int cardstatus = Integer.parseInt(rs1.getString("STATUS"));
// 查询借阅规则
String sql4 = "select * from rules where id = " + rule;
ResultSet rs4 = borrow.executeQuery(sql4);
int n = 0; // 借阅天数
String library = ""; // 可借阅图书馆
String[] libraryArray = {};
int num = 0; // 最大借阅数量
while (rs4.next()) {
n = rs4.getInt("limit_day");
library = rs4.getString("borrow_library");
libraryArray = library.split("、");
num = rs4.getInt("borrow_num");
}
// 计算应还日期
EndTime endtime = new EndTime();
String end = endtime.show(n);
// 借阅证状态检查
if (cardstatus != 0) {
// 查询图书信息
String sql2 = "select * from books where ID =" + book;
ResultSet rs2 = borrow.executeQuery(sql2);
if (rs2.next()) {
int status = Integer.parseInt(rs2.getString("STATUS")); // 图书状态
String lib = Integer.toString(rs2.getInt("library_id")); // 图书所在图书馆
// 检查图书是否在可借阅图书馆列表
boolean validLibrary = false;
for (int z = 0; z < libraryArray.length; z++) {
if (libraryArray[z].equals(lib)) {
validLibrary = true;
// 查询当前用户未处理的借阅数量
String countSql = "select count(*) as count from borrow_books where manager_id is null and card_id =" + user;
ResultSet rsSql = borrow.executeQuery(countSql);
int count = 0;
while (rsSql.next()) {
count = rsSql.getInt("count");
}
// 检查借阅数量限制
if (count < num) {
if (status == 1) { // 图书可用
// 执行借阅操作
String sql = "insert borrow_books(CARD_ID,BOOK_ID,BORROW_DATE,END_DATE) values('" + user + "','" + book + "','" + date1 + "','" + end + "')";
try {
int i = borrow.executeUpdate(sql);
if (i == 1) {
// 更新图书状态为已借出
borrow.executeUpdate("update books set STATUS=0 where ID=" + book);
%>
<script>
alert('借阅成功!');
window.location.href = "02borrow.jsp";
</script>
<%
} else {
%>
<script>
alert('借阅未成功!');
window.location.href = "02borrow.jsp";
</script>
<%
}
} catch (Exception e) {
%>
<script>
alert('借阅未成功!');
window.location.href = "02borrow.jsp";
</script>
<%
}
} else {
%>
<script>
alert('该图书已借出!');
window.location.href = "02borrow.jsp";
</script>
<%
}
} else {
%>
<script>
alert('该用户已达到可借阅数量!若需还书,请先归还!');
window.location.href = "02borrow.jsp";
</script>
<%
}
break;
}
}
// 图书馆权限检查失败
if (!validLibrary) {
%>
<script>
alert('该图书未在可借阅的图书馆内!');
window.location.href = "02borrow.jsp";
</script>
<%
}
} else {
%>
<script>
alert('该图书不存在!');
window.location.href = "02borrow.jsp";
</script>
<%
}
} else {
%>
<script>
alert('借阅证已挂失!');
window.location.href = "02borrow.jsp";
</script>
<%
}
} else {
%>
<script>
alert('用户不存在!');
window.location.href = "02borrow.jsp";
</script>
<%
}
} else {
%>
<script>
alert('请先登录!');
window.parent.location.href = "../loginManager.html";
</script>
<%
}
%>
</body>
// * * * 04judge.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询图书是否逾期</title>
<!-- 引入LayUI CSS样式 -->
<link rel="stylesheet" href="../public/layui/css/layui.css" media="all">
<!-- 引入LayUI核心JS库 -->
<script src="../public/layui/layui.js"></script>
<!-- 自定义样式:调整表单标签左边距 -->
<style>
.layui-form-label {
margin-left: 20%;
}
</style>
</head>
<body>
<!-- 页面标题 -->
<div align="center" style="margin-top: 2%;">
<h1>查询图书是否逾期</h1>
</div>
<!-- 主表单容器 -->
<div align="center" style="margin-left: 30%; margin-top: 5%; width: 40%;">
<!-- LayUI表单 -->
<form class="layui-form layui-form-pane" action="04judgeSus.jsp">
<!-- 图书编号输入 -->
<div class="layui-form-item">
<label class="layui-form-label">图书编号</label>
<div class="layui-input-inline">
<input type="text" name="bookid" lay-verify="required"
placeholder="请输入图书编号" autocomplete="off" class="layui-input">
</div>
</div>
<!-- 查询按钮 -->
<div class="layui-form-item" align="center">
<button class="layui-btn layui-btn-warm" lay-submit lay-filter="demo2">查询</button>
</div>
</form>
<!-- LayUI初始化脚本 -->
<script>
layui.use(['form', 'laydate'], function() {
var form = layui.form,
laydate = layui.laydate;
// 初始化日期选择器(未绑定到表单字段,可能为残留代码)
laydate.render({
elem: '#date1', // 页面中不存在该ID的输入框
type: 'datetime', // 日期时间模式
format: 'yyyy-M-d H:m:s',// 日期格式
min: 0, // 最小时间(当前时间)
max: 0, // 最大时间(当前时间)
value: new Date() // 默认值为当前时间
});
// 监听表单提交
form.on('submit(demo2)', function(data) {
// 实际项目中应使用异步提交如AJAX
layer.alert(JSON.stringify(data.field), { title: '提交数据' });
return false; // 阻止表单自动提交
});
});
</script>
</div>
</body>
// * * * 04judgeSus.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>图书逾期查询处理</title>
</head>
<body>
<!-- 使用JDBCBean进行数据库操作-->
<jsp:useBean id="judge" scope="session" class="javabean.JDBCBean"></jsp:useBean>
<%
// 获取表单提交的图书编号
String book = request.getParameter("bookid");
session.setAttribute("book", book); // 将会话保存到session
// 管理员登录验证
if (session.getAttribute("manager") != null) {
DateTime date = new DateTime();
String now = date.show(); // 获取当前时间
String bookid = request.getParameter("bookid");
// 查询该图书的借阅记录
String sql = "select * from borrow_books where book_id = " + bookid;
ResultSet rs = judge.executeQuery(sql);
String end = ""; // 应还日期
String ret = ""; // 归还日期
String card = ""; // 借阅证号
while (rs.next()) {
end = rs.getString("end_date");
ret = rs.getString("return_date");
card = rs.getString("card_id");
}
if (ret == null) { // 图书未归还
// 计算逾期天数now与end的时间差
long n = CompareDate.show(now, end);
session.setAttribute("days", n); // 保存逾期天数
// 查询借阅证规则
String sql1 = "select * from borrow_card where id = " + card;
ResultSet rs1 = judge.executeQuery(sql1);
String rule = "";
while (rs1.next()) {
rule = rs1.getString("rule_id");
}
// 查询逾期费用规则
String sql2 = "select * from rules where id = " + rule;
ResultSet rs2 = judge.executeQuery(sql2);
String fee = "";
while (rs2.next()) {
fee = rs2.getString("overtime_fee");
}
session.setAttribute("fee", fee); // 保存逾期费用
// 跳转到图书归还页面
%>
<script>
window.location.href = "04return.jsp";
</script>
<%
} else { // 图书已归还
%>
<script>
alert("该书未借出或不存在!");
window.location.href = "04judge.jsp";
</script>
<%
}
} else { // 未登录处理
%>
<script>
alert('请先登录!');
window.parent.location.href = "../loginManager.html";
</script>
<%
}
%>
</body>
// * * * 04return.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>归还图书</title>
<!-- 引入LayUI框架 -->
<link rel="stylesheet" href="../public/layui/css/layui.css" media="all">
<script src="../public/layui/layui.js"></script>
<!-- 自定义样式:调整表单标签左边距 -->
<style>
.layui-form-label {
margin-left: 20%;
}
</style>
</head>
<body>
<!-- 使用JDBCBean进行数据库操作 -->
<jsp:useBean id="judge" scope="session" class="javabean.JDBCBean"></jsp:useBean>
<!-- 页面标题 -->
<div align="center" style="margin-top: 2%;">
<h1>归还图书</h1>
</div>
<!-- 主表单容器 -->
<div align="center" style="margin-left: 30%; margin-top: 5%; width: 40%;">
<%
// 从会话中获取逾期天数、罚款金额和图书编号
Object days = session.getAttribute("days");
Object fee = session.getAttribute("fee");
String book = session.getAttribute("book").toString();
// 初始化提示信息
String mes = "";
String mes2 = "";
float sum = 0;
// 根据逾期天数计算罚款
if (days != null && fee != null) {
int d = Integer.parseInt(days.toString());
float f = Float.parseFloat(fee.toString());
if (d < 0) {
mes = "已逾期 " + (-d) + " 天";
sum = d * f * (-1); // 计算罚款总额
mes2 = "罚款金额:¥" + sum;
} else {
mes = "还剩 " + d + " 天";
}
// 将提示信息保存到会话中
session.setAttribute("mes", mes);
session.setAttribute("mes2", mes2);
}
%>
<!-- 表单 -->
<form class="layui-form layui-form-pane" action="05returnSus.jsp">
<!-- 逾期信息展示 -->
<div>
<blockquote class="layui-elem-quote layui-quote-nm">
<%= session.getAttribute("mes") %>
<br>
<%= session.getAttribute("mes2") %>
</blockquote>
</div>
<!-- 图书编号输入 -->
<div class="layui-form-item">
<label class="layui-form-label">图书编号</label>
<div class="layui-input-inline">
<input type="text" name="bookid" lay-verify="required"
value="<%= session.getAttribute("book") %>"
autocomplete="off" class="layui-input">
</div>
</div>
<!-- 截止日期显示 -->
<%
// 查询该图书的借阅记录(未归还)
String sql2 = "select * from borrow_books where return_date is null and book_id = " + book;
ResultSet rs2 = judge.executeQuery(sql2);
String endDate = "";
while (rs2.next()) {
endDate = rs2.getString("end_date");
%>
<div class="layui-form-item">
<label class="layui-form-label">截止日期</label>
<div class="layui-input-inline">
<input type="text" name="end" autocomplete="off"
class="layui-input" value="<%= endDate %>">
</div>
</div>
<% } %>
<!-- 归还日期选择 -->
<div class="layui-form-item">
<label class="layui-form-label">归还日期</label>
<div class="layui-input-inline">
<input type="text" name="date1" id="date1" autocomplete="off"
class="layui-input">
</div>
</div>
<!-- 违规信息输入 -->
<div class="layui-form-item">
<label class="layui-form-label">违规信息</label>
<div class="layui-input-inline">
<input type="text" name="ill"
placeholder="若无违规信息,则不填"
autocomplete="off" class="layui-input">
</div>
</div>
<!-- 管理员编号(自动填充,只读) -->
<div class="layui-form-item">
<label class="layui-form-label">管理员编号</label>
<div class="layui-input-inline">
<input type="text" name="managerid" readonly="readonly"
class="layui-input" value="<%= session.getAttribute("manager") %>">
</div>
</div>
<!-- 提交按钮 -->
<div class="layui-form-item" align="center">
<button class="layui-btn layui-btn-warm" lay-submit lay-filter="demo2">
归还
</button>
</div>
</form>
<!-- LayUI初始化脚本 -->
<script>
layui.use(['form', 'laydate'], function() {
var form = layui.form,
laydate = layui.laydate;
// 初始化日期选择器(仅当前时间可选)
laydate.render({
elem: '#date1',
type: 'datetime',
format: 'yyyy-MM-dd H:m:s',
min: 0,
max: 0,
value: new Date()
});
// 监听表单提交
form.on('submit(demo2)', function(data) {
// 实际项目中应使用异步提交如AJAX
layer.alert(JSON.stringify(data.field), { title: '提交数据' });
return false; // 阻止表单自动提交
});
});
</script>
</div>
</body>
// * * * 05returnSus.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>图书归还处理</title>
</head>
<body>
<!-- 使用JDBCBean处理数据库操作 -->
<jsp:useBean id="ret" scope="session" class="javabean.JDBCBean"></jsp:useBean>
<%
// 获取表单提交参数
String book = request.getParameter("bookid"); // 图书编号
String date1 = request.getParameter("date1"); // 归还日期
String ill = request.getParameter("ill"); // 违规信息(可选)
String managerid = request.getParameter("managerid"); // 管理员编号
// 管理员登录验证
if (session.getAttribute("manager") != null) {
try {
// 查询图书当前状态
String sql2 = "select * from books where ID = " + book;
ResultSet rs2 = ret.executeQuery(sql2);
if (rs2.next()) {
int status = Integer.parseInt(rs2.getString("STATUS"));
// 图书状态检查0表示已借出1表示可借阅
if (status == 0) {
// 更新借阅记录:设置归还日期、违规信息和处理管理员
String sql = "update borrow_books " +
"set RETURN_DATE = ?, ILLEGAL = ?, MANAGER_ID = ? " +
"where manager_id is null and BOOK_ID = ?";
// 执行更新操作
int i = ret.executeUpdate(sql, new Object[]{date1, ill, managerid, book});
// 更新图书状态为可借阅
ret.executeUpdate("update books set STATUS = 1 where ID = ?", new Object[]{book});
%>
<script>
alert('归还成功!');
window.location.href = "04judge.jsp";
</script>
<%
} else {
%>
<script>
alert('该图书未借出!');
window.location.href = "04judge.jsp";
</script>
<%
}
}
} catch (SQLException e) {
e.printStackTrace();
%>
<script>
alert('归还未成功!');
window.location.href = "04judge.jsp";
</script>
<%
}
} else {
%>
<script>
alert('请先登录!');
window.parent.location.href = "../loginManager.html";
</script>
<%
}
%>
</body>
//* * * 06borrwoTable.jsp
<head>
<meta charset="UTF-8">
<title>借阅记录</title>
<!-- 引入LayUI CSS样式 -->
<link rel="stylesheet" href="../public/layui/css/layui.css" media="all">
<!-- 自定义样式:调整表格边距 -->
<style>
.layui-table, .layui-table-view {
margin: 0 0px;
}
</style>
</head>
<body>
<!-- 引入LayUI核心JS库 -->
<script src="../public/layui/layui.js" charset="utf-8"></script>
<!-- 表格容器(初始隐藏) -->
<table class="layui-hide" id="cardTable" lay-filter="formFilter"></table>
<!-- 头部工具栏模板 -->
<script type="text/html" id="headBar">
条件搜索
<div class="layui-inline">
<!-- 搜索条件下拉菜单 -->
<select id="condition" name="condition" lay-verify="required">
<option value=""></option>
<option value="card_id">借阅证号</option>
<option value="book_id">图书编号</option>
<option value ="borrow_date">借阅日期</option>
<option value="end_date">截止日期</option>
<option value="return_date">归还日期</option>
<option value="illegal">违章信息</option>
<option value="manager_id">处理人</option>
</select>
</div>
<div class="layui-inline">
<!-- 搜索值输入框 -->
<input class="layui-input" id="conditionValue" name="conditionValue" autocomplete="off">
</div>
<!-- 搜索按钮 -->
<button class="layui-btn" name="condition" data-type="reload" lay-event="search">搜索</button>
</script>
<script>
layui.use(['table', 'jquery'], function() {
var $ = layui.jquery;
var table = layui.table;
// 初始化表格渲染
var tableIns = table.render({
elem: '#cardTable', // 绑定表格容器ID
url: './borrowTable', // 数据接口Servlet路径
toolbar: '#headBar', // 绑定头部工具栏模板
cols: [[ // 表格列配置
{field: 'card_id', width: 180, title: '借阅证号', sort: true},
{field: 'book_id', width: 130, title: '图书编号', sort: true},
{field: 'borrow_date', width: 250, title: '借阅日期', sort: true},
{field: 'end_date', title: '截止日期', width: 250, sort: true},
{field: 'return_date', width: 250, title: '归还时间', sort: true},
{field: 'illegal', width: 180, title: '违章信息', sort: true, style: 'color: red;'},
{field: 'manager_id', minWidth: 80, title: '处理人'}
]],
page: true // 启用分页
});
// 头部工具栏事件处理
table.on('toolbar(formFilter)', function(obj) {
var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) {
case 'search':
// 获取搜索条件和值
var conditionValue = $('#conditionValue');
var condition = $('#condition');
// 重新加载表格数据
tableIns.reload({
where: {
"condition": condition.val(), // 过滤字段
"conditionValue": conditionValue.val() // 过滤值
},
page: {
curr: 1 // 重置为第一页
}
});
break;
case 'add':
// 打开添加借阅证弹窗(未实现)
var addCardLayer = layer.open({
type: 2,
title: '添加借书证',
area: ['800px', '500px'],
maxmin: true,
shadeClose: true,
content: 'cardadd.jsp'
});
break;
}
});
// 侧边工具栏事件处理(未实现)
table.on('tool(formFilter)', function(obj) {
var data = obj.data;
var layEvent = obj.event;
var tr = obj.tr;
switch (obj.event) {
case 'edit':
// 打开编辑弹窗(未实现)
layer.open({
type: 2,
title: '更改信息',
area: ['800px', '600px'],
maxmin: true,
shadeClose: true,
content: ''
});
break;
}
});
});
</script>
</body>
//* * * 07returnTable.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>待归还图书列表</title>
<!-- 引入LayUI框架样式 -->
<link rel="stylesheet" href="../public/layui/css/layui.css" media="all">
<!-- 引入LayUI核心JS库 -->
<script src="../public/layui/layui.js" charset="utf-8"></script>
<!-- 自定义样式:调整表格边距 -->
<style>
.layui-table, .layui-table-view {
margin: 0 0px;
}
</style>
</head>
<body>
<!-- 表格容器初始隐藏通过LayUI动态渲染 -->
<table class="layui-hide" id="cardTable" lay-filter="formFilter"></table>
<!-- 头部工具栏模板 -->
<script type="text/html" id="headBar">
条件搜索
<div class="layui-inline">
<!-- 搜索条件下拉菜单 -->
<select id="condition" name="condition" lay-verify="required">
<option value=""></option>
<option value="card_id">借阅证号</option>
<option value="book_id">图书编号</option>
<option value="borrow_date">借阅日期</option>
<option value="end_date">截止日期</option>
</select>
</div>
<div class="layui-inline">
<!-- 搜索值输入框 -->
<input class="layui-input" id="conditionValue" name="conditionValue" autocomplete="off">
</div>
<!-- 搜索按钮 -->
<button class="layui-btn" name="condition" data-type="reload" lay-event="search">搜索</button>
</script>
<script>
layui.use(['table', 'jquery'], function() {
var $ = layui.jquery;
var table = layui.table;
// 初始化表格渲染
var tableIns = table.render({
elem: '#cardTable', // 绑定表格容器ID
url: './returnTable', // 数据接口Servlet路径
toolbar: '#headBar', // 绑定头部工具栏模板
cols: [[ // 表格列配置
{field: 'card_id', width: 180, title: '借阅证号', sort: true},
{field: 'book_id', width: 130, title: '图书编号', sort: true},
{field: 'borrow_date', width: 250, title: '借阅日期', sort: true},
{field: 'end_date', title: '截止日期', width: 250, sort: true}
]],
page: true // 启用分页
});
// 头部工具栏事件处理
table.on('toolbar(formFilter)', function(obj) {
var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) {
case 'search':
// 获取搜索条件和值
var conditionValue = $('#conditionValue');
var condition = $('#condition');
// 重新加载表格数据
tableIns.reload({
where: {
"condition": condition.val(), // 过滤字段
"conditionValue": conditionValue.val() // 过滤值
},
page: {
curr: 1 // 重置为第一页
}
});
break;
case 'add':
// 打开添加借阅证弹窗(未实现)
var addCardLayer = layer.open({
type: 2,
title: '添加借书证',
area: ['800px', '500px'],
maxmin: true,
shadeClose: true,
content: 'cardadd.jsp'
});
break;
}
});
// 侧边工具栏事件处理(未实现)
table.on('tool(formFilter)', function(obj) {
var data = obj.data;
var layEvent = obj.event;
var tr = obj.tr;
switch (obj.event) {
case 'edit':
// 打开编辑弹窗(未实现)
layer.open({
type: 2,
title: '更改信息',
area: ['800px', '600px'],
maxmin: true,
shadeClose: true,
content: ''
});
break;
}
});
});
</script>
</body>
//* * * 08add.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>发布公告</title>
<!-- 引入LayUI CSS样式 -->
<link rel="stylesheet" href="../public/layui/css/layui.css">
<!-- 引入LayUI核心JS库 -->
<script src="../public/layui/layui.js"></script>
</head>
<body>
<!-- 公告发布表单 -->
<form class="layui-form layui-form-pane" action="" lay-filter="formFilter">
<!-- 标题输入 -->
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title"
lay-verify="required" <!-- 启用LayUI必填验证 -->
required <!-- 浏览器原生必填验证 -->
autocomplete="off"
placeholder="请输入标题"
class="layui-input">
</div>
</div>
<!-- 公告内容输入 -->
<div class="layui-form-item" style="height:50%;">
<label class="layui-form-label">公告</label>
<div class="layui-input-block">
<textarea name="detail"
lay-verify="required"
placeholder="请输入公告"
autocomplete="off"
class="layui-input"
style="height:300px;"></textarea>
</div>
</div>
<!-- 提交按钮 -->
<div class="layui-form-item">
<div class="layui-input-block">
<button type="submit"
class="layui-btn"
lay-submit=""
lay-filter="submitButton">
<i class="layui-icon layui-icon-release"
style="font-size: 20px; color: yellow;"></i>
&nbsp;发布
</button>
</div>
</div>
</form>
<script>
layui.use(['form', 'jquery'], function() {
var $ = layui.jquery;
var form = layui.form;
var layer = layui.layer;
// 监听表单提交
form.on('submit(submitButton)', function(data) {
// 使用AJAX异步提交表单数据
$.ajax({
url: './announcementAdd', // 后端Servlet路径
method: 'post', // 请求方法
data: data.field, // 表单数据对象
dataType: 'json', // 期望返回JSON格式
success: function(response) {
if (response.code === "0") {
// 提交成功提示
parent.layer.msg("添加成功", {
icon: 6, // 成功图标
time: 500 // 提示持续时间(毫秒)
});
// 500ms后刷新父页面
setTimeout(function() {
parent.location.reload();
}, 500);
} else {
// 失败提示
layer.msg(response.msg);
}
}
});
return false; // 阻止表单默认提交行为
});
});
</script>
</body>
//* * *08edit.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../public/layui/css/layui.css">
<script src="../public/layui/layui.js"></script>
<title>公告编辑</title>
</head>
<body>
<!-- 使用JDBCBean进行数据库操作 -->
<jsp:useBean id="check" scope="session" class="javabean.JDBCBean"></jsp:useBean>
<%
// 获取URL参数中的公告ID
String id = request.getParameter("id");
// 数据库操作
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try {
connection = Base.getConnection();
// 使用预编译语句查询公告信息
String sql = "select * from announcement where id=?";
pstmt = connection.prepareStatement(sql);
pstmt.setString(1, id);
resultSet = pstmt.executeQuery();
// 移动到结果集第一条记录
if (resultSet.next()) {
// 页面后续会使用这些数据
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源此处未正确关闭建议在finally中处理
}
%>
<!-- 公告编辑表单 -->
<form class="layui-form layui-form-pane" action="" lay-filter="formFilter">
<!-- 隐藏字段公告ID -->
<input type="text" name="id" value="<%=id %>"
lay-verify="required" required
autocomplete="off"
class="layui-input layui-hide">
<!-- 标题输入 -->
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title"
value="<%=resultSet.getString("title") %>"
lay-verify="required" required
autocomplete="off"
placeholder="请输入标题"
class="layui-input">
</div>
</div>
<!-- 公告内容输入 -->
<div class="layui-form-item">
<label class="layui-form-label">公告</label>
<div class="layui-input-block">
<input type="text" name="detail"
value="<%=resultSet.getString("detail") %>"
lay-verify="required"
placeholder="请输入公告"
autocomplete="off"
class="layui-input">
</div>
</div>
<!-- 提交按钮 -->
<div class="layui-form-item">
<div class="layui-input-block">
<button type="submit" class="layui-btn"
lay-submit lay-filter="submitButton">
立即提交
</button>
</div>
</div>
</form>
<script>
layui.use(['form', 'jquery'], function() {
var $ = layui.jquery;
var form = layui.form;
var layer = layui.layer;
// 监听表单提交
form.on('submit(submitButton)', function(data) {
// 使用AJAX异步提交表单数据
$.ajax({
url: './announcementEdit', // 后端Servlet路径
method: 'post', // 请求方法
data: data.field, // 表单数据对象
dataType: 'json', // 期望返回JSON格式
success: function(response) {
if (response.code === "0") {
// 提交成功提示
parent.layer.msg("修改成功", {
icon: 6, // 成功图标
time: 500 // 提示持续时间(毫秒)
});
// 500ms后刷新父页面
setTimeout(function() {
parent.location.reload();
}, 500);
} else {
// 失败提示
layer.msg(response.msg);
}
},
error: function(xhr, status, error) {
// 网络错误处理
layer.msg('网络请求失败,请检查网络连接');
}
});
return false; // 阻止表单默认提交行为
});
});
</script>
</body>
//* * *09managerSelf.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>管理员个人资料</title>
<!-- 引入LayUI框架 -->
<link rel="stylesheet" href="../public/layui/css/layui.css" media="all">
<script src="../public/layui/layui.js"></script>
<!-- 引入Bootstrap框架 -->
<link href="../css/bootstrap.min.css" rel="stylesheet">
<script src="../js/jquery.min.js"></script>
<script src="../js/bootstrap.min.js"></script>
<!-- 引入自定义样式和动画库 -->
<link rel="stylesheet" type="text/css" href="../public/css/default.css" />
<link rel="stylesheet" type="text/css" href="../public/css/component.css" />
<script src="../public/js/modernizr.custom.js"></script>
<!-- 自定义样式 -->
<style>
body {
background-color: white !important;
color: black !important;
}
.md-content {
color: black;
background: white;
position: relative;
border-radius: 3px;
margin: 0 auto;
}
button {
background-color: #009688;
}
button:hover {
background-color: #5FB878;
}
.md-modal {
width: 35%;
}
</style>
</head>
<body>
<!-- 使用JDBCBean进行数据库操作 -->
<jsp:useBean id="gly" scope="session" class="javabean.JDBCBean"></jsp:useBean>
<!-- 管理员基本信息展示 -->
<fieldset class="layui-elem-field" style="width:30%; margin-left:30%; margin-top:5%; height:30%;">
<legend>管理员基本信息</legend>
<div class="layui-field-box" align="center" style="font-size:20px; font-family:YouYuan; margin-top:10%; margin-bottom:10%;">
<%
// 获取当前登录管理员账号
String manacc = session.getAttribute("manager").toString();
// 查询管理员信息存在SQL注入风险
String sql = "select * from manager where ACCOUNT = '" + manacc + "';";
ResultSet rs = gly.executeQuery(sql);
while (rs.next()) {
%>
<!-- 展示基本信息 -->
<p>姓名:<%= rs.getString("name") %></p><br>
<p>账号:<%= rs.getString("account") %></p><br>
<p>邮箱:<%= rs.getString("email") %></p><br>
<!-- 模态框触发按钮 -->
<button class="md-trigger layui-btn layui-btn-radius" data-modal="modal-3">修改名字</button>
<button class="md-trigger layui-btn layui-btn-radius" data-modal="modal-13">修改密码</button>
<button class="md-trigger layui-btn layui-btn-radius" data-modal="modal-1">修改邮箱</button>
<% } %>
</div>
</fieldset>
<!-- 修改密码模态框 -->
<div class="md-modal md-effect-13" id="modal-13">
<div class="md-content">
<h3>修改密码</h3>
<form action="10updateManager.jsp" method="post" class="form-horizontal">
<div class="form-group" align="center" style="margin-left:3%;">
<br>
<label for="psw1" class="col-sm-2 control-label">新密码</label>
<div class="col-sm-10" align="center">
<input type="password" class="form-control" name="psw1" id="password1"
placeholder="请输入新密码" style="width:50%; margin-left:8%;">
</div>
</div>
<br>
<div class="form-group" align="center" style="margin-left:3%;">
<label for="psw2" class="col-sm-2 control-label">确认密码</label>
<div class="col-sm-10">
<input type="password" class="form-control" name="psw2" id="password2"
placeholder="请再次输入密码进行确认" style="width:50%; margin-left:8%;">
</div>
</div>
<div align="center">
<input type="submit" class="layui-btn layui-btn-radius" value="确认">
</div>
<br>
</form>
<button class="md-close layui-btn-radius" style="font-size:14px;">取消</button>
</div>
</div>
<!-- 修改邮箱模态框 -->
<div class="md-modal md-effect-13" id="modal-1">
<div class="md-content">
<h3>修改邮箱</h3>
<form action="10updateManager.jsp" method="post" class="form-horizontal">
<div class="form-group" align="center" style="margin-left:3%;">
<br>
<label for="email1" class="col-sm-2 control-label">新邮箱</label>
<div class="col-sm-10" align="center">
<input type="text" class="form-control" name="email1" id="password1"
placeholder="请输入新邮箱" style="width:50%; margin-left:8%;">
</div>
</div>
<br>
<div class="form-group" align="center" style="margin-left:3%;">
<label for="email2" class="col-sm-2 control-label">确认邮箱</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="email2" id="password2"
placeholder="请再次输入邮箱进行确认" style="width:50%; margin-left:8%;">
</div>
</div>
<div align="center">
<input type="submit" class="layui-btn layui-btn-radius" value="确认">
</div>
<br>
</form>
<button class="md-close layui-btn-radius" style="font-size:14px;">取消</button>
</div>
</div>
<!-- 修改姓名模态框 -->
<div class="md-modal md-effect-13" id="modal-3">
<div class="md-content">
<h3>修改名字</h3>
<form action="10updateManager.jsp" method="post" class="form-horizontal">
<div class="form-group" align="center" style="margin-left:3%;">
<br>
<label for="name1" class="col-sm-2 control-label">新名字</label>
<div class="col-sm-10" align="center">
<input type="text" class="form-control" name="name1" id="password1"
placeholder="请输入新名字" style="width:50%; margin-left:8%;">
</div>
</div>
<br>
<div class="form-group" align="center" style="margin-left:3%;">
<label for="name2" class="col-sm-2 control-label">确认名字</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name2" id="password2"
placeholder="请再次输入名字进行确认" style="width:50%; margin-left:8%;">
</div>
</div>
<div align="center">
<input type="submit" class="layui-btn layui-btn-radius" value="确认">
</div>
<br>
</form>
<button class="md-close layui-btn-radius" style="font-size:14px;">取消</button>
</div>
</div>
<!-- 模态框遮罩层 -->
<div class="md-overlay"></div>
<!-- 模态框动画脚本 -->
<script src="../public/js/classie.js"></script>
<script src="../public/js/modalEffects.js"></script>
<!-- CSS滤镜兼容脚本 -->
<script>
var polyfilter_scriptpath = '/js/';
</script>
<script src="../public/js/cssParser.js"></script>
<script src="../public/js/css-filters-polyfill.js"></script>
</body>
//* * *updateManager.jsp
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>管理员资料修改处理</title>
</head>
<body>
<!-- 使用JDBCBean进行数据库操作 -->
<jsp:useBean id="check" scope="session" class="javabean.JDBCBean"></jsp:useBean>
<%
// 获取表单提交的参数
String psw1 = request.getParameter("psw1"); // 新密码
String psw2 = request.getParameter("psw2"); // 确认密码
String email1 = request.getParameter("email1"); // 新邮箱
String email2 = request.getParameter("email2"); // 确认邮箱
String name1 = request.getParameter("name1"); // 新姓名
String name2 = request.getParameter("name2"); // 确认姓名
// 获取当前登录管理员账号
String id = session.getAttribute("manager").toString();
// 密码修改逻辑
if (psw1 != null && psw2 != null) {
// 验证密码一致性和非空
if (psw1.equals(psw2) && !psw1.trim().isEmpty() && !psw2.trim().isEmpty()) {
// 存在SQL注入风险建议使用预编译语句
String sql = "update manager set PASSWORD = ? where ACCOUNT = ?";
try (Connection conn = check.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, psw1);
pstmt.setString(2, id);
int affectedRows = pstmt.executeUpdate();
if (affectedRows == 1) {
%>
<script>
alert('密码修改成功!');
window.location.href = "09managerSelf.jsp";
</script>
<%
} else {
%>
<script>
alert('密码修改失败!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
} catch (SQLException e) {
e.printStackTrace();
%>
<script>
alert('数据库操作失败!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
} else {
%>
<script>
alert('密码不一致或为空!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
}
// 邮箱修改逻辑
else if (email1 != null && email2 != null) {
// 验证邮箱一致性和非空
if (email1.equals(email2) && !email1.trim().isEmpty() && !email2.trim().isEmpty()) {
// 建议添加邮箱格式验证(正则表达式)
String sql = "update manager set EMAIL = ? where ACCOUNT = ?";
try (Connection conn = check.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, email1);
pstmt.setString(2, id);
int affectedRows = pstmt.executeUpdate();
if (affectedRows == 1) {
%>
<script>
alert('邮箱修改成功!');
window.location.href = "09managerSelf.jsp";
</script>
<%
} else {
%>
<script>
alert('邮箱修改失败!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
} catch (SQLException e) {
e.printStackTrace();
%>
<script>
alert('数据库操作失败!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
} else {
%>
<script>
alert('邮箱不一致或为空!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
}
// 姓名修改逻辑
else if (name1 != null && name2 != null) {
// 验证姓名一致性和非空
if (name1.equals(name2) && !name1.trim().isEmpty() && !name2.trim().isEmpty()) {
String sql = "update manager set NAME = ? where ACCOUNT = ?";
try (Connection conn = check.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, name1);
pstmt.setString(2, id);
int affectedRows = pstmt.executeUpdate();
if (affectedRows == 1) {
%>
<script>
alert('姓名修改成功!');
window.location.href = "09managerSelf.jsp";
</script>
<%
} else {
%>
<script>
alert('姓名修改失败!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
} catch (SQLException e) {
e.printStackTrace();
%>
<script>
alert('数据库操作失败!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
} else {
%>
<script>
alert('姓名不一致或为空!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
} else {
%>
<script>
alert('请选择要修改的内容!');
window.location.href = "09managerSelf.jsp";
</script>
<%
}
%>
</body>
// * * * loginManager.html
<head>
<meta charset="UTF-8">
<title>图书管理员登录页面</title>
<!-- 视口设置:适配移动端 -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- 引入jQuery库 -->
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<!-- Bootstrap框架样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
<!-- Bootstrap核心脚本 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<!-- 可选的Bootstrap主题 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css">
<!-- 自定义样式 -->
<link rel="stylesheet" href="./public/css/animate.css">
<link rel="stylesheet" href="./public/css/login.css">
</head>
<body>
<!-- 主容器 -->
<div class="container main">
<!-- 登录框容器,带淡入动画 -->
<div id="login" class="contain animated fadeInDown">
<h1>工作人员登录</h1>
<!-- 登录表单 -->
<form method="post">
<!-- 用户名输入框 -->
<input type="text" name="user" class="form-control my_input"
placeholder="请输入账号" required="required">
<!-- 密码输入框 -->
<input type="password" name="psw" class="form-control my_input"
placeholder="请输入密码" required="required">
<!-- 提交按钮,阻止默认表单提交 -->
<input type="submit" class="form-control" value="登录" onclick="javascript:void(0);">
</form>
</div>
</div>
<!-- 底部快捷链接 -->
<div style="position:fixed; bottom:0; right:0;">
<!-- 读者系统入口 -->
<a href="reader/04readerFrame.jsp" target="_blank">
<img src="public/image/reader.png" width="50px" height="50px">
</a>
<br>
<!-- 系统管理员入口 -->
<a href="adminLogin.html" target="_blank">
<img src="public/image/admin.png" width="50px" height="50px">
</a>
</div>
<!-- 弹出层插件 -->
<script src="./public/js/layer/layer.js"></script>
<script>
$(function() {
// 登录按钮点击事件
$("input[type=submit]").click(function() {
// 使用AJAX提交表单
$.ajax({
url: "./managerLogin", // 后端Servlet路径
type: "post", // 请求方法
data: $("form").serialize(), // 序列化表单数据
dataType: "json", // 期望返回JSON格式
success: function(data) {
if (data.code === 0) {
// 登录成功提示
layer.msg("登录成功", {
icon: 6, // 成功图标
time: 1000 // 提示持续时间(毫秒)
}, function() {
// 跳转至目标页面
location.href = data.url;
});
} else {
// 登录失败提示
layer.open({
title: "登录失败",
content: data.msg,
icon: 5, // 错误图标
anim: 6 // 动画效果
});
}
}
});
return false; // 阻止表单默认提交行为
});
});
</script>
</body>
// * * * src/main/webapp/index.jsp
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
// 使用response.sendRedirect方法将页面重定向到指定的URL
// 这里将页面重定向到名为04readerFrame.jsp的页面该页面位于reader目录下
response.sendRedirect("./reader/04readerFrame.jsp");
%>
</body>