1. 项目概述这个基于ThymeleafMavenServletMySQL的图书管理系统框架是我在实际开发中总结的一套完整解决方案。它采用了Java Web开发中最经典的架构组合特别适合中小型图书管理系统的快速开发。我在多个实际项目中验证过这套框架的稳定性和扩展性今天就来详细拆解它的技术实现。2. 技术栈选型解析2.1 为什么选择ThymeleafThymeleaf作为现代Java模板引擎相比JSP有显著优势自然模板特性直接在浏览器打开就能预览无需启动服务器强大的表达式语言支持复杂的页面逻辑处理与Spring生态完美集成虽然我们这里用Servlet但Thymeleaf依然表现出色实际开发中我常用这些Thymeleaf特性!-- 数据绑定示例 -- div th:text${book.title}/div !-- 循环处理 -- tr th:eachbook : ${books} td th:text${book.id}/td /tr !-- 条件判断 -- span th:if${book.stock} 0 th:text库存${book.stock}/span2.2 Maven的依赖管理Maven的pom.xml配置是项目基石。关键配置要点dependencies !-- Servlet API -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency !-- Thymeleaf核心 -- dependency groupIdorg.thymeleaf/groupId artifactIdthymeleaf/artifactId version3.0.12.RELEASE/version /dependency !-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.25/version /dependency /dependencies注意MySQL 8.x版本驱动类名已改为com.mysql.cj.jdbc.Driver与5.x的com.mysql.jdbc.Driver不同2.3 Servlet的核心作用在这个框架中Servlet承担着控制器(Controller)的角色。我通常采用一个前端控制器模式WebServlet(/*) public class DispatcherServlet extends HttpServlet { private TemplateEngine templateEngine; Override public void init() { // 初始化Thymeleaf模板引擎 ServletContextTemplateResolver resolver new ServletContextTemplateResolver(getServletContext()); resolver.setPrefix(/WEB-INF/templates/); resolver.setSuffix(.html); templateEngine new TemplateEngine(); templateEngine.setTemplateResolver(resolver); } protected void doGet(HttpServletRequest request, HttpServletResponse response) { String path request.getRequestURI().substring(request.getContextPath().length()); switch(path) { case /books: showBookList(request, response); break; // 其他路由处理... } } }3. 数据库设计与实现3.1 MySQL表结构设计图书系统的核心表结构设计CREATE TABLE books ( id int(11) NOT NULL AUTO_INCREMENT, isbn varchar(20) NOT NULL, title varchar(100) NOT NULL, author varchar(50) NOT NULL, publisher varchar(50) DEFAULT NULL, publish_date date DEFAULT NULL, price decimal(10,2) DEFAULT NULL, stock int(11) DEFAULT 0, category_id int(11) DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY isbn_unique (isbn) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE categories ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL, description varchar(200) DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;3.2 DAO层实现我推荐采用JDBC连接池的方式public class BookDAO { private DataSource dataSource; public BookDAO() { // 使用HikariCP连接池 HikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://localhost:3306/library); config.setUsername(root); config.setPassword(password); dataSource new HikariDataSource(config); } public ListBook findAll() throws SQLException { String sql SELECT * FROM books; try (Connection conn dataSource.getConnection(); PreparedStatement stmt conn.prepareStatement(sql)) { ResultSet rs stmt.executeQuery(); ListBook books new ArrayList(); while (rs.next()) { Book book new Book(); book.setId(rs.getInt(id)); book.setTitle(rs.getString(title)); // 其他字段... books.add(book); } return books; } } }4. 前后端交互实现4.1 控制器到视图的数据传递Servlet中处理请求并渲染视图的典型流程protected void showBookList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { ListBook books bookDAO.findAll(); request.setAttribute(books, books); WebContext ctx new WebContext(request, response, getServletContext(), request.getLocale()); ctx.setVariable(books, books); templateEngine.process(book/list, ctx, response.getWriter()); } catch (SQLException e) { throw new ServletException(Database error, e); } }4.2 Thymeleaf页面展示对应的Thymeleaf模板示例!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org head title图书列表/title /head body h1图书库存/h1 table thead tr thID/th th书名/th th作者/th th价格/th th库存/th /tr /thead tbody tr th:eachbook : ${books} td th:text${book.id}/td td th:text${book.title}/td td th:text${book.author}/td td th:text${#numbers.formatDecimal(book.price, 1, 2)}/td td th:text${book.stock}/td /tr /tbody /table /body /html提示Thymeleaf的#numbers.formatDecimal可以方便地格式化数字显示第一个参数是小数位数第二个是整数部分最小位数5. 项目部署与优化5.1 Maven打包配置war包打包配置示例build finalNamelibrary/finalName plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-war-plugin/artifactId version3.3.2/version /plugin /plugins /build使用命令打包mvn clean package5.2 性能优化建议模板缓存生产环境开启Thymeleaf缓存resolver.setCacheable(true); templateEngine.setCacheManager(new StandardCacheManager());连接池配置合理设置连接池参数config.setMaximumPoolSize(20); config.setMinimumIdle(5); config.setConnectionTimeout(30000);静态资源处理配置默认Servlet处理静态资源servlet-mapping servlet-namedefault/servlet-name url-pattern/static/*/url-pattern /servlet-mapping6. 常见问题解决方案6.1 MySQL连接问题问题现象Communications link failure解决方案检查MySQL服务是否启动确认连接URL格式正确MySQL 8.x需要时区参数jdbc:mysql://localhost:3306/library?useSSLfalseserverTimezoneAsia/Shanghai检查用户名密码是否正确6.2 Thymeleaf模板解析错误问题现象TemplateResolutionException: Template could not be resolved排查步骤确认模板文件放在/WEB-INF/templates/目录下检查模板文件后缀是否与配置一致确认ServletContext路径正确6.3 Maven依赖冲突问题现象NoSuchMethodError 或 ClassNotFoundException解决方案使用mvn dependency:tree查看依赖树排除冲突依赖dependency groupIdgroup/groupId artifactIdartifact/artifactId exclusions exclusion groupIdconflict-group/groupId artifactIdconflict-artifact/artifactId /exclusion /exclusions /dependency7. 扩展与进阶7.1 添加分页功能实现思路DAO层添加分页参数public ListBook findPage(int page, int size) { String sql SELECT * FROM books LIMIT ?, ?; // 使用(preparedStatement.setInt(1, (page-1)*size)等) }控制器计算分页信息int total bookDAO.count(); int totalPages (int) Math.ceil((double)total / size); request.setAttribute(currentPage, page); request.setAttribute(totalPages, totalPages);页面添加分页导航div classpagination a th:href{/books(page${currentPage}-1)} th:unless${currentPage} 1上一页/a span th:eachi : ${#numbers.sequence(1, totalPages)} a th:href{/books(page${i})} th:text${i} th:classappend${i currentPage} ? active/a /span a th:href{/books(page${currentPage}1)} th:unless${currentPage} totalPages下一页/a /div7.2 文件上传功能Servlet 3.0的文件上传实现表单设置form th:action{/upload} methodpost enctypemultipart/form-data input typefile namefile button typesubmit上传/button /formServlet处理MultipartConfig WebServlet(/upload) public class UploadServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) { Part filePart request.getPart(file); String fileName Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); try (InputStream fileContent filePart.getInputStream()) { // 保存文件到服务器 Files.copy(fileContent, Paths.get(/uploads, fileName)); } } }这套框架经过多次项目实战检验在中小型图书管理系统开发中表现稳定可靠。特别是在快速开发原型系统时这种轻量级架构能大大缩短开发周期。我在实际使用中发现合理组织项目结构后后续功能扩展也非常方便。