Jakarta EE课程 微型资料投递与分发 实验指导 (付完整版代码)
摘要:基于之前的HTTP实验(DropsServlet等),我将提供使用H2数据库的版本来改造“资料投递箱”为“临时分享链接”。这个方案实现了:
- 每个文件只允许下载一次(下载后从数据库删除记录)。
- 文件在一定时间后自动过期(使用定时任务每分钟查询并删除过期记录;虽然有轻微延迟,但通过短间隔最小化;相比Redis TTL,H2更适合需要查询/持久化的场景)。
- 其他原功能保持:上传文件+描述、生成ID、HTTP响应(302/201/304/413/415)、XSS转义。
为什么用H2:
- H2是嵌入式SQL数据库,易集成JPA/Hibernate,支持文件模式持久化(数据存盘,重启不丢)。
- 优点:结构化查询(易查看内容)、自动表创建;缺点:清理需定时任务(可能有秒级延迟),但适合您的Jakarta EE项目(无需额外服务器如Redis)。
- 与Redis比较:H2更重但功能丰富(SQL查询);如果需要零延迟,Redis更好,但您指定H2。
代码在IntelliJ IDEA中可直接集成(基于Maven Archetype WebApp项目)。假设项目名为HttpExperiment,运行Tomcat 10+。我提供完整代码文件,便于复制。
设计思路和说明
- 存储结构:使用JPA实体FileEntity(字段:id, description, content (BLOB), contentType, expireTime, downloadCount)。
- 上传(doPost):生成ID,设置expireTime(当前时间 + 1小时),downloadCount=0,persist到H2。
- 下载(doGet):查询记录,检查expireTime(过期删除返回410),downloadCount < 1(否则404);下载后设置downloadCount=1并更新(或直接删除实现单次)。
- 过期清理:Servlet init()启动ScheduledExecutorService,每60秒查询并删除expireTime < now的记录(使用JPA delete query)。
- 单次下载:下载后删除记录(简单实现;可改成更新count,允许多次但这里严格单次)。
- 挑战与解决:定时延迟(短间隔最小化);大文件(BLOB限数据库大小,生产用文件系统);并发(JPA事务锁确保安全)。
- 优缺点:易查看(SQL查询),持久化好;但清理不如Redis TTL即时。
配置步骤
- 确保H2依赖:pom.xml中添加/确认H2和Hibernate(详见代码)。
- 数据库模式:文件模式(jdbc:h2:./filedb),生成filedb.mv.db文件,便于查看。
- 运行:IntelliJ Run Tomcat,访问/drops。
完整代码
pom.xml(完整,包含H2和Hibernate)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>httpexperiment</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- Jakarta EE Web API -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>9.1.0</version>
<scope>provided</scope>
</dependency>
<!-- JSTL for JSP -->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>2.0.0</version>
</dependency>
<!-- Jackson for JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId