package com.example.restaurant.naver;
import com.example.restaurant.naver.dto.SearchLocalRes;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class NaverClient {
// yaml 파일 사용하는데 @Value 어노테이션을 사용하며
// 내부에 "${}"형태로 yaml에 설정한 대로 기입
@Value("${naver.client.id}")
private String naverClientId;
@Value("${naver.client.secret}")
private String naverSecret;
@Value("${naver.url.search.local}")
private String naverLocalSearchUrl;
@Value("${naver.url.search.image}")
private String naverImageSearchUrl;
public SearchLocalRes localSearch() {
}
public void imageSearch() {
}
}
package com.example.restaurant.naver.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SearchLocalReq {
// 지역 검색 요청 변수에 대한 변수 생성
private String query = ""; // 검색을 원하는 문자열로서 UTF-8로 인코딩한다.
private int display = 1; // 검색 결과 출력 건수 지정(1 ~ 5)
private int start = 1; // 검색 시작 위치로 1만 가능
private String sort = "random"; // 정렬 옵션: random(유사도순), comment(카페/블로그 리뷰 개수 순)
public MultiValueMap<String, String> toMultiValueMap() {
var map = new LinkedMultiValueMap<String, String>();
map.add("query", query);
map.add("display", String.valueOf(display));
map.add("start", String.valueOf(start));
map.add("sort", sort);
return map;
}
}
package com.example.restaurant.naver.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SearchLocalRes {
// 지역 검색 출력 결과를 변수화
private String lastBuildDate; // 검색 결과를 생성한 시간이다.
private int total; // 검색 결과 문서의 총 개수를 의미한다.
private int start; // 검색 결과 문서 중, 문서의 시작점을 의미한다.
private int display; // 검색된 검색 결과의 개수이다.
private List<SearchLocalItem> items; // XML 포멧에서는 item 태그로, JSON 포멧에서는 items 속성으로 표현된다. 개별 검색 결과이며 title, link, description, address, mapx, mapy를 포함한다.
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class SearchLocalItem{
private String title; // 검색 결과 업체, 기관명을 나타낸다.
private String link; // 검색 결과 업체, 기관의 상세 정보가 제공되는 네이버 페이지의 하이퍼텍스트 link를 나타낸다.
private String category; // 검색 결과 업체, 기관의 분류 정보를 제공한다.
private String description; // 검색 결과 업체, 기관명에 대한 설명을 제공한다.
private String telephone; // 빈 문자열 반환. 과거에 제공되던 항목이라 하위 호환성을 위해 존재한다.
private String address; // 검색 결과 업체, 기관명의 주소를 제공한다.
private String roadAddress; // 검색 결과 업체, 기관명의 도로명 주소를 제공한다.
private int mapx; // 검색 결과 업체, 기관명 위치 정보의 x좌표를 제공한다. 제공값은 카텍좌표계 값으로 제공된다. 이 좌표값은 지도 API와 연동 가능하다.
private int mapy; // 검색 결과 업체, 기관명 위치 정보의 y좌표를 제공한다. 제공값은 카텍 좌표계 값으로 제공된다. 이 좌표값은 지도 API와 연동 가능하다.
}
}
package com.example.restaurant.naver;
import com.example.restaurant.naver.dto.SearchLocalReq;
import com.example.restaurant.naver.dto.SearchLocalRes;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
@Component
public class NaverClient {
// yaml 파일 사용하는데 @Value 어노테이션을 사용하며
// 내부에 "${}"형태로 yaml에 설정한 대로 기입
@Value("${naver.client.id}")
private String naverClientId;
@Value("${naver.client.secret}")
private String naverSecret;
@Value("${naver.url.search.local}")
private String naverLocalSearchUrl;
@Value("${naver.url.search.image}")
private String naverImageSearchUrl;
public SearchLocalRes localSearch(SearchLocalReq searchLocalReq) {
var uri = UriComponentsBuilder
.fromUriString(naverLocalSearchUrl)
.queryParams(searchLocalReq.toMultiValueMap())
.build()
.encode()
.toUri();
var headers = new HttpHeaders();
headers.set("X-Naver-Client-Id", naverClientId);
headers.set("X-Naver-Client-Secret", naverSecret);
headers.setContentType(MediaType.APPLICATION_JSON);
var httpEntity = new HttpEntity<>(headers);
var responseType = new ParameterizedTypeReference<SearchLocalRes>(){};
var responseEntity = new RestTemplate()
.exchange(
uri,
HttpMethod.GET,
httpEntity,
responseType
);
return responseEntity.getBody();
}
public void imageSearch() {
}
}
package com.example.restaurant.naver;
import com.example.restaurant.naver.dto.SearchLocalReq;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class NaverClientTest {
@Autowired
private NaverClient naverClient;
@Test
public void searchLocalTest() {
var search = new SearchLocalReq();
search.setQuery("갈비집");
var result = naverClient.searchLocal(search);
System.out.println(result);
}
}
package com.example.restaurant.naver.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SearchImageReq {
// 지역 검색 요청 변수에 대한 변수 생성
private String query = ""; // 검색을 원하는 문자열로서 UTF-8로 인코딩한다.
private int display = 1; // 검색 결과 출력 건수 지정(10 ~ 100)
private int start = 1; // 검색 시작 위치로 최대 1000까지 가능
private String sort = "sim"; // 정렬 옵션: sim (유사도순), date (날짜순)
private String filter = "all "; // 사이즈 필터 옵션: all(전체), large(큰 사이즈), medium(중간 사이즈), small(작은 사이즈)
public MultiValueMap<String, String> toMultiValueMap() {
var map = new LinkedMultiValueMap<String, String>();
map.add("query", query);
map.add("display", String.valueOf(display));
map.add("start", String.valueOf(start));
map.add("sort", sort);
map.add("filter", filter);
return map;
}
}
package com.example.restaurant.naver.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SearchImageRes {
// 지역 검색 출력 결과를 변수화
private String lastBuildDate; // 검색 결과를 생성한 시간이다.
private int total; // 검색 결과 문서의 총 개수를 의미한다.
private int start; // 검색 결과 문서 중, 문서의 시작점을 의미한다.
private int display; // 검색된 검색 결과의 개수이다.
private List<SearchImageItem> items; // XML 포멧에서는 item 태그로, JSON 포멧에서는 items 속성으로 표현된다. 개별 검색 결과이며 title, link, description, address, mapx, mapy를 포함한다.
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class SearchImageItem{
private String title; // 검색 결과 업체, 기관명을 나타낸다.
private String link; // 검색 결과 업체, 기관의 상세 정보가 제공되는 네이버 페이지의 하이퍼텍스트 link를 나타낸다.
private String thumbnail; // 검색 결과 이미지의 썸네일 link를 나타낸다.
private String sizeheight; // 검색 결과 이미지의 썸네일 높이를 나타낸다.
private String sizewidth; // 검색 결과 이미지의 너비를 나타낸다. 단위는 pixel이다.
}
}
package com.example.restaurant.naver;
import com.example.restaurant.naver.dto.SearchImageReq;
import com.example.restaurant.naver.dto.SearchImageRes;
import com.example.restaurant.naver.dto.SearchLocalReq;
import com.example.restaurant.naver.dto.SearchLocalRes;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
@Component
public class NaverClient {
// yaml 파일 사용하는데 @Value 어노테이션을 사용하며
// 내부에 "${}"형태로 yaml에 설정한 대로 기입
@Value("${naver.client.id}")
private String naverClientId;
@Value("${naver.client.secret}")
private String naverSecret;
@Value("${naver.url.search.local}")
private String naverLocalSearchUrl;
@Value("${naver.url.search.image}")
private String naverImageSearchUrl;
public SearchLocalRes searchLocal(SearchLocalReq searchLocalReq) {
var uri = UriComponentsBuilder
.fromUriString(naverLocalSearchUrl)
.queryParams(searchLocalReq.toMultiValueMap())
.build()
.encode()
.toUri();
var headers = new HttpHeaders();
headers.set("X-Naver-Client-Id", naverClientId);
headers.set("X-Naver-Client-Secret", naverSecret);
headers.setContentType(MediaType.APPLICATION_JSON);
var httpEntity = new HttpEntity<>(headers);
var responseType = new ParameterizedTypeReference<SearchLocalRes>(){};
var responseEntity = new RestTemplate()
.exchange(
uri,
HttpMethod.GET,
httpEntity,
responseType
);
return responseEntity.getBody();
}
public SearchImageRes searchImage(SearchImageReq searchImageReq) {
var uri = UriComponentsBuilder
.fromUriString(naverImageSearchUrl)
.queryParams(searchImageReq.toMultiValueMap())
.build()
.encode()
.toUri();
var headers = new HttpHeaders();
headers.set("X-Naver-Client-Id", naverClientId);
headers.set("X-Naver-Client-Secret", naverSecret);
headers.setContentType(MediaType.APPLICATION_JSON);
var httpEntity = new HttpEntity<>(headers);
var responseType = new ParameterizedTypeReference<SearchImageRes>(){};
var responseEntity = new RestTemplate()
.exchange(
uri,
HttpMethod.GET,
httpEntity,
responseType
);
return responseEntity.getBody();
}
}
package com.example.restaurant.naver;
import com.example.restaurant.naver.dto.SearchImageReq;
import com.example.restaurant.naver.dto.SearchLocalReq;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class NaverClientTest {
@Autowired
private NaverClient naverClient;
@Test
public void searchLocalTest() {
var search = new SearchLocalReq();
search.setQuery("갈비집");
var result = naverClient.searchLocal(search);
System.out.println(result);
}
@Test
public void searchImageTest() {
var search = new SearchImageReq();
search.setQuery("갈비집");
var result = naverClient.searchImage(search);
System.out.println(result);
}
}
package com.example.restaurant.wishlist.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
// DB의 엔티티가 변경이 되면 프론트엔드까지도 변수 명에도 영향을 끼치기 때문에
// 변화하는 과정만 있으면 되기에 위험성을 없애기 위해서 Entity랑 분리해서 만든다
@NoArgsConstructor
@AllArgsConstructor
@Data
public class WishListDto { // DB에 저장할 내용
private int index;
private String title; // 음식명, 장소명
private String category; // 카테고리
private String address; // 주소
private String readAddress; // 도로명
private String homePageLink; // 홈페이지 주소
private String imageLink; // 음식, 가게 이미지 주소
private boolean isVisit; // 방문 여부
private int visitCount; // 방문 횟수
private LocalDateTime lastVisitDate; // 마지막 방문 일자
}
package com.example.restaurant.wishlist.service;
import com.example.restaurant.naver.NaverClient;
import com.example.restaurant.naver.dto.SearchImageReq;
import com.example.restaurant.naver.dto.SearchLocalReq;
import com.example.restaurant.wishlist.dto.WishListDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class WishListService {
private final NaverClient naverClient;
public WishListDto search(String query){
// 지역 검색
var searchLocalReq = new SearchLocalReq();
searchLocalReq.setQuery(query);
var searchLocalRes = naverClient.searchLocal(searchLocalReq);
if(searchLocalRes.getTotal() > 0) {
var localItem = searchLocalRes.getItems().stream().findFirst().get();
// 이미지 검색
var imageQuery = localItem.getTitle().replaceAll("<[^>]*>", "");
var searchImageReq = new SearchImageReq();
searchImageReq.setQuery(imageQuery);
var searchImageRes = naverClient.searchImage(searchImageReq);
if(searchImageRes.getTotal() > 0) {
var imageItem = searchImageRes.getItems().stream().findFirst().get();
// 결과를 리턴
var result = new WishListDto();
result.setTitle(localItem.getTitle());
result.setCategory(localItem.getCategory());
result.setAddress(localItem.getAddress());
result.setReadAddress(localItem.getRoadAddress());
result.setHomePageLink(localItem.getLink());
result.setImageLink(imageItem.getLink());
return result;
}
}
return new WishListDto();
}
}
package com.example.restaurant.wishlist.service;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class WishListServiceTest {
@Autowired
private WishListService wishListService;
@Test
public void searchTest() {
var result = wishListService.search("갈비집");
System.out.println(result);
Assertions.assertNotNull(result);
}
}
package com.example.restaurant.controller;
import com.example.restaurant.wishlist.dto.WishListDto;
import com.example.restaurant.wishlist.service.WishListService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/restaurant")
@RequiredArgsConstructor
public class ApiController {
private final WishListService wishListService;
@GetMapping("/search")
public WishListDto search(@RequestParam String query) {
return wishListService.search(query);
}
}
package com.example.restaurant.db;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class MemoryDbEntity {
protected Integer index;
}
package com.example.restaurant.wishlist.entity;
import com.example.restaurant.db.MemoryDbEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class WishListEntity extends MemoryDbEntity { // DB에 저장할 내용
private String title; // 음식명, 장소명
private String category; // 카테고리
private String address; // 주소
private String roadAddress; // 도로명
private String homePageLink; // 홈페이지 주소
private String imageLink; // 음식, 가게 이미지 주소
private boolean isVisit; // 방문 여부
private int visitCount; // 방문 횟수
private LocalDateTime lastVisitDate; // 마지막 방문 일자
}
package com.example.restaurant.wishlist.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
// DB의 엔티티가 변경이 되면 프론트엔드까지도 변수 명에도 영향을 끼치기 때문에
// 변화하는 과정만 있으면 되기에 위험성을 없애기 위해서 Entity랑 분리해서 만든다
@NoArgsConstructor
@AllArgsConstructor
@Data
public class WishListDto { // DB에 저장할 내용
private Integer index;
private String title; // 음식명, 장소명
private String category; // 카테고리
private String address; // 주소
private String roadAddress; // 도로명
private String homePageLink; // 홈페이지 주소
private String imageLink; // 음식, 가게 이미지 주소
private boolean isVisit; // 방문 여부
private int visitCount; // 방문 횟수
private LocalDateTime lastVisitDate; // 마지막 방문 일자
}
package com.example.restaurant.wishlist.service;
import com.example.restaurant.naver.NaverClient;
import com.example.restaurant.naver.dto.SearchImageReq;
import com.example.restaurant.naver.dto.SearchLocalReq;
import com.example.restaurant.wishlist.dto.WishListDto;
import com.example.restaurant.wishlist.entity.WishListEntity;
import com.example.restaurant.wishlist.repository.WishListRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class WishListService {
private final NaverClient naverClient;
private final WishListRepository wishListRepository;
public WishListDto search(String query){
// 지역 검색
var searchLocalReq = new SearchLocalReq();
searchLocalReq.setQuery(query);
var searchLocalRes = naverClient.searchLocal(searchLocalReq);
if(searchLocalRes.getTotal() > 0) {
var localItem = searchLocalRes.getItems().stream().findFirst().get();
// 이미지 검색
var imageQuery = localItem.getTitle().replaceAll("<[^>]*>", "");
var searchImageReq = new SearchImageReq();
searchImageReq.setQuery(imageQuery);
var searchImageRes = naverClient.searchImage(searchImageReq);
if(searchImageRes.getTotal() > 0) {
var imageItem = searchImageRes.getItems().stream().findFirst().get();
// 결과를 리턴
var result = new WishListDto();
result.setTitle(localItem.getTitle());
result.setCategory(localItem.getCategory());
result.setAddress(localItem.getAddress());
result.setRoadAddress(localItem.getRoadAddress());
result.setHomePageLink(localItem.getLink());
result.setImageLink(imageItem.getLink());
return result;
}
}
return new WishListDto();
}
// db에 있는 MemoryDbEntity에 데이터 등록
public WishListDto add(WishListDto wishListDto) {
var entity = dtoToEntity(wishListDto);
var saveEntity = wishListRepository.save(entity);
return entityToDto(saveEntity);
}
private WishListEntity dtoToEntity(WishListDto wishListDto) {
var entity = new WishListEntity();
entity.setIndex(wishListDto.getIndex());
entity.setTitle(wishListDto.getTitle());
entity.setCategory(wishListDto.getCategory());
entity.setAddress(wishListDto.getAddress());
entity.setRoadAddress(wishListDto.getRoadAddress());
entity.setHomePageLink(wishListDto.getHomePageLink());
entity.setImageLink(wishListDto.getImageLink());
entity.setVisit(wishListDto.isVisit());
entity.setVisitCount(wishListDto.getVisitCount());
entity.setLastVisitDate(wishListDto.getLastVisitDate());
return entity;
}
private WishListDto entityToDto(WishListEntity wishListEntity) {
var dto = new WishListDto();
dto.setIndex(wishListEntity.getIndex());
dto.setTitle(wishListEntity.getTitle());
dto.setCategory(wishListEntity.getCategory());
dto.setAddress(wishListEntity.getAddress());
dto.setRoadAddress(wishListEntity.getRoadAddress());
dto.setHomePageLink(wishListEntity.getHomePageLink());
dto.setImageLink(wishListEntity.getImageLink());
dto.setVisit(wishListEntity.isVisit());
dto.setVisitCount(wishListEntity.getVisitCount());
dto.setLastVisitDate(wishListEntity.getLastVisitDate());
return dto;
}
}
package com.example.restaurant.controller;
import com.example.restaurant.wishlist.dto.WishListDto;
import com.example.restaurant.wishlist.service.WishListService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/api/restaurant")
@RequiredArgsConstructor
public class ApiController {
private final WishListService wishListService;
@GetMapping("/search")
public WishListDto search(@RequestParam String query) {
return wishListService.search(query);
}
@PostMapping("")
public WishListDto add(@RequestBody WishListDto wishListDto) {
log.info("{}", wishListDto);
return wishListService.add(wishListDto);
}
}
package com.example.restaurant.wishlist.service;
import com.example.restaurant.naver.NaverClient;
import com.example.restaurant.naver.dto.SearchImageReq;
import com.example.restaurant.naver.dto.SearchLocalReq;
import com.example.restaurant.wishlist.dto.WishListDto;
import com.example.restaurant.wishlist.entity.WishListEntity;
import com.example.restaurant.wishlist.repository.WishListRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class WishListService {
private final NaverClient naverClient;
private final WishListRepository wishListRepository;
public WishListDto search(String query){
// 지역 검색
var searchLocalReq = new SearchLocalReq();
searchLocalReq.setQuery(query);
var searchLocalRes = naverClient.searchLocal(searchLocalReq);
if(searchLocalRes.getTotal() > 0) {
var localItem = searchLocalRes.getItems().stream().findFirst().get();
// 이미지 검색
var imageQuery = localItem.getTitle().replaceAll("<[^>]*>", "");
var searchImageReq = new SearchImageReq();
searchImageReq.setQuery(imageQuery);
var searchImageRes = naverClient.searchImage(searchImageReq);
if(searchImageRes.getTotal() > 0) {
var imageItem = searchImageRes.getItems().stream().findFirst().get();
// 결과를 리턴
var result = new WishListDto();
result.setTitle(localItem.getTitle());
result.setCategory(localItem.getCategory());
result.setAddress(localItem.getAddress());
result.setRoadAddress(localItem.getRoadAddress());
result.setHomePageLink(localItem.getLink());
result.setImageLink(imageItem.getLink());
return result;
}
}
return new WishListDto();
}
// db에 있는 MemoryDbEntity에 데이터 등록
public WishListDto add(WishListDto wishListDto) {
var entity = dtoToEntity(wishListDto);
var saveEntity = wishListRepository.save(entity);
return entityToDto(saveEntity);
}
private WishListEntity dtoToEntity(WishListDto wishListDto) {
var entity = new WishListEntity();
entity.setIndex(wishListDto.getIndex());
entity.setTitle(wishListDto.getTitle());
entity.setCategory(wishListDto.getCategory());
entity.setAddress(wishListDto.getAddress());
entity.setRoadAddress(wishListDto.getRoadAddress());
entity.setHomePageLink(wishListDto.getHomePageLink());
entity.setImageLink(wishListDto.getImageLink());
entity.setVisit(wishListDto.isVisit());
entity.setVisitCount(wishListDto.getVisitCount());
entity.setLastVisitDate(wishListDto.getLastVisitDate());
return entity;
}
private WishListDto entityToDto(WishListEntity wishListEntity) {
var dto = new WishListDto();
dto.setIndex(wishListEntity.getIndex());
dto.setTitle(wishListEntity.getTitle());
dto.setCategory(wishListEntity.getCategory());
dto.setAddress(wishListEntity.getAddress());
dto.setRoadAddress(wishListEntity.getRoadAddress());
dto.setHomePageLink(wishListEntity.getHomePageLink());
dto.setImageLink(wishListEntity.getImageLink());
dto.setVisit(wishListEntity.isVisit());
dto.setVisitCount(wishListEntity.getVisitCount());
dto.setLastVisitDate(wishListEntity.getLastVisitDate());
return dto;
}
public List<WishListDto> findAll() {
return wishListRepository.listAll()
.stream()
.map(it -> entityToDto(it))
.collect(Collectors.toList());
}
}
package com.example.restaurant.controller;
import com.example.restaurant.wishlist.dto.WishListDto;
import com.example.restaurant.wishlist.service.WishListService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/api/restaurant")
@RequiredArgsConstructor
public class ApiController {
private final WishListService wishListService;
@GetMapping("/search")
public WishListDto search(@RequestParam String query) {
return wishListService.search(query);
}
@PostMapping("")
public WishListDto add(@RequestBody WishListDto wishListDto) {
log.info("{}", wishListDto);
return wishListService.add(wishListDto);
}
@GetMapping("/all")
public List<WishListDto> findAll() {
return wishListService.findAll();
}
}
package com.example.restaurant.wishlist.service;
import com.example.restaurant.naver.NaverClient;
import com.example.restaurant.naver.dto.SearchImageReq;
import com.example.restaurant.naver.dto.SearchLocalReq;
import com.example.restaurant.wishlist.dto.WishListDto;
import com.example.restaurant.wishlist.entity.WishListEntity;
import com.example.restaurant.wishlist.repository.WishListRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class WishListService {
private final NaverClient naverClient;
private final WishListRepository wishListRepository;
public WishListDto search(String query){
// 지역 검색
var searchLocalReq = new SearchLocalReq();
searchLocalReq.setQuery(query);
var searchLocalRes = naverClient.searchLocal(searchLocalReq);
if(searchLocalRes.getTotal() > 0) {
var localItem = searchLocalRes.getItems().stream().findFirst().get();
// 이미지 검색
var imageQuery = localItem.getTitle().replaceAll("<[^>]*>", "");
var searchImageReq = new SearchImageReq();
searchImageReq.setQuery(imageQuery);
var searchImageRes = naverClient.searchImage(searchImageReq);
if(searchImageRes.getTotal() > 0) {
var imageItem = searchImageRes.getItems().stream().findFirst().get();
// 결과를 리턴
var result = new WishListDto();
result.setTitle(localItem.getTitle());
result.setCategory(localItem.getCategory());
result.setAddress(localItem.getAddress());
result.setRoadAddress(localItem.getRoadAddress());
result.setHomePageLink(localItem.getLink());
result.setImageLink(imageItem.getLink());
return result;
}
}
return new WishListDto();
}
// db에 있는 MemoryDbEntity에 데이터 등록
public WishListDto add(WishListDto wishListDto) {
var entity = dtoToEntity(wishListDto);
var saveEntity = wishListRepository.save(entity);
return entityToDto(saveEntity);
}
private WishListEntity dtoToEntity(WishListDto wishListDto) {
var entity = new WishListEntity();
entity.setIndex(wishListDto.getIndex());
entity.setTitle(wishListDto.getTitle());
entity.setCategory(wishListDto.getCategory());
entity.setAddress(wishListDto.getAddress());
entity.setRoadAddress(wishListDto.getRoadAddress());
entity.setHomePageLink(wishListDto.getHomePageLink());
entity.setImageLink(wishListDto.getImageLink());
entity.setVisit(wishListDto.isVisit());
entity.setVisitCount(wishListDto.getVisitCount());
entity.setLastVisitDate(wishListDto.getLastVisitDate());
return entity;
}
private WishListDto entityToDto(WishListEntity wishListEntity) {
var dto = new WishListDto();
dto.setIndex(wishListEntity.getIndex());
dto.setTitle(wishListEntity.getTitle());
dto.setCategory(wishListEntity.getCategory());
dto.setAddress(wishListEntity.getAddress());
dto.setRoadAddress(wishListEntity.getRoadAddress());
dto.setHomePageLink(wishListEntity.getHomePageLink());
dto.setImageLink(wishListEntity.getImageLink());
dto.setVisit(wishListEntity.isVisit());
dto.setVisitCount(wishListEntity.getVisitCount());
dto.setLastVisitDate(wishListEntity.getLastVisitDate());
return dto;
}
public List<WishListDto> findAll() {
return wishListRepository.listAll()
.stream()
.map(it -> entityToDto(it))
.collect(Collectors.toList());
}
public void delete(int index) {
wishListRepository.deleteById(index);
}
public void addVisit(int index) {
var wishItem = wishListRepository.findById(index);
if(wishItem.isPresent()) {
var item = wishItem.get();
item.setVisit(true);
item.setVisitCount(item.getVisitCount()+1);
}
}
}
package com.example.restaurant.controller;
import com.example.restaurant.wishlist.dto.WishListDto;
import com.example.restaurant.wishlist.service.WishListService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/api/restaurant")
@RequiredArgsConstructor
public class ApiController {
private final WishListService wishListService;
@GetMapping("/search")
public WishListDto search(@RequestParam String query) {
return wishListService.search(query);
}
@PostMapping("")
public WishListDto add(@RequestBody WishListDto wishListDto) {
log.info("{}", wishListDto);
return wishListService.add(wishListDto);
}
@GetMapping("/all")
public List<WishListDto> findAll() {
return wishListService.findAll();
}
@DeleteMapping("/{index}")
public void delete(@PathVariable int index) {
wishListService.delete(index);
}
@PostMapping("/{index}")
public void addVisit(@PathVariable int index) {
wishListService.addVisit(index);
}
}
package com.example.restaurant.db;
import java.util.List;
import java.util.Optional;
public interface MemoryDbRepositoryIfs<T> {
Optional<T> findById(int index);
T save(T entity);
void deleteById(int index);
List<T> findAll();
}