spring기초 4주차 정리

Today Jeeho Learned·2022년 6월 8일
0

Spring

목록 보기
7/31

네이버 쇼핑 api사용

먼저 네이버에서 클라이언트id랑 secret키를 발급받는다.

get 방식으로 요청할때는 네이버에서 지정해준 url에 요청하게 되는데

https://openapi.naver.com/v1/search/shop.json 까지가 지정해준 url이고
< ?query=아디다스 > 이부분은 내가 원하는 값을 지정해주는 것이다.

arc의 헤더값에다가 네이버 인증값들을 넣어주고 지정해준 url에 내가 검색하고자하는 쿼리값을 넣어줘서 요청을 보내니 값들이 요청했던 json 형식으로 출력되었다.

자바코드에서 네이버 api 하기

public class NaverShopSearch {
    public String search() {
        RestTemplate rest = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("~~~~~", "~~~");
        headers.add("~~~~~~~~~", "~~~~~~~~");
        String body = "";

        HttpEntity<String> requestEntity = new HttpEntity<String>(body, headers);
        ResponseEntity<String> responseEntity = rest.exchange("https://openapi.naver.com/v1/search/shop.json?query=iphone", HttpMethod.GET, requestEntity, String.class);
        HttpStatus httpStatus = responseEntity.getStatusCode();
        int status = httpStatus.value();
        String response = responseEntity.getBody();
        System.out.println("Response status: " + status);
        System.out.println(response);

        return response;

    }

    public static void main(String[] args) {
        NaverShopSearch naverShopSearch = new NaverShopSearch();
        naverShopSearch.search();
    }
}

ARC에서 CODE를 누르고 JAVA SPRING을 누르면 내가 스프링에서 사용할 수 있도록 코드를 변경해준다.

나만의 셀렉샵만들기

TimeStamped

@Getter // get 함수를 자동 생성합니다.
@MappedSuperclass // 상속한 클래스에 멤버 변수가 컬럼이 되도록 합니다.
@EntityListeners(AuditingEntityListener.class) // 변경되었을 때 자동으로 기록합니다.
public abstract class Timestamped {
    @CreatedDate // 최초 생성 시점
    private LocalDateTime createdAt;

    @LastModifiedDate // 마지막 변경 시점
    private LocalDateTime modifiedAt;
}
  • getter / MappedSuperclass / @EntityListeners(AuditingEntityListener.class) / abstract 사용하기

  • main에서 @EnableJpaAuditing(시간 자동 변경이 가능하도록 합니다.)를 넣어주는데 jpa에서 timestamp기능을 사용할때는 시간 자동변경기능이 들어가도록 넣어줘야한다.

product 클래스

먼저 요구조건을 살펴보면, title, image, link, lprice, myprice정보가 필요하다.
(이미지, 제목, 가격이 제일 중요하고, 링크와 최저가정보 + 내가설정한 관심가격)

@Getter // get 함수를 일괄적으로 만들어줍니다.
@NoArgsConstructor // 기본 생성자를 만들어줍니다.
@Entity // DB 테이블 역할을 합니다.
public class Product extends Timestamped{

		// ID가 자동으로 생성 및 증가합니다.
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Id
    private Long id;

		// 반드시 값을 가지도록 합니다.
    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String image;

    @Column(nullable = false)
    private String link;

    @Column(nullable = false)
    private int lprice;

    @Column(nullable = false)
    private int myprice;
}

class에는 항상 기본생성자@NoArgsConstructor 와 테이블이기때문에 @Entity임을 알려주고, timestamped를 상속받는다. 또한 private로 멤버변수들이 선언되기때문에 getter을 꼭 사용해주자.

Repository

public interface ProductRepository extends JpaRepository<Product, Long> {
}

jpa를 상속받고, Product을 대상으로 상속받고 long형태이다.

ProductRestController

@RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다.
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class ProductRestController {

    private final ProductRepository productRepository;

    // 등록된 전체 상품 목록 조회
    @GetMapping("/api/products")
    public List<Product> getProducts() {
        return productRepository.findAll();
    }
}

controller 사용시에는 @RestController사용해서 controller임을 알려주고 멤버변수로 repository가 fianl로 들어감을 잊지말자. 또한 반드시 repository를 넣어주기 위해서
@RequiredArgsConstructor를 사용한다.

get api를 만들때에는 상품목록을 조회해주는 것이기때문에 list형으로 반환값을 만들어준다.

DTO

@Getter
public class ProductRequestDto {
    private String title;
    private String link;
    private String image;
    private int lprice;
}

DTO를 관심상품DTO를 생성해주는데 별거없다~

다만 Product에서 dto 생성자를 꼭 생성해주자.

    public Product(ProductRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.image = requestDto.getImage();
        this.link = requestDto.getLink();
        this.lprice = requestDto.getLprice();
        this.myprice = 0;
    }

myprice로 nullable= false이기에 값을 넣어줘야하는데, 내가 설정한 최저가가 0으로 설정해놓고 시작한다.

Service

수정에 가까운 기능인데 한번해보자. 나의 최저가를 설정해줄때 사용하는 수정기능이다.

@RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다.
@Service // 서비스임을 선언합니다.
public class ProductService {

    private final ProductRepository productRepository;

