一种策略是通过将相关数据存储在数据库中并使用缓存库来跟踪expiry date-time
所有用户(在检查到期日期时减少数据库命中)。这是一个小例子:
创建一个数据库表,其中包含将用户 ID 映射到到期日期的列:id, unique_user_id, expiry_date_time
。您需要在代码中创建唯一的用户 ID 并将其保存在数据库中,然后再将 URL 发送给具有此 ID 的用户。您可以保留null
为 的初始值expiry_date_time
。在 Java 中创建一个类来表示此映射:
class UserIdWithExpiryDate{
private String userId;
private Date expiryDateTime;
...
}
定义一个Service
方法,该cacheable
方法将为给定的返回 this 的实例userId
:
public interface CacheableService {
@Cacheable("expiryDates")
public UserIdWithExpiryDate getUserIdWithExpiryDate(String id);
public void updateUserIdWithExpiryDate(String userId);
}
import org.joda.time.DateTime;
@Service
public class CacheableServiceImpl implements CacheableService {
@Autowired
private YourDao dao;
@Override
public UserIdWithExpiryDate getUserIdWithExpiryDate(String id) {
return dao.getUserIdWithExpiryDate(id);
}
public void updateUserIdWithExpiryDate(String userId){
Date expiryDate = new Date(new DateTime().plusHours(24).getMillis());
dao.update(userId, expiryDate);
}
}
方法的结果getUserIdWithExpiryDate
存储在缓存中,因此在后续调用(使用相同的参数)时,无需实际执行方法即可返回缓存中的值。
下一步是在访问网站时检查用户的到期日期。这可以使用OncePerRequestFilter来完成:
@Component("timeoutFilter")
public class TimeoutFilter extends OncePerRequestFilter {
@Autowired
CacheableService cacheableService;
// Here you need to decide whether to proceed with the request or not
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(request, response);
}
}
在方法内部可以采取的步骤doFilterInternal
来检查用户的有效性:
- 从请求中获取用户 ID
- 执行:
cacheableService.getUserIdWithExpiryDate(userId)
- 如果第 2 步返回 null,则不存在具有此 ID 的用户。您不应继续执行该请求。
- 如果第 2 步返回 UserIdWithExpiryDate 的实例,请检查“expiryDateTime”的值
- 如果“expiryDateTime”的值为空,则表示用户是第一次访问该站点。更新“userExpiryDate”:cacheableService.updateUserIdWithExpiryDate(userId)并继续请求。
- 如果“expiryDateTime”不为空,请将其与当前 date_time 进行比较。如果
expiryDateTime.isAfter(currentDateTime)
,请继续请求。
对于缓存,您可以将Spring Cache Abstraction与EHCACHE一起使用。