src
main
ㄴ resources
ㄴ static
ㄴ templates
ㄴ application.properties
ㄴ java
ㄴ com.sparta.springcore
ㄴ controller
ㄴ ProductController
ㄴ SearchRequestController
ㄴ dto
ㄴ ItemDto
ㄴ ProductMyPriceRequestDto
ㄴ ProductRequestDto
ㄴ model
ㄴ Product
ㄴ Timestamped
ㄴ repository
ㄴ ProductRepository (i)
ㄴ sevice
ㄴ ProductService
ㄴ util
ㄴ NaverShopSearch
ㄴ SpringcoreApplication
타임라인 API
기능 | Method | URL | Return |
---|---|---|---|
관심 상품 검색,목록 보여주기 | GET | /api/search?query=검색어 | List<'ItemDto'> |
관심 상품 조회 | GET | /api/products/ | List<'Product'> |
관심 상품 등록 | POST | /api/products/ | Product |
관심 상품 가격 등록 | PUT | /api/products/{id} | Long |
요구기능
- 상품명에 따른 검색, 그 결과를 목록으로 보여주기
- 관심 상품 등록 & 조회
- 관심 상품에 대한 최저가 등록하기
# build.gradle 파일의 dependencies에 추가
implementation group: 'org.json', name: 'json', version: '20160810'
@Controller
class ExamController {
@GetMapping("/home")
public String home() {
return "/home.html";
}
}
# String객체로 html 보내주면 view가 해당 html 찾아서 클라이언트에게 보내줌
# Json 형태를 보내고 싶으면 @ResponseBody 추가
@Controller
class ExamController {
@Autowired
private ProductRepository productRepository
@GetMapping("/product/list")
public @ResponseBody List<Product> getProducts() {
return productRepository.findAll();
}
}
# Json 형태만 보낼 때 @Controller + RequestBody
@RestController
class ExamController {
@Autowired
private ProductRepository productRepository
@GetMapping("/product/list")
public List<Product> getProducts() {
return productRepository.findAll();
}
}
Controller : 클라이언트의 요청 받고 응답해줌
: 요청에 대한 처리는 Service에게
Service : 비즈니스 로직을 처리 (서버에서 사용자의 요구사항 처리)
: DB정보가 필요할 때에는 Repositroy에게
Repository : DB관리 , DB CRUD 작업처리
Refactorying
# ProductServie
// ProductService에서 필요할 때마다
// new ProductRepository로 객체 생성해서 사용 (중복)
public class ProductService {
public List<Product> getProducts() throws SQLException {
ProductRepository productRepository = new ProductRepository();
// ...
}
public Product createProduct(ProductRequestDto requestDto) throws SQLException {
ProductRepository productRepository = new ProductRepository();
// ...
}
public Product updateProduct(Long id, ProductMypriceRequestDto requestDto) throws SQLException {
ProductRepository productRepository = new ProductRepository();
// ...
}
}
# 멤버 변수로 ProductRepository 만들어 중복 줄임
public class ProductService {
// 멤버 변수 선언
private final ProductRepository productRepository;
// 생성자
public ProductService() {
// 멤버 변수 생성(this 지시자 생략 가능)
this.oductRepository = new ProductRepository();
}
public List<Product> getProducts() throws SQLException {
// 멤버 변수 사용 (this 지시자 생략 가능!)
return this.productRepository.getProducts();
}
// ...
}
}
서비스가 늘어나면서 계속 리포지토리를 만들면 그 개수가 증가하게 됨
하나의 객체에서 다른 객체가 필요할 때, 객체를 직접 생성하지 않고, 이미 생성되어 있는 객체를 가져오는 작업(Dependency Injection)
IoC(Inversion of Control) : 제어의 역전
사용자가 자신이 필요한 객체를 생성해서 사용하는 것이 일반적인데, 그 반대라 제어의 역전이라고도 함
Repository1 객체 생성 (ID,PW 입력)
Service1 객체 생성 (이미 생성된 Repository1 DI)
Controller 5개 생성 (이미 생성된 Service1 DI)
public class ProductRepository {
private String dbId;
private String dbPassword;
// 생성자
public ProductRepository(String dbId, String dbPassword) {
this.dbId = dbId;
this.dbPassword = dbPassword;
}
}
public class ProductService {
// 멤버 변수 선언
private final ProductRepository productRepository;
// 생성자: ProductService() 가 생성될 때 호출됨
public ProductService(String dbId,String dbPassword) {
// 멤버 변수 생성
this.productRepository = new ProductRepository(dbId, dbPassword);
}
}
public class ProductController {
// 멤버 변수 선언
private final ProductService productService;
// 생성자: ProductController() 가 생성될 때 호출됨
public ProductController() {
// 멤버 변수 생성
String dbId = "sa";
String dbPassword = "";
productService = new ProductService(dbId, dbPassword);
}
}
controller(service)
service(repository)
respository -> DB
(미리 생성)
# productRepository 미리 생성
String dbId = "sa";
String dbPassword = "";
ProductRepository productRepository = new ProductRepository(dbId, dbPassword);
# productRepository 사용
public class ProductService {
private final ProductRepository productRepository;
// 사용
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
}
// 사용
ProductService productService = new ProductService(productRepository);
# productService 사용
public class ProductController {
private final ProductService productService;
// 사용
public ProductController(ProductService productService) {
this.productService = productService;
}
}
// 사용
ProductController productController = new ProductController(productService);
// 이 때 추가적으로 ProductRepository에 DB의 URL이 필요해짐
public class ProductRepository {
private String dbId;
private String dbPassword;
private String dbUrl; // 추가!!
// 생성자
public ProductRepository(String dbId, String dbPassword, String dbUrl) {
this.dbId = dbId;
this.dbPassword = dbPassword;
this.dbUrl = dbUrl;
}
}
-> 생성자에 어떠한 변화가 생겨도 service, controller 모두 고칠 필요 없음
-> ProductRepository가 만들어지는 곳에서만 변경되면 됨
String dbId = "sa";
String dbPassword = "";
String dbUrl = "jdbc:h2:mem:springcoredb"; // 추가
// 변경
ProductRepository productRepository = new ProductRepository(dbId, dbPassword, dbUrl);
# BeanConfiguration 파일 만듦
# Bean으로 ProductRepository, ProductService 만듦
@Configuration
public class BeanConfiguration {
@Bean
public ProductRepository productRepository() {
String dbId = "sa";
String dbPassword = "";
String dbUrl = "jdbc:h2:mem:springcoredb";
return new ProductRepository(dbId, dbPassword, dbUrl);
}
@Bean
@Autowired
public ProductService productService(ProductRepository productRepository) {
return new ProductService(productRepository);
}
}
public interface ProductRepository extends JpaRepository<Product, Long> {}
Entity, id 타입
# extends 라면 @ 없어도 자동으로 @Repository로 추가됨
# 원래 class로 선언되야 하지만 JPA가 알아서 class로 만들고 객체로 만들어서 Bean으로 등록해 줌
# productService
getProduct() -> findAll()
createProduct() -> save()
getProduct(Id) -> findByID(Id) .orElseThrow() 필요
updatePrice()
-> 1. save(product)
public Product updateProduct(Long id, ProductMypriceRequestDto requestDto) throws SQLException {
Product product = productRepository.findById(id)
.orElseThrow(() -> new NullPointerException("해당 아이디가 존재하지 않습니다."));
int myPrice = requestDto.getMyprice();
product.setMyprice(myPrice);
productRepository.save(product);
return product;
}
-> 2. @Transactional
@Transactional
public Product updateProduct(Long id, ProductMypriceRequestDto requestDto) throws SQLException {
Product product = productRepository.findById(id)
.orElseThrow(() -> new NullPointerException("해당 아이디가 존재하지 않습니다."));
int myPrice = requestDto.getMyprice();
product.updateMyPrice(myPrice); 함수 만들어 사용
return product;
}
-> updateMyPrice 함수 만들고
-> create Methodf로 Product에도 새로 메소드 생성
findAll() 함수들을 알아보려면
JPARepository(ProductRepository) - Go to (op+cmd+B)
- SimpleJpaRepository에서 찾아보면됨
findById(), save() 등 다 구현되어 있음
# ProductService
@Service
public class ProductService {
private final ProductRepository productRepository; // 멤버 변수 선언
// 생성자: ProductService() 가 생성될 때 호출됨
@Autowired
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository; // 멤버 변수 생성
}
public List<Product> getProducts() {
return productRepository.findAll(); // 멤버 변수 사용
}
@Transactional // 메소드 동작이 SQL 쿼리문임을 선언
public Product createProduct(ProductRequestDto requestDto){
Product product = new Product(requestDto); // 요청받은 DTO 로 DB에 저장할 객체 만들기
productRepository.save(product);
return product;
}
@Transactional
public Product updateProduct(Long id, ProductMypriceRequestDto requestDto) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new NullPointerException("해당 아이디가 존재하지 않습니다."));
int myPrice = requestDto.getMyprice();
product.updateMyPrice(myPrice);
return product;
}
}
# ProductController
@RestController // JSON으로 데이터를 주고받음
public class ProductController {
private final ProductService productService; // 멤버 변수 선언
// 생성자: ProductController() 가 생성될 때 호출됨
@Autowired
public ProductController(ProductService productService) {
this.productService = productService; // 멤버 변수 생성
}
// 등록된 전체 상품 목록 조회
@GetMapping("/api/products")
public List<Product> getProducts() {
List<Product> products = productService.getProducts();
// 응답 보내기
return products;
}
// 신규 상품 등록
@PostMapping("/api/products")
public Product createProduct(@RequestBody ProductRequestDto requestDto) {
Product product = productService.createProduct(requestDto);
// 응답 보내기
return product;
}
// 설정 가격 변경
@PutMapping("/api/products/{id}")
public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto requestDto) {
Product product = productService.updateProduct(id, requestDto);
return product.getId();
}
}