diff --git a/src/main/java/com/example/capd/User/domain/Contest.java b/src/main/java/com/example/capd/User/domain/Contest.java index e8105f4..0b28603 100644 --- a/src/main/java/com/example/capd/User/domain/Contest.java +++ b/src/main/java/com/example/capd/User/domain/Contest.java @@ -3,37 +3,53 @@ import jakarta.persistence.*; import lombok.AccessLevel; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.util.ArrayList; -import java.util.List; -@Entity +@Entity(name = "contest") @Getter -@AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) -//테스트용 +@Builder +@AllArgsConstructor public class Contest { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(length = 200) private String title; - //참여할게요 매핑 - @OneToMany(mappedBy = "contest") - private List participations = new ArrayList<>(); + @Column(length = 200) + private String host; + + @Column(length = 200) + private String targetParticipants; + + @Column(length = 40) + private String receptionPeriod; + + @Column(length = 40) + private String decisionPeriod; + + @Column(length = 200) + private String compatitionArea; + + @Column(length = 200) + private String award; + @Column(length = 300) + private String homepage; - //유저 매핑 -// @ManyToOne -// @JoinColumn(name = "user_id") -// private User user; + @Column(length = 20) + private String howToApply; - // 팀 매핑 - @OneToMany(mappedBy = "contest") - private List teams = new ArrayList<>(); + @Column(length = 20) + private String fee; + @Column(length = 400) + private String image; + @Column(length = 2000) + private String detailText; } diff --git a/src/main/java/com/example/capd/contest/controller/ContestController.java b/src/main/java/com/example/capd/contest/controller/ContestController.java new file mode 100644 index 0000000..6c5c062 --- /dev/null +++ b/src/main/java/com/example/capd/contest/controller/ContestController.java @@ -0,0 +1,24 @@ +package com.example.capd.contest.controller; + +import com.example.capd.contest.controller.dto.ContestResponse; +import com.example.capd.contest.service.ContestService; +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 java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/contests") +public class ContestController { + private final ContestService contestService; + + @GetMapping + public ResponseEntity> findAllContest() { + final List contestResponses = contestService.findAllContest(); + return ResponseEntity.ok(contestResponses); + } +} diff --git a/src/main/java/com/example/capd/contest/controller/dto/ContestResponse.java b/src/main/java/com/example/capd/contest/controller/dto/ContestResponse.java new file mode 100644 index 0000000..591659d --- /dev/null +++ b/src/main/java/com/example/capd/contest/controller/dto/ContestResponse.java @@ -0,0 +1,17 @@ +package com.example.capd.contest.controller.dto; + +public record ContestResponse( + Long id, + String title, + String host, + String targetParticipants, + String receptionPeriod, + String decisionPeriod, + String compatitionArea, + String award, + String homepage, + String howToApply, + String fee, + String image, + String detailText +){} diff --git a/src/main/java/com/example/capd/contest/repository/ContestRepository.java b/src/main/java/com/example/capd/contest/repository/ContestRepository.java new file mode 100644 index 0000000..2c64ac8 --- /dev/null +++ b/src/main/java/com/example/capd/contest/repository/ContestRepository.java @@ -0,0 +1,18 @@ +package com.example.capd.contest.repository; + +import com.example.capd.User.domain.Contest; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Repository +public interface ContestRepository extends JpaRepository { + + @Query(value = "select * from capstone_crawling.contest", nativeQuery = true) + List> fetchDataFromDatabase(); + + Contest findByTitle(String title); +} \ No newline at end of file diff --git a/src/main/java/com/example/capd/contest/service/ContestService.java b/src/main/java/com/example/capd/contest/service/ContestService.java new file mode 100644 index 0000000..2c2ac1a --- /dev/null +++ b/src/main/java/com/example/capd/contest/service/ContestService.java @@ -0,0 +1,38 @@ +package com.example.capd.contest.service; + +import com.example.capd.User.domain.Contest; +import com.example.capd.contest.controller.dto.ContestResponse; +import com.example.capd.contest.repository.ContestRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class ContestService { + private final ContestRepository contestRepository; + + @Transactional(readOnly = true) + public List findAllContest() { + final List contests = contestRepository.findAll(); + + return contests.stream() + .map(contest -> new ContestResponse( + contest.getId(), + contest.getTitle(), + contest.getHost(), + contest.getTargetParticipants(), + contest.getReceptionPeriod(), + contest.getDecisionPeriod(), + contest.getCompatitionArea(), + contest.getAward(), + contest.getHomepage(), + contest.getHowToApply(), + contest.getFee(), + contest.getImage(), + contest.getDetailText())).toList(); + } +} diff --git a/src/main/java/com/example/capd/contest/service/CrawlingScriptService.java b/src/main/java/com/example/capd/contest/service/CrawlingScriptService.java new file mode 100644 index 0000000..daf7efa --- /dev/null +++ b/src/main/java/com/example/capd/contest/service/CrawlingScriptService.java @@ -0,0 +1,80 @@ +package com.example.capd.contest.service; + +import com.example.capd.User.domain.Contest; +import com.example.capd.contest.repository.ContestRepository; +import lombok.RequiredArgsConstructor; +import org.apache.tomcat.util.json.JSONParser; +import org.apache.tomcat.util.json.ParseException; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.io.FileReader; +import java.io.IOException; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class CrawlingScriptService { + + private final ContestRepository contestRepository; + private final List filePath = + List.of("contestkorea__contest_data.json", + "wevity_contest_data.json", + "thinkgood_contest_data.json"); + + @Scheduled(fixedRate = 30000) + public void executeCrawlingScript() { + try { + String pythonScriptPath = "C:/IntelliJ/crawlingpracticeCopy/src/main/java/crawlingpractice/example/crawlingpractice/contestkorea_crawling.py"; + + ProcessBuilder processBuilder = new ProcessBuilder("python", pythonScriptPath); + processBuilder.redirectErrorStream(true); + Process process = processBuilder.start(); + + int exitCode = process.waitFor(); + System.out.println("파이썬 스크립트 실행 종료, 종료 코드: " + exitCode); + + filePath.forEach(this::readContestkorea); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } + + private void readContestkorea(final String siteName) { + try (FileReader reader = new FileReader(siteName)) { + JSONParser parser = new JSONParser(reader); + JSONArray jsonArray = (JSONArray) parser.parse(); + + for (Object json : jsonArray) { + JSONObject jsonObj = (JSONObject) json; + String contestTitle = (String) jsonObj.get(siteName); + + Contest existingContest = contestRepository.findByTitle(contestTitle); + if (existingContest != null) { + continue; + } + + final Contest contest = Contest.builder() + .title((String) jsonObj.get("contest_title")) + .host((String) jsonObj.get("contest_host")) + .targetParticipants((String) jsonObj.get("contest_target_participants")) + .receptionPeriod((String) jsonObj.get("contest_reception_period")) + .decisionPeriod((String) jsonObj.get("contest_decision_period")) + .compatitionArea((String) jsonObj.get("contest_compatition_area")) + .award((String) jsonObj.get("contest_award")) + .homepage((String) jsonObj.get("contest_homepage")) + .howToApply((String) jsonObj.get("contest_how_to_apply")) + .fee((String) jsonObj.get("contest_fee")) + .image((String) jsonObj.get("contest_image")) + .detailText((String) jsonObj.get("contest_detail_text")) + .build(); + + contestRepository.save(contest); + } + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file