Spring(ベース)-第4週-5


1.スケジューラの作成

  • 毎日午前1時に興味のあるカタログタイトルを検索し、最低価格情報を更新するスケジューラ
  • を生成する.

    スケジューラクラス

  • Scheduler.java (src > main > java > com.sparta.week04 > utils)
  • package com.sparta.week04.utils;
    
    import com.sparta.week04.models.ItemDto;
    import com.sparta.week04.models.Product;
    import com.sparta.week04.models.ProductRepository;
    import com.sparta.week04.service.ProductService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @RequiredArgsConstructor // final 멤버 변수를 자동으로 생성합니다.
    @Component // 스프링이 필요 시 자동으로 생성하는 클래스 목록에 추가합니다.
    public class Scheduler {
    
        private final ProductRepository productRepository;
        private final ProductService productService;
        private final NaverShopSearch naverShopSearch;
    
        // 초, 분, 시, 일, 월, 주 순서
        @Scheduled(cron = "0 0 1 * * *")    // 정확히 1시 일 때
        public void updatePrice() throws InterruptedException {
            System.out.println("가격 업데이트 실행");
            // 저장된 모든 관심상품을 조회합니다.
            List<Product> productList = productRepository.findAll();
            for (int i=0; i<productList.size(); i++) {
                // 1초에 한 상품 씩 조회합니다 (Naver 제한)
                TimeUnit.SECONDS.sleep(1);  // 계속 너무많이 요청오면 네이버에서 막음
                // i 번째 관심 상품을 꺼냅니다.
                Product p = productList.get(i);
                // i 번째 관심 상품의 제목으로 검색을 실행합니다.
                String title = p.getTitle();
                String resultString = naverShopSearch.search(title);
                // i 번째 관심 상품의 검색 결과 목록 중에서 첫 번째 결과를 꺼냅니다.
                List<ItemDto> itemDtoList = naverShopSearch.fromJSONtoItems(resultString);
                ItemDto itemDto = itemDtoList.get(0);
                // i 번째 관심 상품 정보를 업데이트합니다.
                Long id = p.getId();
                productService.updateBySearch(id, itemDto);
            }
        }
    }

    ProductServiceクラスの拡張機能

    package com.sparta.week04.service;
    
    import com.sparta.week04.models.ItemDto;
    import com.sparta.week04.models.Product;
    import com.sparta.week04.models.ProductMypriceRequestDto;
    import com.sparta.week04.models.ProductRepository;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Service;
    
    import javax.transaction.Transactional;
    
    @RequiredArgsConstructor
    @Service
    public class ProductService {
    
        private final ProductRepository productRepository;
    
        @Transactional
        public Long update(Long id, ProductMypriceRequestDto requestDto) {
            Product product = productRepository.findById(id).orElseThrow(
                    () -> new NullPointerException("해당 아이디가 존재하지 않습니다.")
            );
            product.update(requestDto);
            return id;
        }
    
        ////////// 추가 //////////
        @Transactional
        public Long updateBySearch(Long id, ItemDto itemDto){
            Product product = productRepository.findById(id).orElseThrow(
                    () -> new IllegalArgumentException("아이디가 존재하지 않습니다")
            );
            product.updateByItemDto(itemDto);
            return id;
        }
        /////////////////////////
    
    
    }
    

    アプリケーションの機能強化

    package com.sparta.week04;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @EnableScheduling   // 추가: 스프링 부트에서 스케줄러가 작동하게 합니다.
    @EnableJpaAuditing // 시간 자동 변경이 가능하도록 합니다.
    @SpringBootApplication // 스프링 부트임을 선언합니다.
    public class Week04Application {
        public static void main(String[] args) {
            SpringApplication.run(Week04Application.class, args);
        }
    }
    

    2.最低価格変更の作成


    setMypriceの作成

    function setMyprice() {
        /**
         * 숙제! myprice 값 설정하기.
         * 1. id가 myprice 인 input 태그에서 값을 가져온다.
         * 2. 만약 값을 입력하지 않았으면 alert를 띄우고 중단한다.
         * 3. PUT /api/product/${targetId} 에 data를 전달한다.
         *    주의) contentType: "application/json",
         *         data: JSON.stringify({myprice: myprice}),
         *         빠뜨리지 말 것!
         * 4. 모달을 종료한다. $('#container').removeClass('active');
         * 5, 성공적으로 등록되었음을 알리는 alert를 띄운다.
         * 6. 창을 새로고침한다. window.location.reload();
         */
            // 1. id가 myprice 인 input 태그에서 값을 가져온다.
        let myprice = $('#myprice').val();
        // 2. 만약 값을 입력하지 않았으면 alert를 띄우고 중단한다.
        if (myprice == '') {
            alert('올바른 가격을 입력해주세요');
            return;
        }
        // 3. PUT /api/product/${targetId} 에 data를 전달한다.
        $.ajax({
            type: "PUT",
            url: `/api/products/${targetId}`,
            contentType: "application/json",
            data: JSON.stringify({myprice: myprice}),
            success: function (response) {
                // 4. 모달을 종료한다. $('#container').removeClass('active');
                $('#container').removeClass('active');
                // 5. 성공적으로 등록되었음을 알리는 alert를 띄운다.
                alert('성공적으로 등록되었습니다.');
                // 6. 창을 새로고침한다. window.location.reload();
                window.location.reload();
            }
        })
    }

    ProductRestControlの強化

    package com.sparta.week04.controller;
    
    import com.sparta.week04.models.Product;
    import com.sparta.week04.models.ProductMypriceRequestDto;
    import com.sparta.week04.models.ProductRepository;
    import com.sparta.week04.models.ProductRequestDto;
    import com.sparta.week04.service.ProductService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다.
    @RestController // JSON으로 데이터를 주고받음을 선언합니다.
    public class ProductRestController {
    
        private final ProductRepository productRepository;
        private final ProductService productService;        // 추가
    
        // 등록된 전체 상품 목록 조회
        @GetMapping("/api/products")
        public List<Product> getProducts() {
            return productRepository.findAll();
        }
    
        // 신규 상품 등록
        @PostMapping("/api/products")
        public Product createProduct(@RequestBody ProductRequestDto requestDto) {
            Product product = new Product(requestDto);
            productRepository.save(product);
            return product;
        }
    
        ////////// 추가 //////////
        // 설정 가격 변경
        @PutMapping("/api/products/{id}")
        public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto requestDto) {
            return productService.update(id, requestDto);
        }
        ////////////////////////
    }