SpringBoot集成Redis--配置自定義的RedisCacheManager

配置自定義的RedisCacheManager--1自定義鍵生成規則

默認的鍵生成器

當不指定緩存的key時,SpringBoot會使用SimpleKeyGenerator生成key。java

SimpleKeyGenerator

SimpleKey

查看源碼能夠發現,它是使用方法參數組合生成的一個key。web

經過SpEL自定義鍵生成規則

諸以下面紅框的代碼,SpEL實際上能夠寫很是複雜的生成規則。redis

自定義鍵生成器

@Configuration 標註的類中,能夠根據本身設計的規則自定義鍵生成器。spring

自定義鍵生成器代碼

/**

 * 新的鍵生成規則

 */

@Bean 

@Override 

public KeyGenerator keyGenerator() {

return new KeyGenerator(){

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();

}

};

}

代碼分析

上面自定義的鍵生成器鍵的生成規則是:包名+方法名+參數列表。數據庫

配置自定義的RedisCacheManager--2建立RedisTemplate模板時自定義序列化器

RedisTemplate默認提供的序列化器

RedisSerializer redis序列化的接口類apache

OxmSerializer xml到object的序列化/反序列化json

StringRedisSerializer string字符串的序列化/反序列化數組

JacksonJsonRedisSerializer json到object的序列化/反序列化緩存

Jackson2JsonRedisSerializer json到object的序列化/反序列化app

JdkSerializationRedisSerializer java對象的序列化/反序列化

RedisTemplate默認使用的是JdkSerializationRedisSerializer

常見序列化方式的特色

JdkSerializationRedisSerializer:JDK自帶的序列化方式、存儲的字符串內容在序列化的狀況下偏長,會佔用過多的內存

OxmSerializer:序列化的時間相對較長

Jackson2JsonRedisSerializer:json數據格式、序列化時間和序列化以後內容的長度都要優於前兩種

自定義序列化器--使用Jackson2JsonRedisSerializer

代碼

/**

 * RedisTemplate 使用 Jackson2JsonRedisSerializer 做爲序列化器

 * @return

 */

@Bean 

public RedisTemplate<String, String> redisTemplate() {

StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);


Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);

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;

}

Jackson2JsonRedisSerializer的序列化器須要引入Jackson的依賴

<dependency>

      <groupId>com.fasterxml.jackson.core</groupId>

      <artifactId>jackson-databind</artifactId>

      <version>2.6.7</version>

</dependency>

配置自定義的RedisCacheManager--3示例代碼

整體項目結構

POM文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.ding.data</groupId>

<artifactId>RedisCacheCase</artifactId>

<version>0.0.1-SNAPSHOT</version>



<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<boot.version>1.3.5.RELEASE</boot.version>

</properties>


<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

<version>${boot.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<version>${boot.version}</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-cache</artifactId>

<version>${boot.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-redis</artifactId>

<version>${boot.version}</version>

</dependency>

<dependency>

      <groupId>com.fasterxml.jackson.core</groupId>

      <artifactId>jackson-databind</artifactId>

      <version>2.6.7</version>

</dependency>

<!-- <dependency>

<groupId>com.google.guava</groupId>

<artifactId>guava</artifactId>

<version>19.0</version>

</dependency> -->

</dependencies>

</project>

配置文件application.yml

    

spring:

      cache:

        #緩存名稱

        #cache-names: guavaDemo

        #緩存最大數量500條, 緩存失效時間 6個小時

        #guava.spec: maximumSize=500,expireAfterWrite=360m

      # REDIS (RedisProperties)  

      redis :

        host : localhost # server host  

        port : 6379 # connection port  

        password : 123

        database : 1

        pool.max-idle : 8 # pool settings ...  

        pool.min-idle : 1

        pool.max-active : 8  

        pool.max-wait : -1

 

主啓動類

package com.ding.data;


import java.text.SimpleDateFormat;

import java.util.Date;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cache.annotation.EnableCaching;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;


import com.ding.data.cache.DataCache;


/**

 * 是Spring Boot項目的核心註解,主要是開啓自動配置

 */

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan

@RestController

// 開啓緩存

@EnableCaching

public class RedisCacheCase {


@Autowired

private DataCache dataCache;


public static void main(String[] args) {

SpringApplication.run(RedisCacheCase.class, args);

}


@RequestMapping("/put")

public String put(Long id, String value) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

return  sdf.format(new Date()) + " : value is " + dataCache.put(id, value) ;

}


@RequestMapping("/get")

public String query(Long id){

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

return sdf.format(new Date()) + " : value is " +dataCache.query(id) ;

}


@RequestMapping("/remove")

public String remove(Long id) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

dataCache.remove(id) ;

return sdf.format(new Date()) + " : success " ;

}


}

配置類代碼

package com.ding.data.config;

import java.lang.reflect.Method;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cache.CacheManager;

import org.springframework.cache.annotation.CachingConfigurerSupport;

import org.springframework.cache.interceptor.KeyGenerator;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.data.redis.cache.RedisCacheManager;

import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;


import com.fasterxml.jackson.annotation.JsonAutoDetect;

