Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

전남대 BE_안원모 1주차 과제(2단계) #183

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
# spring-gift-product
# spring-gift-product
## 기능 요구사항
상품 CRUD를 수행하는 관리자 페이지 구현

1. 상품 정보를 저장할 수 있어야 함
- 상품명, 가격, 수량, 이미지url을 입력받아 저장할 수 있어야 함
2. 상품 정보를 조회할 수 있어야 함
- ID를 입력받아 해당 ID의 상품 정보를 조회할 수 있어야 함
- 모든 상품 정보를 조회할 수 있어야 함
3. 상품 정보를 수정할 수 있어야 함
- 상품 정보를 입력받아 가격, 수량, 이미지url을 수정할 수 있어야 함
4. 상품 정보를 삭제할 수 있어야 함
- ID를 입력받아 상품 정보를 삭제할 수 있어야 함
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)

languageVersion = JavaLanguageVersion.of(17)
Wonmoan marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand All @@ -21,6 +22,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
Wonmoan marked this conversation as resolved.
Show resolved Hide resolved
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/gift/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
}
50 changes: 50 additions & 0 deletions src/main/java/gift/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package gift;

public class Product {
private long id;
private String name;
private int price;
private String imageUrl;

public Product() {
}

public Product(long id, String name, int price, String imageUrl) {
this.id = id;
this.name = name;
this.price = price;
this.imageUrl = imageUrl;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getPrice() {
return price;
}

public void setPrice(int price) {
this.price = price;
}

public String getImageUrl() {
return imageUrl;
}

public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
41 changes: 41 additions & 0 deletions src/main/java/gift/ProductController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package gift;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService productService;

@Autowired
public ProductController(ProductService productService) {
this.productService = productService;
}

@GetMapping
public List<Product> getProducts() {
return productService.findAllProducts();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ResponseEntity 부분이 사라졌네요.
제가 물음표 빌런이라, 이를 왜 없애주셨는지 역시 궁금해요 :)

}

@PostMapping
public Product postProduct(@RequestBody Product product) {
return productService.createProduct(product);
}
@PutMapping("/{id}")
public Product putProduct(@PathVariable Long id, @RequestBody Product product) {
return productService.updateProduct(id, product);
}
@DeleteMapping("/{id}")
public Long deleteProduct(@PathVariable Long id) {
return productService.deleteProduct(id);
}
}
42 changes: 42 additions & 0 deletions src/main/java/gift/ProductRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package gift;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Repository;

@Repository
public class ProductRepository {

private final Map<Long, Product> products = new HashMap<>();
private Long counter = 0L;

public List<Product> findAllProducts() {
return new ArrayList<>(products.values());
}

public Product createProduct(Product product) {
Long productId = ++counter;
product.setId(productId);
products.put(productId, product);
return products.get(productId);
}

public Product updateProduct(Long id, Product product) {
product.setId(id);
products.put(id, product);
return products.get(id);
}
public Long deleteProduct(Long id) {
Wonmoan marked this conversation as resolved.
Show resolved Hide resolved
products.remove(id);
return id;
}

public boolean isExist(Long id) {
return products.containsKey(id);
}
public Product findProductById(Long id) {
return products.get(id);
}
}
45 changes: 45 additions & 0 deletions src/main/java/gift/ProductService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package gift;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
private final ProductRepository productRepository;

@Autowired
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

생성자를 통한 bean 주입을 할 때 보통 @Autowired 를 빼주셨는데,
이부분만 어노테이션을 달아주신 이유가 있나요?


public List<Product> findAllProducts() {
return productRepository.findAllProducts();
}
public Product createProduct(Product product) {
return productRepository.createProduct(product);
}

public Product updateProduct(Long id, Product product) {
if(!isExist(id)) {
return createProduct(product);
}
return productRepository.updateProduct(id, product);
}

public Long deleteProduct(Long id) {
if(!isExist(id)) {

return -1L;
}
return productRepository.deleteProduct(id);
}

