SpringBoot之优雅地使用Redis

1,432 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

前言

ok,通过咱们一段时间的努力,咱们终于把大部分的前端做好了,但是这还没有完毕,因为咱们的后端才开始真正复杂的业务,其实纵观咱们的整个的WhiteHole项目,其实它的业务逻辑并不是很复杂,其实业务的难度顶多和xx商城的难度类似,只是说咱们的中间将调用到一些第三方服务。本质上来说,他其实还是一个curd 的项目,只是说它可能使用到的第三方组件,中间键比较多。然后里面的聊天好友功能可能是和单纯的CURD有了那么一点点区别。之后的话是我们的一些推荐算法,当前版本的话,还是一个大体的架构版本,个性推荐算法是暂时没有的,但是做咱们是一定要做的,毕竟咱们不能只做一个CURD程序员。还是要做算法的,而且说实话作为一个pythoner兼修Java,不在自己的项目里面放点python的东西真说不过去,做web python确实和Java差一点,那么咱们就用这个做算法。在完成我们主要的第一阶段开发之后,咱们的第二阶段就是上算法,一个个性推介算法,这个可能还是打算用最简单的KNN来做,之后是聊天+检索机器人,也就是咱们主页的那个小姐姐,不过这个功能主要是给PC端用的,移动端还是得等等,但愿小叶,毕业的时候可以做出来吧,还有1年左右吧。

那么今天要做的就是使用SpringBoot去整合咱们的Redis.

然后咱们做的主要就是两点。 1.导入redis依赖,并且将对象以json格式去报错至redis服务器当中。 2.对咱们的这个redistemplete进行简单封装,方便使用,这个封装的话,咱们其实还有对于Http的封装,主要是用来做Auto的,这个咱们明天再说。当然不保证更新哈,最近忙着练车+论文(大二暑假欠下的债)。

导入依赖

这个老规矩了。首先是导入咱们的依赖。

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

之后是配置

spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=123456

配置对象Json序列化

这个其实很重要的,虽然Java自己也可以序列号,但是这个是二进制字节码啥的,反之很不优化,而且还大,这个咱们先前在使用rabbitmq的时候也是要进行json序列化的,不用Java自带的那套的。用的也是阿里的fastjson

不过这里要导入的依赖稍微多一点。

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.0</version>
        </dependency>
 
        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.74</version>
        </dependency>

