在上一篇博客中,我们深入探讨了 MyBatis 的核心应用技巧,包括日志配置、缓存优化以及映射机制等关键知识点。
本篇将进一步结合 JSP 前端技术与 MySQL数据库,
通过完整的示例代码演示如何实现数据的增删查找操作,并将结果实时展示在 Web 页面上。






然后创建以下JSP框架

Servlet-MyBatis-001/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── niit/ │ │ │ ├── mapper/ # MyBatis映射接口 │ │ │ ├── pojo/ # 实体类 │ │ │ ├── service/ # 业务逻辑层 │ │ │ ├── servlet/ # Web Servlet │ │ │ └── util/ # 工具类 │ │ └── resources/ │ │ ├── com/ │ │ │ └── niit/ │ │ │ └── mapper/ # SQL映射XML文件 │ │ └── mybatis-config.xml # MyBatis核心配置 │ └── test/ │ └── java/ ├── pom.xml # Maven依赖配置 └── target/ # 编译输出目录
<!-- JSP API依赖 - 提供JSP页面开发支持 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> <!-- 由Servlet容器提供,无需打包进应用 --> </dependency> <!-- Servlet API依赖 - 提供Servlet开发支持 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> <!-- 由Servlet容器提供,无需打包进应用 --> </dependency> <!-- JSTL表达式语言依赖 - 简化JSP页面开发 --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency> <!-- JSTL标准标签库实现 - 提供核心标签和格式化标签 --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- JSTL 1.2实现 - 替代taglibs:standard的另一种选择 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- MySQL数据库驱动 - 用于连接MySQL 8.x数据库 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!-- MyBatis持久层框架 - 简化数据库操作 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.19</version> </dependency> <!-- SLF4J日志API - 提供统一的日志接口 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.7</version> </dependency> <!-- Jackson JSON处理库 - 用于JSON与Java对象的互相转换 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> <!-- Lombok代码简化工具 - 通过注解减少样板代码 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.38</version> <scope>provided</scope> <!-- 编译时使用,无需打包进应用 --> </dependency> <!-- JUnit测试框架 - 用于编写单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> <!-- 仅在测试时使用 --> </dependency>



点击创建工件和应用
然后创建一个与class同级的目录lib