    @Transactional // 메소드 동작이 SQL 쿼리문임을 선언합니다.
    public Long update(Long id, ProductMypriceRequestDto requestDto) {
        Product product = productRepository.findById(id).orElseThrow(
                () -> new NullPointerException("해당 아이디가 존재하지 않습니다.")
        );
        product.update(requestDto);
        return id;
    }
}

fianl repoistory에는 @RequiredArgsConstructor를 선언해주고~ 서비스임을 @Service알려주고~ product클래스의 update 메소드를 생성해줘야한다.

키워드로 상품검색하기

요구사항

  • 검색어를 요구에 따라 바꿀 수 있어야 한다.
  • 검색결과를 문자열에서 DTO로 바꿔야 한다.

검색결과를 문자열에서 DTO로 바꾸기

JSON을 자바에서 다루기 위해선S JSONObject와 JSONArray 클래스가 필요하다.
직접만들기보다는 다른 사람이 만들어놓은 훌륭한 라이브러리를 가져와서 사용한다.
maven central 에서 json을 검색후 가장 많이 사용하는 것으로 고르고
build.gradle > dependencies안에 붙여넣는다. 그리고 dependencies옆에 run을해준다.

  • 문자열 정보를 JSONObject로 바꾸기
JSONObject rjson = new JSONObject(result);

여기서 result는 문자열인데 이 문자열을 JSONObject로 바꿔준다.

    public static void main(String[] args) {
        NaverShopSearch naverShopSearch = new NaverShopSearch();
        String result = naverShopSearch.search("아이맥 ");
        JSONObject rjson = new JSONObject(result);
        JSONArray items = rjson.getJSONArray("items");
        System.out.println(rjson);
    }

rjson을 출력하면 검색한 결과값들이 itmes안에 배열형태로 한줄로 출력된다.

  • JSONObject에서 items 배열 꺼내기

우리는 item안에 있는 키값인데 검색 결과를 꺼내야 하는데

JSONArray items = rsjon.getJSONArray("items");
 for (int i=0; i<items.length(); i++) {
            JSONObject itemJson = (JSONObject) items.get(i);
            System.out.println(itemJson);
            String title = itemJson.getString("title");
            String image = itemJson.getString("image");
            int lprice = itemJson.getInt("lprice");
            String link = itemJson.getString("link");
            System.out.println(lprice);
        }

그리고 item배열의 원소를 하나씩 출력해줄수도있고, 내가 원하는 값들만을 뽑아내서 출력할수도있다. 이런 item의 정보를 넘겨주기위해서 DTO가 필요한데 ItemDto클래스를 만들어보자.


@Getter
public class ItemDto {
    private String title;
    private String link;
    private String image;
    private int lprice;

    public ItemDto(JSONObject itemJson) {
        this.title = itemJson.getString("title");
        this.link = itemJson.getString("link");
        this.image = itemJson.getString("image");
        this.lprice = itemJson.getInt("lprice");
    }
}

기존의 생성자와 다를게 없지만, 생성자를 request로 받아오는 것이 아니고 ,json object형태로 받아와야한다.

public List<ItemDto> fromJSONtoItems(String result) {
        JSONObject rjson = new JSONObject(result);
        JSONArray items = rjson.getJSONArray("items");

        List<ItemDto> itemDtoList = new ArrayList<>();

        for (int i = 0; i < items.length(); i++) {
            JSONObject itemJson = (JSONObject) items.get(i);
            ItemDto itemDto = new ItemDto(itemJson);
            itemDtoList.add(itemDto);
        }
        return itemDtoList;
    }

메인문에서 따로 메소드를 만들어준다.

public List<ItemDto> fromJSONtoItems(String result) {
        JSONObject rjson = new JSONObject(result);
        JSONArray items = rjson.getJSONArray("items");

        List<ItemDto> itemDtoList = new ArrayList<>();

        for (int i = 0; i < items.length(); i++) {
            JSONObject itemJson = (JSONObject) items.get(i);
            ItemDto itemDto = new ItemDto(itemJson);
            itemDtoList.add(itemDto);
        }
        return itemDtoList;
    }

컴포넌트 등록하기

검색을 main메소드에서 진행하는 것이 아니라, controller에서 써야하기때문에 따로 스프링에게 쓸수있도록 해줘야 하는데, 그것이 컴포넌트이다.

스프링에게 필요할때 쓸 수 있는 권한을 주는 것

@Component
public class NaverShopSearch

이렇게 그냥 클래스 위에다가 컴포넌트라고 적어주었다.

이제 컨트롤러를 새로 만들어 주면 되는데

@RequiredArgsConstructor // final 로 선언된 클래스를 자동으로 생성합니다.
@RestController // JSON으로 응답함을 선언합니다.
public class SearchRequestController {

    private final NaverShopSearch naverShopSearch;

    @GetMapping("/api/search")
    public List<ItemDto> getItems(@RequestParam String query) {
        String resultString = naverShopSearch.search(query);
        return naverShopSearch.fromJSONtoItems(resultString);
    }
}

검색어를 받아야하기에 string query를 사용해야하는데 ?물음표 뒤에 오는 검색어를 받아야하는데
스프링에서는 추가적인 장치를 해줘어야하는데 이것이 @RequestParam을 붙여줘야한다!

profile
기록해야 (살아)남는다 !

0개의 댓글