SpringBoot 如何实现自定义Redis序列化

目录
  • 问题
  • 环境
  • 入口点
  • 实现自定义序列化
  • 小结

问题

在使用RedisTemplate存储对象时,如果采用JDK默认的序列化方式,数据会出现许多编码字符,辨析度不高。比如一个空的User对象,存储到redis后如下:

这些使用JDK默认序列化方式序列化后的数据简直惨不忍睹,在使用命令行查询数据时会很头疼。

如何使数据更容易辨别呢?

一种办法是使用StringRedisTemplate,在存入redis前先将数据处理成字符串格式再存入redis,但这种方式的缺点就是每次存入数据前都要手动对非字符串数据进行处理。

另一种方法就是自定义序列化方式,只需要使用RedisTemplate就能按照自定义的序列化方式存储对象。

这里使用的是第二种方法。

环境

这里使用的SpringBoot2.0.5版本。

依赖信息:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.9.9</version>
    </dependency>
</dependencies>

SpringBoot启动类:

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class);
    }
}

User实体类:

public class User implements Serializable {
    private String username;
    private String password;
    private DateTime birthday;
    public DateTime getBirthday() {
        return birthday;
    }
    public void setBirthday(DateTime birthday) {
        this.birthday = birthday;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

测试类:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void testRedis(){
        User user = new User();
        user.setUsername("charviki");
        user.setPassword("123456");
        redisTemplate.opsForValue().set("user", user);
        User user1 = (User) redisTemplate.opsForValue().get("user");
        System.out.println(user1);
    }
}

入口点

当引入redis启动器时,SpringBoot通过RedisTemplate这个类自动帮我们配置了许多默认参数,包括redis主机,默认序列化方式等。找到RedisAutoConfiguration这个类,这个类中有如下代码:

这里使用了注解@ConditionalOnMissingBean(name = "redisTemplate"),大致意思就是如果Spring容器中没有RedisTemplate这个bean,就会返回一个默认的RedisTemplate(配置信息都在这个类里面)。

到这里就有大致的思路了,要想实现自定义redis序列化,首先定义一个返回类型为RedisTemplate的bean,并将该bean交由Spring容器管理。

实现自定义序列化

定义RedisConfig类,自定义序列化:

@Component
public class RedisConfig {
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 自定义key序列化方式,直接将String字符串直接作为redis中的key
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        // 自定义value序列化方式,序列化成json格式
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }
}

运行测试类,程序报错,错误信息如下:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to cn.charviki.pojo.User

at cn.charviki.test.RedisTest.testRedis(RedisTest.java:33)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
 at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
 at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
 at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
 at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
 at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
 at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
 at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
 at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
 at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

先不管错误信息,先去在redis中查看数据,如下:

也就是说数据存进去了,但是取不出来。

这个时候回去看错误信息:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to cn.charviki.pojo.User

看异常名也可以知道,类转换异常,即从redis中取数据后反序列化异常。

这个异常出现的原因是在序列化的时候我们没有加入类信息,取出来的时候jvm找不到类信息,无法将该json数据转换对应的类。

解决这个问题只需要在对值序列化的时候加入类信息,修改redisTemplate方法如下:

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
    RedisTemplate redisTemplate = new RedisTemplate();
    redisTemplate.setConnectionFactory(redisConnectionFactory);
    // 自定义key序列化方式,直接将String字符串直接作为redis中的key
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    redisTemplate.setKeySerializer(stringRedisSerializer);
    // 自定义value序列化方式,序列化成json格式
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new 					Jackson2JsonRedisSerializer(Object.class);
    //jackson底层的序列化和反序列化使用的是ObjectMapper,我们可以通过ObjectMapper设置序列化信息
    // 设置值的默认类型,即类信息
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    // 添加进序列化中
    jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
    return redisTemplate;
}

再次运行测试类,控制台打印信息如下:

这里我们就实现了将对象使用json的序列化方式,但是这里会出现一个问题,就是当对象中成员变量的数据类型不是JDK中的数据类型时就会出现问题。比如说User类中有一个DateTime类型的birthday变量,这个DateTime是joda-time包下的一个日期类,在上面pom文件中已经引入了依赖。在上面测试类中我们没有为这个变量值赋值,现在让我们修改测试类:

@Test
public void testRedis(){
    User user = new User();
    user.setUsername("charviki");
    user.setPassword("123456");
    // 这里打印出dateTime,方便和redis中对比
    DateTime dateTime = new DateTime();
    System.out.println("dateTime = " + dateTime);
    user.setBirthday(dateTime);
    redisTemplate.opsForValue().set("user",user);
    User user1 = (User) redisTemplate.opsForValue().get("user");
    System.out.println(user1);
}

运行测试类,这个时候程序报错,错误信息如下:

