news 2026/9/11 8:14:46

Java Web开发实战:Thymeleaf+Servlet+MySQL图书管理系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java Web开发实战:Thymeleaf+Servlet+MySQL图书管理系统

1. 项目背景与技术选型解析

这个基于Thymeleaf+Maven+Servlet+MySQL的图书管理系统框架,是典型的Java Web应用开发实践案例。作为系列教程的第三部分(共九章),它聚焦于企业级应用开发中最核心的技术栈组合。

为什么选择这个技术组合?我在实际项目中多次验证过它的可靠性:

  • Thymeleaf:相比JSP,它天然支持HTML5,能与前端开发工具无缝配合,且不依赖Servlet容器
  • Maven:解决依赖管理的噩梦,特别是处理MySQL Connector这类经常需要版本适配的库
  • Servlet 3.1+:保持轻量级的同时支持注解配置,避免web.xml的繁琐
  • MySQL 5.7+:事务完整性和JSON字段支持已足够成熟

提示:初学者常犯的错误是直接使用最新版本组件。建议初学者采用稳定组合:Thymeleaf 3.0 + Servlet 4.0 + MySQL 5.7 + Maven 3.6

2. 环境准备与项目初始化

2.1 Maven环境配置要点

在IDEA中创建Maven项目时,我推荐使用以下原型:

<archetype> <groupId>org.apache.maven.archetypes</groupId> <artifactId>maven-archetype-webapp</artifactId> <version>1.4</version> </archetype>

关键配置项说明:

  1. settings.xml镜像配置(解决国内下载慢问题):
<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
  1. pom.xml基础依赖
<dependencies> <!-- Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- Thymeleaf --> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.12.RELEASE</version> </dependency> <!-- MySQL Connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> </dependencies>

2.2 数据库初始化脚本

创建图书管理核心表:

CREATE TABLE `books` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL, `author` varchar(50) NOT NULL, `isbn` varchar(20) UNIQUE, `publish_date` date, `price` decimal(10,2), `stock` int(11) DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 添加测试数据 INSERT INTO `books` VALUES (1,'Java编程思想','Bruce Eckel','9787111213826','2007-06-01',108.00,50), (2,'Spring实战','Craig Walls','9787115480661','2018-10-01',89.00,30);

3. Servlet与Thymeleaf集成架构

3.1 视图解析器配置

创建ThymeleafViewResolver是整合的关键:

public class ThymeleafConfig { private static TemplateEngine templateEngine; static { ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); resolver.setPrefix("/WEB-INF/templates/"); resolver.setSuffix(".html"); resolver.setTemplateMode(TemplateMode.HTML); resolver.setCharacterEncoding("UTF-8"); templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(resolver); } public static TemplateEngine getTemplateEngine() { return templateEngine; } }

3.2 基础Servlet实现

图书列表展示的Servlet示例:

@WebServlet("/book/list") public class BookListServlet extends HttpServlet { private BookService bookService = new BookServiceImpl(); protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List<Book> books = bookService.getAllBooks(); req.setAttribute("books", books); WebContext ctx = new WebContext( req, resp, req.getServletContext(), req.getLocale()); ctx.setVariable("books", books); ThymeleafConfig.getTemplateEngine() .process("book/list", ctx, resp.getWriter()); } }

对应的Thymeleaf模板(/WEB-INF/templates/book/list.html):

<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>图书列表</title> </head> <body> <table> <tr th:each="book : ${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> </tr> </table> </body> </html>

4. 数据访问层实现

4.1 JDBC工具类封装

避免在每个DAO中重复创建连接:

