Skip to content

Commit 0523e88

Browse files
committed
feat: GzipRedisSerializer를 통해서 직렬화 & 역직렬화 수행
1 parent 13c8fd7 commit 0523e88

File tree

2 files changed

+139
-2
lines changed

2 files changed

+139
-2
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.example.log4u.common.config.redis;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
import java.util.zip.Deflater;
7+
import java.util.zip.GZIPInputStream;
8+
import java.util.zip.GZIPOutputStream;
9+
10+
import org.springframework.data.redis.serializer.RedisSerializer;
11+
import org.springframework.data.redis.serializer.SerializationException;
12+
import org.springframework.util.FileCopyUtils;
13+
14+
import com.fasterxml.jackson.core.type.TypeReference;
15+
import com.fasterxml.jackson.databind.ObjectMapper;
16+
17+
import lombok.RequiredArgsConstructor;
18+
19+
@RequiredArgsConstructor
20+
public class GzipRedisSerializer<T> implements RedisSerializer<T> {
21+
22+
private static final byte[] GZIP_MAGIC_BYTES = new byte[]{
23+
(byte) (GZIPInputStream.GZIP_MAGIC & 0xFF),
24+
(byte) ((GZIPInputStream.GZIP_MAGIC >> 8) & 0xFF)
25+
};
26+
27+
private final ObjectMapper objectMapper;
28+
private final TypeReference<T> typeReference;
29+
private final int minCompressionSize;
30+
private final int bufferSize;
31+
32+
public GzipRedisSerializer(ObjectMapper objectMapper, TypeReference<T> typeReference) {
33+
this(objectMapper, typeReference, 1024, 4096);
34+
}
35+
36+
@Override
37+
public byte[] serialize(T t) throws SerializationException {
38+
if (t == null) {
39+
return null;
40+
}
41+
try {
42+
if (minCompressionSize == -1) {
43+
return encodeGzip(t);
44+
}
45+
byte[] bytes = objectMapper.writeValueAsBytes(t);
46+
if (bytes.length <= minCompressionSize) {
47+
return bytes;
48+
}
49+
return encodeGzip(t);
50+
51+
} catch (Exception e) {
52+
throw new SerializationException("Failed to serialize", e);
53+
}
54+
}
55+
56+
@Override
57+
public T deserialize(byte[] bytes) throws SerializationException {
58+
if (bytes == null) {
59+
return null;
60+
}
61+
try {
62+
if (isGzipCompressed(bytes)) {
63+
byte[] decompressed = decodeGzip(bytes);
64+
return objectMapper.readValue(decompressed, 0, decompressed.length, typeReference);
65+
}
66+
return objectMapper.readValue(bytes, 0, bytes.length, typeReference);
67+
68+
} catch (IOException e) {
69+
throw new SerializationException("Failed to deserialize", e);
70+
}
71+
}
72+
73+
private byte[] encodeGzip(byte[] original) {
74+
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(bufferSize);
75+
GZIPOutputStream gos = new GZIPOutputStream(bos, bufferSize) {
76+
{
77+
def.setLevel(Deflater.BEST_SPEED);
78+
}
79+
}
80+
) {
81+
FileCopyUtils.copy(original, gos);
82+
return bos.toByteArray();
83+
84+
} catch (IOException e) {
85+
throw new IllegalStateException("Failed to encode GZIP", e);
86+
}
87+
}
88+
89+
private byte[] encodeGzip(T t) {
90+
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(bufferSize);
91+
GZIPOutputStream gos = new GZIPOutputStream(bos, bufferSize) {
92+
{
93+
def.setLevel(Deflater.BEST_SPEED);
94+
}
95+
}
96+
) {
97+
objectMapper.writeValue(gos, t);
98+
return bos.toByteArray();
99+
100+
} catch (IOException e) {
101+
throw new IllegalStateException("Failed to encode GZIP", e);
102+
}
103+
}
104+
105+
private byte[] decodeGzip(byte[] encoded) {
106+
try (
107+
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
108+
GZIPInputStream gis = new GZIPInputStream(bis, bufferSize);
109+
ExposedBufferByteArrayOutputStream out = new ExposedBufferByteArrayOutputStream(bufferSize);
110+
) {
111+
FileCopyUtils.copy(gis, out);
112+
return out.getRawByteArray();
113+
} catch (IOException e) {
114+
throw new IllegalStateException("Failed to decode GZIP", e);
115+
}
116+
}
117+
118+
private boolean isGzipCompressed(byte[] bytes) {
119+
return bytes.length > 2 && bytes[0] == GZIP_MAGIC_BYTES[0] && bytes[1] == GZIP_MAGIC_BYTES[1];
120+
}
121+
122+
static class ExposedBufferByteArrayOutputStream extends ByteArrayOutputStream {
123+
124+
ExposedBufferByteArrayOutputStream(int size) {
125+
super(size);
126+
}
127+
128+
public byte[] getRawByteArray() {
129+
return this.buf;
130+
}
131+
}
132+
}

src/main/java/com/example/log4u/common/config/redis/RedisConfig.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
88
import org.springframework.data.redis.serializer.StringRedisSerializer;
99

10+
import com.fasterxml.jackson.core.type.TypeReference;
1011
import com.fasterxml.jackson.databind.ObjectMapper;
1112
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
1213

@@ -23,12 +24,16 @@ public RedisTemplate<String, String> redisTemplate() {
2324
RedisTemplate<String, String> template = new RedisTemplate<>();
2425
template.setConnectionFactory(redisConnectionFactory);
2526
template.setKeySerializer(new StringRedisSerializer());
26-
template.setValueSerializer(new StringRedisSerializer());
27+
template.setValueSerializer(new GzipRedisSerializer<>(
28+
ObjectMapperFactory.objectMapper, new TypeReference<String>() {
29+
}, 1024, 4096));
2730
return template;
2831
}
2932

3033
@Bean
3134
public ObjectMapper objectMapper() {
32-
return ObjectMapperFactory.objectMapper;
35+
ObjectMapper objectMapper = new ObjectMapper();
36+
objectMapper.registerModule(new JavaTimeModule());
37+
return objectMapper;
3338
}
3439
}

0 commit comments

Comments
 (0)