org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unrecognized field "era" (class org.joda.time.DateTime), not marked as ignorable (2 known properties: "chronology", "millis"])
 at [Source: (byte[])"["cn.charviki.pojo.User",{"username":"charviki","password":"123456","birthday":{"era":1,"dayOfMonth":16,"dayOfWeek":3,"dayOfYear":289,"year":2019,"hourOfDay":15,"minuteOfHour":30,"yearOfEra":2019,"yearOfCentury":19,"monthOfYear":10,"weekyear":2019,"centuryOfEra":20,"millisOfDay":55811047,"secondOfDay":55811,"minuteOfDay":930,"weekOfWeekyear":42,"millisOfSecond":47,"secondOfMinute":11,"zone":["org.joda.time.tz.CachedDateTimeZone",{"fixed":false,"uncachedZone":["org.joda.time.tz.DateTimeZoneBuilde"[truncated 439 bytes]; line: 1, column: 88] (through reference chain: cn.charviki.pojo.User["birthday"]->org.joda.time.DateTime["era"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "era" (class org.joda.time.DateTime), not marked as ignorable (2 known properties: "chronology", "millis"])
 at [Source: (byte[])"["cn.charviki.pojo.User",{"username":"charviki","password":"123456","birthday":{"era":1,"dayOfMonth":16,"dayOfWeek":3,"dayOfYear":289,"year":2019,"hourOfDay":15,"minuteOfHour":30,"yearOfEra":2019,"yearOfCentury":19,"monthOfYear":10,"weekyear":2019,"centuryOfEra":20,"millisOfDay":55811047,"secondOfDay":55811,"minuteOfDay":930,"weekOfWeekyear":42,"millisOfSecond":47,"secondOfMinute":11,"zone":["org.joda.time.tz.CachedDateTimeZone",{"fixed":false,"uncachedZone":["org.joda.time.tz.DateTimeZoneBuilde"[truncated 439 bytes]; line: 1, column: 88] (through reference chain: cn.charviki.pojo.User["birthday"]->org.joda.time.DateTime["era"])

at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.deserialize(Jackson2JsonRedisSerializer.java:75)
 at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:334)
 at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:60)
 at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
 at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
 at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95)
 at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:48)
 at cn.charviki.test.RedisTest.testRedis(RedisTest.java:34)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
 at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
 at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
 at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
 at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
 at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
 at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
 at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
 at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
 at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "era" (class org.joda.time.DateTime), not marked as ignorable (2 known properties: "chronology", "millis"])
 at [Source: (byte[])"["cn.charviki.pojo.User",{"username":"charviki","password":"123456","birthday":{"era":1,"dayOfMonth":16,"dayOfWeek":3,"dayOfYear":289,"year":2019,"hourOfDay":15,"minuteOfHour":30,"yearOfEra":2019,"yearOfCentury":19,"monthOfYear":10,"weekyear":2019,"centuryOfEra":20,"millisOfDay":55811047,"secondOfDay":55811,"minuteOfDay":930,"weekOfWeekyear":42,"millisOfSecond":47,"secondOfMinute":11,"zone":["org.joda.time.tz.CachedDateTimeZone",{"fixed":false,"uncachedZone":["org.joda.time.tz.DateTimeZoneBuilde"[truncated 439 bytes]; line: 1, column: 88] (through reference chain: cn.charviki.pojo.User["birthday"]->org.joda.time.DateTime["era"])
 at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:60)
 at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
 at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
 at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1589)
 at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1567)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
 at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
 at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:116)
 at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:71)
 at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712)
 at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
 at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3129)
 at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.deserialize(Jackson2JsonRedisSerializer.java:73)
 ... 37 more

跟前面一样先查看redis中的数据:

查看控制台打印的DataTime数据:

对比控制台数据和redis中的数据,redisTemplate将DataTime使用默认的json序列化后,多了许多字段。

再看报错信息,问题同样出在反序列化上。从报错信息中我们可以看出,在反序列化的时候找不到相应的字段。这里的解决版本是实现针对DataTime类型的序列化和反序列化器,注册到ObjectMapper中,实现对json序列化器的扩展。

先自定义序列化器,这里定义序列化器JodaDateTimeJsonSerializer和反序列化器JodaDateTimeJsonDeserializer,两者都要继承JsonDeserializer并重写父类serialize()或deserialize方法。实现代码如下:

// JodaDateTimeJsonSerializer.java
public class JodaDateTimeJsonSerializer extends JsonSerializer<DateTime> {
    @Override
    public void serialize(DateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // 序列化
        gen.writeString(value.toString("yyyy-MM-dd HH:mm:ss"));
    }
}
// JodaDateTimeJsonDeserializer.java
public class JodaDateTimeJsonDeserializer extends JsonDeserializer<DateTime> {
    @Override
    public DateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String dateString = p.readValueAs(String.class);
        DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
        // 反序列化
        return DateTime.parse(dateString,dateTimeFormatter);
    }
}

