java中Redis的使用

准备工作

1、导入依赖

        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>5.3.6.RELEASE</version>
        </dependency>

2、创建一个Redis连接对象工具类

对连接对象进行封装,

public class RedisUtils {

    /**
     * redis的连接对象
     */
    private static StatefulRedisConnection connection;

    /**
     * 初始化连接对象
     */
    static {
        //初始化连接的uri
        RedisURI redisURI = RedisURI.Builder
                .redis("lettuce")
                .withHost("127.0.0.1")
                .withPort(6379)
                .withPassword("123456")
                .withDatabase(0)
                .withTimeout(Duration.ofSeconds(2))
                .build();
         //初始化连接对象
         //connection = RedisClient.create(redisURI).connect();
         //初始化连接对象并设置自定义序列化器
         connection = RedisClient.create(redisURI)
                 .connect(new ObjectRedisSerializer());
    }

    /**
     * 从连接对象中获取一个命令来操作redis
     * @return
     */
    public static RedisCommands getCommands() {
        //获取一个同步命令
        return connection.sync();
    }
}

3、创建自定义序列化器

public class ObjectRedisSerializer implements RedisCodec<String, Object> {

    /**
     * 这个方法将key从redis取出来的时候转换为字符串类型
     * 将key的字节缓冲(ByteBuffer)转换为String类型
     * @param byteBuffer
     * @return
     */
    @Override
    public String decodeKey(ByteBuffer byteBuffer) {
        //在系统中先分配内存
        ByteBuffer buffer = ByteBuffer.allocate(byteBuffer.capacity());
        buffer.put(byteBuffer);
        //将字节数组以UTF-8的编码转换成String并返回
        return new String(buffer.array(), StandardCharsets.UTF_8);
    }

    /**
     * 从redis中取出的字节数组转换成任意的Object对象
     * @param byteBuffer
     * @return
     */
    @Override
    public Object decodeValue(ByteBuffer byteBuffer) {
        //先分配系统内存空间
        ByteBuffer buffer = ByteBuffer.allocate(byteBuffer.capacity());
        buffer.put(byteBuffer);
        //构建字节数组的输入流,这样就可以在jvm的内存中将这个字节数组
        //反序列为任意的Object对象
        try(ByteArrayInputStream bais =
                    new ByteArrayInputStream(buffer.array());
            //再通过对象输入流将其转换为Object即可
            ObjectInputStream ois = new ObjectInputStream(bais)) {
            return ois.readObject();
        }catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("无法反序列化value", e);
        }
    }

    /**
     * 将字符串的key序列化成字节数组保存到redis
     * @param key
     * @return
     */
    @Override
    public ByteBuffer encodeKey(String key) {
        return ByteBuffer.wrap(key.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 将Object序列化成字节数组保存到redis中
     * @param value
     * @return
     */
    @Override
    public ByteBuffer encodeValue(Object value) {
        try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            //将对象写入流中变成字节数组
            oos.writeObject(value);
            //从流中获取这个字节数组
            byte[] bytes = baos.toByteArray();
            //将字节数组包装成ByteBuffer对象并返回
            return ByteBuffer.wrap(bytes);
        }catch(IOException e) {
            throw new RuntimeException("无法序列化value", e);
        }
    }
}

注意:这个类主要是对java中的实体类进行序列化操作,将实体类转换成json类型存储,需要实现RedisCodec<String, Object> 接口,或者不定义自定义序列化器,可以直接通过ObjectMapper对象进行序列化

4、测试

@Slf4j
public class RedisTest {

    @Test
    public void testLettuce() {
        //获取RedisCommands命令对象
        RedisCommands commands = RedisUtils.getCommands();
        commands.set("user:1001", "wangl");
        String val = (String) commands.get("user:1001");
        log.info("=====> " + val);
        Map<String, Object> map = new HashMap<>();
        map.put("user:1002", "user2");
        map.put("user:1003", "user3");
        commands.mset(map);
        List<KeyValue> list = commands.mget("user:1001",
                "user:1002","user:1003");
        list.forEach(keyValue -> log.info("===>" + keyValue.getValue()));
    }

