要实现档案销毁提醒,首先需要在数据库中存储档案的保留期限及提醒状态。我们设计一张sys_archive表,包含档案名称、到期时间、销毁状态以及是否已发送提醒标志。为了提高查询效率,必须对expiry_date字段建立索引。
请执行以下SQL脚本完成表结构创建:
CREATE TABLE `sys_archive` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`archive_no` varchar(50) NOT NULL COMMENT '档案编号',
`archive_name` varchar(200) NOT NULL COMMENT '档案名称',
`category` varchar(50) DEFAULT NULL COMMENT '档案分类',
`expiry_date` datetime NOT NULL COMMENT '到期销毁日期',
`is_destroyed` tinyint(1) DEFAULT '0' COMMENT '是否已销毁:0-未销毁,1-已销毁',
`is_reminded` tinyint(1) DEFAULT '0' COMMENT '是否已发送提醒:0-未提醒,1-已提醒',
`responsible_person` varchar(50) DEFAULT NULL COMMENT '负责人邮箱',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_expiry_date` (`expiry_date`) COMMENT '到期时间索引,用于定时任务扫描'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='档案管理主表';
执行完成后,插入几条测试数据,其中一条数据的expiry_date设置为当前时间或过去时间,以便后续测试提醒功能。
INSERT INTO `sys_archive` (`archive_no`, `archive_name`, `expiry_date`, `responsible_person`) VALUES
('ARC2023001', '2022年度财务凭证', '2023-10-01 00:00:00', 'admin@example.com'),
('ARC2023002', '2023年度人事档案', '2025-12-31 23:59:59', 'hr@example.com');
本指南基于Spring Boot 2.7.x版本,使用MyBatis-Plus作为ORM框架。在pom.xml中引入必要的依赖:Web模块、MySQL驱动、MyBatis-Plus以及Mail模块(用于发送提醒邮件)。
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
runtime
com.baomidou
mybatis-plus-boot-starter
3.5.3.1
org.springframework.boot
spring-boot-starter-mail
org.projectlombok
lombok
true
在application.yml中配置数据源连接信息及邮件发送配置。请将数据库账号密码及邮箱配置替换为你实际环境的信息。
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/archive_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: your_password
mail:
host: smtp.qq.com
port: 587
username: your_email@qq.com
password: your_email_authorization_code
protocol: smtp
default-encoding: UTF-8
properties:
mail.smtp.auth: true
mail.smtp.starttls.enable: true
mail.smtp.starttls.required: true
mybatis-plus:
mapper-locations: classpath:mapper/.xml
type-aliases-package: com.example.archive.entity
创建对应的实体类SysArchive,使用Lombok注解简化Getter/Setter。同时创建Mapper接口用于数据库操作。
实体类代码如下:
package com.example.archive.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("sys_archive")
public class SysArchive {
@TableId(type = IdType.AUTO)
private Long id;
private String archiveNo;
private String archiveName;
private String category;
private LocalDateTime expiryDate;
private Integer isDestroyed;
private Integer isReminded;
private String responsiblePerson;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
Mapper接口代码如下,我们需要定义两个方法:一个是查询待提醒的档案列表,另一个是更新提醒状态。
package com.example.archive.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.archive.entity.SysArchive;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysArchiveMapper extends BaseMapper {
List selectExpiredRemindArchives();
int updateRemindedStatus(@Param("id") Long id);
}
在resources/mapper目录下创建SysArchiveMapper.xml文件,编写具体的SQL语句。注意:查询条件必须包含is_destroyed=0(未销毁)、is_reminded=0(未提醒)以及expiry_date <= NOW()(已到期)。
UPDATE sys_archive
SET is_reminded = 1
WHERE id = {id}
创建ArchiveService类,在其中注入SysArchiveMapper和JavaMailSender。使用Spring Task的@Scheduled注解来实现定时扫描。建议设置在每天上午9点执行一次。

在启动类上添加@EnableScheduling注解以开启定时任务支持。
package com.example.archive;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class ArchiveApplication {
public static void main(String[] args) {
SpringApplication.run(ArchiveApplication.class, args);
}
}
编写核心业务逻辑类。这里包含两个关键步骤:1. 查询到期档案;2. 发送邮件并更新状态。为了防止重复发送,更新状态的操作必须紧跟在发送成功之后。
package com.example.archive.service;
import com.example.archive.entity.SysArchive;
import com.example.archive.mapper.SysArchiveMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class ArchiveDestroyService {
@Autowired
private SysArchiveMapper sysArchiveMapper;
@Autowired
private JavaMailSender mailSender;
@Autowired
private MailConfigProperties mailConfigProperties;
// 每天上午9点执行一次
@Scheduled(cron = "0 0 9 ?")
public void checkAndNotifyExpiry() {
List expiredArchives = sysArchiveMapper.selectExpiredRemindArchives();
if (expiredArchives == null || expiredArchives.isEmpty()) {
return;
}
for (SysArchive archive : expiredArchives) {
try {
sendEmail(archive);
// 发送成功后,更新提醒状态,防止重复发送
sysArchiveMapper.updateRemindedStatus(archive.getId());
} catch (Exception e) {
// 记录日志,避免因为一条邮件发送失败导致后续循环中断
System.err.println("发送失败,档案ID: " + archive.getId() + ", 错误: " + e.getMessage());
}
}
}
private void sendEmail(SysArchive archive) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(mailConfigProperties.getUsername());
message.setTo(archive.getResponsiblePerson());
message.setSubject("【重要提醒】档案销毁到期通知");
String content = String.format(
"您好,\n\n您负责的档案(编号:%s,名称:%s)已于 %s 到期,请及时进行销毁处理。\n\n请登录系统查看详情。",
archive.getArchiveNo(),
archive.getArchiveName(),
archive.getExpiryDate()
);
message.setText(content);
mailSender.send(message);
}
}
为了方便注入邮件配置,可以创建一个配置属性类:
package com.example.archive.service;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "spring.mail")
public class MailConfigProperties {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
在上一步的代码中已经集成了JavaMailSender。为了确保邮件服务可用,请确保application.yml中的spring.mail.password填写的是邮箱的授权码,而非登录密码。以QQ邮箱为例,需要在设置中开启SMTP服务并获取授权码。
如果需要在开发环境跳过邮件发送或仅打印日志,可以通过配置文件增加一个开关notify.enabled,然后在Service中通过@Value注入进行控制。
application.yml 新增配置
notify:
enabled: true
修改ArchiveDestroyService,增加开关控制:
@Value("${notify.enabled}")
private boolean notifyEnabled;
@Scheduled(cron = "0 0 9 ?")
public void checkAndNotifyExpiry() {
if (!notifyEnabled) {
System.out.println("提醒功能已关闭,跳过执行。");
return;
}
// ...其余代码保持不变
}
完成上述代码编写后,启动Spring Boot项目。由于定时任务设定为每天9点执行,为了立即验证功能,我们可以通过单元测试或手动调用Service方法来触发。
创建一个简单的测试控制器TestController,提供手动触发接口:
package com.example.archive.controller;
import com.example.archive.service.ArchiveDestroyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ArchiveDestroyService archiveDestroyService;
@GetMapping("/trigger-remind")
public String triggerRemind() {
archiveDestroyService.checkAndNotifyExpiry();
return "手动触发执行完成,请检查控制台日志及邮箱。";
}
}
验证步骤如下:
expiry_date小于当前时间、is_reminded为0且is_destroyed为0的数据。http://localhost:8080/test/trigger-remind。is_reminded字段应变为1。is_reminded已更新。至此,一套完整的档案销毁到期自动提醒功能已落地。该方案利用了Spring Boot的定时任务和Mail能力,配合MyBatis-Plus的持久化操作,无需依赖外部复杂的调度中间件,适合中小型系统直接部署使用。