Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.example.customerservice.actor.entity;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

import static jakarta.persistence.CascadeType.ALL;

@Entity
@Table(name = "actor")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Actor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "actor_id")
private Long id;

@Column(name = "actor_name", length = 30, nullable = false)
private String actorName;

@OneToMany(mappedBy = "actor", cascade = ALL)
private List<ActorAppearances> actorAppearances = new ArrayList<>();

@Builder
private Actor(String actorName) {
this.actorName = actorName;
}

public static Actor of(String actorName) {
return Actor.builder()
.actorName(actorName)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.example.customerservice.actor.entity;

import com.example.customerservice.contents.entity.Contents;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import static jakarta.persistence.FetchType.LAZY;

@Entity
@Table(name = "actor_appearances")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ActorAppearances {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "actor_appearances_id")
private Long id;

@JsonIgnore
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "contents_id")
private Contents contents;

@JsonIgnore
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "actor_id")
private Actor actor;

@Builder
private ActorAppearances(Contents contents, Actor actor) {
setContents(contents);
setActor(actor);
}

public static ActorAppearances of(Contents contents, Actor actor) {
return ActorAppearances.builder()
.contents(contents)
.actor(actor)
.build();
}

private void setContents(Contents contents) {
this.contents = contents;
contents.getActorAppearances().add(this);
}
private void setActor(Actor actor) {
this.actor = actor;
actor.getActorAppearances().add(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.customerservice.actor.repository;

import com.example.customerservice.actor.entity.ActorAppearances;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ActorAppearancesRepository extends JpaRepository<ActorAppearances, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.customerservice.actor.repository;

import com.example.customerservice.actor.entity.Actor;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface ActorRepository extends JpaRepository<Actor, Long> {

Optional<Actor> findByActorName(String actorName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.customerservice.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class MovieSchedulerConfig {

@Bean(name = "movieTaskScheduler")
public ThreadPoolTaskScheduler movieTaskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("MovieUpdateScheduler-");
scheduler.initialize();
return scheduler;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package com.example.customerservice.contents.entity;

import com.example.customerservice.actor.entity.ActorAppearances;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

import static jakarta.persistence.CascadeType.ALL;

@Getter
@Entity
@Table(name="contents")
Expand Down Expand Up @@ -34,6 +40,9 @@ public class Contents {
@Column
private Long heartCount;

@OneToMany(mappedBy = "contents", cascade = ALL)
private List<ActorAppearances> actorAppearances = new ArrayList<>();

@Builder
public Contents(String category, String title, String writer, String summary, String image, Long heartCount) {
this.category = category;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@
public interface ContentsRepository extends JpaRepository<Contents, Long> {
@Query("SELECT CONCAT(c.title, '|', c.writer) FROM Contents c")
List<String> findAllTitlesAndWriters();

boolean existsByTitle(String title);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package com.example.customerservice.movie.client;

import com.example.customerservice.movie.dto.KoficMovieInfoDto;
import com.example.customerservice.movie.dto.KoficMovieListDto;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

@Slf4j
@Component
public class MovieApiClient {

private final RestTemplate restTemplate;
private final String KOFIC_URL = "https://kobis.or.kr/kobisopenapi/webservice/rest/movie";
private final String API_KEY;

public MovieApiClient(@Value("${kofic.key}") String API_KEY) {
this.restTemplate = new RestTemplate();
this.API_KEY = API_KEY;
}

/**
* 1 전체 페이지를 조회합니다.
*/
public Integer fetchMoviesTotalsCount() {
LocalDate today = LocalDate.now();

String date = today.format(DateTimeFormatter.ofPattern("yyyy"));

URI uri = UriComponentsBuilder.fromUriString(KOFIC_URL + "/searchMovieList.json")
.queryParam("key", API_KEY)
.queryParam("curPage", "1")
.queryParam("itemPerPage", "100")
.queryParam("openStartDt", date)
.build()
.toUri();

try {
String response = restTemplate.getForObject(uri, String.class);
ObjectMapper objectMapper = new ObjectMapper();
KoficMovieListDto koficMovieListDto = objectMapper.readValue(response, KoficMovieListDto.class);

return koficMovieListDto.getMovieListResult().getTotalCount();
} catch (Exception e) {
throw new RuntimeException("Failed", e);
}
}

/**
* 2 영화를 조회합니다.
*/
public KoficMovieListDto fetchMovie(int page, int maxResults) {
LocalDate today = LocalDate.now();
String date = today.format(DateTimeFormatter.ofPattern("yyyy"));

URI uri = UriComponentsBuilder.fromUriString(KOFIC_URL + "/searchMovieList.json")
.queryParam("key", API_KEY)
.queryParam("curPage", page)
.queryParam("itemPerPage", maxResults)
.queryParam("openStartDt", date)
.build()
.toUri();

try {
String response = restTemplate.getForObject(uri, String.class);
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(response, KoficMovieListDto.class);
} catch (Exception e) {
throw new RuntimeException("Failed to fetch movie data", e);
}
}

/**
* 3 배우를 조회 합니다.
*/
public KoficMovieInfoDto fetchActor(String movieCode) {

URI uri = UriComponentsBuilder.fromUriString(KOFIC_URL + "/searchMovieInfo.json")
.queryParam("key", API_KEY)
.queryParam("movieCd", movieCode)
.build()
.toUri();

try {
String response = restTemplate.getForObject(uri, String.class);
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(response, KoficMovieInfoDto.class);
} catch (Exception e) {
throw new RuntimeException("Failed", e);
}
}


/**
* batch 에 사용합니다.
* 요청이 많아지면 API 키 만료 되서 사용 X
*/
// public KoficMovieListDto fetchBathMovie(int page, int maxResults) {
// LocalDate today = LocalDate.now();
//
// String startDate = today.minusYears(2).format(DateTimeFormatter.ofPattern("yyyy"));
// String endDate = today.format(DateTimeFormatter.ofPattern("yyyy"));
//
// URI uri = UriComponentsBuilder.fromUriString(KOFIC_URL + "/searchMovieList.json")
// .queryParam("key", API_KEY)
// .queryParam("curPage", page)
// .queryParam("itemPerPage", maxResults)
// .queryParam("openStartDt", startDate)
// .queryParam("openEndDt", endDate)
// .build()
// .toUri();
//
// try {
// String response = restTemplate.getForObject(uri, String.class);
// ObjectMapper objectMapper = new ObjectMapper();
// return objectMapper.readValue(response, KoficMovieListDto.class);
// } catch (Exception e) {
// throw new RuntimeException("Failed", e);
// }
// }

// public Integer fetchMoviesTotalsCount() {
// LocalDate today = LocalDate.now();
//
// String startDate = today.minusYears(2).format(DateTimeFormatter.ofPattern("yyyy"));
// String endDate = today.format(DateTimeFormatter.ofPattern("yyyy"));
//
// URI uri = UriComponentsBuilder.fromUriString(KOFIC_URL + "/searchMovieList.json")
// .queryParam("key", API_KEY)
// .queryParam("curPage", "1")
// .queryParam("itemPerPage", "10")
// .queryParam("openStartDt", startDate)
// .queryParam("openEndDt", endDate)
// .build()
// .toUri();
//
// try {
// String response = restTemplate.getForObject(uri, String.class);
// ObjectMapper objectMapper = new ObjectMapper();
// KoficMovieListDto koficMovieListDto = objectMapper.readValue(response, KoficMovieListDto.class);
//
// return koficMovieListDto.getMovieListResult().getTotalCount();
// } catch (Exception e) {
// throw new RuntimeException("Failed", e);
// }
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.example.customerservice.movie.controller;

import com.example.customerservice.contents.entity.SchedulerStatus;
import com.example.customerservice.movie.service.MovieSchedulerService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/movies")
public class MovieController {

private final MovieSchedulerService movieSchedulerService;

@PostMapping("/start")
public ResponseEntity<SchedulerStatus> startScheduler() {
SchedulerStatus status = movieSchedulerService.startMovieSync(true);
return ResponseEntity.ok(status);
}

@PostMapping("/stop")
public ResponseEntity<SchedulerStatus> stopScheduler() {
SchedulerStatus status = movieSchedulerService.stopMovieSync();
return ResponseEntity.ok(status);
}

/** 요청이 많아지면 API 키 만료 되서 사용 X **/
// @GetMapping("/batch")
// public String startBath() {
// movieSchedulerService.startBathSaveMovie();
// return "success";
// }
}
Loading
Loading