redis操作

/ 工具和中间件 / 2 条评论 / 1335浏览

redis

增加redis包

<!-- redis -->       
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>   
<!-- 对象池,使用redis时必须引入 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
 </dependency>

在yml中增加redis配置

spring:
  redis:
    host: 47.106.189.196
    # 连接超时时间(记得添加单位,Duration)
    timeout: 10000ms
    # Redis默认情况下有16个分片,这里配置具体使用的分片
    database: 2
    password: ******
    lettuce:
      pool:
        # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-wait: -1ms
        # 连接池中的最大空闲连接 默认 8
        max-idle: 8
        # 连接池中的最小空闲连接 默认 0
        min-idle: 0
  cache:
    # 一般来说是不用配置的,Spring Cache 会根据依赖的包自行装配
    type: redis

启动增加注解,以开启缓存

@SpringBootApplication
@EnableCaching
public class How2jApplication {

    public static void main(String[] args) {
        SpringApplication.run(How2jApplication.class, args);
    }

}

Redis 缓存配置类(SpringBoot2x以上)

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30L))//设置缓存延时时间为30分钟
                .disableCachingNullValues()//如果是空值,不缓存
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))//设置key值序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));//设置value值序列化为json
        return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
                .cacheDefaults(redisCacheConfiguration).build();

    }
}

service中使用缓存注解

@CacheConfig(cacheNames="category"):

表示 分类数据在 redis 中都放在 category 这个分组里

@Cacheable(key="'category '+#p0.offset + '-' + #p0.pageSize "):

假如是第一页,即offset=0,pageSize=5,那么会创建一个 key: "category 0-5",下次访问根据这个key直接获取数据

@Cacheable(key="'category '+ #p0"):

假如是获取id=71的数据,那么就会以 key= "category 71" 到reids中去获取

@CacheEvict(allEntries=true):

清除category分租下的所有缓存

@CachePut(key="'category '+ #p0"):

更新一条 key= "category 71"的缓存记录

@Service
@CacheConfig(cacheNames="category")
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryDAO categoryDAO;

    @Override
    @Cacheable(key="'category '+#p0.offset + '-' + #p0.pageSize ")
    public Page4Navigator<Category> list(Pageable pageable) {
        Page<Category> categories = categoryDAO.findAll(pageable);
        Page4Navigator<Category> page = new Page4Navigator<>(categories,5);
        return page;
    }

    @Override
    @CacheEvict(allEntries=true)
    public void save(Category category) {
        categoryDAO.save(category);
    }

    @Override
    @CacheEvict(allEntries=true)
    public void delete(int id) {
        categoryDAO.deleteById(id);
    }

    @Override
    @Cacheable(key="'category '+#p0 ")
    public Category get(int id) {
        return categoryDAO.findById(id).get();
    }
}

直接操作redis

    1>redisTemplate.opsForValue();//操作字符串
        stringRedisTemplate.opsForValue();//字符串专用模板
    2>redisTemplate.opsForHash();//操作hash
    3>redisTemplate.opsForList();//操作list
    4>redisTemplate.opsForSet();//操作set
    5>redisTemplate.opsForZSet();//操作有序set
    /**
     * 默认情况下的模板只能支持RedisTemplate<String, String>,也就是只能存入字符串,因此支持序列化
     */
    @Bean
    public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Serializable> template = new RedisTemplate<>();
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
    @Autowired
    private RedisTemplate redisCacheTemplate;

    @Test
    public void fun5(){
        redisCacheTemplate.opsForValue().set("aaa","bbb");
    }

springboot中使用

一般在service中使用注解进行缓存,
@CacheConfig(配置)、@Cacheable(添加/获取)、@CacheEvict(清楚)、@CachePut(更新)

Application中增加注解@EnableCaching用于启动缓存

@EnableCaching
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

yml配置,同上(略)

service中使用缓存注解

@CacheConfig(cacheNames="categories")
public class CategoryService {
    @Autowired
    private CategoryDAO categoryDAO;

    /**
     * 分页查询数据
     * @param start 起始页
     * @param size  每页显示条数
     * @param navigatePages  导航栏显示的页码个数
     * @return
     */
    @Cacheable(key="'categories-page-'+#p0+ '-' + #p1")
    public Page4Navigator list(int start, int size, int navigatePages){
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(start, size, sort);
        Page<Category> page = categoryDAO.findAll(pageable);
        return new Page4Navigator<>(page,navigatePages);
    }

    /**
     * 增加类别数据,使用@CacheEvict直接更新分页缓存
     * @param category
     * @return
     */
    @CacheEvict(allEntries=true)
    public Category add(Category category){
        return categoryDAO.save(category);
    }

    /**
     * 根据id删除类别数据
     * @param id
     */
    @CacheEvict(allEntries=true)
    public void delete(Integer id){
        categoryDAO.delete(id);
    }

    /**
     * 根据id查询数据
     * @param id
     * @return
     */
    @Cacheable(key="'categories-one-'+ #p0")
    public Category get(Integer id){
        return categoryDAO.getOne(id);
    }

    /**
     * 更新类别数据
     * @param category
     * @return
     */
    @CacheEvict(allEntries=true)
    public Category update(Category category) {
        return categoryDAO.save(category);
    }
}

service调用其他service方法不能缓存

springboot的缓存机制是通过切面编程aop来实现的。从service方法里直接调用其他service方法, aop是拦截不到的,也就不会走缓存了

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private SpringContextUtil() {
    }

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext){
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}
    public void fill(Category category){
        ProductService productService = SpringContextUtil.getBean(ProductService.class);
        //其他service中的方法(有缓存的)
        List<Product> products = productService.listByCategory(category);
        productImageService.setFirstProdutImages(products);
        category.setProducts(products);
    }