欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Springboot整合(8)——Redis

程序员文章站 2022-03-01 20:34:51
...

Springboot整合(8)——Redis

0. 搭建redis环境,可参考我之前的文章:用docker搭建redis

1. pom中增加redis依赖

        <!-- redis -->

        <dependency>

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

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

        </dependency>

2. application.ymlspring的节点下(跟datasource同一层)增加redis配置

  #Redis配置

  redis:

    database: 0

    host: 192.168.59.103

    port: 6379

    pool:

      max-idle: 8

      min-idle: 0

      max-active: 8

      max-wait: -1

3. 编写redis序列化对象类

import org.springframework.core.convert.converter.Converter;

import org.springframework.core.serializer.support.DeserializingConverter;

import org.springframework.core.serializer.support.SerializingConverter;

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

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

 

/**

 * redis序列化对象

 */

publicclass RedisObjectSerializer implements RedisSerializer<Object> {

    private Converter<Object, byte[]> serializer = new SerializingConverter();

    private Converter<byte[], Object> deserializer = new DeserializingConverter();

    staticfinalbyte[] EMPTY_ARRAY = newbyte[0];

 

    public Object deserialize(byte[] bytes) {

        if (isEmpty(bytes)) {

            returnnull;

        }

        try {

            returndeserializer.convert(bytes);

        } catch (Exception ex) {

            thrownew SerializationException("Cannot deserialize", ex);

        }

    }

 

    publicbyte[] serialize(Object object) {

        if (object == null) {

            returnEMPTY_ARRAY;

        }

        try {

            returnserializer.convert(object);

        } catch (Exception ex) {

            returnEMPTY_ARRAY;

        }

    }

 

    privateboolean isEmpty(byte[] data) {

        return (data == null || data.length == 0);

    }

}

 

4. 编写redis配置类RedisCacheConfig

/**

 * Redis缓存配置类

 */

@Configuration

@EnableCaching

publicclass RedisCacheConfig extends CachingConfigurerSupport {

 

    // 自定义缓存key生成策略

    @Bean

    public KeyGenerator keyGenerator() {

        returnnew KeyGenerator() {

            @Override

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

                StringBuffer sb = new StringBuffer();

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

                sb.append(method.getName());

                for (Object obj : params) {

                    if (obj == null) {

                        continue;

                    }

                    sb.append(obj.toString());

                }

                returnsb.toString();

            }

        };

    }

 

    // 缓存管理器

    @Bean

    public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {

        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);

        // 设置缓存过期时间

        cacheManager.setDefaultExpiration(1800);

        returncacheManager;

    }

 

    @Bean

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

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

        template.setConnectionFactory(factory);

        template.setKeySerializer(new StringRedisSerializer());

        template.setValueSerializer(new RedisObjectSerializer ());

        returntemplate;

    }

 

}

 

5. 使用缓存有2种方法,一种是直接在Controller里使用注解的方式,另一种是自已手动读取写入缓存,前者更加方便,后者更加灵活,根据实际需求选择具体使用哪种,下面将2中方法分别说明

5.1 Controller中使用注解方式使用缓存

@Cacheable 从缓存读取数据

@CacheEvict 清除缓存

示例:

Springboot整合(8)——Redis
            
    
    博客分类: 框架整合
访问http://localhost:8088/KnowledgeIsland/user/cacheList,首次后台会打印sql,再次访问就不会打印sql,从redis里读取

进入http://localhost:8088/KnowledgeIsland/user/add,添加一个user,查看redis,会看到redisuser的缓存已经被清除,再次访问http://localhost:8088/KnowledgeIsland/user/cacheList,又会去数据库查询

 

5.2 自己编码实现读取写入缓存

编写操作缓存的工具类

/**

 * Cache工具类

 */

