在写库时,实现一个缓存请求,需要用到全局变量,所以我们可以添加cratelazy_static
Cargo.toml添加以下依赖
[dependencies]
chrono = "0.4.31"
lazy_static = "1.4.0"
reqwest = { version = "0.11.23", features = ["blocking", "json"] }
serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
use std::{sync::Mutex, collections::HashMap};
use chrono::{DateTime, Utc};
use lazy_static::lazy_static;
use serde_json::Value;
lazy_static! {
static ref REQUESTS_RESPONSE_CACHE: Mutex<HashMap<String, RequestsResponseCache>> =
Mutex::new(HashMap::new());
}
pub struct RequestsResponseCache {
pub response: Value,
pub datetime: DateTime<Utc>,
}
pub fn get_requests_response_cache(url: &str) -> Result<Value, reqwest::Error> {
let mut cache = REQUESTS_RESPONSE_CACHE.lock().unwrap();
if let Some(cache_entry) = cache.get(url) {
let elapsed = Utc::now() - cache_entry.datetime;
if elapsed.num_seconds() > 3600 {
let response: Value = reqwest::blocking::get(url)?.json()?;
let res = response.clone();
let cache_entry = RequestsResponseCache {
response,
datetime: Utc::now(),
};
cache.insert(url.to_string(), cache_entry);
return Ok(res);
}
}
let response: Value = reqwest::blocking::get(url)?.json()?;
let res = response.clone();
let cache_entry = RequestsResponseCache {
response,
datetime: Utc::now(),
};
cache.insert(url.to_string(), cache_entry);
Ok(res)
}
使用了 lazy_static
宏创建了一个静态的全局变量 REQUESTS_RESPONSE_CACHE
,这个全局变量是一个 Mutex
包裹的 HashMap
,用来存储请求的响应缓存。这个缓存是线程安全的,因为被 Mutex
包裹了起来,这样就可以在多个线程中安全地访问和修改这个缓存。
接着定义了一个 RequestsResponseCache
结构体,用来表示缓存中的一个条目,其中包含了响应数据 response
和缓存的时间戳 datetime
。
然后定义了一个 get_requests_response_cache
函数,用来从缓存中获取请求的响应。它首先尝试从缓存中获取指定 url
的响应数据,如果缓存中有对应的条目,并且距离上次缓存的时间超过了 3600 秒(1 小时),则重新发起请求并更新缓存,然后返回响应数据。如果缓存中没有对应的条目,或者缓存的时间未超过 3600 秒,则直接发起请求并更新缓存,然后返回响应数据。
这样就提供了一个简单的请求响应的缓存功能,能够在需要时缓存请求的响应数据,并在一定时间内有效,从而减少对远程服务的重复请求,提高程序性能。