SpringBoot 2.x 集成 Redis


SpringBoot 2.x 集成 Redis

windows上搭建redis環境

添加依賴

此處redis客戶端使用jedis。

<!-- redis -->
<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
    	<exclusion>
        	<groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </exclusion>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- redis 客戶端使用jedis -->
<dependency>
	<groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
  • Jedis

    直接連接 redis server。在多線程環境下是非線程安全的,需要使用連接池,為每個Jedis實例增加物理連接。

  • Lettuce

    連接基於Netty,連接實例可以在多個線程間並發訪問。因為連接實例是線程安全的,所以一個連接實例就可以滿足多線程環境下的並發訪問。

添加配置

2.0 版本之前的一些配置已被移除。使用jedis就配置jedis(如下配置),使用lettuce換下名稱即可。

# REDIS (RedisProperties)
# Redis數據庫索引(默認為0)
spring.redis.database=0
# Redis服務器地址
spring.redis.host=127.0.0.1
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認為空)
spring.redis.password=
# 連接超時時間(毫秒)
spring.redis.timeout=0ms
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 連接池中的最大空閑連接
spring.redis.jedis.pool.max-idle=8
# 連接池中的最小空閑連接
spring.redis.jedis.pool.min-idle=0

添加redis配置類

  • SpringBoot1.5x之前,Redis配置類如下:

      @Configuration
      @EnableCaching
      public class RedisConfig extends CachingConfigurerSupport {
    
      	@Bean
      	public KeyGenerator keyGenerator() {
     			return new KeyGenerator() {
          	    @Override
          	    public Object generate(Object target, Method method, Object... params) {
              	    StringBuilder sb = new StringBuilder();
              	    sb.append(target.getClass().getName());
              	    sb.append(method.getName());
              	    for (Object obj : params) {
                  	    sb.append(obj.toString());
              	    }
              	    return sb.toString();
          	    }
      	    };
          }
    
      	@Bean
      	public CacheManager cacheManager(RedisTemplate redisTemplate) {
      		RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
      		return redisCacheManager;
      	}
      }
    
  • SpringBoot2.0 Redis配置類如下(普遍使用了build模式),

      @Configuration
      @EnableCaching
      public class RedisConfig extends CachingConfigurerSupport {
      	@Bean
      	public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
      		RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).build();
      		return redisCacheManager;
      	}
    
      	@Bean
      	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
      		RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
      		redisTemplate.setConnectionFactory(redisConnectionFactory);
      		// key序列化
      		redisTemplate.setKeySerializer(new StringRedisSerializer());
      		// value序列化
      		redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class));  
      		redisTemplate.afterPropertiesSet();
      		return redisTemplate;
      	}
      }
    

    緩存管理器

    • RedisCacheManager
    • SimpleCacheManager
    • NoOpCacheManager
    • ConcurrentMapCacheManager
    • CompositeCacheManager
    • EhCacheCacheManager

    序列化器

    • GenericToStringSerializer:使用Spring轉換服務進行序列化;
    • JacksonJsonRedisSerializer:使用Jackson 1,將對象序列化為JSON;
    • Jackson2JsonRedisSerializer:使用Jackson 2,將對象序列化為JSON;
    • JdkSerializationRedisSerializer:使用Java序列化;
    • OxmSerializer:使用Spring O/X映射的編排器和解排器(marshaler和unmarshaler)實現序列化,用於XML序列化;
    • StringRedisSerializer:序列化String類型的key和value。

