SpringBoot整合Redis

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。

1、安装redis;
2、引入redis的starter
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
3、配置redis

这一步也很简单只需要在配置文件中指定redis的主机地址即可

spring.redis.host=118.24.44.169
4.原理分析

当我们在项目中配置好了redis后,RedisAutoConfiguration配置类就会起作用,下面是配置类的内容:

public class RedisAutoConfiguration {
    public RedisAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

可以看到配置类为我们向容器中加入了零个redisTemplate(redisTemplate和stringRedisTemplate),这个就是我们用来操作redis的工具。(类似于JpaTemplate)。我们使用redis时@Autowired这两个template即可使用redis,例如:

@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot01CacheApplicationTests {
	@Autowired
	EmployeeMapper employeeMapper;
	@Autowired
	StringRedisTemplate stringRedisTemplate;  //操作k-v都是字符串的
	@Autowired
	RedisTemplate redisTemplate;  //k-v都是对象的
	@Autowired
	RedisTemplate<Object, Employee> empRedisTemplate;

	/**
	 * Redis常见的五大数据类型
	 *  String(字符串)、List(列表)、Set(集合)、Hash(散列)、ZSet(有序集合)
	 *  stringRedisTemplate.opsForValue()[String(字符串)]
	 *  stringRedisTemplate.opsForList()[List(列表)]
	 *  stringRedisTemplate.opsForSet()[Set(集合)]
	 *  stringRedisTemplate.opsForHash()[Hash(散列)]
	 *  stringRedisTemplate.opsForZSet()[ZSet(有序集合)]
	 */
	@Test
	public void test01(){
		给redis中保存数据
	    stringRedisTemplate.opsForValue().append("msg","hello");
 		String msg = stringRedisTemplate.opsForValue().get("msg");
 		System.out.println(msg);

 		stringRedisTemplate.opsForList().leftPush("mylist","1");
      	stringRedisTemplate.opsForList().leftPush("mylist","2");
	}

	//测试保存对象
	@Test
	public void test02(){
		Employee empById = employeeMapper.getEmpById(1);
		//默认如果保存对象,使用jdk序列化机制,序列化后的数据保存到redis中
		redisTemplate.opsForValue().set("emp-01",empById);
	}

	@Test
	public void contextLoads() {
		Employee empById = employeeMapper.getEmpById(1);
		System.out.println(empById);
	}

}

在上面的测测试中我们会发现,如果保存对象,默认使用jdk序列化机制,序列化后的数据保存到redis中,这会导致redis数据库中存入的值很不友好。

5.定义序列化机制

要让存入的结果友好我们有两种方式:
(1)自己将对象转为json
(2)redisTemplate默认的序列化规则;改变默认的序列化规则;
其实我们来看看RedisTemplate就会发现其中定义了很多Serializer(序列化器)

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
    private boolean enableTransactionSupport = false;
    private boolean exposeConnection = false;
    private boolean initialized = false;
    private boolean enableDefaultSerializer = true;
    @Nullable
    private RedisSerializer<?> defaultSerializer;
    @Nullable
    private ClassLoader classLoader;
    @Nullable
    private RedisSerializer keySerializer = null;
    @Nullable
    private RedisSerializer valueSerializer = null;
    @Nullable
    private RedisSerializer hashKeySerializer = null;
    @Nullable
    private RedisSerializer hashValueSerializer = null;
    private RedisSerializer<String> stringSerializer = RedisSerializer.string();
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        //这里可以看到当defaultSerializer 为null时,默认使用JdkSerializationRedisSerializer(jdk的序列化器)
        if (this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
        }

        if (this.enableDefaultSerializer) {
            if (this.keySerializer == null) {
                this.keySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.valueSerializer == null) {
                this.valueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashKeySerializer == null) {
                this.hashKeySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashValueSerializer == null) {
                this.hashValueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }
        }

        if (this.enableDefaultSerializer && defaultUsed) {
            Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
        }

        if (this.scriptExecutor == null) {
            this.scriptExecutor = new DefaultScriptExecutor(this);
        }

        this.initialized = true;
    }

因为默认使用JdkSerializationRedisSerializer,所以我们可以设置DefaultSerializer为自己想要的序列化器,就像RedisAutoConfiguration 中一样在加RedisTemplate时设置defaultSerializer,代码如下:

@Configuration
public class MyRedisConfig {

    @Bean
    public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
        template.setConnectionFactory(redisConnectionFactory);
        //这里使用Jackson2JsonRedisSerializer。
        Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
        template.setDefaultSerializer(ser);
        return template;
    }
}

这样我们在使用RedisTemplate时就会按照自定义的序列化机制来存入数据了。

6.缓存原理

在我的SpringBoot缓存配置原理博文中介绍了缓存实际上是通过cacheManager来实现的,当容器中没有cacheManager时会默认配置SimpleCacheConfiguration。因为我们引入了Redis,所以容器会自动匹配到RedisCacheConfiguration.这是为什么呢?我们先来看看RedisCacheConfiguration:

@ConditionalOnClass({RedisConnectionFactory.class})
@AutoConfigureAfter({RedisAutoConfiguration.class})
@ConditionalOnBean({RedisConnectionFactory.class})
@ConditionalOnMissingBean({CacheManager.class})
@Conditional({CacheCondition.class})
class RedisCacheConfiguration {
    RedisCacheConfiguration() {
    }

@Bean
RedisCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers, ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration, ObjectProvider<RedisCacheManagerBuilderCustomizer> redisCacheManagerBuilderCustomizers, RedisConnectionFactory redisConnectionFactory, ResourceLoader resourceLoader) {
        RedisCacheManagerBuilder builder = 		RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(this.determineConfiguration(cacheProperties, redisCacheConfiguration, resourceLoader.getClassLoader()));
        List<String> cacheNames = cacheProperties.getCacheNames();
        if (!cacheNames.isEmpty()) {
            builder.initialCacheNames(new LinkedHashSet(cacheNames));
        }
...

可以看出,容器根据@Conditional注解匹配到RedisCacheConfiguration 后,RedisCacheConfiguration 会给我们在容器中@Bean一个
cacheManager(RedisCacheManager ) ,这就使SimpleCacheManager 的匹配条件失败。(匹配过程是有顺序的)。
下面就可以来看看RedisCacheManager是如何帮我们缓存的:

public class RedisCacheManager extends AbstractTransactionSupportingCacheManager {

//加载缓存
	 protected Collection<RedisCache> loadCaches() {
        List<RedisCache> caches = new LinkedList();
        Iterator var2 = this.initialCacheConfiguration.entrySet().iterator();

        while(var2.hasNext()) {
            Entry<String, RedisCacheConfiguration> entry = (Entry)var2.next();
            caches.add(this.createRedisCache((String)entry.getKey(), (RedisCacheConfiguration)entry.getValue()));
        }

        return caches;
    }
    //创建缓存
	protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) {
        return new RedisCache(name, this.cacheWriter, cacheConfig != null ? cacheConfig : this.defaultCacheConfig);
    }

可以看到RedisCacheManager 会给我们创建RedisCache 作为缓存组件,RedisCache通过操作redis来存取数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值