    @Test
    public void testHash() {
        RedisCommands commands = RedisUtils.getCommands();
        commands.hset("user", "name", "user1");
        commands.hset("user", "age", "21");
        commands.hset("user", "sex", "男");
        log.info("==>" + commands.hget("user", "name"));
        log.info("==>" + commands.hget("user", "age"));
        log.info("==>" + commands.hget("user", "sex"));
    }

    @Test
    public void testDel() {
        RedisCommands commands = RedisUtils.getCommands();
        //删除键
        commands.del("user:1001", "user:1002", "user:1003", "user");
    }

    @Test
    public void testExpire() throws InterruptedException {
        RedisCommands commands = RedisUtils.getCommands();
        //过期时间单位是秒
        commands.setex("user:1001", 2, "user1");
        Thread.sleep(3000);
        log.info("===>" + commands.get("user:1001"));

        commands.set("user:1002", "user2");
        //给已存在的key设置过期时间
        commands.expire("user:1002", 2);
    }

    @Test
    public void testSerialize() throws JsonProcessingException {
        Product p = new Product();
        p.setProductName("iPhone");
        p.setFirm("Apple Inc");
        p.setPlace("China");
        //将实体序列化成JSON字符串
        String productJson = new ObjectMapper().writeValueAsString(p);

        RedisCommands commands = RedisUtils.getCommands();
        commands.set("product:10001", productJson);
        Object json = commands.get("product:10001");
        //将json字符串反序列化为Product对象
        p = new ObjectMapper().readValue(json.toString(), Product.class);
        commands.del("product:10001");
        log.info("===>" + p);
    }
    
    /**
     * 自定义序列化器
     */
    @Test
    public void testSerialize2() {
        Product p = new Product();
        p.setProductName("iPhone");
        p.setFirm("Apple Inc");
        p.setPlace("China");
        RedisCommands commands = RedisUtils.getCommands();
        commands.set("user:1001", p);
        p = ( Product) commands.get("user:1001");
        log.info(p.getProductName());
        log.info(p.getFirm());
        log.info(p.getPlace());
    }
}

基于Spring

创建RedisConfig配置类

@Configuration
public class RedisConfig {

    /**
     * 装配lettuce的redis连接工厂
     * @return
     */
    @Bean
    public RedisConnectionFactory connectionFactory() {
        //创建单机模式的redis配置
        RedisStandaloneConfiguration configuration =
                new RedisStandaloneConfiguration("127.0.0.1", 6379);
        //设置密码
        configuration.setPassword("wangl");
        //选择要访问的数据库
        configuration.setDatabase(0);
        //创建lettuce连接工厂
        return new LettuceConnectionFactory(configuration);
    }

    /**
     * 装配String类型的RedisTemplate,用于操作redis数据库,
     * 这个template只能用于操作key和value都是String类型的数据
     * @return
     */
    /*@Bean
    public RedisTemplate<String, String> stringRedisTemplate() {
        //创建StringRedisTemplate并注入连接工厂
        return new StringRedisTemplate(connectionFactory());
    }*/

    /**
     * 装配自定义的RedisTemplate,通过使用不同的序列化器
     * 来定制序列化key和value的数据类型
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate();
        //使用StringRedisSerializer来序列化和反序列化key
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //使用Jackson序列化器来序列化和反序列value
        template.setValueSerializer(RedisSerializer.json());
        template.setHashValueSerializer(RedisSerializer.json());
        //注入RedisConnectionFactory
        template.setConnectionFactory(connectionFactory());
        return template;
    }
}

注意:这里需要在容器中装配一个连接对象工厂,需要设置账号密码和主机地址,然后装配RedisTemplate,这里面需要配置好序列化设置,RedisTemplate会对实体类类型进行转成json型。

测试

    @Test
    public void testRedisTemplate() {
        User user = new User("user1", 21);
        RedisTemplate<String, Object> template = getApplicationContext()
                .getBean(RedisTemplate.class);
        template.opsForValue().set("user:1001", user);
        User u = (User) template.opsForValue().get("user:1001");
        log.info(u.getUserName());
        log.info(String.valueOf(u.getAge()));
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值