将自定义序列化器通过ObjectMapper注册到json序列化器中,修改redisTemplate方法如下:

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
    RedisTemplate redisTemplate = new RedisTemplate();
    redisTemplate.setConnectionFactory(redisConnectionFactory);
    // 自定义key序列化方式,直接将String字符串直接作为redis中的key
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    redisTemplate.setKeySerializer(stringRedisSerializer);
    // 自定义value序列化方式,序列化成json格式
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    //jackson底层的序列化和反序列化使用的是ObjectMapper,我们可以通过ObjectMapper设置序列化信息
    // 设置值的默认类型,即类信息
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    // SimpleModule用于设置自定义序列化器
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(DateTime.class,new JodaDateTimeJsonSerializer());
    simpleModule.addDeserializer(DateTime.class,new JodaDateTimeJsonDeserializer());
    objectMapper.registerModule(simpleModule);
    // 添加进json序列化器中
    jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
    return redisTemplate;
}

这个时候再运行测试类就没什么问题了。

控制台打印信息如下:

redis中的数据信息如下:

网上还有一种更加简便的方法就是使用jackson提供的包,引入依赖:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-joda</artifactId>
    <version>2.9.9</version>
</dependency>

这个包已经帮我们实现了关于joda-time的序列化与反序列化器,我们只需要在redisTemplate方法中将对应的SimpleModel注册到ObjectMapper中就行:

objectMapper.registerModule(new JodaModule());

这样也可以达到同样的效果。

小结