点击加号,导入全部库文件
在recourse下的mybatis-config.xml文件里加入以下代码
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="autoMappingBehavior" value="FULL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> </settings> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/2023se3"/> <property name="username" value="root"/> <property name="password" value=" "/> </dataSource> </environment> </environments> <mappers> <mapper resource="com.niit/mapper/UserMapper.xml"/> <mapper resource="com.niit/mapper/MachineMapper.xml"/> </mappers> </configuration>
其中
<dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/2023se3"/> <property name="username" value="root"/> <property name="password" value=" "/> </dataSource>
这里需要与我们的数据库 信息 链接
创建Machine类,定义机器实体的数据结构,作为系统数据交互的基础载体
package com.niit.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @AllArgsConstructor @NoArgsConstructor @Data public class Machine { private int id; private String domain; private String ip; private String sphinxPath; private String remark; private String createTime; }
接口类名MachineMapper
映射文件:MachineMapper.xml
package com.niit.mapper; import com.niit.pojo.Machine; import java.util.List; import java.util.Map; public interface MachineMapper { List<Machine> findMachines(); int addMachine(Machine machine); Machine findMachineById(int id); int updateMachine(Machine machine); int deleteMachine(int id); //搜索方法。使用Map接收参数 List<Machine> searchMachines(Map<String, Object> params); }
MachineServlet,处理 HTTP 请求,协调服务层与视图层的数据交互
package com.niit.service; import com.niit.mapper.MachineMapper; import com.niit.pojo.Machine; import com.niit.util.MybatisUtil; import org.apache.ibatis.session.SqlSession; import java.util.HashMap; import java.util.List; import java.util.Map; public class MachineService { public List<Machine> findMachines() { try (SqlSession sqlSession = MybatisUtil.getSqlSession()) { MachineMapper mapper = sqlSession.getMapper(MachineMapper.class); return mapper.findMachines(); } } public Machine findMachineById(int id) { try (SqlSession sqlSession = MybatisUtil.getSqlSession()) { MachineMapper mapper = sqlSession.getMapper(MachineMapper.class); return mapper.findMachineById(id); } } public int addMachine(Machine machine) { try (SqlSession sqlSession = MybatisUtil.getSqlSession()) { MachineMapper mapper = sqlSession.getMapper(MachineMapper.class); int result = mapper.addMachine(machine); sqlSession.commit(); return result; } catch (Exception e) { System.err.println("添加机器失败: " + e.getMessage()); throw e; // 抛出异常,让调用者处理 } } public int updateMachine(Machine machine) { try (SqlSession sqlSession = MybatisUtil.getSqlSession()) { MachineMapper mapper = sqlSession.getMapper(MachineMapper.class); int result = mapper.updateMachine(machine); sqlSession.commit(); return result; } catch (Exception e) { System.err.println("更新机器失败: " + e.getMessage()); throw e; // 抛出异常,让调用者处理 } } public int deleteMachine(int id) { System.out.println("开始删除机器,ID: " + id); try (SqlSession sqlSession = MybatisUtil.getSqlSession()) { MachineMapper mapper = sqlSession.getMapper(MachineMapper.class); int result = mapper.deleteMachine(id); System.out.println("删除结果: " + result); sqlSession.commit(); return result; } catch (Exception e) { System.err.println("删除机器失败: " + e.getMessage()); e.printStackTrace(); // 打印完整堆栈信息 throw e; } } // 添加搜索方法 public List<Machine> searchMachines(String keyword) { try (SqlSession sqlSession = MybatisUtil.getSqlSession()) { MachineMapper mapper = sqlSession.getMapper(MachineMapper.class); Map<String, Object> params = new HashMap<>(); params.put("keyword", "%" + keyword + "%"); return mapper.searchMachines(params); } } }
MachineService 类
封装机器管理的业务逻辑,处理数据库事务和异常
package com.niit.servlet; import com.niit.pojo.Machine; import com.niit.service.MachineService; 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 java.io.IOException; import java.util.List; @WebServlet("/machine") public class MachineServlet extends HttpServlet { private MachineService machineService = new MachineService(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String action = req.getParameter("action"); String keyword = req.getParameter("keyword"); if ("add".equals(action)) { // 跳转到添加页面 req.getRequestDispatcher("machine.jsp").forward(req, resp); } else if ("edit".equals(action)) { String idStr = req.getParameter("id"); if (idStr != null) { int id = Integer.parseInt(idStr); Machine machine = machineService.findMachineById(id); if (machine != null) { req.setAttribute("machine", machine); System.out.println("已设置编辑机器: " + machine.getDomain()); // 添加调试输出 } else { req.setAttribute("error", "未找到该机器信息"); } } else { req.setAttribute("error", "缺少机器ID参数"); } req.getRequestDispatcher("machine.jsp").forward(req, resp); } else if ("delete".equals(action)) { String idStr = req.getParameter("id"); if (idStr != null) { int id = Integer.parseInt(idStr); try { int result = machineService.deleteMachine(id); if (result > 0) { // 成功时直接返回JSON格式的成功标识(而非重定向) resp.setContentType("application/json;charset=UTF-8"); resp.getWriter().write("{\"success\":true,\"message\":\"删除成功\"}"); return; } else { resp.setContentType("application/json;charset=UTF-8"); resp.getWriter().write("{\"success\":false,\"message\":\"删除失败:记录不存在\"}"); return; } } catch (Exception e) { System.err.println("删除异常:" + e.getMessage()); resp.setContentType("application/json;charset=UTF-8"); resp.getWriter().write("{\"success\":false,\"message\":\"删除失败:" + e.getMessage() + "\"}"); return; } } // ID为空的情况 resp.setContentType("application/json;charset=UTF-8"); resp.getWriter().write("{\"success\":false,\"message\":\"删除失败:缺少ID参数\"}"); }else { List<Machine> machines; if (keyword != null && !keyword.trim().isEmpty()) { // 执行搜索 machines = machineService.searchMachines(keyword.trim()); req.setAttribute("searchKeyword", keyword.trim()); } else { // 查询所有机器 machines = machineService.findMachines(); } req.setAttribute("machines", machines); req.getRequestDispatcher("machine.jsp").forward(req, resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); String action = req.getParameter("action"); if ("add".equals(action)) { // 处理添加机器请求 String domain = req.getParameter("domain"); String ip = req.getParameter("ip"); String sphinxPath = req.getParameter("sphinxPath"); String remark = req.getParameter("remark"); // 数据验证 if (domain == null || domain.trim().isEmpty() || ip == null || ip.trim().isEmpty()) { req.setAttribute("error", "域名和IP为必填项"); // 添加失败,返回添加页面 req.getRequestDispatcher("machine.jsp").forward(req, resp); return; } // 设置创建时间 java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String createTime = dateFormat.format(new java.util.Date()); Machine machine = new Machine(); machine.setDomain(domain); machine.setIp(ip); machine.setSphinxPath(sphinxPath); machine.setRemark(remark); machine.setCreateTime(createTime); int result = machineService.addMachine(machine); if (result > 0) { resp.sendRedirect(req.getContextPath() + "/machine"); } else { req.setAttribute("error", "添加机器失败"); req.getRequestDispatcher("machine.jsp").forward(req, resp); } } else if ("edit".equals(action)) { // 处理编辑机器请求 String idStr = req.getParameter("id"); if (idStr == null) { resp.sendRedirect(req.getContextPath() + "/machine"); return; } int id = Integer.parseInt(idStr); String domain = req.getParameter("domain"); String ip = req.getParameter("ip"); String sphinxPath = req.getParameter("sphinxPath"); String remark = req.getParameter("remark"); // 数据验证 if (domain == null || domain.trim().isEmpty() || ip == null || ip.trim().isEmpty()) { req.setAttribute("error", "域名和IP为必填项"); // 编辑失败,返回当前页面并显示错误 Machine machine = new Machine(); machine.setId(id); machine.setDomain(domain); machine.setIp(ip); machine.setSphinxPath(sphinxPath); machine.setRemark(remark); req.setAttribute("machine", machine); req.getRequestDispatcher("machine.jsp").forward(req, resp); return; } Machine machine = new Machine(); machine.setId(id); machine.setDomain(domain); machine.setIp(ip); machine.setSphinxPath(sphinxPath); machine.setRemark(remark); int result = machineService.updateMachine(machine); if (result > 0) { resp.sendRedirect(req.getContextPath() + "/machine"); } else { req.setAttribute("error", "更新机器失败"); req.setAttribute("machine", machine); req.getRequestDispatcher("machine.jsp").forward(req, resp); } } } }
MybatisUtil,封装 MyBatis 初始化和 SqlSession 管理,提供统一的数据库连接入口
package com.niit.util; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MybatisUtil { private static SqlSessionFactory factory = null; static { try { // 1、定义 mybatis 主配置文件的位置,从类路径开始的相对路径 String configXml = "mybatis-config.xml"; // 2、读取主配置文件,使用 mybatis 框架中的 Resources 类 InputStream inputStream = Resources.getResourceAsStream(configXml); // 3、创建 SqlSessionFactory 对象, 使用 SqlSessionFactoryBuilder 类 factory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { SqlSession sqlSession = null; if (null != factory) { // 不自动提交事务(autoCommit: false) sqlSession = factory.openSession(); } return sqlSession; } }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.niit.mapper.MachineMapper"> <select id="findMachines" resultType="com.niit.pojo.Machine"> SELECT id, domain, ip, sphinx_path as sphinxPath, remark, create_time as createTime FROM machine_info; </select> <select id="findMachineById" resultType="com.niit.pojo.Machine" parameterType="int"> SELECT id, domain, ip, sphinx_path as sphinxPath, remark, create_time as createTime FROM machine_info WHERE id = #{id}; </select> <insert id="addMachine" parameterType="com.niit.pojo.Machine"> INSERT INTO machine_info (domain, ip, sphinx_path, remark, create_time) VALUES (#{domain}, #{ip}, #{sphinxPath}, #{remark}, #{createTime}) </insert> <update id="updateMachine" parameterType="com.niit.pojo.Machine"> UPDATE machine_info SET domain = #{domain}, ip = #{ip}, sphinx_path = #{sphinxPath}, remark = #{remark} WHERE id = #{id} </update> <delete id="deleteMachine" parameterType="int"> DELETE FROM machine_info WHERE id = #{id} </delete> <!-- 搜索机器的SQL,支持按域名、IP搜索 --> <select id="searchMachines" resultType="com.niit.pojo.Machine" parameterType="map"> SELECT id, domain, ip, sphinx_path as sphinxPath, remark, create_time as createTime FROM machine_info <where> <if test="keyword != null and keyword != ''"> (domain LIKE CONCAT('%', #{keyword}, '%') OR ip LIKE CONCAT('%', #{keyword}, '%')) </if> </where> ORDER BY id DESC </select> </mapper>
<mapper resource="com.niit/mapper/MachineMapper.xml"/>
我们的HTML例子文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1 , user-scalable=no"> <title>pha-Admin</title> <link rel="stylesheet" href="css/bootstrap.min.css"/> <link rel="stylesheet" href="css/bootstrap-maizi.css"/> <link rel="stylesheet" href="css/content-style.css"/> <link rel="stylesheet" href="css/mricode.pagination.css"/> <link rel="stylesheet" href="css/jquery.fancybox.css"/> <link rel="stylesheet" href="css/sweetalert.css"/> </head> <body> <!--导航--> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <!--小屏幕导航按钮和logo--> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="index.html" class="navbar-brand"> pha-Admin</a> </div> <!--小屏幕导航按钮和logo--> <!--导航--> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="index.html"><span class="glyphicon glyphicon-home"></span> 后台首页</a></li> <li><a href="user.html"><span class="glyphicon glyphicon-user"></span> 用户管理</a></li> <li class="active"><a href="machine.html"><span class="glyphicon glyphicon-expand"></span> 机器管理</a></li> <li><a href="service.html"><span class="glyphicon glyphicon-tasks"></span> 服务管理</a></li> <li><a href="log.html"><span class="glyphicon glyphicon-list-alt"></span> 日志管理</a></li> <li><a href="wiki.html"><span class="glyphicon glyphicon-book"></span> 使用文档</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li class="dropdown"> <a id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> admin <span class="caret"></span> </a> <ul class="dropdown-menu" aria-labelledby="dLabel"> <li><a href="index.html"><span class="glyphicon glyphicon-cog"></span> 个人设置</a></li> </ul> </li> <li><a href="#bbs"><span class="glyphicon glyphicon-off"></span> 退出</a></li> </ul> </div> <!--导航--> </div> </nav> <!--导航--> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="panel-body" style="padding: 15px 0;"> <ul class="nav nav-tabs"> <li class="active"><a href="#list" aria-controls="machine" role="tab" data-toggle="tab">机器列表</a></li> <li><a href="#form" aria-controls="machine" role="tab" data-toggle="tab">添加机器</a></li> </ul> </div> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="list"> <div class="panel-body"> <div class="row"> <form> <div class="col-md-3 col-lg-offset-9"> <div class="input-group"> <input class="form-control" type="text" value="" placeholder="用户名" name="keyword"> <span class="input-group-btn"> <button type="submit" class="btn btn-primary"><i class="glyphicon glyphicon-search"></i></button> </span> </div> </div> </form> </div> </div> <div class="panel panel-default"> <div class="table-responsive"> <table class="table table-bordered"> <thead> <tr> <th class="w8p">id</th> <th class="w18p">域名</th> <th class="w18p">ip</th> <th class="w13p">sphinx路径</th> <th class="w10p">备注</th> <th class="w15p">创建时间</th> <th class="w15p">操作</th> </tr> </thead> <tbody> <tr> <td class="center">1</td> <td>sphinx.test.com.cn</td> <td>192.168.128.12</td> <td>/usr/local/sphinx</td> <td class="center">主机</td> <td class="center">2017-03-28 12:21:09</td> <td class="center"><a name="remove" onclick="Common.confirm('确认要删除吗?')"><i class="glyphicon glyphicon-remove"></i>删除</a></td> </tr> <tr> <td class="center">2</td> <td>sphinx.test.com.cn</td> <td>192.168.128.13</td> <td>/usr/local/sphinx</td> <td class="center">备机</td> <td class="center">2017-03-28 12:21:09</td> <td class="center"><a name="remove" onclick="Common.confirm('确认要屏蔽吗?')"><i class="glyphicon glyphicon-remove"></i>删除</a></td> </tr> <tr> <td class="center">3</td> <td>sphinx.video.com.cn</td> <td>192.168.158.13</td> <td>/usr/local/sphinx</td> <td class="center">主机</td> <td class="center">2017-03-28 12:21:09</td> <td class="center"><a name="remove" onclick="Common.confirm('确认要屏蔽吗?')"><i class="glyphicon glyphicon-remove"></i>删除</a></td> </tr> <tr> <td class="center">4</td> <td>sphinx.test.com.cn</td> <td>192.168.158.14</td> <td>/usr/local/sphinx</td> <td class="center">备机</td> <td class="center">2017-03-28 12:21:09</td> <td class="center"><a name="remove" onclick="Common.confirm('确认要屏蔽吗?')"><i class="glyphicon glyphicon-remove"></i>删除</a></td> </tr> </tbody> </table> </div> <div class="panel-footer"> <div class="row"> <div class="col-md-8 m-pagination" id="paginator"> </div> </div> </div> </div> </div> <div role="tabpanel" class="tab-pane" id="form"> <div class="panel-body"> <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger"></span>域名</label> <div class="col-sm-4"> <input type="text" name="username" class="form-control" placeholder="机器域名" required> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger"> * </span>IP</label> <div class="col-sm-4"> <input type="email" name="email" class="form-control" placeholder="机器ip" required> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger"> * </span>Sphinx<br>安装目录</label> <div class="col-sm-4"> <input type="text" name="sphinx_path" class="form-control" placeholder="sphinx安装目录"> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger"></span>备注信息</label> <div class="col-sm-4"> <input type="text" class="form-control" placeholder="备注" required> </div> </div> <div class="form-group"> <div class="col-sm-offset-1 col-sm-10"> <button type="submit" onclick="" class="btn btn-success">保存</button> </div> </div> </form> <hr> </div> </div> </div> </div> </div> </div> <!--footer--> <footer> <div class="container"> <div class="row"> <div class="col-md-12"> <p class="text-muted center"> Copyright © 2017-2018 phachon@163.com </p> </div> </div> </div> </footer> <!--footer--> <script src="js/plugins/jquery/jquery.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/plugins/pagination/mricode.pagination.js"></script> <script src="js/plugins/fancybox/jquery.fancybox.js"></script> <script src="js/plugins/sweetalert/sweetalert.min.js"></script> <script src="js/common/common.js"></script> <script src="js/module/account.js"></script> <script type="text/javascript"> var pageData = []; pageData.push({'pageSize': '10', 'total': '1000', 'pageIndex': '2'}); Common.paginator("#paginator", pageData); Account.bindFancyBox(); </script> </body> </html>
修改之后的样子
<%@ page import="com.niit.service.MachineService" %> <%@ page import="java.util.List" %> <%@ page import="com.niit.pojo.Machine" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1 , user-scalable=no"> <title>机器管理 - pha-Admin</title> <link rel="stylesheet" href="css/bootstrap.min.css"/> <link rel="stylesheet" href="css/bootstrap-maizi.css"/> <link rel="stylesheet" href="css/content-style.css"/> <link rel="stylesheet" href="css/mricode.pagination.css"/> <link rel="stylesheet" href="css/jquery.fancybox.css"/> <link rel="stylesheet" href="css/sweetalert.css"/> </head> <body> <!--导航--> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="index.jsp" class="navbar-brand"> pha-Admin</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="index.jsp"><span class="glyphicon glyphicon-home"></span> 后台首页</a></li> <li><a href="/user"><span class="glyphicon glyphicon-user"></span> 用户管理</a></li> <li class="active"><a href="machine.jsp"><span class="glyphicon glyphicon-expand"></span> 机器管理</a></li> <li><a href="service.jsp"><span class="glyphicon glyphicon-tasks"></span> 服务管理</a></li> <li><a href="log.jsp"><span class="glyphicon glyphicon-list-alt"></span> 日志管理</a></li> <li><a href="wiki.jsp"><span class="glyphicon glyphicon-book"></span> 使用文档</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li class="dropdown"> <a id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <% String displayName = (String) session.getAttribute("displayName"); out.print(displayName != null ? displayName : "admin"); %> <span class="caret"></span> </a> <ul class="dropdown-menu" aria-labelledby="dLabel"> <li><a href="index.jsp"><span class="glyphicon glyphicon-cog"></span> 个人设置</a></li> </ul> </li> <li><a href="#bbs"><span class="glyphicon glyphicon-off"></span> 退出</a></li> </ul> </div> </div> </nav><!--导航--> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="panel-body" style="padding: 15px 0;"> <ul class="nav nav-tabs"> <li class="active"><a href="#list" aria-controls="machine" role="tab" data-toggle="tab">机器列表</a></li> <li><a href="#form" aria-controls="machine" role="tab" data-toggle="tab">添加机器</a></li> </ul> </div> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="list"> <div class="panel-body"> <div class="row"> <form action="machine" method="get"> <div class="col-md-3 col-lg-offset-9"> <div class="input-group"> <input class="form-control" type="text" value="${searchKeyword != null ? searchKeyword : ''}" placeholder="输入域名或IP搜索" name="keyword"> <span class="input-group-btn"> <button type="submit" class="btn btn-primary"><i class="glyphicon glyphicon-search"></i> 搜索</button> </span> </div> </div> </form> </div> <!-- 搜索结果提示 --> <c:if test="${searchKeyword != null and not empty searchKeyword}"> <div class="alert alert-info"> 搜索结果: " ${searchKeyword} " <c:if test="${empty machines}"> <span class="text-danger"> - 未找到匹配的机器</span> </c:if> </div> </c:if> </div> <div class="panel panel-default"> <div class="table-responsive"> <table class="table table-bordered" id="machineTable"> <thead> <tr> <th class="w8p">ID</th> <th class="w18p">域名</th> <th class="w18p">IP</th> <th class="w13p">Sphinx路径</th> <th class="w10p">备注</th> <th class="w15p">创建时间</th> <th class="w15p">操作</th> </tr> </thead> <tbody> <c:choose> <c:when test="${not empty machines}"> <c:forEach items="${machines}" var="machine"> <tr> <td class="center">${machine.id}</td> <td>${machine.domain}</td> <td>${machine.ip}</td> <td>${machine.sphinxPath}</td> <td class="center">${machine.remark}</td> <td class="center">${machine.createTime}</td> <td class="center"> <a href="javascript:;" onclick="deleteMachine(${machine.id})"><i class="glyphicon glyphicon-remove"></i>删除</a> </td> </tr> </c:forEach> </c:when> <c:otherwise> <tr> <td colspan="7" class="text-center">没有找到机器数据</td> </tr> </c:otherwise> </c:choose> </tbody> </table> </div> <div class="panel-footer"> <div class="row"> <div class="col-md-8 m-pagination" id="paginator"> </div> </div> </div> </div> </div> <div role="tabpanel" class="tab-pane" id="form"> <div class="panel-body"> <c:if test="${not empty error}"> <div class="alert alert-danger" role="alert"> ${error} </div> </c:if> <form class="form-horizontal" action="machine" method="post"> <input type="hidden" name="action" value="add"> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger">*</span>域名</label> <div class="col-sm-4"> <input type="text" name="domain" class="form-control" placeholder="机器域名" required> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger">*</span>IP</label> <div class="col-sm-4"> <input type="text" name="ip" class="form-control" placeholder="机器IP" required> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger"></span>Sphinx<br>安装目录</label> <div class="col-sm-4"> <input type="text" name="sphinxPath" class="form-control" placeholder="Sphinx安装目录"> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label"><span class="text-danger"></span>备注信息</label> <div class="col-sm-4"> <input type="text" name="remark" class="form-control" placeholder="备注信息"> </div> </div> <div class="form-group"> <div class="col-sm-offset-1 col-sm-10"> <button type="submit" class="btn btn-success">保存</button> <a href="machine" class="btn btn-default">取消</a> </div> </div> </form> <hr> </div> </div> </div> </div> </div> </div> <footer> <div class="container"> <div class="row"> <div class="col-md-12"> <p class="text-muted center"> Copyright © 2017-2025 phachon@163.com </p> </div> </div> </div> </footer> <!--footer--> <script src="js/plugins/jquery/jquery.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/plugins/pagination/mricode.pagination.js"></script> <script src="js/plugins/fancybox/jquery.fancybox.js"></script> <script src="js/plugins/sweetalert/sweetalert.min.js"></script> <script src="js/common/common.js"></script> <!-- 替换旧版JS --> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script type="text/javascript"> // 初始化分页 var pageData = []; pageData.push({'pageSize': '10', 'total': '100', 'pageIndex': '1'}); Common.paginator("#paginator", pageData); function deleteMachine(id) { Swal.fire({ // 注意Swal.fire替换旧版swal title: "确认删除?", text: "此操作将永久删除该机器信息,无法恢复!", icon: "warning", showCancelButton: true, confirmButtonText: "删除", cancelButtonText: "取消", dangerMode: true }).then((result) => { if (result.isConfirmed) { $.ajax({ url: "machine?action=delete&id=" + id, type: "GET", success: function(response) { if (response.includes("删除成功")) { Swal.fire("已删除!", "该机器信息已被成功删除。", "success") .then(() => location.reload()); } else { Swal.fire("删除失败", response, "error"); } }, error: function(xhr, status, error) { Swal.fire("删除错误", "服务器错误:" + error, "error"); } }); } }); } </script> </body> </html>
搜索表单动态化
表单添加action="machine" method="get",支持后端接收搜索参数。
输入框默认值使用EL表达式获取前端传递的搜索关键词:
<input class="form-control" type="text" value="${searchKeyword != null ? searchKeyword : ''}" placeholder="输入域名或IP搜索" name="keyword">
添加搜索结果提示信息,使用JSTL条件判断:
<c:if test="${searchKeyword != null and not empty searchKeyword}"> <div class="alert alert-info"> 搜索结果: " ${searchKeyword} " <c:if test="${empty machines}"> <span class="text-danger"> - 未找到匹配的机器</span> </c:if> </div> </c:if>
表格数据动态渲染
移除原始静态数据行,使用JSTL循环渲染后端传递的machines列表:
<c:forEach items="${machines}" var="machine"> <tr> <td class="center">${machine.id}</td> <td>${machine.domain}</td> <td>${machine.ip}</td> <td>${machine.sphinxPath}</td> <td class="center">${machine.remark}</td> <td class="center">${machine.createTime}</td> <td class="center"> <a href="javascript:;" onclick="deleteMachine(${machine.id})"><i class="glyphicon glyphicon-remove"></i>删除</a> </td> </tr> </c:forEach>
无数据时显示提示信息:
<c:otherwise> <tr> <td colspan="7" class="text-center">没有找到机器数据</td> </tr> </c:otherwise>
表单提交逻辑修改
表单action="machine" method="post",添加隐藏字段action="add"标识添加操作。
新增错误提示区域,使用JSTL显示后端错误信息:
<c:if test="${not empty error}"> <div class="alert alert-danger" role="alert"> ${error} </div> </c:if>