之后是配置类:

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfiguration {

    /**
     * 采用FastJson进行key/value序列化
     *
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        final RedisTemplate<String, Object> template = new RedisTemplate<>();
        final FastJsonRedisSerializer<?> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setEnableTransactionSupport(true);
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

封装

RedisTelempent封装

咱们使用的话,一般直接使用那个RedisTelempent 。但是比较麻烦,所以这里有个封装,可以拿过来用。

@Component
public class RedisUtils {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    public boolean expire(String key, long time) {
        if (time > 0) {
            redisTemplate.expire(key, time, TimeUnit.SECONDS);
            return true;
        } else {
            throw new RuntimeException("超时时间小于0");
        }
    }

    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

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

    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

// ============================String=============================

    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    public boolean set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
        return true;
    }

    public boolean set(String key, Object value, long time) {
        if (time > 0) {
            redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
        } else {
            this.set(key, value);
        }
        return true;
    }

    public boolean set(String key, Object value, long time,TimeUnit tiemtype) {
        if (time > 0) {
            redisTemplate.opsForValue().set(key, value, time, tiemtype);
        } else {
            this.set(key, value);
        }
        return true;
    }

    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

// ================================Map=================================
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }


    public boolean hmset(String key, Map<String, Object> map) {
        redisTemplate.opsForHash().putAll(key, map);
        return true;
    }

    public boolean hmset(String key, Map<String, Object> map, long time) {
        redisTemplate.opsForHash().putAll(key, map);
        if (time > 0) {
            expire(key, time);
        }
        return true;
    }

    public boolean hset(String key, String item, Object value) {
        redisTemplate.opsForHash().put(key, item, value);
        return true;
    }

    public boolean hset(String key, String item, Object value, long time) {
        redisTemplate.opsForHash().put(key, item, value);
        if (time > 0) {
            expire(key, time);
        }
        return true;
    }

    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }
    // ============================set=============================

    public Set<Object> sGet(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    public boolean sHasKey(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    public long sSet(String key, Object... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    public long sSetAndTime(String key, long time, Object... values) {
        final Long count = redisTemplate.opsForSet().add(key, values);
        if (time > 0)
            expire(key, time);
        return count;
    }

    public long sGetSetSize(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    public long setRemove(String key, Object... values) {
        final Long count = redisTemplate.opsForSet().remove(key, values);
        return count;
    }
    // ===============================list=================================
    public List<Object> lGet(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    public long lGetListSize(String key) {
        return redisTemplate.opsForList().size(key);
    }
    public Object lGetIndex(String key, long index) {
        return redisTemplate.opsForList().index(key, index);
    }
    public boolean lSet(String key, Object value) {
        redisTemplate.opsForList().rightPush(key, value);
        return true;
    }

    public boolean lSet(String key, Object value, long time) {
        redisTemplate.opsForList().rightPush(key, value);
        if (time > 0) {
            expire(key, time);
        }
        return true;
    }

    public boolean lSetList(String key, List<Object> value) {
        redisTemplate.opsForList().rightPushAll(key, value);
        return true;
    }

    public boolean lSetList(String key, List<Object> value, long time) {
        redisTemplate.opsForList().rightPushAll(key, value);
        if (time > 0) {
            expire(key, time);
        }
        return true;
    }

    public boolean lUpdateIndex(String key, long index, Object value) {
        redisTemplate.opsForList().set(key, index, value);
        return true;
    }

}

不用管那么多,我知道对你们有用的就4个方法

get(key)
set(key,object)
set(key,object,Secends)
set(key,object,time,timeType)自己设定时间的类型,是秒还是啥
del(key,...)

其他的东西我相信,你们都是直接封装一个对象的,然转json转object让操作。

FastJson封装

之后的话还有对这个FastJson的封装。


/**

 * FastJson工具类
 * 支持Object --> JSON(String)
 * 也支持 JSON(String) --> Object
 * 支持集合和JSON的变化
 * 支持自定义日期转化格式等
 * 这是一个静态的工具类
 */
public class FastJsonUtils {

    private static final SerializeConfig config;
    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    static {
        config = new SerializeConfig();
        // 使用和json-lib兼容的日期输出格式
        config.put(java.util.Date.class, new JSONLibDataFormatSerializer());
        // 使用和json-lib兼容的日期输出格式
        config.put(java.sql.Date.class, new JSONLibDataFormatSerializer());
        config.put(java.sql.Timestamp.class, new JSONLibDataFormatSerializer());
    }

    private static final SerializerFeature[] features = {
      
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullListAsEmpty,
            SerializerFeature.WriteNullNumberAsZero,
            SerializerFeature.WriteNullBooleanAsFalse,
            SerializerFeature.WriteNullStringAsEmpty
    };

    /**
     * 将json转换成字符串(带序列化Feature)
     * 
     * 输出空置字段
     *
     * list字段如果为null,输出为[],而不是null
     * 
     * 数值字段如果为null,输出为0,而不是null
     * 
     * Boolean字段如果为null,输出为false,而不是null
     * 
     * 字符类型字段如果为null,输出为"",而不是null
     * 
     * @param object
     * @return
     */
    public static String toJsonWithFeatures(Object object) {
        return JSON.toJSONString(object, config, features);
    }

    /**
     * 经json转换成字符串,按实际情况
     *
     * @param object
     * @return
     */
    public static String toJson(Object object) {
        if (object == null) {
            return null;
        }
        return JSON.toJSONString(object, config);
    }

    /**
     * 将json转成object
     *
     * @param json
     * @return
     */
    public static Object fromJson(String json) {
        return JSON.parse(json);
    }

    /**
     * 将json转成对应的对象
     *
     * @param json
     * @param clazz
     * @return
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz);
    }

    /**
     * 按类型转化
     *
     * @param json
     * @param type 例: new TypeReference<Map<String, Object>>() {}
     * @return
     */
    public static <T> T fromJson(String json, TypeReference<T> type) {
        return JSON.parseObject(json, type.getType());
    }

    /**
     * 将json转成数组
     *
     * @param json
     * @return
     */
    public static <T> Object[] toArray(String json) {
        return toArray(json, null);
    }

    /**
     * 转换为数组
     *
     * @param json
     * @param clazz
     * @return
     */
    public static <T> Object[] toArray(String json, Class<T> clazz) {
        return JSON.parseArray(json, clazz).toArray();
    }

    /**
     * 转换为List
     *
     * @param json
     * @param clazz
     * @return
     */
    public static <T> List<T> toList(String json, Class<T> clazz) {
        return JSON.parseArray(json, clazz);
    }

    /**
     * 将javabean转化为序列化的json字符串
     *
     * @param keyvalue
     * @return
     */
    public static Object beanToJson(Object keyvalue) {
        String textJson = JSON.toJSONString(keyvalue);
        Object objectJson = JSON.parse(textJson);
        return objectJson;
    }

    /**
     * 将string转化为序列化的json字符串
     *
     * @param json
     * @return
     */
    public static Object textToJson(String json) {
        Object objectJson = JSON.parse(json);
        return objectJson;
    }

    /**
     * json字符串转化为map
     *
     * @param json
     * @return
     */
    public static Map<String, Object> stringToCollect(String json) {
        return JSONObject.parseObject(json);
    }

    /**
     * 指定时间格式 的json转换
     *
     * @param object
     * @param dateFormat
     * @return
     */
    public static String toJSONStringWithDateFormat(Object object, String dateFormat) {

        return JSON.toJSONStringWithDateFormat(object, dateFormat);
    }

    /**
     * 默认时间格式 的json转换
     *
     * @param object
     * @return
     */
    public static String toJSONStringWithDefaultDateFormat(Object object) {

        return JSON.toJSONStringWithDateFormat(object, DEFAULT_DATE_FORMAT);
    }
}

测试

这里有一个测试的pojo类

@Data
@ToString
public class User {
    private String name;
    private int age;
    private double height;
}

    @Test
    public void redisSave(){
        User user = new User();
        user.setAge(18);
        user.setHeight(17.5);
        user.setName("s");
        boolean huterox = redisUtils.set("huterox", user,100, TimeUnit.SECONDS);
        System.out.println("存储成功");
    }

在这里插入图片描述

总结

这个就是咱们对于redis的一个简单操作,后面咱们很多骚操作都要用这个来实现。