1. 概述
在本教程中,我們將繼續 Spring Security 的 註冊系列,設置一個定時任務來清除過期的 驗證令牌。 在註冊過程中,一個 驗證令牌 會被持久化。 在本文中,我們將演示如何刪除這些實體。
2. 取消過期的令牌
回顧之前文章所述,驗證令牌具有成員 expiryDate,代表令牌的過期時間戳:
@Entity
public class VerificationToken {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String token;
@OneToOne(targetEntity = User.class, fetch = FetchType.EAGER)
@JoinColumn(nullable = false, name = "user_id",
foreignKey = @ForeignKey(name="FK_VERIFY_USER"))
private User user;
private Date expiryDate;
...
}我們將使用此 expiryDate 屬性來生成一個使用 Spring Data 的查詢。
如果您想了解更多關於 Spring Data JPA 的信息,請查看這篇文章。
2.1. 刪除操作
為了方便標記令牌的移除,我們將為我們的 VerificationTokenRepository 添加一個新的方法,用於刪除過期的令牌:
public interface VerificationTokenRepository
extends JpaRepository<VerificationToken, Long> {
void deleteByExpiryDateLessThan(Date now);
}使用 查詢關鍵字 LessThan 表示 Spring Data 的 查詢創建 機制,我們僅對具有 expiryDate 屬性且小於指定時間的 token 感興趣。
請注意,因為 VerificationToken 具有與 User 的 @OneToOne 關聯,並且該關聯標記為 FetchType.EAGER,因此 還會發出 select 語句來填充 User 實體——即使 deleteByExpiryDateLessThan 方法的返回類型為 void:
select
*
from
VerificationToken verification
where
verification.expiryDate < ?
select
*
from
user_account user
where
user.id=?
delete from
VerificationToken
where
id=?
2.2. 使用 JPQL 刪除
如果不需要將實體加載到持久性上下文中,我們可以創建 JPQL 查詢:
public interface VerificationTokenRepository
extends JpaRepository<VerificationToken, Long> {
@Modifying
@Query("delete from VerificationToken t where t.expiryDate <= ?1")
void deleteAllExpiredSince(Date now);
}Hibernate 將不會將實體加載到持久化上下文中。
delete from
VerificationToken
where
expiryDate <= ?
3. 安排令牌清除任務
現在我們有一個查詢需要定期執行;我們將利用 Spring 的調度支持並創建一個方法來運行我們的刪除邏輯。
如果您想了解更多關於 Spring Job Scheduling 框架的信息,請查看這篇文章。
3.1. 啓用任務調度
為了啓用任務調度,我們創建一個新的配置類 SpringTaskConfig,並使用 @EnableScheduling 註解進行標註:
@Configuration
@EnableScheduling
public class SpringTaskConfig {
//
}
3.2. 清除令牌任務
在服務層,我們使用當前時間調用我們的存儲庫。
然後,我們使用 @Scheduled 註解標記該方法,指示 Spring 應該週期性地執行它:
@Service
@Transactional
public class TokensPurgeTask {
@Autowired
private VerificationTokenRepository tokenRepository;
@Scheduled(cron = "${purge.cron.expression}")
public void purgeExpired() {
Date now = Date.from(Instant.now());
tokenRepository.deleteAllExpiredSince(now);
}
}3.3. 計劃
我們使用一個屬性來存儲crontab設置的值,以避免更改時重新編譯。在 application.properties 中,我們指定該值:
# 5am every day
purge.cron.expression=0 0 5 * * ?4. 結論
在本文中,我們使用 Spring Data JPA 解決了 VerificationToken 的移除問題。我們演示了使用屬性表達式創建查詢,以查找具有過期日期小於指定時間的全部令牌。並且,我們創建了一個任務來在運行時調用此邏輯,並將其註冊到 Spring Job Scheduling 框架中,以便定期執行。