总之,想要在SpringBoot中实现redis的自定义序列化,需要自定义创建一个redisTemplate的bean,设置要使用的序列化方式。通过ObjectMapper设置一些自定义序列化信息,如反序列化所要用到的类信息等。还可以对特定的数据类型进行自定义序列化,只需要通过SimpleModel注册到相应的序列化器即可。最后再将该bean交由Spring容器管理。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • springboot集成redis lettuce

    目前java操作redis的客户端有jedis跟Lettuce.在springboot1.x系列中,其中使用的是jedis,但是到了springboot2.x其中使用的是Lettuce. 因为我们的版本是springboot2.x系列,所以今天使用的是Lettuce. 关于jedis跟lettuce的区别: Lettuce 和 Jedis 的定位都是Redis的client,所以他们当然可以直接连接redis server. Jedis在实现上是直接连接的redis server,如果在多线程环

  • Java SpringCache+Redis缓存数据详解

    目录 前言 一.什么是SpringCache 二.项目集成Spring Cache + Redis 1.配置方式 三.使用Spring Cache 四.SpringCache原理与不足 1.读模式 2.写模式:(缓存与数据库一致) 五.总结 前言 这几天学习谷粒商城又再次的回顾了一次SpringCache,之前在学习谷粒学院的时候其实已经学习了一次了!!! 这里就对自己学过来的内容进行一次的总结和归纳!!! 一.什么是SpringCache Spring Cache 是一个非常优秀的缓存组件.自

  • Java SpringBoot 集成 Redis详解

    目录 1.概述 Redis是什么? Redis能该干什么? 特性 2.测试Redis 3.自定义redisTemplate 1.概述 Redis是什么? Redis(Remote Dictionary Server ),即远程字典服务. 是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 与memcached一样,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加

  • Springboot中如何使用Redisson实现分布式锁浅析

    目录 前言 1. 概述 2. Redisson 在 Springboot 中的使用 2.1 引入依赖 2.2 在 Springboot 配置中配置Redis 2.3 Demo代码 3. 综述 前言 在分布式场景下为了保证数据最终一致性.在单进程的系统中,存在多个线程可以同时改变某个变量(可变共享变量)时,就需要对变量或代码块做同步(lock-synchronized),使其在修改这种变量时能够线性执行消除并发修改变量.但分布式系统是多部署.多进程的,开发语言提供的并发处理API在此场景下就无能为

  • 详解Spring集成Redis的两种方式

    目录 一.使用Jedis方式集成 1.增加依赖 2.配置项 3.配置连接池 4.测试 使用spring-data-redis 1.引入依赖 2.配置项 3.使用 4.可能会遇到的坑 哨兵和集群 总结: 在工作中,我们用到分布式缓存的时候,第一选择就是Redis,今天介绍一下SpringBoot如何集成Redis的,分别使用Jedis和Spring-data-redis两种方式. 一.使用Jedis方式集成 1.增加依赖 <!-- spring-boot-starter-web不是必须的,这里是为

  • SpringBoot 如何实现自定义Redis序列化

    目录 问题 环境 入口点 实现自定义序列化 小结 问题 在使用RedisTemplate存储对象时,如果采用JDK默认的序列化方式,数据会出现许多编码字符,辨析度不高.比如一个空的User对象,存储到redis后如下: 这些使用JDK默认序列化方式序列化后的数据简直惨不忍睹,在使用命令行查询数据时会很头疼. 如何使数据更容易辨别呢? 一种办法是使用StringRedisTemplate,在存入redis前先将数据处理成字符串格式再存入redis,但这种方式的缺点就是每次存入数据前都要手动对非字符

  • SpringBoot集成Redis,并自定义对象序列化操作

    SpringBoot项目使用redis非常简单,pom里面引入redis的场景启动器,在启动类上加@EnableCaching注解,项目启动会自动匹配上redis,这样项目中就可以愉快地使用了, 使用方法:要么使用@Cacheable一类的注解自动缓存,要么使用RedisTemplate手动缓存. (前提是你的本机或者是远程主机要先搭好redis环境) 虽然SpringBoot好用,但这里也有好多坑,SpringBoot和MySQL一样,易学难精,阳哥说的对,练武不练功,到老一场空. 下面,我将

  • SpringBoot自定义Redis实现缓存序列化详解

    目录 1.自定义RedisTemplate 1.1.Redis API默认序列化机制 1.2.自定义RedisTemplate序列化机制 1.3.效果测试 2.自定义RedisCacheManager 2.1.Redis注解默认序列化机制 2.2.自定义RedisCacheManager 刚刚完成了Spring Boot整合Redis进行了数据的缓存管理,但缓存管理的实体类数据使用的是JDK序列化方式,不便于使用可视化管理工具进行查看和管理. 接下来分别针对基于注解的Redis缓存实现和基于AP

  • 如何自定义redis工具jar包供其他SpringBoot项目直接使用

    注:(最终redis数据库连接信息由使用者项目模块配置提供) 一.Redis常用存储操作实现(redis-util模块,该module最后会打包成jar供其他服务使用) 1.引用相关依赖 <!-- 如果有继承父级spring-boot-starter-parent,可不用添加版本号 --> <!-- Redis缓存 [start] --> <dependency> <groupId>org.springframework.boot</groupId&g

  • SpringBoot @JsonDeserialize自定义Json序列化方式

    目录 @JsonDeserialize自定义Json序列化 1.问题 2.现象 3.解决办法 @JsonSerialize与@JsonDeserialize使用 1.以注解方式使用 2.自定义实现类 @JsonDeserialize自定义Json序列化 1.问题 在项目上使用SpringBoot为框架,调用第三方接口时,返回的参数Date类型,需要自定义进行Json序列化,需要进行处理,接受数据 2.现象 调用第三方接口,返回参数类型为Date类型,格式如下: { "created":

  • 解决SpringBoot下Redis序列化乱码的问题

    目录 SpringBoot下Redis序列化乱码 注意问题 SpringBoot配置Redis序列化规则,防止乱码 下面我们可以编写测试类了 具体可以看下图 我们需要对它进行配置 SpringBoot下Redis序列化乱码 项目最初的序列化方案用的是JDK序列化类,但保存到redis里会产生乱码不方便查看管理. public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {         redisTem

  • Springboot项目中使用redis的配置详解

    程序结构: 一.配置 1. 在pom.xml中添加依赖 pom.xml文件如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=&q

  • SpringBoot整合Shiro和Redis的示例代码

    demo源码 此demo用SpringBoot+Shiro简单实现了登陆.注册.认证.授权的功能,并用redis做分布式缓存提高性能. 1.准备工作 导入pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XM

  • SpringBoot详解整合Redis缓存方法

    目录 1.Spring Boot支持的缓存组件 2.基于注解的Redis缓存实现 3.基于API的Redis缓存实现 1.Spring Boot支持的缓存组件 在Spring Boot中,数据的缓存管理存储依赖于Spring框架中cache相关的org.springframework.cache.Cache和org.springframework.cache.CacheManager缓存管理器接口. 如果程序中没有定义类型为CacheManager的Bean组件或者是名为cacheResolve

  • SpringBoot项目中使用redis缓存的方法步骤

    本文介绍了SpringBoot项目中使用redis缓存的方法步骤,分享给大家,具体如下: Spring Data Redis为我们封装了Redis客户端的各种操作,简化使用. - 当Redis当做数据库或者消息队列来操作时,我们一般使用RedisTemplate来操作 - 当Redis作为缓存使用时,我们可以将它作为Spring Cache的实现,直接通过注解使用 1.概述 在应用中有效的利用redis缓存可以很好的提升系统性能,特别是对于查询操作,可以有效的减少数据库压力. 具体的代码参照该

随机推荐