Skip to content

Commit

Permalink
TMDB를 통해 영화정보를 가져오도록 변경한다
Browse files Browse the repository at this point in the history
  • Loading branch information
cheolwon1994 committed Nov 16, 2023
1 parent 238d1d3 commit bccc31f
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 137 deletions.
66 changes: 41 additions & 25 deletions src/main/java/com/catcher/batch/core/dto/MovieApiResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,55 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Setter
@Getter

@CatcherJson(path = "boxOfficeResult")
@JsonIgnoreProperties(ignoreUnknown = true)
@CatcherJson(path = "")
public class MovieApiResponse {

@JsonProperty("dailyBoxOfficeList")
private List<MovieItemDTO> response;
@JsonProperty("dates")
private MovieNowPlayingDate movieNowPlayingDate;

@Getter
private static class MovieNowPlayingDate {
@JsonProperty("maximum")
private String maximumDate;

@JsonProperty("minimum")
private String minimumDate;
}

@JsonProperty("results")
private List<MovieItem> items;

@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
public static class MovieItemDTO {
private String rnum;
private String rank;
private String rankInten;
private String rankOldAndNew;
private String movieCd;
private String movieNm;
private String openDt;
private String salesAmt;
private String salesShare;
private String salesInten;
private String salesChange;
private String salesAcc;
private String audiCnt;
private String audiInten;
private String audiChange;
private String audiAcc;
private String scrnCnt;
private String showCnt;
public static class MovieItem {
@JsonProperty("id")
private int id;
@JsonProperty("original_title")
private String originalTitle;
@JsonProperty("poster_path")
private String posterPath;
@JsonProperty("release_date")
private String releaseDate;
@JsonProperty("title")
private String title;
@JsonProperty("overview")
private String overview;
@JsonProperty("poster_path")
public void setPosterPath(String posterPath) {
this.posterPath = "https://image.tmdb.org/t/p/w300" + posterPath;
}
}

@JsonProperty("total_pages")
@Getter
private int totalPages;

@JsonProperty("total_results")
@Getter
private int totalResults;
}
67 changes: 67 additions & 0 deletions src/main/java/com/catcher/batch/core/service/MovieService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.catcher.batch.core.service;

import com.catcher.batch.core.database.CatcherItemRepository;
import com.catcher.batch.core.database.CategoryRepository;
import com.catcher.batch.core.domain.entity.CatcherItem;
import com.catcher.batch.core.domain.entity.Category;
import com.catcher.batch.core.dto.MovieApiResponse;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.catcher.batch.common.utils.HashCodeGenerator.hashString;

@Service
@RequiredArgsConstructor
public class MovieService {
private final CatcherItemRepository catcherItemRepository;
private final CategoryRepository categoryRepository;
public static final String CATEGORY_NAME = "movie";

@Transactional
public void batch(List<MovieApiResponse.MovieItem> movies){

Category category = categoryRepository.findByName(CATEGORY_NAME)
.orElseGet(()->categoryRepository.save(Category.create(CATEGORY_NAME)));

Map<String, CatcherItem> itemHashKeyToDBItem = catcherItemRepository.findByCategory(category).stream()
.collect(Collectors.toMap(CatcherItem::getItemHashValue, Function.identity()));


//TODO: 썸네일URL, 개봉일 변경 여부 확인 로직 필요

// Map<String, MovieApiResponse.MovieItem> itemHashKeyToApiItem = movies.stream()
// .collect(Collectors.toMap(
// movieItem -> hashString(CATEGORY_NAME, String.valueOf(movieItem.getId())),
// movieItem -> movieItem
// ));

// List<CatcherItem> catcherItems = itemHashKeyToApiItem.entrySet().stream()
// .map(entry -> {
// DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE;
// LocalDate localDate = LocalDate.parse(entry.getValue().getReleaseDate(), dateFormatter);
//
// ZonedDateTime releaseDate = localDate.atStartOfDay(ZoneId.systemDefault());
//
// return CatcherItem.builder()
// .category(category)
// .title(entry.getValue().getTitle())
// .itemHashValue(entry.getKey())
// .thumbnailUrl(entry.getValue().getPosterPath())
// .startAt(releaseDate)
// .build();
// })
// .collect(Collectors.toList());
//DB에 추가
// catcherItemRepository.saveAll(catcherItems);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,42 @@
import com.catcher.batch.common.service.CatcherFeignService;
import com.catcher.batch.core.dto.MovieApiResponse;
import com.catcher.batch.core.service.ApiService;
import com.catcher.batch.core.service.MovieService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.IntStream;

@Component
@RequiredArgsConstructor
public class MovieApiAdapter implements ApiService<MovieApiResponse> {

private final CatcherFeignService catcherFeignService;
private final MovieService movieService;

@Override
public MovieApiResponse getData() {
HashMap<String, Object> params = new HashMap<>();
return catcherFeignService.parseService(params, MovieApiResponse.class);
MovieApiResponse response = catcherFeignService.parseService(params, MovieApiResponse.class);

List<MovieApiResponse.MovieItem> movieList = response.getItems();
int totalPages = response.getTotalPages();

IntStream.rangeClosed(2, totalPages)
.parallel()
.forEach(page -> {
params.put("page", page);
MovieApiResponse extraResponse = catcherFeignService.parseService(params, MovieApiResponse.class);
movieList.addAll(extraResponse.getItems());
});

movieService.batch(movieList);

return response;
}

}
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
package com.catcher.batch.infrastructure.properties;

import com.catcher.batch.core.dto.MovieApiResponse;
import com.catcher.batch.core.properties.HeaderSupport;
import com.catcher.batch.core.properties.PropertyBase;
import com.catcher.batch.infrastructure.utils.KmsUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Map;

@Component
public class MovieProperties extends PropertyBase {
public class MovieProperties extends PropertyBase implements HeaderSupport {

@Value("${movie.key}")
private String serviceKey;

private String targetDate;

public MovieProperties(@Value("${movie.baseUrl}") String endPoint) {
super(endPoint);
}

@Override
public boolean support(Class<?> clazz) {
if (clazz.isAssignableFrom(MovieApiResponse.class)) {
initCurrentDate();
return true;
}
return false;
return clazz.isAssignableFrom(MovieApiResponse.class);
}

@Override
public URI getURI() {
return UriComponentsBuilder
UriComponentsBuilder uriBuilder = UriComponentsBuilder
.fromUriString(this.getEndPoint())
.queryParam("key", KmsUtils.decrypt(serviceKey))
.queryParam("targetDt", targetDate)
.queryParam("language", "ko-KR");

return this.addParams(uriBuilder)
.build().toUri();
}

private void initCurrentDate() {
ZonedDateTime currentDateTime = ZonedDateTime.now();
ZonedDateTime previousDate = currentDateTime.minus(1, ChronoUnit.DAYS);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
private UriComponentsBuilder addParams(UriComponentsBuilder uriComponentsBuilder ) {
Map<String, Object> params = getParams();
for (String key : params.keySet()) {
uriComponentsBuilder
.queryParam(key, params.get(key));
}
return uriComponentsBuilder;
}

targetDate = previousDate.format(formatter);
@Override
public HttpHeaders addHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + KmsUtils.decrypt(serviceKey));
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ public class KmsUtils {
@Value("${aws.kms.keyId}")
private static String KEY_ID;

// @Value("${spring.profiles.active}")
// private static String PROFILE;

public static String encrypt(String text) {
try {
AWSKMS kmsClient = AWSKMSClientBuilder.standard()
Expand Down
27 changes: 1 addition & 26 deletions src/main/java/com/catcher/batch/resource/MovieController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,22 @@

import com.catcher.batch.common.response.CommonResponse;
import com.catcher.batch.core.dto.MovieApiResponse;
import com.catcher.batch.common.service.CatcherFeignService;
import com.catcher.batch.common.service.CatcherJsonService;
import com.catcher.batch.core.service.ApiService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.util.HashMap;

@RequiredArgsConstructor
@RestController
@RequestMapping("/movie")
public class MovieController {
private final CatcherJsonService catcherJsonService;
private final CatcherFeignService catcherFeignService;
private final ApiService apiService;

@GetMapping("/webclient-batch")
public Mono<ResponseEntity<MovieApiResponse>> getMovieDataByWebClient() {
HashMap<String, Object> params = new HashMap<>();
Mono<MovieApiResponse> stringMono = catcherJsonService.parseService(params, MovieApiResponse.class);

return stringMono
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}

@GetMapping("/feign-batch")
public CommonResponse<MovieApiResponse> getMovieDataByFeign() {
HashMap<String, Object> params = new HashMap<>();
MovieApiResponse movieResponse = catcherFeignService.parseService(params, MovieApiResponse.class);

return CommonResponse.success(200, movieResponse);
}

@GetMapping("/batch")
public CommonResponse<MovieApiResponse> movieData() {
MovieApiResponse response = (MovieApiResponse) apiService.getData();

return CommonResponse.success(200, response);
}
}
24 changes: 20 additions & 4 deletions src/main/resources/application-dev.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,21 @@ ssh.local-port=3306
aws.kms.keyId=5d1c783d-6c8e-4661-a8ed-a12654aac8c3
aws.kms.encryptionAlgorithm=SYMMETRIC_DEFAULT

## movie api
movie.baseUrl=http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json
movie.key=AQICAHg2j0pl3GguoQNkjcreuBPYJqI3OPeLEOelKIkMSzn01AEdAQDVPqdOhpfNbxFhaX/rAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMnYW/M8ND+IPKIhQ8AgEQgDv37SLjLvGtPBohoi8i1Z+SFBaopteVK3e+36yH3RB44h/Ik0ZyxE69hlJ0T8SHnTLWzLKsk5TKP0uwFA==
## festival api
festival.baseUrl=http://api.data.go.kr/openapi/tn_pubr_public_cltur_fstvl_api
festival.key=AQICAHg2j0pl3GguoQNkjcreuBPYJqI3OPeLEOelKIkMSzn01AGEXII6Ufa8dIEGD6MQNyM9AAAAujCBtwYJKoZIhvcNAQcGoIGpMIGmAgEAMIGgBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDEphbmyNQTiCTHtF/gIBEIBz8Fj7Ij/xk+O5hXWQfMOsIfc6uAYrvF2Xew+p0qLkX3DO0Plzjt4EMzaUP504RIMr7s+Yhx2y2Lq5SZ9I/cZ4swMYIOwj8FXDLeFy/k3dfwFdnBRh1kmvIDiMSg5kj4kgk05nzHyJ5KloYXXngp/ZQzsdpA==

## camping api
camping.key=AQICAHg2j0pl3GguoQNkjcreuBPYJqI3OPeLEOelKIkMSzn01AF5N6HoIJmz3ef5mw7h81sOAAAAujCBtwYJKoZIhvcNAQcGoIGpMIGmAgEAMIGgBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDDvX80CMep9JqAHwVgIBEIBzD41zp/0NHhhvJ4nFvikmteZp501dy09Q/RjJ631ggAcTPaskdGKn6+qwvQVLw3vWesWOSycm3NiMeatVHUwSBZ4AKFGxfhHIsinf1Hyl2RdKjbbeYLYTtTiJY8jh4kZrXUPn6zQ4/vVr75WcIi9eny6lhw==
camping.baseUrl=http://apis.data.go.kr/B551011/GoCamping/basedList

## movie tmdb api
movie.baseUrl=https://api.themoviedb.org/3/movie/now_playing
movie.key=AQICAHgxTvGwZVD/2MLMvR9/01Wy8IeL4nGHGGgc5XMYIhkQ2gHcHnoKktvPjhKq4S/u+OZcAAABOjCCATYGCSqGSIb3DQEHBqCCAScwggEjAgEAMIIBHAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAwBkI+xMEv8XYOM0pUCARCAge6UDyvSeG2ksvB7Yk7bdfxbcPp2PyCCy5L7XhQ43Wj9adChP8Gm4pzfLjwvj/akTcsN/7GYGsCZdl8VPKHbsv1AsS2rKVmydwpwye/yr693mjVUKU8WznLVnMqTrNxP3UgSsrqFyJ335hc5t+DBH7IQDnMMhy37e6l/D5o33NArwxDkzJF/rhLUdvIgoQ15ruZ1NFBXxgh32OP2lRdZA61E48qLj/CvNcqxBDgwr4jpyy2p0vSZ/mVaRsOUxawoTx2bUeJt6G5Df93MFKeSZ4ytzf4NNdOwA4sgif5YMUnC2bui6V7cANH0WMpfbH4k

## restaurant api
restaurant.key=AQICAHgxTvGwZVD/2MLMvR9/01Wy8IeL4nGHGGgc5XMYIhkQ2gFwIra357LjWgWTfXdGHOTMAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM0t0Y5XX4gbI1BsAnAgEQgDtbOGiG1iS5qgxCIfnvMf/pEad1kQAOJrPoc39lLxiTk/Vw+bw/DqE/Sdmj/ibi3fakUgdXhdK111insQ==
restaurant.baseUrl=https://dapi.kakao.com/v2/local/search/category

#update the schema with the given values.
spring.jpa.hibernate.ddl-auto=update
Expand All @@ -31,4 +43,8 @@ spring.jpa.properties.hibernate.show-sql=true
logging.level.org.hibernate.type.descriptor.sql=DEBUG

logging.level.org.hibernate.SQL=DEBUG
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MariaDBDialect
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MariaDBDialect

## swagger - openAPI
springdoc.packagesToScan=com.catcher.batch.resource
springdoc.pathsToMatch=/**
Loading

0 comments on commit bccc31f

Please sign in to comment.