-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
259 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
.../dto/request/PollOptionCreateRequest.java → .../dto/request/PollOptionCreateRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...options/dto/response/OptionsResponse.java → ...ce/poll/dto/response/OptionsResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
...ore/threedollar-common/src/main/java/com/threedollar/common/exception/util/JsonUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.threedollar.common.exception.util; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.DeserializationFeature; | ||
import com.fasterxml.jackson.databind.JavaType; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.ObjectReader; | ||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import static com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS; | ||
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class JsonUtils { | ||
|
||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() | ||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) | ||
.configure(WRITE_DATES_AS_TIMESTAMPS, false) | ||
.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true) | ||
.configure(FAIL_ON_EMPTY_BEANS, false); | ||
|
||
public static <T> T toObject(String input, Class<T> toClass) { | ||
try { | ||
return OBJECT_MAPPER.readValue(input, toClass); | ||
} catch (IOException e) { | ||
throw new IllegalArgumentException(String.format("역직렬화 중 에러가 발생하였습니다. input: (%s) toClass: (%s) message: (%s)", input, toClass.getSimpleName(), e.getMessage())); | ||
} | ||
} | ||
|
||
public static <T> String toJson(T input) { | ||
try { | ||
return OBJECT_MAPPER.writeValueAsString(input); | ||
} catch (JsonProcessingException e) { | ||
throw new IllegalArgumentException(String.format("직렬화 중 에러가 발생하였습니다. input: (%s) message: (%s)", input, e.getMessage())); | ||
} | ||
} | ||
|
||
public static <T> List<T> toList(String json, Class<T> clazz) { | ||
try { | ||
JavaType listType = OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, clazz); | ||
ObjectReader reader = OBJECT_MAPPER.readerFor(listType); | ||
List<T> listValue = reader.readValue(toJsonNode(json)); | ||
return listValue == null ? List.of() : listValue; | ||
} catch (IOException e) { | ||
throw new IllegalArgumentException(String.format("List 직렬화 중 에러가 발생하였습니다. input: <%s> message: <%s>", json, e.getMessage())); | ||
} | ||
} | ||
|
||
public static <T> List<T> toList(JsonNode jsonNode, Class<T> clazz) { | ||
try { | ||
JavaType listType = OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, clazz); | ||
ObjectReader reader = OBJECT_MAPPER.readerFor(listType); | ||
List<T> listValue = reader.readValue(jsonNode); | ||
return listValue == null ? List.of() : listValue; | ||
} catch (IOException e) { | ||
throw new IllegalArgumentException(String.format("List 직렬화 중 에러가 발생하였습니다. input: <%s> message: <%s>", jsonNode, e.getMessage())); | ||
} | ||
} | ||
|
||
public static JsonNode toJsonNode(String json) { | ||
try { | ||
return OBJECT_MAPPER.readTree(json); | ||
} catch (IOException e) { | ||
throw new IllegalArgumentException(String.format("JsonNode 직렬화 중 에러가 발생하였습니다. input: <%s> message: <%s>", json, e.getMessage())); | ||
} | ||
} | ||
|
||
public static ObjectMapper getObjectMapper() { | ||
return OBJECT_MAPPER; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
...ar-core/threedollar-domain/src/main/java/com/threedollar/domain/redis/StringRedisKey.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.threedollar.domain.redis; | ||
|
||
import java.time.Duration; | ||
|
||
public interface StringRedisKey<K, V> { | ||
|
||
String getKey(); | ||
|
||
V deserializeValue(String value); | ||
|
||
String serializeValue(V value); | ||
|
||
Duration getTtl(); | ||
} |
34 changes: 34 additions & 0 deletions
34
.../threedollar-domain/src/main/java/com/threedollar/domain/redis/StringRedisRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.threedollar.domain.redis; | ||
|
||
import java.time.Duration; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public interface StringRedisRepository<K extends StringRedisKey<K, V>,V> { | ||
|
||
V get(K k); | ||
|
||
List<V> getBulk(List<K> keys); | ||
|
||
void set(K k, V v); | ||
|
||
void setBulk(Map<K, V> keyValues); | ||
|
||
void setWithTtl(K k, V v, Duration ttl); | ||
|
||
void incr(K k); | ||
|
||
void incrBulk(List<K> keys); | ||
|
||
void incrBy(K k, long value); | ||
|
||
void decr(K k); | ||
|
||
void decrBulk(List<K> keys); | ||
|
||
void decrBy(K k, long value); | ||
|
||
void del(K k); | ||
|
||
void delBulk(List<K> keys); | ||
} |
131 changes: 131 additions & 0 deletions
131
...eedollar-domain/src/main/java/com/threedollar/domain/redis/StringRedisRepositoryImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package com.threedollar.domain.redis; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.redis.core.RedisCallback; | ||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.data.redis.core.ValueOperations; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.time.Duration; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.stream.Collectors; | ||
|
||
@RequiredArgsConstructor | ||
@Repository | ||
public class StringRedisRepositoryImpl<K extends StringRedisKey<K, V>, V> implements StringRedisRepository<K, V>{ | ||
|
||
private final RedisTemplate<String, String> redisTemplate; | ||
|
||
@Override | ||
public V get(K k) { | ||
ValueOperations<String, String> operations = redisTemplate.opsForValue(); | ||
return k.deserializeValue(operations.get(k.getKey())); | ||
} | ||
|
||
@Override | ||
public List<V> getBulk(List<K> keys) { | ||
if (keys.isEmpty()) { | ||
return new ArrayList<>(); | ||
} | ||
K k = keys.get(0); | ||
|
||
ValueOperations<String, String> operations = redisTemplate.opsForValue(); | ||
|
||
List<String> values = operations.multiGet(keys.stream() | ||
.map(K::getKey) | ||
.collect(Collectors.toList()) | ||
); | ||
|
||
if (values == null) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
return values.stream() | ||
.map(k::deserializeValue) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Override | ||
public void set(K k, V v) { | ||
setWithTtl(k, v, k.getTtl()); | ||
|
||
} | ||
|
||
@Override | ||
public void setBulk(Map<K, V> keyValues) { | ||
ValueOperations<String, String> operations = redisTemplate.opsForValue(); | ||
redisTemplate.executePipelined((RedisCallback<Object>) pipeline -> { | ||
keyValues.forEach((k, v) -> operations.set(k.getKey(), String.valueOf(v))); | ||
return null; | ||
}); | ||
} | ||
|
||
@Override | ||
public void setWithTtl(K k, V v, Duration ttl) { | ||
ValueOperations<String, String> operations = redisTemplate.opsForValue(); | ||
if (ttl == null) { | ||
operations.set(k.getKey(), k.serializeValue(v)); | ||
return; | ||
} | ||
operations.set(k.getKey(), k.serializeValue(v), ttl.getSeconds(), TimeUnit.SECONDS); | ||
} | ||
|
||
@Override | ||
public void incr(K k) { | ||
incrBy(k, 1); | ||
} | ||
|
||
@Override | ||
public void incrBulk(List<K> keys) { | ||
redisTemplate.executePipelined((RedisCallback<Object>) pipeline -> { | ||
keys.forEach(k -> pipeline.incr(k.getKey().getBytes(StandardCharsets.UTF_8))); | ||
return null; | ||
}); | ||
} | ||
|
||
@Override | ||
public void incrBy(K k, long value) { | ||
ValueOperations<String, String> operations = redisTemplate.opsForValue(); | ||
operations.increment(k.getKey(), value); | ||
|
||
} | ||
|
||
@Override | ||
public void decr(K k) { | ||
decrBy(k, 1); | ||
|
||
} | ||
|
||
@Override | ||
public void decrBulk(List<K> keys) { | ||
redisTemplate.executePipelined((RedisCallback<Object>) pipeline -> { | ||
keys.forEach(k -> pipeline.decr(k.getKey().getBytes(StandardCharsets.UTF_8))); | ||
return null; | ||
}); | ||
} | ||
|
||
@Override | ||
public void decrBy(K k, long value) { | ||
ValueOperations<String, String> operations = redisTemplate.opsForValue(); | ||
operations.decrement(k.getKey(), value); | ||
} | ||
|
||
@Override | ||
public void del(K k) { | ||
redisTemplate.delete(k.getKey()); | ||
} | ||
|
||
@Override | ||
public void delBulk(List<K> keys) { | ||
Set<String> keyStrings = keys.stream() | ||
.map(K::getKey) | ||
.collect(Collectors.toSet()); | ||
redisTemplate.delete(keyStrings); | ||
} | ||
} |