【redis】springboot2.0集成Redis使用发布订阅机制实现对超时的订单进行过期处理

一、集成redis及配置订阅代码

1.redis参数配置

2.redis配置类 

package com.esgcc.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * 类 名: RedisConfig
 * 描 述: 
 * 作 者: 
 * 创 建: 2020/5/26 11:36
 * 邮 箱: 
 */

@Slf4j
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {

    /**
     * 配置自定义redisTemplate
     *
     * @return
     */
    @Bean
    RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

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

        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);

        template.setValueSerializer(serializer);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }

}

3.redis工具类 

package com.esgcc.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis 工具类
 *
 * @author djk
 */
@Slf4j
@Service
public class RedisService {

    private RedisTemplate<String, ?> redisTemplate;

    public RedisTemplate<String, ?> getRedisTemplate() {
        return redisTemplate;
    }

    @Resource(name = "redisTemplate")
    public void setRedisTemplate(RedisTemplate<String, ?> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 根据key删除缓存
     *
     * @param key
     * @return
     */
    public void delete(final String key) {
        try {
            redisTemplate.delete(key);
        } catch (Exception e) {
            log.error("Delete cache fail and key : " + key);
        }
    }

    /**
     * 保存数据到redis中
     */
    public boolean put(final String key, final Serializable value) {
        try {
            return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
                connection.set(redisTemplate.getStringSerializer().serialize(key),
                        new JdkSerializationRedisSerializer().serialize(value));
                return true;
            });
        } catch (Exception e) {
            log.error("Put value to redis fail...", e);
        }

        return false;
    }

    /**
     * 保存字符串到redis中
     */
    public boolean setString(final String key, final String value) {
        try {
            return redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {
                redisConnection.set(redisTemplate.getStringSerializer().serialize(key),
                        redisTemplate.getStringSerializer().serialize(value));
                return true;
            });
        } catch (Exception e) {
            log.error("putString value to redis fail...", e);
        }

        return false;
    }

    public boolean hset(final String key, final String field, final String value) {
        try {
            return redisTemplate.execute((RedisCallback<Boolean>) redisConnection ->
                    redisConnection.hSet(redisTemplate.getStringSerializer().serialize(key),
                            redisTemplate.getStringSerializer().serialize(field),
                            redisTemplate.getStringSerializer().serialize(value)));
        } catch (Exception e) {
            log.error("hset value to redis fail...", e);
        }

        return false;
    }

    public String hget(final String key, final String field) {
        try {
            return redisTemplate.execute((RedisCallback<String>) redisConnection -> {
                byte[] bytes = redisConnection.hGet(redisTemplate.getStringSerializer().serialize(key),
                        redisTemplate.getStringSerializer().serialize(field));
                return null != bytes ? redisTemplate.getStringSerializer().deserialize(bytes) : null;
            });
        } catch (Exception e) {
            log.error("hget value from redis fail...", e);
        }

        return null;
    }

    /**
     * 从redis 中查询数据
     */
    public Object get(final String key) {
        try {
            return redisTemplate.execute((RedisCallback<Object>) connection ->
                    new JdkSerializationRedisSerializer()
                            .deserialize(connection.get(redisTemplate.getStringSerializer().serialize(key))));
        } catch (Exception e) {
            log.error("Get value from  redis fail...", e);
        }
        return null;
    }

    /**
     * 从redis 中查询字符串对象
     */
    public String getString(final String key) {
        try {
            return redisTemplate.execute((RedisCallback<String>) connection -> {
                byte[] bytes = connection.get(redisTemplate.getStringSerializer().serialize(key));
                return null != bytes ? redisTemplate.getStringSerializer().deserialize(bytes) : null;
            });
        } catch (Exception e) {
            log.error("getString value from  redis fail...", e);
        }
        return null;
    }


    public boolean hasKey(final String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 以毫秒为单位设置key的超时时间
     *
     * @param key        key
     * @param expireTime 超时时间
     * @return boolean
     */
    public boolean expireByMilliseconds(String key, Long expireTime) {
        return redisTemplate.expire(key, expireTime, TimeUnit.MILLISECONDS);
    }

    /**
     * 以分钟为单位设置key的超时时间
     *
     * @param key        key
     * @param expireTime 超时时间
     * @return boolean
     */
    public boolean expireByMinutes(String key, Long expireTime){
        return redisTemplate.expire(key, expireTime, TimeUnit.MINUTES);
    }

    /**
     * 对存储在指定key的数值执行原子的加1操作
     *
     * @param key key
     * @return
     */
    public Long incrKey(String key) {
        return redisTemplate.execute((RedisCallback<Long>) connection ->
                connection.incr(redisTemplate.getStringSerializer().serialize(key))
        );
    }

    /**
     * 检测set集合中ke是否存在{@code value}
     *
     * @param key   键
     * @param value 元素
     */
    public boolean isMember(String key, String value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 在set中添加元素
     *
     * @param key    键
     * @param values 值
     */
    public Long sadd(String key, String... values) {
        SetOperations<String, Object> set = (SetOperations<String, Object>) redisTemplate.opsForSet();
        return set.add(key, values);
    }

    /**
     * 在set中移除元素
     *
     * @param key    键
     * @param values 值
     */
    public Long srem(String key, String... values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 获得set数据量
     *
     * @param key 键
     * @return size
     */
    public Long scard(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 扫描出满足条件的key
     *
     * @param pattern 表达式
     * @return keys
     */
    public List<String> scan(String pattern) {
        try {
            Set<String> execute = redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
                Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(pattern).count(10000).build());
                Set<String> binaryKeys = new HashSet<>();
                while (cursor.hasNext()) {
                    binaryKeys.add(new String(cursor.next()));
                }
                return binaryKeys;
            });
            return new ArrayList<>(execute);
        } catch (Exception e) {
            log.info("scan", e);
            return new ArrayList<>(0);
        }
    }

    /**
     * 根据key的集合获取values
     *
     * @param set key数组
     * @return value数组(顺序与key数组一致)
     */
    public List<String> multiGetString(List<String> set) {
        List<String> result = new ArrayList<>();
        set.forEach(s -> result.add(this.getString(s)));
        return result;
    }

    /**
     *@Description TODO 接受监听到的消息
     *@Param
     * @param redis消息key值
     *@Return
     *@Author 
     *@Date 15:05 2020/5/25
     */
    public void receiveMessage(String message) {

        log.info("接收redis通道消息:"+message);
        //业务逻辑调用区域
    }

}

4.监听器及执行方法

/**
     *@Description TODO 初始化监听器
     *@Param
     * @param
     *@Return
     *@Author 
     *@Date 15:13 2020/5/25
     */
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory,
                                            MessageListenerAdapter listenerAdapter,@Value("${spring.redis.listenerDatabase}") String dataBase) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        //配置监听通道
        container.addMessageListener(listenerAdapter,new PatternTopic("__keyevent@"+ dataBase +"__:expired"));// 通道的名字
        return container;
    }

    /**
     *@Description TODO 利用反射来创建监听到消息之后的执行方法
     *@Param
     * @param
     *@Return
     *@Author 
     *@Date 15:22 2020/5/25
     */
    @Bean
    MessageListenerAdapter listenerAdapter(RedisService receiver) {
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

二、配置redis开启过期通知

redis开启过期键通知
找到redis配置文件redis.conf,打开配置文件找到
notify-keyspace-events配置查看是否开启,默认是没有开启的,添加配置
notify-keyspace-events Ex

猜你喜欢

转载自blog.csdn.net/xiaren_1988/article/details/106279857