SpringBoot

SpringBoot - @Schedulder, @Data, Builder (2024.05.15)

hminor 2024. 5. 15. 18:11

2024.05.15(수) 

1. 스케줄러
main에 @EnableScheduling 어노테이션을 적용 후
controller에서 @Scheduled 어노테이션의 cron 속성을 활용하여
주식장이 열리는 시간과 유사하게 우선은 월요일에서 금요일 오전 9-15:30분까지 조회하되
4분 주기로 조회하도록 코드를 작성

// controller
@Scheduled(cron = "0 */4 9-14 * * 1-5")
@Scheduled(cron = "0 0-30/4 15 * * 1-5")
public void getStockScrapScheduled() throws IOException{
    stockService.saveStockService();
}
// service
public void saveStockService() throws IOException {
    Document doc = Jsoup.connect("https://finance.naver.com/sise/sise_quant.naver?sosok=0").get();
    Elements rows = doc.select("table.type_2 tbody tr"); // 위 링크에 있는 tbody에 있는 tr 데이터를 모두 조회

    StockEntity stock = new StockEntity();
    stock.setCreatedAt(LocalDateTime.now());
    StockEntity saveStock = stockRepository.save(stock);

    List<DetailStockEntity> detailStockList = new ArrayList<>();

    for (Element row : rows) {
        // 각 행에서 데이터 추출
        String 종목명 = row.select("td:nth-child(2) a").text();
        String 전일비 = row.select("td:nth-child(4)").text().replaceAll(",","");
        String 등락률 = row.select("td:nth-child(5)").text();
        String[] 전일비_li = 전일비.split(" ");
        // NaN 값이 포함되지 않은 행만 처리
        Integer cnt = 0;
        if (!종목명.isEmpty() && !전일비.isEmpty() && !등락률.isEmpty()) {
            System.out.println(++cnt);

            Integer lastRate = 0;
            if (전일비_li[0].substring(0,2).equals("보합")) {
                lastRate = Integer.parseInt(전일비_li[0].substring(2));
                System.out.println(전일비_li[0].substring(2));
            }
            else if (전일비_li[0].equals("상승")){ lastRate = Integer.parseInt(전일비_li[1]);}
            else {lastRate = Integer.parseInt(전일비_li[1])*-1;}

            BigDecimal fluctuationRate = new BigDecimal(등락률.replaceAll("%",""));

            DetailStockEntity detailStock = DetailStockEntity.builder()
                    .stockName(종목명)
                    .lastRate(lastRate)
                    .fluctuationRate(fluctuationRate)
                    .stock(saveStock)
                    .createdAt(saveStock.getCreatedAt())
                    .build();

            detailStockList.add(detailStock);
        }
        detailStockRepository.saveAll(detailStockList);
        System.out.println("조회 완료");
    }
}
 




2. @Data
해당 어노테이션은 클래스에 대한 Getter, Setter, Equals, HashCode, ToString 등의 메서드를 자동으로 생성.

 

3. Builder
DetailStockRepository에 저장한 데이터를 모두 가져오는 과정에서
원하는 데이터만 가져오기 위해 dto를 만들었는데 repository에서 가져온 주식 데이터를 dto로 변경하는 과정은
forEach로 조회한 상세 주식 데이터를 DetailStockReqDto 타입의 변수를 만들고
DetailStockReqDto 클래스의 builder를 사용해서 데이터를 넣어주고 감싸주면 됨.
다만 순간 헷갈린 점으론 타입은 DetailStockReqDto의 변수를 만들었는데
` 뭔가 DetailStockEntity에 따로 builder 어노테이션을 적용한 메서드를 만들어야 하는건가
고민을 했었지만 단순히 Dto 클래스를 불러와서 builder로 감싸주면 되는 것을 다시 상기했음.