public class JdbcUtil { private static DataSource dataSource; static { try { Context ctx = new InitialContext(); dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/BookDB"); } catch (NamingException e) { throw new RuntimeException("数据源配置错误", e); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void close(ResultSet rs, Statement stmt, Connection conn) { try { if(rs != null) rs.close(); } catch (SQLException ignored) {} try { if(stmt != null) stmt.close(); } catch (SQLException ignored) {} try { if(conn != null) conn.close(); } catch (SQLException ignored) {} } }

4.2 DAO模式实现

图书DAO接口与实现:

public interface BookDao { List<Book> findAll() throws SQLException; Book findById(int id) throws SQLException; int insert(Book book) throws SQLException; int update(Book book) throws SQLException; int delete(int id) throws SQLException; } public class BookDaoImpl implements BookDao { @Override public List<Book> findAll() throws SQLException { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; List<Book> books = new ArrayList<>(); try { conn = JdbcUtil.getConnection(); stmt = conn.prepareStatement("SELECT * FROM books"); rs = stmt.executeQuery(); while(rs.next()) { Book book = new Book(); book.setId(rs.getInt("id")); book.setTitle(rs.getString("title")); book.setAuthor(rs.getString("author")); book.setIsbn(rs.getString("isbn")); book.setPublishDate(rs.getDate("publish_date")); book.setPrice(rs.getBigDecimal("price")); book.setStock(rs.getInt("stock")); books.add(book); } } finally { JdbcUtil.close(rs, stmt, conn); } return books; } // 其他方法实现类似... }

5. 常见问题排查指南

5.1 Thymeleaf模板不渲染问题

症状:页面直接显示Thymeleaf表达式(如${books}

排查步骤:

  1. 检查模板文件是否放在/WEB-INF/templates/目录下
  2. 确认HTML标签添加了命名空间:<html xmlns:th="http://www.thymeleaf.org">
  3. 查看Servlet是否正确设置了模板引擎
  4. 检查IDEA是否识别Thymeleaf语法(需安装Thymeleaf插件)

5.2 MySQL连接失败处理

典型错误信息:Communications link failure

解决方案矩阵:

错误类型可能原因解决方法
连接超时数据库地址/端口错误检查jdbc.url中的IP和端口
拒绝访问用户名密码错误核对application.properties配置
SSL错误MySQL 8.0+默认启用SSL在连接字符串添加?useSSL=false
时区问题服务器时区未设置添加serverTimezone=Asia/Shanghai

5.3 Maven依赖冲突解决

使用以下命令分析依赖树:

mvn dependency:tree -Dverbose

常见冲突处理:

  1. Servlet API冲突:确保scope为provided
  2. 日志框架冲突:排除冲突的logging依赖
<exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions>

6. 性能优化实践

6.1 数据库连接池配置

推荐使用HikariCP替代传统DBCP:

<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>4.0.3</version> </dependency>

配置示例(context.xml):

<Resource name="jdbc/BookDB" auth="Container" type="com.zaxxer.hikari.HikariDataSource" factory="com.zaxxer.hikari.HikariJNDIFactory" jdbcUrl="jdbc:mysql://localhost:3306/bookdb" username="root" password="123456" maximumPoolSize="20" connectionTimeout="30000"/>

6.2 Thymeleaf模板缓存

开发阶段应禁用缓存:

resolver.setCacheable(false); // 开发环境设置为false

生产环境配置:

resolver.setCacheTTLMs(3600000L); // 1小时缓存

6.3 静态资源处理

正确配置静态资源映射(web.xml):

<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping>

7. 安全防护措施

7.1 SQL注入防护

必须使用PreparedStatement:

// 错误示范(存在注入风险) String sql = "SELECT * FROM books WHERE title = '" + title + "'"; // 正确做法 PreparedStatement stmt = conn.prepareStatement( "SELECT * FROM books WHERE title = ?"); stmt.setString(1, title);

7.2 XSS防护

Thymeleaf默认会进行HTML转义,特殊场景需要取消转义时:

<div th:text="${#strings.escapeXml(book.title)}"></div> <!-- 或 --> <div th:utext="${book.title}"></div> <!-- 慎用 -->

7.3 CSRF防护

实现简单的CSRF Token机制:

// 生成Token String csrfToken = UUID.randomUUID().toString(); session.setAttribute("csrfToken", csrfToken); // 验证Token String requestToken = request.getParameter("csrfToken"); String sessionToken = (String) session.getAttribute("csrfToken"); if(!requestToken.equals(sessionToken)) { throw new SecurityException("CSRF验证失败"); }

8. 项目结构规范建议

推荐的标准目录结构:

src/ ├── main/ │ ├── java/ │ │ └── com/ │ │ └── example/ │ │ ├── config/ # 配置类 │ │ ├── controller/ # Servlet │ │ ├── dao/ # 数据访问层 │ │ ├── model/ # 实体类 │ │ ├── service/ # 业务逻辑 │ │ └── util/ # 工具类 │ ├── resources/ │ │ ├── db/ # SQL脚本 │ │ └── config.properties # 配置文件 │ └── webapp/ │ ├── static/ # 静态资源 │ │ ├── css/ │ │ ├── js/ │ │ └── images/ │ └── WEB-INF/ │ ├── templates/ # Thymeleaf模板 │ └── web.xml └── test/ # 测试代码

9. 扩展功能实现思路

9.1 分页查询优化

前端传递分页参数:

int page = Integer.parseInt(request.getParameter("page")); int size = Integer.parseInt(request.getParameter("size")); List<Book> books = bookService.findByPage(page, size);

MySQL分页SQL:

SELECT * FROM books LIMIT ?, ?

9.2 文件上传功能

Servlet 3.0+的文件上传处理:

@WebServlet("/upload") @MultipartConfig public class UploadServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Part filePart = req.getPart("file"); String fileName = Paths.get(filePart.getSubmittedFileName()) .getFileName().toString(); InputStream fileContent = filePart.getInputStream(); // 保存文件到指定目录 Files.copy(fileContent, Paths.get("/uploads", fileName)); } }

9.3 日志系统集成

Logback配置示例(logback.xml):

<configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>logs/bookstore.log</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="FILE" /> </root> </configuration>

在项目开发过程中,我发现很多初学者容易在Maven依赖版本管理上栽跟头。建议锁定关键依赖的版本号,而不是使用动态版本(如RELEASE、LATEST)。对于数据库操作,一定要记得在finally块中关闭资源,否则随着系统运行时间增长,会出现连接泄漏问题。Thymeleaf的模板缓存机制在开发阶段应该关闭,否则每次修改模板都需要重启服务器才能生效

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 8:05:04

迅雷使用教程:下载、磁力链接与云盘功能

迅雷是知名下载工具。这篇文章讲它的下载、磁力链接和云盘功能。 一、下载安装 官网地址&#xff1a;迅雷下载官网支持 Windows、Mac、Android、iOS。 二、普通下载 复制下载链接&#xff0c;迅雷自动识别。或浏览器点击下载&#xff0c;迅雷接管。选择保存路径&#xff0c;…

作者头像 李华
网站建设 2026/9/11 8:02:29

新闻媒体资源怎么找?曜道媒介发稿平台提供10万+传播资源

新闻媒体资源怎么找?曜道媒介发稿平台提供10万传播资源企业做新闻传播时,经常遇到“去哪里找媒体”的问题。互联网上虽然能够搜索到很多新闻网站,但真正执行品牌传播时,还要考虑媒体类型、行业方向、区域属性和具体发布需求。一个稳定、丰富且方便查询的媒体资源入口,可以明显…

作者头像 李华
网站建设 2026/9/11 8:00:48

工业自动化未来十年:存量改造、预测性维护、AI质检等六大机会

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 7:58:14

用Golang攻克三数之和:排序+双指针的优雅解法与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 7:58:02

2 分钟完整转换 Visio 文件:drawio-desktop 上手

2 分钟完整转换 Visio 文件&#xff1a;drawio-desktop 上手 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop 同事发来的 .vsdx 在你 Mac 上双击&#xff0c;只有一句「无法打开…

作者头像 李华