Application Scenarios
We want to reduce the database pressure by reducing the number of queries to the relational database through caching. In the execution of the DAO class select***()
, the query***()
method, the first Redis
query from the cache data, if there is a direct from the Redis
results, if there is no further to the database to initiate the query request fetching data.
Serialization issues
To save domain object as KEY-VALUEC on a redis, you have to solve the object serialization problem. Spring Data Redis provides us with some ready-made solutions:
JdkSerializationRedisSerializer
. Use the serialization functionality provided by the JDK. The advantage is that you do not need to provide type information when deserializing ( class
), but the drawback is that the result of serialization is very large, about 5 times times the JSON format, which consumes a lot of memory from the Redis server.
Jackson2JsonRedisSerializer
. Jackson
serializes an object into a JSON string using the library. The advantage is that fast, serialized strings are short and concise. But the disadvantage is also very deadly, that is, the constructor of this class has a type parameter and must provide the type information (object) of the object to serialize .class
. By looking at the source code, it is discovered that only type information is used during deserialization.
If you use scenario one, you have to pay the cache more than 4 times times the cost of memory, it can not afford. If you use scenario two, you must configure a serializer for each domain object, that is, if there are 100 domain objects in my app, you must configure 100 in the spring configuration file Jackson2JsonRedisSerializer
, which is obviously unrealistic.
With Google, a #145 pull request was found in the Spring data Redis project, and the content of the submission request was the answer Jackson
to the question of having to provide type information. Unfortunately, however, this request has not yet been taken merge
. But we can offload the code copy to our project:
/** * @author Christoph Strobl * @since 1.6 * *Public class Genericjackson2jsonredisserializer implements Redisserializer< Object> { Private FinalObjectmapper mapper;/** * Creates {@link Genericjackson2jsonredisserializer} and configures {@link Objectmapper} for Default typing. */Public Genericjackson2jsonredisserializer () { This((String)NULL); }/** * Creates {@link Genericjackson2jsonredisserializer} and configures {@link Objectmapper} for Default typing using the * given {@literal name}. In case of a {@literal empty} or {@literal null} String the default * {@link jsontypeinfo. Id#class} 'll be used. * * @param classpropertytypename Name of the JSON property holding type information. Can be {@literal null}. */Public Genericjackson2jsonredisserializer (String classpropertytypename) { This(NewObjectmapper ());if(Stringutils.hastext (Classpropertytypename)) {Mapper.enabledefaulttypingasproperty (defaulttyping.non_final, classpropertytypename); }Else{mapper.enabledefaulttyping (defaulttyping.non_final, As.property); } }/** * Setting a custom-configured {@link Objectmapper} is one-to-take further control of the JSON ser Ialization * process. For example, an extended {@link serializerfactory} can is configured that provides custom serializers for * s pecific types. * * @param Mapper must not is {@literal null}. */Public Genericjackson2jsonredisserializer (Objectmapper mapper) {assert.notnull (mapper,"Objectmapper must not being null!"); This. Mapper = Mapper; }/* * (non-javadoc) * @see org.springframework.data.redis.serializer.redisserializer#serialize (java.lang.Object ) */ @OverridePublic byte[] Serialize (Object source)throwsSerializationException {if(Source = =NULL) {returnSerializationutils.empty_array; }Try{returnMapper.writevalueasbytes (source); }Catch(Jsonprocessingexception e) {Throw NewSerializationException ("Could not write JSON:"+ E.getmessage (), E); } }/* * (non-javadoc) * @see org.springframework.data.redis.serializer.redisserializer#deserialize (byte[]) */ @OverridePublic Object Deserialize (byte[] source)throwsSerializationException {returnDeserialize (source, Object.class); }/** * @param source can be {@literal null}. * @param type must not is {@literal null}. * @return {@literal null} for empty source. * @throws serializationexception * *Public <T> T Deserialize (byte[] source, class<t>type)throwsserializationexception {assert.notnull (type,"deserialization type must not being null! Pleaes provide object.class to make use of Jackson2 default typing. ");if(Serializationutils.isempty (source)) {return NULL; }Try{returnMapper.readvalue (Source,type); }Catch(Exception ex) {Throw NewSerializationException ("Could not read JSON:"+ Ex.getmessage (), ex); } }}
Then use this in the configuration file GenericJackson2JsonRedisSerializer
:
<bean id="jacksonSerializer" class="com.fh.taolijie.component.GenericJackson2JsonRedisSerializer"> </bean>
Rebuilding the deployment, we found that this serializer can support many different types of domain objects at the same time, problem solving.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Solve serialization problems in query results using Spring cache + Redis + Jackson Serializer Cache database