一、背景
在日常开发中,有很多情况下需要使用缓存来提高系统的访问速度,本文章将使用redis和jetcache来介绍一种缓存在spring boot项目中的使用
二、使用
2.1引入相关依赖
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.2配置文件
spring:
redis:
port: 6379
password: 123
host: 127.0.0.1
jetcache:
areaInCacheName: false
statIntervalMinutes: 15
local:
default:
type: caffeine
keyConvertor: fastjson
remote:
default:
type: redis
keyConvertor: fastjson
valueEncoder: java
valueDecoder: java
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
host: ${spring.redis.host}
timeout: 100
soTimeout: 500
port: ${spring.redis.port}
password: 123
2.3 主类增加注解开启缓存
package com.xx.main;
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableMethodCache(basePackages = "com.xx.service")
@EnableCreateCacheAnnotation
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
- EnableCreateCacheAnotation 开启缓存
- EnableMethodCache 开启方法缓存,这个注解会扫描basePackages包下的方法,并把配置的参数作为缓存的key,方法的返回值作为value进行保存
2.4 redis 和 jetcatch 配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class RestTemplateConfiguration {
// @Value("${ConnectTimeout}")
private int CONNECT_TIME_OUT = 10000;
// @Value("${ReadTimeout}")
private int READ_TIME_OUT = 30000;
@Bean
public RestTemplate spRestTemplate() {
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(CONNECT_TIME_OUT);
httpRequestFactory.setConnectTimeout(CONNECT_TIME_OUT);
httpRequestFactory.setReadTimeout(READ_TIME_OUT);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
restTemplate.getMessageConverters().add(new CustomHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("utf-8")));
return restTemplate;
}
/**
* 自定义转换器以支持text/plain和text/html
*/
private class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter {
public CustomHttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.TEXT_PLAIN);
mediaTypes.add(MediaType.TEXT_HTML);
mediaTypes.add(MediaType.APPLICATION_JSON);
mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
mediaTypes.add(MediaType.APPLICATION_ATOM_XML);
mediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
mediaTypes.add(MediaType.APPLICATION_PDF);
mediaTypes.add(MediaType.APPLICATION_RSS_XML);
mediaTypes.add(MediaType.APPLICATION_XHTML_XML);
mediaTypes.add(MediaType.APPLICATION_XML);
mediaTypes.add(MediaType.IMAGE_GIF);
mediaTypes.add(MediaType.IMAGE_JPEG);
mediaTypes.add(MediaType.IMAGE_PNG);
mediaTypes.add(MediaType.TEXT_EVENT_STREAM);
mediaTypes.add(MediaType.TEXT_HTML);
mediaTypes.add(MediaType.TEXT_MARKDOWN);
mediaTypes.add(new MediaType("text", "plain", StandardCharsets.UTF_8));
setSupportedMediaTypes(mediaTypes);
}
}
}
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheAutoConfiguration {
@Bean(value = “redisTemplate”)
public RedisTemplate redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}
2.5 在需要缓存的方法上使用
需要缓存的方法
import com.alicp.jetcache.anno.Cached;
@Slf4j
@Service
public class TestLoadHelper {
@Cached(name = "test", key="#arg")
public List<Object> getTest(String arg) {
ArrayList<String> list = new ArrayList<String>();
list = baseMapper.select(arg);
return list;
}
}
生成的缓存key为 testarg,value就是getTest方法返回的值
调用者
import com.alicp.jetcache.anno.Cached;
@Slf4j
@Service
public class TestService {
@Resource
private TestLoadHelper testLoadHelper;
public List<Object> getTest(String arg) {
return testLoadHelper.getTest(arg);
}
}
通过断点可以观察到,arg相同的第一次请求,会进入 testLoadHelper.getTest方法,第二次请求就不会进入了,直接返回了值
三、总结
- 注意redis 和 jetcatch 的版本要与spring boot 版本对应
- 安装的redis外网访问需要该配置 bind requirepass ,防火墙要放行,如果是云主机,还要在安全组开启端口