설명
- Controller에 전달된 요청을 처리하기 위한 실질적인 로직을 담당하는 클래스
- 로직을 처리하고 Controller로 결과를 반환한다.
설정
- Interest 클래스와 모든 메서드,리스폰스 타입이 동일하다는 가정하에 진행
Title |
Method Name |
Request Param |
Response Type |
관심사 전체 리스트 조회 |
getInterest |
String path : 조회할 옵션의 도메인 Path |
InteresteResponse : 옵션 값의 정보를 담은 Response 객체 |
제품 리스트 조회 |
getProduct |
- |
ProductResponse |
인기 게시글 조회 |
getPopular |
- |
GatheringContentsResponse |
표현 조회 하기 |
getExpression |
- |
ExpressionResponse |
근처 모임 모임 리스트 조회 |
getGathering |
- |
GatheringResponse |
노출 위치별 배너 조회 |
getBanner |
- |
BannerResponse |
유저 리프레쉬 토큰 업데이트 |
getAuthRefresh |
- |
RefreshTokenResponse |
Service.java
package com.sinor.cache.main.service;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.WebClient;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sinor.cache.admin.metadata.model.MetadataGetResponse;
import com.sinor.cache.admin.metadata.service.MetadataService;
import com.sinor.cache.common.CustomException;
import com.sinor.cache.common.ResponseStatus;
import com.sinor.cache.main.model.MainCacheResponse;
import lombok.AllArgsConstructor;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.Map;
@AllArgsConstructor
@Service
@Transactional
public class MainCacheService implements IMainCacheServiceV1 {
private WebClient webClient;
private final RedisTemplate<String, String> redisTemplate;
private final ObjectMapper objectMapper;
private final MetadataService metadataService;
/**
* Main 서버에 요청을 보내는 메서드
* @param path 요청 path
* @param queryString 요청 queryString
*/
public String getMainPathData(String path, MultiValueMap<String, String> queryString) {
//테스트 Main uri
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("<http://mainHost:8080/{path}>");
builder.path(path);
if(queryString != null) builder.queryParams(queryString);
// uri 확인
System.out.println(builder.toUriString());
String mainResponse = webClient.get()
.uri(builder.build().toUri())
.retrieve()
.bodyToMono(String.class) // 메인 서버에서 오는 요청을 String 으로 받는다.
// main 서버는 모든 데이터에 대해 ok, data 형태로 넘어온다. 이를 받을 Response 객체를 활용할 수 없을까?
.log()
.block();
System.out.println(mainResponse);
// 여기서 그냥 반환을 MainServerResponse 로 하는 것
// 캐시 서버에서 Main 의 데이터를 활용할 것도 아닌데 String 에서 꼭 변환을 해야할까?
return mainResponse;
}
/**
* Main 서버에 요청을 보내는 메서드
* @param path 요청 path
* @param queryString 요청 queryString
* @param body Requestbody
*/
public String postMainPathData(String path, MultiValueMap<String, String> queryString, Map<String, String> body) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("<http://mainHost:8080/{path}>");
builder.path(path);
if(queryString != null) builder.queryParams(queryString);
// uri 확인
System.out.println(builder.toUriString());
return webClient.post()
.uri(builder.build().toUri())
.bodyValue(body)
.retrieve()
.bodyToMono(String.class)
.log()
.block();
}
/**
* Main 서버에 요청을 보내는 메서드
* @param path 요청 path
* @param queryString 요청 queryString
*/
public String deleteMainPathData(String path, MultiValueMap<String, String> queryString) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("<http://mainHost:8080/{path}>");
builder.path(path);
if(queryString != null) builder.queryParams(queryString);
// uri 확인
System.out.println(builder.toUriString());
return webClient.delete()
.uri(builder.build().toUri())
.retrieve()
.bodyToMono(String.class)
.log()
.block();
}
/**
* Main 서버에 요청을 보내는 메서드
* @param path 요청 path
* @param queryString 요청 queryString
* @param body Requestbody
*/
public String updateMainPathData(String path, MultiValueMap<String, String> queryString, Map<String, String> body) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("<http://mainHost:8080/{path}>");
builder.path(path);
if(queryString != null) builder.queryParams(queryString);
// uri 확인
System.out.println(builder.toUriString());
return webClient.put()
.uri(builder.build().toUri())
.bodyValue(body)
.retrieve()
.bodyToMono(String.class)
.log()
.block();
}
/**
* 캐시에 데이터가 있는지 확인하고 없으면 데이터를 조회해서 있으면 데이터를 조회해서 반환해주는 메소드
* opsForValue() - Strings 를 쉽게 Serialize / Deserialize 해주는 Interface
* @param path 특정 path에 캐시가 있나 확인하기 위한 파라미터
* @return 값이 있다면 value, 없다면 null
*/
public String getDataInCache(String path) {
String cachedData = redisTemplate.opsForValue().get(path);
System.out.println("cachedData: " + cachedData + "값입니다.");
return cachedData;
}
/**
* 캐시에 데이터가 없으면 메인 데이터를 조회해서 캐시에 저장하고 반환해주는 메소드
* @param path 검색할 캐시의 Path
* @param queryString 각 캐시의 구별을 위한 QueryString
*/
public String postInCache(String path, MultiValueMap<String, String> queryString) {
try {
String response = getMainPathData(path, queryString);
MainCacheResponse userCacheResponse = MainCacheResponse.builder()
.response(response)
.build();
MetadataGetResponse metadata = metadataService.findOrCreateMetadataById(path);
redisTemplate.opsForValue().set(path, objectMapper.writeValueAsString(userCacheResponse), metadata.getMetadataTtlSecond());
return userCacheResponse.getResponse();
} catch (JsonProcessingException e) {
throw new CustomException(ResponseStatus.INTERNAL_SERVER_ERROR);
}
}
// 1. RequestBody에 다음과 같은 형식으로 전달하면 캐시에 저장해주는 API
// application/json
// {
// "key": /main/expression,
// "value": { "url": "<http://localhost:8080/main/expression>", "createAt": "2021-08-31T15:00:00", "ttl": 600 }
// }
// public UserCacheResponse postCache(String key, Object value) {
// try {
// String jsonValue = objectMapper.writeValueAsString(value);
// redisTemplate.opsForValue().set(key, jsonValue);
// System.out.println("redisTemplate.opsForValue().get(key) = " + redisTemplate.opsForValue().get(key));
// return objectMapper.readValue(jsonValue, UserCacheResponse.class);
// } catch (Exception e) {
// e.fillInStackTrace();
// return null;
// }
// }
}
Controller.java
package com.sinor.cache.main.controller;
import com.sinor.cache.main.model.MainCacheRequest;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RestController;
import com.sinor.cache.main.service.MainCacheService;
@RestController
public class MainCacheController implements IMainCacheControllerV1 {
private final MainCacheService mainCacheService;
public MainCacheController(MainCacheService mainCacheService) {
this.mainCacheService = mainCacheService;
}
/**
* 데이터 조회 및 캐시 조회
*
* @param path 요청에 전달된 path
* @param queryParams 요청에 전달된 queryString
* @apiNote <a href="<https://www.baeldung.com/spring-request-response-body#@requestbody>">reference</a>
*/
@Override
public String getDataReadCache(String path, MultiValueMap<String, String> queryParams) {
String pathCache = mainCacheService.getDataInCache(path);
if (pathCache == null) {
return mainCacheService.postInCache(path, queryParams);
}
return pathCache;
}
/**
* 데이터 조회 또는 생성 및 캐시 조회
*
* @apiNote <a href="<https://www.baeldung.com/spring-request-response-body#@requestbody>">reference</a>
* @param path 요청에 전달된 path
* @param queryParams 요청에 전달된 queryString
* @param body 요청에 전달된 RequestBody 내용에 매핑된 RequestBodyDto 객체
*/
@Override
public String postDataReadCache(String path, MultiValueMap<String, String> queryParams, MainCacheRequest body) {
return mainCacheService.postMainPathData(path, queryParams, body.getRequestBody());
}
/**
* 데이터 삭제 및 캐시 갱신
*
* @apiNote <a href="<https://www.baeldung.com/spring-request-response-body#@requestbody>">reference</a>
* @param path 요청에 전달된 path
* @param queryParams 요청에 전달된 queryString
*/
@Override
public String deleteDataRefreshCache(String path, MultiValueMap<String, String> queryParams) {
return mainCacheService.deleteMainPathData(path, queryParams);
}
/**
* 데이터 수정 및 캐시 갱신
* @apiNote <a href="<https://www.baeldung.com/spring-request-response-body#@requestbody>">reference</a>
* @param path 요청에 전달된 path
* @param queryParams 요청에 전달된 queryString
* @param body 요청에 전달된 RequestBody 내용에 매핑된 RequestBodyDto 객체
*/
@Override
public String updateDataRefreshCache(String path, MultiValueMap<String, String> queryParams, MainCacheRequest body) {
return mainCacheService.updateMainPathData(path, queryParams, body.getRequestBody());
}
}