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

122 KiB

/* 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 时间差计算为毫秒差除以一天的毫秒数246060*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

<!-- 头部导航区域 -->
<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>

// * * 02borrow.jsp

<head> </head>

借阅图书

<!-- 主表单容器 -->
<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>

// * * * 03borrowSus.jsp

<head> </head> <% // 获取表单提交参数 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>
        <%
    }
%>
// * * * 04judge.jsp <head> </head>

查询图书是否逾期

<!-- 主表单容器 -->
<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>

// * * * 04judgeSus.jsp

<head> </head> <% // 获取表单提交的图书编号 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>
        <%
    }
%>
// * * * 04return.jsp <head> </head>
<!-- 页面标题 -->
<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>
// * * * 05returnSus.jsp <head> </head>
<%
    // 获取表单提交参数
    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>
        <%
    }
%>
//* * * 06borrwoTable.jsp <head> </head>
<!-- 表格容器(初始隐藏) -->
<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>
//* * * 07returnTable.jsp <head> </head>
<!-- 头部工具栏模板 -->
<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>
//* * * 08add.jsp <head> </head>
required autocomplete="off" placeholder="请输入标题" class="layui-input">
    <!-- 公告内容输入 -->
    <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>
//* * *08edit.jsp <head> </head>
<%
    // 获取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>
//* * *09managerSelf.jsp <head>
<!-- 引入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>
<!-- 管理员基本信息展示 -->
<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>
//* * *updateManager.jsp <head> </head>
<%
    // 获取表单提交的参数
    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>
        <%
    }
%>
// * * * loginManager.html <head>
<!-- 引入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>

工作人员登录

<!-- 底部快捷链接 -->
<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>
// * * * src/main/webapp/index.jsp <head> </head> <% // 使用response.sendRedirect方法将页面重定向到指定的URL // 这里将页面重定向到名为04readerFrame.jsp的页面该页面位于reader目录下 response.sendRedirect("./reader/04readerFrame.jsp"); %>