import com.fasterxml.jackson.annotation.PropertyAccessor;

import com.fasterxml.jackson.databind.ObjectMapper;


@Configuration

public class MyRedisCacheConfig extends CachingConfigurerSupport{


@Autowired

private JedisConnectionFactory jedisConnectionFactory;


@Bean

public CacheManager cacheManager() {

RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate());

redisCacheManager.setDefaultExpiration(86400);

return redisCacheManager;

}


/**

 * RedisTemplate 使用 Jackson2JsonRedisSerializer 做爲序列化器

 * @return

 */

@Bean 

public RedisTemplate<String, String> redisTemplate() {

StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);


Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);

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;

}


/**

 * 新的鍵生成規則

 */

@Bean 

@Override 

public KeyGenerator keyGenerator() {

return new KeyGenerator(){

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();

}

};

}

}

業務層代碼

package com.ding.data.cache;


import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;


import javax.annotation.PostConstruct;


import org.springframework.cache.annotation.CacheEvict;

import org.springframework.cache.annotation.CachePut;

import org.springframework.cache.annotation.Cacheable;

import org.springframework.stereotype.Component;


@Component

public class DataCache {


private Map<Long, String> dataMap = new HashMap<Long, String>();


/**

 * 初始化

 */

@PostConstruct

public void init() {

dataMap.put(1L, "張三");

dataMap.put(2L, "李四");

dataMap.put(3L, "王五");

}


/**

 * 查詢

 * 若是數據沒有緩存,那麼從dataMap裏面獲取,若是緩存了,

 * 那麼從redisDemo裏面獲取

 * 而且將緩存的數據存入到 redisDemo裏面

 * 其中key 爲 #id+dataMap

 */

// @Cacheable(value="redisDemo" ,key="#id + 'dataMap'")

@Cacheable(value="redisDemo")

public String query(Long id) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println(sdf.format(new Date()) + " : query id is " + id);

return dataMap.get(id);

}


/**

 * 插入 或者更新

 * 插入或更新數據到dataMap中

 * 而且緩存到 redisDemo中

 * 若是存在了那麼更新緩存中的值

 * 其中key 爲 #id+dataMap

 */

// @CachePut(value="redisDemo" ,key="#id + 'dataMap'")

@CachePut(value="redisDemo")

public String put(Long id, String value) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);

dataMap.put(id, value);

// data persistence

return value;

}


/**

 * 刪除

 * 刪除dataMap裏面的數據

 * 而且刪除緩存redisDemo中的數據

 * 其中key 爲 #id+dataMap

 */

// @CacheEvict(value="redisDemo" , key="#id + 'dataMap'")

@CacheEvict(value="redisDemo")

public void remove(Long id) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println(sdf.format(new Date()) + " : remove id is "+ id + " data");

dataMap.remove(id);

// data remove  

}



}

測試

依次訪問:

http://localhost:8080/get?id=1

http://localhost:8080/get?id=2

http://localhost:8080/put?id=1&value=meixi

http://localhost:8080/put?id=1&value=neimaer

http://localhost:8080/put?id=1&value=cluo

查看Redis內存的內容,以下(由於Redis的database參數用的1,因此用的是Redis中的db1庫)

與代碼的邏輯是相符的,可是出現了新的問題,除了 @Cacheable 註解的方法仍然起到緩存的做用,其餘的緩存方法實際上沒起做用。這主要是由於如今緩存鍵生成的規則不具有重複利用性,實際項目須要根據需求對鍵生成規則進行修改的。

代碼改造一下:使 @CachePut 註解的方法也能起做用

新增一個類MyKeyGenerator

package com.ding.data.config;


import java.lang.reflect.Method;


import org.springframework.cache.interceptor.KeyGenerator;

import org.springframework.stereotype.Component;


@Component

public class MyKeyGenerator implements KeyGenerator{


public Object generate(Object target, Method method, Object... params) {

StringBuilder sb = new StringBuilder();

sb.append(target.getClass().getName());

sb.append("::" + "query" + ":" + params[0].toString());

return sb.toString();

    }

}

DataCache類中 @CachePut 標註的方法改造以下

/**

 * 插入 或者更新

 * 插入或更新數據到dataMap中

 * 而且緩存到 redisDemo中

 * 若是存在了那麼更新緩存中的值

 * 其中key 爲 #id+dataMap

 */

// @CachePut(value="redisDemo" ,key="#id + 'dataMap'")

@CachePut(value="redisDemo",keyGenerator="myKeyGenerator")

public String put(Long id, String value) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);

dataMap.put(id, value);

// data persistence

return value;

}

keyGenerator="myKeyGenerator"啥意思

意思就是說明這個方法的鍵生成規則採用myKeyGenerator這個類

再次測試(先將剛纔測試的數據都清空)

依次訪問:

http://localhost:8080/get?id=1

http://localhost:8080/put?id=1&value=meixi

查看Redis數據庫中的數據

可見改造後@CachePut 標註的方法也起做用了。

可是如今代碼仍然太「死性」,沒法應用於實際項目。要想應用於實際項目,還須要根據具體需求進行設計。

相關文章
相關標籤/搜索