ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

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

Java Web开发实战:Thymeleaf+Servlet+MySQL图书管理系统 1. 项目背景与技术选型解析这个基于ThymeleafMavenServletMySQL的图书管理系统框架是典型的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.62. 环境准备与项目初始化2.1 Maven环境配置要点在IDEA中创建Maven项目时我推荐使用以下原型archetype groupIdorg.apache.maven.archetypes/groupId artifactIdmaven-archetype-webapp/artifactId version1.4/version /archetype关键配置项说明settings.xml镜像配置解决国内下载慢问题mirror idaliyunmaven/id mirrorOf*/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirrorpom.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 Connector -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.27/version /dependency /dependencies2.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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 添加测试数据 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 { ListBook 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:thhttp://www.thymeleaf.org head meta charsetUTF-8 title图书列表/title /head body table 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 /tr /table /body /html4. 数据访问层实现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 { ListBook 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 ListBook findAll() throws SQLException { Connection conn null; PreparedStatement stmt null; ResultSet rs null; ListBook 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}排查步骤检查模板文件是否放在/WEB-INF/templates/目录下确认HTML标签添加了命名空间html xmlns:thhttp://www.thymeleaf.org查看Servlet是否正确设置了模板引擎检查IDEA是否识别Thymeleaf语法需安装Thymeleaf插件5.2 MySQL连接失败处理典型错误信息Communications link failure解决方案矩阵错误类型可能原因解决方法连接超时数据库地址/端口错误检查jdbc.url中的IP和端口拒绝访问用户名密码错误核对application.properties配置SSL错误MySQL 8.0默认启用SSL在连接字符串添加?useSSLfalse时区问题服务器时区未设置添加serverTimezoneAsia/Shanghai5.3 Maven依赖冲突解决使用以下命令分析依赖树mvn dependency:tree -Dverbose常见冲突处理Servlet API冲突确保scope为provided日志框架冲突排除冲突的logging依赖exclusions exclusion groupIdcommons-logging/groupId artifactIdcommons-logging/artifactId /exclusion /exclusions6. 性能优化实践6.1 数据库连接池配置推荐使用HikariCP替代传统DBCPdependency groupIdcom.zaxxer/groupId artifactIdHikariCP/artifactId version4.0.3/version /dependency配置示例context.xmlResource namejdbc/BookDB authContainer typecom.zaxxer.hikari.HikariDataSource factorycom.zaxxer.hikari.HikariJNDIFactory jdbcUrljdbc:mysql://localhost:3306/bookdb usernameroot password123456 maximumPoolSize20 connectionTimeout30000/6.2 Thymeleaf模板缓存开发阶段应禁用缓存resolver.setCacheable(false); // 开发环境设置为false生产环境配置resolver.setCacheTTLMs(3600000L); // 1小时缓存6.3 静态资源处理正确配置静态资源映射web.xmlservlet-mapping servlet-namedefault/servlet-name url-pattern/static/*/url-pattern /servlet-mapping7. 安全防护措施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)); ListBook books bookService.findByPage(page, size);MySQL分页SQLSELECT * 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.xmlconfiguration appender nameFILE classch.qos.logback.core.FileAppender filelogs/bookstore.log/file encoder pattern%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n/pattern /encoder /appender root levelINFO appender-ref refFILE / /root /configuration在项目开发过程中我发现很多初学者容易在Maven依赖版本管理上栽跟头。建议锁定关键依赖的版本号而不是使用动态版本如RELEASE、LATEST。对于数据库操作一定要记得在finally块中关闭资源否则随着系统运行时间增长会出现连接泄漏问题。Thymeleaf的模板缓存机制在开发阶段应该关闭否则每次修改模板都需要重启服务器才能生效
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表