publicclass CacheUtil {

 

    privatestatic Logger logger = LoggerFactory.getLogger(CacheUtil.class);

    privatestatic CacheManager cacheManager = SpringUtil.getBean(CacheManager.class);

    //是否开启缓存

    privatestaticbooleanenableCache = true;

 

    /**

     * 获取缓存

     *

     * @param cacheName

     * @param key

     * @return

     */

    publicstatic Object get(String cacheName, String key) {

        if (!enableCache) {

            returnnull;

        }

        ValueWrapper valueWrapper = getCache(cacheName).get(key);

        if (valueWrapper == null) {

            returnnull;

        }

        return getCache(cacheName).get(key).get();

    }

 

    /**

     * 获取缓存

     *

     * @param cacheName

     * @param key

     * @param defaultValue

     * @return

     */

    publicstatic Object get(String cacheName, String key, Object defaultValue) {

        if (!enableCache) {

            returndefaultValue;

        }

        Object value = get(cacheName, key);

        returnvalue != null ? value : defaultValue;

    }

 

    /**

     * 写入缓存

     *

     * @param cacheName

     * @param key

     * @param value

     */

    publicstaticvoid put(String cacheName, String key, Object value) {

        if (!enableCache) {

            return;

        }

        getCache(cacheName).put(key, value);

    }

 

    /**

     * 从缓存中移除

     *

     * @param cacheName

     * @param key

     */

    publicstaticvoid remove(String cacheName, String key) {

        if (!enableCache) {

            return;

        }

        getCache(cacheName).evict(key);

    }

 

    /**

     * 从缓存中移除所有

     *

     * @param cacheName

     */

    publicstaticvoid removeAll(String cacheName) {

        if (!enableCache) {

            return;

        }

        getCache(cacheName).clear();

        logger.info("清理缓存: {} => {}", cacheName);

    }

 

    /**

     * 获得一个Cache,没有则显示日志。

     *

     * @param cacheName

     * @return

     */

    privatestatic Cache getCache(String cacheName) {

        Cache cache = cacheManager.getCache(cacheName);

        if (cache == null) {

            thrownew RuntimeException("当前系统中没有定义“" + cacheName + "”这个缓存。");

        }

        returncache;

    }

 

}

 

注:该类引用了一个SpringUtil类,该类的作用是可以让那些没有注册为spring component的普通类调用spring bean,代码如下:

import org.springframework.beans.BeansException;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.stereotype.Component;

 

/**

 * 普通类调用Spring bean对象:说明: 1、此类需要放到App.java同包或者子包下才能被扫描,否则失效。

*/

@Component

publicclass SpringUtil implements ApplicationContextAware {

    privatestatic ApplicationContext applicationContext = null;

 

    @Override

    publicvoid setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        if (SpringUtil.applicationContext == null) {

            SpringUtil.applicationContext = applicationContext;

        }

        System.out.println("---------------------------------------------------------------------");

        System.out.println("---------------------------------------------------------------------");

        System.out.println(

                "---------------com.kfit.base.util.SpringUtil------------------------------------------------------");

        System.out.println(

                "========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext="

                        + SpringUtil.applicationContext + "========");

        System.out.println("---------------------------------------------------------------------");

    }

 

    // 获取applicationContext

    publicstatic ApplicationContext getApplicationContext() {

        returnapplicationContext;

    }

 

    // 通过name获取 Bean.

    publicstatic Object getBean(String name) {

        return getApplicationContext().getBean(name);

    }

 

    // 通过class获取Bean.

    publicstatic <T> T getBean(Class<T> clazz) {

        return getApplicationContext().getBean(clazz);

    }

 

    // 通过name,以及Clazz返回指定的Bean

    publicstatic <T> T getBean(String name, Class<T> clazz) {

        return getApplicationContext().getBean(name, clazz);

    }

}

 

调用工具类操作缓存,操作逻辑可放在任何地方,本文示例放在UserService里。putremoveclear,完全*控制(本处只示例getput

 

controller层调用代码不变

Springboot整合(8)——Redis
            
    
    博客分类: 框架整合
③访问http://localhost:8088/KnowledgeIsland/user/list测试

6. 特别注意的地方,所有放入redis的对象,需要实现Serializable接口。将对象类型数据放入redis,本文采用的方法是将对象序列化之后放入。另一种方法是,将对象全部转为json字符串,然后再放入,拿出来的时候再转回来。

  • Springboot整合(8)——Redis
            
    
    博客分类: 框架整合
  • 大小: 17.9 KB
  • Springboot整合(8)——Redis
            
    
    博客分类: 框架整合
  • 大小: 18.1 KB
  • Springboot整合(8)——Redis
            
    
    博客分类: 框架整合
  • 大小: 10.6 KB