spring-boot:spring-boot2.0集成redis

配置

pom依赖

        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!-- jedis客户端 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

        <!-- spring2.X集成redis所需common-pool2,使用jedis必须依赖它-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

配置文件

# 数据苦索引(默认0)
spring.redis.database=0
spring.redis.host=
spring.redis.port=6379
spring.redis.password=
# 最大连接数
spring.redis.jedis.pool.max-active=8
# 最大阻塞时间
spring.redis.jedis.pool.max-wait=5000ms
# 最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间
spring.redis.timeout=50000ms

测试

测试代码

这里只展示最核心的代码片段,完整代码可以进入项目查看

service

import com.ouyanglol.demo.dao.UserDAO;
import com.ouyanglol.demo.model.User;
import com.ouyanglol.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


/**
 * @author Ouyang
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public User selectById(String id) {
        //首次查询redis数据库有无缓存,没有就从数据库查,并把查到的数据放入redis缓存
        if (redisTemplate.opsForValue().get(id)==null) {
            User user = userDAO.selectByPrimaryKey(id);
            redisTemplate.opsForValue().set(id,user);
            return user;
        }
        return (User)redisTemplate.opsForValue().get(id);
    }
}

controller

import com.ouyanglol.demo.model.User;
import com.ouyanglol.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Ouyang
 */
@RestController
@RequestMapping("user")
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public String get(@PathVariable(name = "id") String id) {
        log.info("id-->{}",id);
        User user = userService.selectById(id);
        log.info("user-->{}",user);
        return user.toString();
    }
}

test

public class UserControllerTest  extends DemoApplicationTests {

    @Autowired
    private UserController userController;
    @Test
    public void get() {
        assertNotNull(userController.get("12"));
    }
}

测试结果

初次执行

在这里插入图片描述

图(1)

可以看出,第一次有执行sql语句,说明redis没有查到数据。

第二次执行

在这里插入图片描述

图(2)

第二次没有sql语句的打印,说明直接从redis获取了数据,并且user内容和数据库直接读取的内容一样。

优化使用

序列化

如果只做如上配置,其实仅仅是能使用RedisTemplate而已,如果直接进入数据库查看刚才插入的数据,只是一堆乱码而已。

图(3)

添加fastjson依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.54</version>
</dependency>

个人比较喜欢使用fastjson,如果不想依赖三方包,也可以使用Jackson2JsonRedisSerializer代替FastJsonRedisSerializer

新增config类

import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import java.time.Duration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author Ouyang
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<String, Object> template = new RedisTemplate<>();

        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
        //使用fastjson序列化
        GenericFastJsonRedisSerializer jsonRedisSerializer = new GenericFastJsonRedisSerializer();
//        Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //解决Jackson2JsonRedisSerializer配置序列化(解决乱码的问题)
//        ObjectMapper om = new ObjectMapper();
//        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//        jsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        //value序列化
        template.setValueSerializer(jsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jsonRedisSerializer);
        return template;
    }

    /**
     * 默认保存30秒
     * @param factory RedisConnectionFactory
     * @return CacheManager
     */
    @Bean
    @Primary
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
        //使用fastjson序列化
        GenericFastJsonRedisSerializer jsonRedisSerializer = new GenericFastJsonRedisSerializer();
        //解决查询缓存转换异常的问题
//        Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //解决Jackson2JsonRedisSerializer配置序列化(解决乱码的问题)
//        ObjectMapper om = new ObjectMapper();
//        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//        jsonRedisSerializer.setObjectMapper(om);
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(30))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer))
                .disableCachingNullValues();
        return RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
    }

    /**
     * 保存一个月
     * @param factory RedisConnectionFactory
     * @return CacheManager
     */
    @Bean("month")
    public CacheManager cacheManagerForMonth(RedisConnectionFactory factory) {
        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
        //使用fastjson序列化
        GenericFastJsonRedisSerializer jsonRedisSerializer = new GenericFastJsonRedisSerializer();
//        Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //解决Jackson2JsonRedisSerializer配置序列化(解决乱码的问题)
//        ObjectMapper om = new ObjectMapper();
//        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//        jsonRedisSerializer.setObjectMapper(om);
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(30))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer))
                .disableCachingNullValues();
        return RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
    }

}

使用注释

service

package com.ouyanglol.demo.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ouyanglol.demo.dao.UserDAO;
import com.ouyanglol.demo.model.User;
import com.ouyanglol.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


/**
 * @author Ouyang
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;
    
    @Override
    @Cacheable(value = "user",key = "#id")
    public User selectByIdV2(String id) {
        return userDAO.selectByPrimaryKey(id);
    }
}

使用@Cacheable的方法,会根据valuekey的值,对缓存的key进行查找,如果能找到,则不进入方法内部,直接返回缓存数据,比自己手动使用redisTemplate方便许多。
自己可以设定多个CacheManager(比如每个manager过期时间不同),使用注释的时候使用cacheManager ="xxxx"使用指定的manager,当存在多个manger的时候,一定要指定一个默认的manager,使用@Primary注解。

测试结果

在这里插入图片描述

图(4)

已经没有乱码的情况了,缓存使用的测试代码已经写在项目里了,测试结果肯定是缓存使用成功,这里就不多贴图了。

项目地址

地址:https://github.com/a252937166/spring-boot-demo
分支:feature/redis

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值