public Product getProductById(Long id) {
return productRepository.findProductById(id);
}

private boolean isExist(Long id) {
return productRepository.isExist(id);
}
}
63 changes: 63 additions & 0 deletions src/main/java/gift/ProductWebController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package gift;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/")
public class ProductWebController {
private final ProductService productService;

@Autowired
public ProductWebController(ProductService productService) {
this.productService = productService;
}

@GetMapping("/products")
public String getProductsPage(Model model) {
List<Product> products = productService.findAllProducts();
model.addAttribute("products", products);
return "products";
}

@PostMapping("/products")
public String postProduct(@RequestParam String name, @RequestParam int price, @RequestParam String imageUrl) {
Product product = new Product();
product.setName(name);
product.setPrice(price);
product.setImageUrl(imageUrl);

productService.createProduct(product);
return "redirect:/products";
}
@PostMapping("/products/delete")
public String deleteProduct(@RequestParam List<Long> productIds) {
for (Long id : productIds) {
productService.deleteProduct(id);
}
return "redirect:/products";
}
@GetMapping("/products/edit/{id}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

섬세하게 애플리케이션을 아주 잘 만들어주셨네요 👍

public String getEditForm(@PathVariable Long id, Model model) {
Product product = productService.getProductById(id);
model.addAttribute("product", product);
return "productEdit";
}
@PostMapping("/products/edit/{id}")
public String editProduct(@RequestParam Long id, @RequestParam String name, @RequestParam int price, @RequestParam String imageUrl) {
Product product = new Product();
product.setName(name);
product.setPrice(price);
product.setImageUrl(imageUrl);

productService.updateProduct(id, product);
return "redirect:/products";
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
spring.application.name=spring-gift
spring.application.name=spring-gift
26 changes: 26 additions & 0 deletions src/main/resources/templates/productEdit.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>상품 수정 페이지</title>
</head>
<body>
<h2>상품 수정 페이지</h2>
<form th:action="@{/products/edit/{id}}" th:object="${product}" method="post">
<input type="hidden" th:field="*{id}"/>

<label for="name">상품 이름:</label>
<input type="text" id="name" th:field="*{name}" required><br><br>

<label for="price">상품 가격:</label>
<input type="number" id="price" th:field="*{price}" required><br><br>

<label for="imageUrl">이미지 URL:</label>
<input type="text" id="imageUrl" th:field="*{imageUrl}"><br><br>

<button type="submit">수정</button>
</form>
<br>
<a href="/products">돌아가기</a>
</body>
</html>
51 changes: 51 additions & 0 deletions src/main/resources/templates/products.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>상품 관리 페이지</title>
</head>
<body>
<h1>상품 관리 페이지</h1>

<form th:action="@{/products}" method="post">
<label for="name">상품 이름:</label>
<input type="text" id="name" name="name" required>

<label for="price">상품 가격:</label>
<input type="number" id="price" name="price" required>

<label for="imageUrl">이미지 URL :</label>
<input type="text" id="imageUrl" name="imageUrl">

<button type="submit">상품 추가</button>
</form>

<h2>상품 목록</h2>
<form th:action="@{/products/delete}" method="post">
<table border="1" cellpadding="10" cellspacing="0" style="width: 100%; margin-top: 20px;">
<thead>
<tr>
<th>선택</th>
<th>상품 번호</th>
<th>상품 이름</th>
<th>상품 가격</th>
<th>이미지 URL</th>
<th>수정</th>
</tr>
</thead>
<tbody>
<tr th:each="product : ${products}">
<td><input type="checkbox" name="productIds" th:value="${product.id}"></td>
<td th:text="${product.id}"></td>
<td th:text="${product.name}"></td>
<td th:text="${product.price}"></td>
<td th:text="${product.imageUrl}"></td>
<td><a th:href="@{'/products/edit/' + ${product.id}}">수정</a></td>
</tr>
</tbody>
</table>
<button type="submit">선택 상품 삭제</button>
</form>

</body>
</html>