redis使用

  • 自動根據方法生成緩存

    訪問/api/user/{id}接口,會將結果緩存。代碼如下:

      @RestController
      @RequestMapping(value = "/api")
      public class StudentController {
    
      	@Autowired
      	OmsUserRepository omsUserRepository;
    
      	@GetMapping(value = "/user")
      	public List<OmsUser> getAllUser() {
      		return this.omsUserRepository.findAll();
      	}
    
      	@GetMapping(value = "/user/{id}")
      	@Cacheable(value = "user-key")
      	public OmsUser getUserById(@PathVariable("id") String id) {
      		return omsUserRepository.findById(id).get();
      	}
      }
    
    • @Cacheable

      表明spring在調用方法之前,首先應該在緩存中查找方法的返回值。如果這個值能夠找到,就會返回緩存的值。否則的話,這個方法就會被調用,返回值會放到緩存之中。

    • @CachePut

      表明spring應該將方法的返回值放到緩存中。在方法的調用前不會檢查緩存,方法始終都會被調用。

    • @CacheEvict

      表明spring應該在緩存中清除一個或多個條目

    • @Caching

      這是一個分組的注解,能夠同時應用多個其它的緩存注解。

    自定義key

    @Cacheable@CachePut都有一個名為key屬性,可使用spel表達式獲取值。

    • #root.args:傳遞給緩存方法的參數,形式為數組
    • #root.caches:該方法執行時所對應的緩存,形式為數組
    • #root.target:目標對象
    • #root.targetClass:目標對象的類,等同#root.target.class
    • #root.method:緩存方法
    • #root.methodName:緩存方法的名字,等同root.method.name
    • #result:方法調用的返回值,不能用在@Cacheable注解上
    • #Argument:任意的方法參數名(如#argName)或參數索引(如#a0#p0)

    條件化緩存

    @Cacheable@CachePut提供了兩個屬性用以實現條件化緩存:unlesscondition,這兩個屬性都接受一個SpEL表達式。

    • unless

      僅阻止將對象放進緩存,在這個方法被調用的時候,依然會去緩存中進行查找,如果找到了匹配的值,就會返回找到的值。

    • condition

      如果表達式計算結果為false,那么在這個方法調用的過程中,緩存是被禁用的。即在這個方法被調用的時候,不會去緩存進行查找,同時返回值也不會放進緩存中。

  • 使用 Template(模版)

    模版種類:

    • StringRedisTemplate
    • RedisTemplate

    測試代碼:

      @RunWith(SpringRunner.class)
      @SpringBootTest
      public class TestRedis {
    
      	@Autowired
      	private StringRedisTemplate stringRedisTemplate;
    
      	@Autowired
      	private RedisTemplate redisTemplate;
    
      	@Test
      	public void test() throws Exception {
      		// set
      		stringRedisTemplate.opsForValue().set("key", "value");
      		// get
      		String value = stringRedisTemplate.opsForValue().get("key");
      		Assert.assertEquals("value", value);
      	}
    
      	@Test
      	public void testObj() throws Exception {
      		User user = new User("king", "boy", 18);
      		ValueOperations<String, User> operations = redisTemplate.opsForValue();
      		// set
      		operations.set("obj.user.key", user);
      		// get
      		User user2 = operations.get("obj.user.key");
      		Assert.assertEquals(user.getName(), user2.getName());
      		Assert.assertEquals(user.getSex(), user2.getSex());
      		Assert.assertEquals(user.getAge(), user2.getAge());
      	}
      }
    

    測試代碼中User user2 = operations.get("obj.user.key")會報錯java.util.LinkedHashMap cannot be cast to User。修改redis配置類,如下:

      @Configuration
      @EnableCaching
      public class RedisConfig extends CachingConfigurerSupport {
    
      	@Bean
      	public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
      		RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).build();
      		return redisCacheManager;
      	}
    
      	@Bean
      	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
      		RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
      		redisTemplate.setConnectionFactory(redisConnectionFactory);
      		// key序列化
      		redisTemplate.setKeySerializer(new StringRedisSerializer());
      		// value序列化
      		// 使用Jackson ,將對象序列化為JSON
      		Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
      		
      		//json 轉對象類,不設置默認的會將json轉成hashmap
      		ObjectMapper om = new ObjectMapper();
      		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
      		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
      		jackson2JsonRedisSerializer.setObjectMapper(om);
    
      		redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
      		redisTemplate.afterPropertiesSet();
      		return redisTemplate;
      	}
      }
    
  • 共享 session

    • 添加依賴

        <dependency>
        	<groupId>org.springframework.session</groupId>
        	<artifactId>spring-session-data-redis</artifactId>
        </dependency>
      
    • session配置

        @Configuration
        @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
        public class SessionConfig {
        }
      
    • 測試

        @RequestMapping("/uid")
        String uid(HttpSession session) {
        	UUID uid = (UUID) session.getAttribute("uid");
        	if (uid == null) {
       			uid = UUID.randomUUID();
        	}
        	session.setAttribute("uid", uid);
        	return session.getId();
        }
      

      第一次訪問后生成session,第二次及以后訪問獲取到session值相同。redis存儲session形式如下圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM