如何利用 RedisTemplate 自定义一个类似@Cacheable的注解的方法 拦截 FeignClient的请求调用
时间: 2024-03-16 14:42:10 浏览: 104
可以通过自定义注解和拦截器的方式实现类似@Cacheable的注解方法拦截FeignClient的请求调用。
具体实现步骤如下:
1. 定义自定义注解,比如@FeignCacheable,并指定缓存名称和缓存key。
```java
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FeignCacheable {
String value();
String key();
}
```
2. 编写拦截器,拦截带有@FeignCacheable注解的方法,并根据注解信息从缓存中获取数据或发起FeignClient请求获取数据。
```java
public class FeignCacheableInterceptor implements ClientHttpRequestInterceptor {
private RedisTemplate<String, Object> redisTemplate;
public FeignCacheableInterceptor(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
// 判断请求方法是否带有@FeignCacheable注解
FeignCacheable feignCacheable = getAnnotation(request.getHeaders(), FeignCacheable.class);
if (feignCacheable != null) {
String key = feignCacheable.key();
String cacheName = feignCacheable.value();
// 从缓存中获取数据
Object cacheData = redisTemplate.opsForValue().get(key);
if (cacheData != null) {
// 缓存中存在数据,直接返回
return new CachedResponse(cacheData);
} else {
// 缓存中不存在数据,发起FeignClient请求
ClientHttpResponse response = execution.execute(request, body);
byte[] responseBytes = StreamUtils.copyToByteArray(response.getBody());
// 将请求结果存入缓存中
redisTemplate.opsForValue().set(key, responseBytes);
redisTemplate.expire(key, 1, TimeUnit.MINUTES);
return new CachedResponse(responseBytes);
}
} else {
// 没有@FeignCacheable注解,直接执行请求
return execution.execute(request, body);
}
}
private <T extends Annotation> T getAnnotation(HttpHeaders headers, Class<T> annotationClass) {
RequestTemplate template = new RequestTemplate();
headers.forEach((key, values) -> template.header(key, values.toArray(new String[0])));
return template.methodMetadata().method().getAnnotation(annotationClass);
}
private static class CachedResponse implements ClientHttpResponse {
private byte[] body;
public CachedResponse(byte[] body) {
this.body = body;
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(body);
}
// 省略其他方法
}
}
```
3. 在FeignClient的配置中添加拦截器。
```java
@Configuration
public class FeignConfig {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Bean
public Feign.Builder feignBuilder() {
return Feign.builder()
.client(new OkHttpClient())
.requestInterceptor(new FeignCacheableInterceptor(redisTemplate));
}
}
```
通过以上步骤实现了类似@Cacheable的注解方法拦截FeignClient的请求调用并缓存数据的功能。
阅读全文