应用场景
根据数据库消息表存入的消息推送时间,定时执行消息推送
实现方案
1. 定时任务 使用定时任务定期扫描数据库的消息数据,比较每个推送时间小于当前时间并没有被执行推送的消息,得到消息列表,执行推送任务。
2. 定时器 使用定时器来处理消息推送。每次向数据库中添加一条消息数据时,创建一个对应的定时器,定时器的触发时间为消息的推送时间,当定时器触发时,执行推送操作.并在系统重启时从数据库查询未被推送的消息,重新生成定时器。
3. 消息队列 通过MQ消息队列中间件实现定时消息的推送,相对更可靠和稳定
示例
定时器实现举例
@Entity
@Data
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String content;
private LocalDateTime pushTime;
private boolean pushed;
}
@Service
public class MessageService {
@Autowired
private MessageRepository messageRepository;
@Autowired
private ScheduledExecutorService scheduledExecutorService;
private Map<Long, ScheduledFuture<?>> scheduledFutures = new HashMap<>();
public void addMessage(Message message) {
message.setPushed(false);
messageRepository.save(message);
LocalDateTime pushTime = message.getPushTime();
long delay = Duration.between(LocalDateTime.now(), pushTime).toMillis();
ScheduledFuture<?> scheduledFuture = scheduledExecutorService.schedule(() -> {
pushMessage(message);
}, delay, TimeUnit.MILLISECONDS);
scheduledFutures.put(message.getId(), scheduledFuture);
}
public void deleteMessage(Long messageId) {
Message message = messageRepository.findById(messageId).orElse(null);
if (message == null) {
return;
}
ScheduledFuture<?> scheduledFuture = scheduledFutures.get(messageId);
if (scheduledFuture != null) {
scheduledFuture.cancel(false);
scheduledFutures.remove(messageId);
}
messageRepository.delete(message);
}
@PostConstruct
public void initScheduledFutures() {
List<Message> messages = messageRepository.findByPushTimeAfter(LocalDateTime.now());
for (Message message : messages) {
addMessage(message);
}
}
@PreDestroy
public void stopScheduledFutures() {
scheduledExecutorService.shutdown();
}
private void pushMessage(Message message) {
// 实现消息推送逻辑,例如调用接口推送消息给用户
message.setPushed(true);
messageRepository.save(message);
}
}
消息队列实现举例
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
@Service
public class MessageService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void addMessage(Message message) {
message.setPushed(false);
rabbitTemplate.convertAndSend("message-exchange", "message-routing-key", message, message1 -> {
message1.getMessageProperties().setExpiration(String.valueOf(Duration.between(LocalDateTime.now(), message.getPushTime()).toMillis()));
return message1;
});
}
private void pushMessage(Message message) {
// 实现消息推送逻辑,例如调用接口推送消息给用户
message.setPushed(true);
// 更新消息状态
}
}
@Component
public class MessageConsumer {
@Autowired
private MessageService messageService;
@RabbitListener(queues = "message-queue")
public void handleMessage(Message message) {
messageService.pushMessage(message);
}
}
**```**