From 9e6be0687aecd2b273e9c2aac7cdd42f8dae7c3b Mon Sep 17 00:00:00 2001 From: Jang Hyeon Woong Date: Sun, 18 Aug 2024 12:10:03 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EC=83=81=ED=92=88=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=ED=8B=80=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/controller/ProductController.java | 88 +++++++++++++++++++ .../java/shopping/product/dto/BookDto.java | 9 ++ .../product/service/ProductService.java | 47 ++++++++++ 3 files changed, 144 insertions(+) create mode 100644 src/main/java/shopping/product/controller/ProductController.java create mode 100644 src/main/java/shopping/product/dto/BookDto.java create mode 100644 src/main/java/shopping/product/service/ProductService.java diff --git a/src/main/java/shopping/product/controller/ProductController.java b/src/main/java/shopping/product/controller/ProductController.java new file mode 100644 index 0000000..5d52240 --- /dev/null +++ b/src/main/java/shopping/product/controller/ProductController.java @@ -0,0 +1,88 @@ +package shopping.product.controller; + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import shopping.product.dto.BookDto; +import shopping.product.service.ProductService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@RequestMapping("/api") +@RestController +public class ProductController { + + @Autowired + private ProductService productService; + + + /** 상품 목록 조회 + * + * @return + */ + @GetMapping("/products") + public List findAll() { + List bookList = new ArrayList<>(); + + return bookList; + } + + /** 특정 상품 조회 기능 + * + * @param productId + * @return + */ + @GetMapping("/products") + public Map findById(@RequestParam("productId") int productId) { + Map result = new HashMap(); + + + return result; + } + + + /** 상품 추가 기능 + * + * @param book + * @return + */ + @PostMapping("/products") + public String insertByMap(@RequestBody Map book) { + Map result = new HashMap(); + + if (productService.check(book.get("name"))) { + + } + + + return ""; + } + + /** + * 상품 수정 기능 + * @param book + * @return + */ + @PutMapping("products") + public Map updateByMap(@RequestBody Map book) { + Map result = new HashMap(); + + return result; + } + + /** 상품 삭제 기능 + * + * @param ProductId + * @return + */ + @DeleteMapping("products") + public String deleteById(@RequestParam int ProductId) { + + return ""; + } + +} diff --git a/src/main/java/shopping/product/dto/BookDto.java b/src/main/java/shopping/product/dto/BookDto.java new file mode 100644 index 0000000..e9c747e --- /dev/null +++ b/src/main/java/shopping/product/dto/BookDto.java @@ -0,0 +1,9 @@ +package shopping.product.dto; + +public class BookDto { + + private String name; // 상품명 + private int price; // 상품가격 + private String fileUrl; // 이미지 경로 + +} diff --git a/src/main/java/shopping/product/service/ProductService.java b/src/main/java/shopping/product/service/ProductService.java new file mode 100644 index 0000000..3b06c02 --- /dev/null +++ b/src/main/java/shopping/product/service/ProductService.java @@ -0,0 +1,47 @@ +package shopping.product.service; + +import org.springframework.stereotype.Service; + +import java.util.regex.Pattern; + +@Service +public class ProductService { + + + /** 상품명 유효성 검사 + * + * @param name + * @return + */ + public boolean check(String name) { + String[] swearWords = new String[] {"시발", "새끼", "개새끼", "병신" }; + String regExp = "^[가-힣a-zA-Z0-9\s]*$"; + String[] sign = {"\\(", "\\)" ,"\\[", "\\]", "\\+" ,"\\-", "\\&", "\\/", "\\_"}; + + // 최대 15자 + if(name.length() > 15) + return false; + + // 비속어 필터링 + for(int i=0; i Date: Sun, 18 Aug 2024 17:32:39 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=EC=83=81=ED=92=88=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 38 ++++++++ .../java/shopping/member/dto/MemberDto.java | 41 +++++++++ .../member/repository/MemberRepository.java | 13 +++ .../member/service/MemberService.java | 44 +++++++++ .../product/controller/ProductController.java | 72 +++++++-------- .../java/shopping/product/dto/BookDto.java | 9 -- .../java/shopping/product/dto/ProductDto.java | 67 ++++++++++++++ .../product/repository/ProductRepository.java | 25 +++++ .../product/service/ProductService.java | 92 +++++++++++++++++++ src/main/resources/application.properties | 8 ++ 10 files changed, 363 insertions(+), 46 deletions(-) create mode 100644 src/main/java/shopping/member/controller/MemberController.java create mode 100644 src/main/java/shopping/member/dto/MemberDto.java create mode 100644 src/main/java/shopping/member/repository/MemberRepository.java create mode 100644 src/main/java/shopping/member/service/MemberService.java delete mode 100644 src/main/java/shopping/product/dto/BookDto.java create mode 100644 src/main/java/shopping/product/dto/ProductDto.java create mode 100644 src/main/java/shopping/product/repository/ProductRepository.java diff --git a/src/main/java/shopping/member/controller/MemberController.java b/src/main/java/shopping/member/controller/MemberController.java new file mode 100644 index 0000000..cc82cf3 --- /dev/null +++ b/src/main/java/shopping/member/controller/MemberController.java @@ -0,0 +1,38 @@ +package shopping.member.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import shopping.member.service.MemberService; + +import java.util.HashMap; +import java.util.Map; + +@RequestMapping("/members") +@RestController +public class MemberController { + + @Autowired + private MemberService memberService; + + // 회원가입 + @PostMapping("/register") + public Map register(@RequestBody Map member){ + Map result = new HashMap<>(); + + + return result; + } + + // 로그인 + @PostMapping("/login") + public Map login(@RequestBody Map member){ + Map result = new HashMap<>(); + + return result; + } + + +} diff --git a/src/main/java/shopping/member/dto/MemberDto.java b/src/main/java/shopping/member/dto/MemberDto.java new file mode 100644 index 0000000..c35eabb --- /dev/null +++ b/src/main/java/shopping/member/dto/MemberDto.java @@ -0,0 +1,41 @@ +package shopping.member.dto; + + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name="Member") +public class MemberDto { + + @Id + private String email; + + private String password; + + public MemberDto() { + + } + + public MemberDto(String email, String password) { + this.email = email; + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/shopping/member/repository/MemberRepository.java b/src/main/java/shopping/member/repository/MemberRepository.java new file mode 100644 index 0000000..0e4c4a3 --- /dev/null +++ b/src/main/java/shopping/member/repository/MemberRepository.java @@ -0,0 +1,13 @@ +package shopping.member.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import shopping.member.dto.MemberDto; + +public interface MemberRepository extends JpaRepository { + + // 회원가입 + public MemberDto save(MemberDto memberDto); + + // 로그인 + public MemberDto getMemberDto(MemberDto memberDto); +} diff --git a/src/main/java/shopping/member/service/MemberService.java b/src/main/java/shopping/member/service/MemberService.java new file mode 100644 index 0000000..5b6d4f5 --- /dev/null +++ b/src/main/java/shopping/member/service/MemberService.java @@ -0,0 +1,44 @@ +package shopping.member.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import shopping.member.dto.MemberDto; +import shopping.member.repository.MemberRepository; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class MemberService { + + @Autowired + private MemberRepository memberRepository; + + // 회원가입 + public Map register(MemberDto memberDto) { + Map result = new HashMap<>(); + + if (memberRepository.getMemberDto(memberDto).equals(memberDto.getEmail())) { + result.put("resultMsg", "동일한 이메일 존재합니다."); + return result; + } + + + return result; + } + + + // 로그인 + public Map login(MemberDto memberDto) { + Map result = new HashMap<>(); + + MemberDto member = memberRepository.getMemberDto(memberDto); + + result.put("email", member.getEmail()); + result.put("password", member.getPassword()); + + + return result; + } + +} diff --git a/src/main/java/shopping/product/controller/ProductController.java b/src/main/java/shopping/product/controller/ProductController.java index 5d52240..641f8b4 100644 --- a/src/main/java/shopping/product/controller/ProductController.java +++ b/src/main/java/shopping/product/controller/ProductController.java @@ -3,7 +3,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import shopping.product.dto.BookDto; +import shopping.product.dto.ProductDto; import shopping.product.service.ProductService; import java.util.ArrayList; @@ -20,69 +20,67 @@ public class ProductController { private ProductService productService; - /** 상품 목록 조회 - * - * @return - */ + // 상품 목록 조회 @GetMapping("/products") - public List findAll() { - List bookList = new ArrayList<>(); + public List findAll() { + List productList = productService.findAll(); - return bookList; + return productList; } - /** 특정 상품 조회 기능 - * - * @param productId - * @return - */ - @GetMapping("/products") - public Map findById(@RequestParam("productId") int productId) { + + // 특정 상품 조회 + @GetMapping("/products/{productId}") + public Map findById(@RequestParam("productId") Long productId) { Map result = new HashMap(); + result = productService.findById(productId); return result; } - /** 상품 추가 기능 - * - * @param book - * @return - */ + + // 상품 추가 @PostMapping("/products") - public String insertByMap(@RequestBody Map book) { + public Map save(@RequestBody Map product) { Map result = new HashMap(); - if (productService.check(book.get("name"))) { - + if (!productService.check(product.get("name"))) { + result.put("resultMsg", "상품 명명규칙이 잘못되었습니다."); + return result; } + result = productService.save(product); + - return ""; + return result; } - /** - * 상품 수정 기능 - * @param book - * @return - */ + + // 상품 수정 @PutMapping("products") - public Map updateByMap(@RequestBody Map book) { + public Map update(@RequestBody Map product) { Map result = new HashMap(); + if (!productService.check(product.get("name"))) { + result.put("resultMsg", "상품 명명규칙이 잘못되었습니다."); + return result; + } + + result = productService.update(product); + return result; } - /** 상품 삭제 기능 - * - * @param ProductId - * @return - */ + + // 상품 삭제 @DeleteMapping("products") - public String deleteById(@RequestParam int ProductId) { + public String deleteById(@RequestParam Long productId) { + + productService.deleteById(productId); - return ""; + return "삭제 완료"; } } diff --git a/src/main/java/shopping/product/dto/BookDto.java b/src/main/java/shopping/product/dto/BookDto.java deleted file mode 100644 index e9c747e..0000000 --- a/src/main/java/shopping/product/dto/BookDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package shopping.product.dto; - -public class BookDto { - - private String name; // 상품명 - private int price; // 상품가격 - private String fileUrl; // 이미지 경로 - -} diff --git a/src/main/java/shopping/product/dto/ProductDto.java b/src/main/java/shopping/product/dto/ProductDto.java new file mode 100644 index 0000000..664a377 --- /dev/null +++ b/src/main/java/shopping/product/dto/ProductDto.java @@ -0,0 +1,67 @@ +package shopping.product.dto; + + +import jakarta.persistence.*; + +@Entity +@Table(name="product") +public class ProductDto { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + + @Column(name="name") + private String name; // 상품명 + + @Column(name="price") + private int price; // 상품가격 + + @Column(name="file_url") + private String fileUrl; // 이미지 경로 + + public ProductDto() { + + } + + + public ProductDto(int id, String name, int price, String fileUrl) { + this.id = id; + this.name = name; + this.price = price; + this.fileUrl = fileUrl; + } + + public int getId() { + return id; + } + + public void setId(int 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 getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } +} diff --git a/src/main/java/shopping/product/repository/ProductRepository.java b/src/main/java/shopping/product/repository/ProductRepository.java new file mode 100644 index 0000000..72222d8 --- /dev/null +++ b/src/main/java/shopping/product/repository/ProductRepository.java @@ -0,0 +1,25 @@ +package shopping.product.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import shopping.product.dto.ProductDto; + +import java.util.List; +import java.util.Optional; + +public interface ProductRepository extends JpaRepository { + + + // 상품 추가 + public ProductDto save(ProductDto productDto); + + // 상품 목록 + public List findAll(); + + // 상품 조회 + public Optional findById(Long id); + + // 상품 삭제 + public void deleteById(Long id); + + +} diff --git a/src/main/java/shopping/product/service/ProductService.java b/src/main/java/shopping/product/service/ProductService.java index 3b06c02..8fefd37 100644 --- a/src/main/java/shopping/product/service/ProductService.java +++ b/src/main/java/shopping/product/service/ProductService.java @@ -1,12 +1,104 @@ package shopping.product.service; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import shopping.product.dto.ProductDto; +import shopping.product.repository.ProductRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.regex.Pattern; @Service public class ProductService { + @Autowired + private ProductRepository productRepository; + + + public Map findById(Long productId) { + Optional rst = productRepository.findById(productId); + + Map result = new HashMap<>(); + if(rst.isEmpty()) { + result.put("resultMsg", "조회 결과가 없습니다."); + } else { + ProductDto productDto = rst.get(); + + result.put("id", Integer.toString(productDto.getId())); + result.put("name", productDto.getName()); + result.put("price", Integer.toString(productDto.getPrice())); + result.put("fileUrl", productDto.getFileUrl()); + } + + return result; + } + /** + * 상품 목록 조회 + * @return + */ + public List findAll() { + return productRepository.findAll(); + } + + /** + * 상품 추가 + * @param book + * @return + */ + public Map save(Map book){ + ProductDto productDto = new ProductDto(); + productDto.setName(book.get("name")); + productDto.setPrice(Integer.parseInt(book.get("price"))); + productDto.setFileUrl(book.get("fileUrl")); + + productRepository.save(productDto); + + return book; + } + + /** + * 상품 업데이트 + * @param product + * @return + */ + public Map update(Map product) { + Map result = new HashMap<>(); + + Optional getDto = productRepository.findById(Long.parseLong(product.get("id"))); + + + if(!getDto.isEmpty()) { + ProductDto productDto = getDto.get(); + productDto.setName(product.get("name")); + productDto.setPrice(Integer.parseInt(product.get("price"))); + productDto.setFileUrl(product.get("fileUrl")); + + productRepository.save(productDto); + + result.put("id", Integer.toString(productDto.getId())); + result.put("name", productDto.getName()); + result.put("price", Integer.toString(productDto.getPrice())); + result.put("fileUrl", productDto.getFileUrl()); + + } else { + result.put("resultMsg", "상품 조회 결과가 없습니다."); + } + + return result; + } + + /** + * 상품 삭제 + * + * @param productId + */ + public void deleteById(Long productId) { + productRepository.deleteById(productId); + } + /** 상품명 유효성 검사 * diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c33078c..fe89b94 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,9 @@ spring.application.name=spring-shopping + + +spring.datasource.url=jdbc:mysql://localhost:3306/test2?autoReconnect=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.jdbc.Driver + +spring.flyway.baseline-on-migrate = true \ No newline at end of file From 65a1e5b0a0f55192124a83487ae47bf071a85f39 Mon Sep 17 00:00:00 2001 From: Jang Hyeon Woong Date: Thu, 29 Aug 2024 14:37:02 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=20=EB=B0=8F=20entity,=20service(?= =?UTF-8?q?=EC=83=81=ED=92=88=EC=A1=B0=ED=9A=8C,=20=EC=83=81=ED=92=88?= =?UTF-8?q?=EC=B6=94=EA=B0=80)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 ++- build.gradle.kts | 2 + .../api/entity/CreateProductRequest.java | 30 ++++ .../shopping/api/service/ProductService.java | 32 ++++ .../java/shopping/domain/entity/ImageUrl.java | 22 +++ .../java/shopping/domain/entity/Name.java | 21 +++ .../java/shopping/domain/entity/Price.java | 16 ++ .../java/shopping/domain/entity/Product.java | 47 ++++++ .../shopping/domain/util/IDGenarator.java | 13 ++ .../member/controller/MemberController.java | 38 ----- .../java/shopping/member/dto/MemberDto.java | 41 ------ .../member/repository/MemberRepository.java | 13 -- .../member/service/MemberService.java | 44 ------ .../product/controller/ProductController.java | 86 ----------- .../java/shopping/product/dto/ProductDto.java | 67 --------- .../product/repository/ProductRepository.java | 25 ---- .../product/service/ProductService.java | 139 ------------------ src/main/resources/application.properties | 10 +- src/main/resources/schema.sql | 6 + .../shopping/api/entity/ImageUrlTest.java | 18 +++ .../java/shopping/api/entity/NameTest.java | 24 +++ .../java/shopping/api/entity/ProductTest.java | 28 ++++ .../api/service/ProductServiceTest.java | 46 ++++++ 23 files changed, 329 insertions(+), 463 deletions(-) create mode 100644 src/main/java/shopping/api/entity/CreateProductRequest.java create mode 100644 src/main/java/shopping/api/service/ProductService.java create mode 100644 src/main/java/shopping/domain/entity/ImageUrl.java create mode 100644 src/main/java/shopping/domain/entity/Name.java create mode 100644 src/main/java/shopping/domain/entity/Price.java create mode 100644 src/main/java/shopping/domain/entity/Product.java create mode 100644 src/main/java/shopping/domain/util/IDGenarator.java delete mode 100644 src/main/java/shopping/member/controller/MemberController.java delete mode 100644 src/main/java/shopping/member/dto/MemberDto.java delete mode 100644 src/main/java/shopping/member/repository/MemberRepository.java delete mode 100644 src/main/java/shopping/member/service/MemberService.java delete mode 100644 src/main/java/shopping/product/controller/ProductController.java delete mode 100644 src/main/java/shopping/product/dto/ProductDto.java delete mode 100644 src/main/java/shopping/product/repository/ProductRepository.java delete mode 100644 src/main/java/shopping/product/service/ProductService.java create mode 100644 src/main/resources/schema.sql create mode 100644 src/test/java/shopping/api/entity/ImageUrlTest.java create mode 100644 src/test/java/shopping/api/entity/NameTest.java create mode 100644 src/test/java/shopping/api/entity/ProductTest.java create mode 100644 src/test/java/shopping/api/service/ProductServiceTest.java diff --git a/README.md b/README.md index a4f7992..fa87a4e 100644 --- a/README.md +++ b/README.md @@ -1 +1,23 @@ -# spring-shopping-precourse \ No newline at end of file +# spring-shopping-precourse + +## 기능사항 + + +### 상품 +- [x] 상품이름은 공백 포함 최대 15자이다. +- [x] 특수문자 (),[],+,-,&,/,_만 가능하다. +- [x] 상품을 조회할 수 있다. +- [x] 상품을 추가할 수 있다. +- [ ] 상품을 수정할 수 있다. +- [ ] 상품을 삭제할 수 있다. +- [ ] 비속어를 포함할 수 없다. + + +### 개발 진행 +1. TDD 형태로 개발할 것 +2. 작은 단계부터 큰 단계로 진행 +- [x] 모델 +- [ ] 서비스 +- [ ] 컨트롤러 +- [ ] 레포지토리 +- [ ] DB 연결 \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3f75395..98bb6f3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,8 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + testImplementation ("org.assertj:assertj-core:3.11.1") } kotlin { diff --git a/src/main/java/shopping/api/entity/CreateProductRequest.java b/src/main/java/shopping/api/entity/CreateProductRequest.java new file mode 100644 index 0000000..abb860f --- /dev/null +++ b/src/main/java/shopping/api/entity/CreateProductRequest.java @@ -0,0 +1,30 @@ +package shopping.api.entity; + +import shopping.domain.entity.ImageUrl; +import shopping.domain.entity.Name; +import shopping.domain.entity.Price; + +public class CreateProductRequest { + + private Name name; + private Price price; + private ImageUrl imageUrl; + + public CreateProductRequest(Name name, Price price, ImageUrl imageUrl) { + this.name = name; + this.price = price; + this.imageUrl = imageUrl; + } + + public Name getName() { + return name; + } + + public Price getPrice() { + return price; + } + + public ImageUrl getImageUrl() { + return imageUrl; + } +} diff --git a/src/main/java/shopping/api/service/ProductService.java b/src/main/java/shopping/api/service/ProductService.java new file mode 100644 index 0000000..dab47dd --- /dev/null +++ b/src/main/java/shopping/api/service/ProductService.java @@ -0,0 +1,32 @@ +package shopping.api.service; + +import org.springframework.stereotype.Service; +import shopping.api.entity.CreateProductRequest; +import shopping.domain.entity.Product; +import shopping.domain.util.IDGenarator; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +@Service +public class ProductService { + + private final Map database = new HashMap<>(); + + public Product save(CreateProductRequest createProductRequest) { + long id = IDGenarator.generate(); + + Product product = new Product(id, createProductRequest.getName(), createProductRequest.getPrice(), createProductRequest.getImageUrl()); + database.put(id, product); + + return product; + } + + public Product findById(Long id) throws RuntimeException{ + if(database.isEmpty()) + throw new RuntimeException("등록된 상품이 없습니다."); + + return database.get(id); + } +} diff --git a/src/main/java/shopping/domain/entity/ImageUrl.java b/src/main/java/shopping/domain/entity/ImageUrl.java new file mode 100644 index 0000000..a454b84 --- /dev/null +++ b/src/main/java/shopping/domain/entity/ImageUrl.java @@ -0,0 +1,22 @@ +package shopping.domain.entity; + +import java.util.regex.Pattern; + +public class ImageUrl { + + private final String regex = "^(https?:\\/\\/.*\\.(png|jpg))$"; + private final Pattern pattern = Pattern.compile(regex); + + private String value; + + public ImageUrl(String value) throws IllegalArgumentException{ + if(!pattern.matcher(value).matches()) + throw new IllegalArgumentException("잘못된 이미지 경로입니다."); + + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/shopping/domain/entity/Name.java b/src/main/java/shopping/domain/entity/Name.java new file mode 100644 index 0000000..8745034 --- /dev/null +++ b/src/main/java/shopping/domain/entity/Name.java @@ -0,0 +1,21 @@ +package shopping.domain.entity; + +import java.util.regex.Pattern; + +public class Name { + + private final String regx = "^[a-zA-Z0-9가-힣 ()\\[\\]+\\-&/_]{1,15}$"; + private final Pattern pattern = Pattern.compile(regx); + private String value; + + public Name(String value) throws IllegalArgumentException{ + if(!pattern.matcher(value).matches()) + throw new IllegalArgumentException("상품 명이 올바르지 않습니다."); + + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/shopping/domain/entity/Price.java b/src/main/java/shopping/domain/entity/Price.java new file mode 100644 index 0000000..ec5bc06 --- /dev/null +++ b/src/main/java/shopping/domain/entity/Price.java @@ -0,0 +1,16 @@ +package shopping.domain.entity; + +public class Price { + + private int value; + + public Price(int value) throws IllegalArgumentException{ + if(value < 0) + throw new IllegalArgumentException("상품 가격은 음수가 될 수 없습니다."); + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/shopping/domain/entity/Product.java b/src/main/java/shopping/domain/entity/Product.java new file mode 100644 index 0000000..e06aae8 --- /dev/null +++ b/src/main/java/shopping/domain/entity/Product.java @@ -0,0 +1,47 @@ +package shopping.domain.entity; + +import java.util.concurrent.atomic.AtomicLong; + +public class Product { + + private Long id; + private Name name; + private Price price; + private ImageUrl imageUrl; + + public Product(Long id, Product product) { + this.id = id; + this.name = product.getName(); + this.price = product.getPrice(); + this.imageUrl = product.getImageUrl(); + } + + public Product(Long id, Name name, Price price, ImageUrl imageUrl) { + this.id = id; + this.name = name; + this.price = price; + this.imageUrl = imageUrl; + } + + public Product(Name name, Price price, ImageUrl imageUrl) { + this.name = name; + this.price = price; + this.imageUrl = imageUrl; + } + + public Long getId() { + return id; + } + + public Name getName() { + return name; + } + + public Price getPrice() { + return price; + } + + public ImageUrl getImageUrl() { + return imageUrl; + } +} diff --git a/src/main/java/shopping/domain/util/IDGenarator.java b/src/main/java/shopping/domain/util/IDGenarator.java new file mode 100644 index 0000000..d7706d2 --- /dev/null +++ b/src/main/java/shopping/domain/util/IDGenarator.java @@ -0,0 +1,13 @@ +package shopping.domain.util; + +import java.util.concurrent.atomic.AtomicLong; + +public class IDGenarator { + + private static final AtomicLong id = new AtomicLong(1); + + public static long generate() { + return id.getAndIncrement(); + } + +} diff --git a/src/main/java/shopping/member/controller/MemberController.java b/src/main/java/shopping/member/controller/MemberController.java deleted file mode 100644 index cc82cf3..0000000 --- a/src/main/java/shopping/member/controller/MemberController.java +++ /dev/null @@ -1,38 +0,0 @@ -package shopping.member.controller; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import shopping.member.service.MemberService; - -import java.util.HashMap; -import java.util.Map; - -@RequestMapping("/members") -@RestController -public class MemberController { - - @Autowired - private MemberService memberService; - - // 회원가입 - @PostMapping("/register") - public Map register(@RequestBody Map member){ - Map result = new HashMap<>(); - - - return result; - } - - // 로그인 - @PostMapping("/login") - public Map login(@RequestBody Map member){ - Map result = new HashMap<>(); - - return result; - } - - -} diff --git a/src/main/java/shopping/member/dto/MemberDto.java b/src/main/java/shopping/member/dto/MemberDto.java deleted file mode 100644 index c35eabb..0000000 --- a/src/main/java/shopping/member/dto/MemberDto.java +++ /dev/null @@ -1,41 +0,0 @@ -package shopping.member.dto; - - -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -@Entity -@Table(name="Member") -public class MemberDto { - - @Id - private String email; - - private String password; - - public MemberDto() { - - } - - public MemberDto(String email, String password) { - this.email = email; - this.password = password; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} diff --git a/src/main/java/shopping/member/repository/MemberRepository.java b/src/main/java/shopping/member/repository/MemberRepository.java deleted file mode 100644 index 0e4c4a3..0000000 --- a/src/main/java/shopping/member/repository/MemberRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package shopping.member.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import shopping.member.dto.MemberDto; - -public interface MemberRepository extends JpaRepository { - - // 회원가입 - public MemberDto save(MemberDto memberDto); - - // 로그인 - public MemberDto getMemberDto(MemberDto memberDto); -} diff --git a/src/main/java/shopping/member/service/MemberService.java b/src/main/java/shopping/member/service/MemberService.java deleted file mode 100644 index 5b6d4f5..0000000 --- a/src/main/java/shopping/member/service/MemberService.java +++ /dev/null @@ -1,44 +0,0 @@ -package shopping.member.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import shopping.member.dto.MemberDto; -import shopping.member.repository.MemberRepository; - -import java.util.HashMap; -import java.util.Map; - -@Service -public class MemberService { - - @Autowired - private MemberRepository memberRepository; - - // 회원가입 - public Map register(MemberDto memberDto) { - Map result = new HashMap<>(); - - if (memberRepository.getMemberDto(memberDto).equals(memberDto.getEmail())) { - result.put("resultMsg", "동일한 이메일 존재합니다."); - return result; - } - - - return result; - } - - - // 로그인 - public Map login(MemberDto memberDto) { - Map result = new HashMap<>(); - - MemberDto member = memberRepository.getMemberDto(memberDto); - - result.put("email", member.getEmail()); - result.put("password", member.getPassword()); - - - return result; - } - -} diff --git a/src/main/java/shopping/product/controller/ProductController.java b/src/main/java/shopping/product/controller/ProductController.java deleted file mode 100644 index 641f8b4..0000000 --- a/src/main/java/shopping/product/controller/ProductController.java +++ /dev/null @@ -1,86 +0,0 @@ -package shopping.product.controller; - - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import shopping.product.dto.ProductDto; -import shopping.product.service.ProductService; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -@RequestMapping("/api") -@RestController -public class ProductController { - - @Autowired - private ProductService productService; - - - // 상품 목록 조회 - @GetMapping("/products") - public List findAll() { - List productList = productService.findAll(); - - return productList; - } - - - // 특정 상품 조회 - @GetMapping("/products/{productId}") - public Map findById(@RequestParam("productId") Long productId) { - Map result = new HashMap(); - - result = productService.findById(productId); - - return result; - } - - - - // 상품 추가 - @PostMapping("/products") - public Map save(@RequestBody Map product) { - Map result = new HashMap(); - - if (!productService.check(product.get("name"))) { - result.put("resultMsg", "상품 명명규칙이 잘못되었습니다."); - return result; - } - - result = productService.save(product); - - - return result; - } - - - // 상품 수정 - @PutMapping("products") - public Map update(@RequestBody Map product) { - Map result = new HashMap(); - - if (!productService.check(product.get("name"))) { - result.put("resultMsg", "상품 명명규칙이 잘못되었습니다."); - return result; - } - - result = productService.update(product); - - return result; - } - - - // 상품 삭제 - @DeleteMapping("products") - public String deleteById(@RequestParam Long productId) { - - productService.deleteById(productId); - - return "삭제 완료"; - } - -} diff --git a/src/main/java/shopping/product/dto/ProductDto.java b/src/main/java/shopping/product/dto/ProductDto.java deleted file mode 100644 index 664a377..0000000 --- a/src/main/java/shopping/product/dto/ProductDto.java +++ /dev/null @@ -1,67 +0,0 @@ -package shopping.product.dto; - - -import jakarta.persistence.*; - -@Entity -@Table(name="product") -public class ProductDto { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private int id; - - - @Column(name="name") - private String name; // 상품명 - - @Column(name="price") - private int price; // 상품가격 - - @Column(name="file_url") - private String fileUrl; // 이미지 경로 - - public ProductDto() { - - } - - - public ProductDto(int id, String name, int price, String fileUrl) { - this.id = id; - this.name = name; - this.price = price; - this.fileUrl = fileUrl; - } - - public int getId() { - return id; - } - - public void setId(int 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 getFileUrl() { - return fileUrl; - } - - public void setFileUrl(String fileUrl) { - this.fileUrl = fileUrl; - } -} diff --git a/src/main/java/shopping/product/repository/ProductRepository.java b/src/main/java/shopping/product/repository/ProductRepository.java deleted file mode 100644 index 72222d8..0000000 --- a/src/main/java/shopping/product/repository/ProductRepository.java +++ /dev/null @@ -1,25 +0,0 @@ -package shopping.product.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import shopping.product.dto.ProductDto; - -import java.util.List; -import java.util.Optional; - -public interface ProductRepository extends JpaRepository { - - - // 상품 추가 - public ProductDto save(ProductDto productDto); - - // 상품 목록 - public List findAll(); - - // 상품 조회 - public Optional findById(Long id); - - // 상품 삭제 - public void deleteById(Long id); - - -} diff --git a/src/main/java/shopping/product/service/ProductService.java b/src/main/java/shopping/product/service/ProductService.java deleted file mode 100644 index 8fefd37..0000000 --- a/src/main/java/shopping/product/service/ProductService.java +++ /dev/null @@ -1,139 +0,0 @@ -package shopping.product.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import shopping.product.dto.ProductDto; -import shopping.product.repository.ProductRepository; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.regex.Pattern; - -@Service -public class ProductService { - - @Autowired - private ProductRepository productRepository; - - - public Map findById(Long productId) { - Optional rst = productRepository.findById(productId); - - Map result = new HashMap<>(); - if(rst.isEmpty()) { - result.put("resultMsg", "조회 결과가 없습니다."); - } else { - ProductDto productDto = rst.get(); - - result.put("id", Integer.toString(productDto.getId())); - result.put("name", productDto.getName()); - result.put("price", Integer.toString(productDto.getPrice())); - result.put("fileUrl", productDto.getFileUrl()); - } - - return result; - } - /** - * 상품 목록 조회 - * @return - */ - public List findAll() { - return productRepository.findAll(); - } - - /** - * 상품 추가 - * @param book - * @return - */ - public Map save(Map book){ - ProductDto productDto = new ProductDto(); - productDto.setName(book.get("name")); - productDto.setPrice(Integer.parseInt(book.get("price"))); - productDto.setFileUrl(book.get("fileUrl")); - - productRepository.save(productDto); - - return book; - } - - /** - * 상품 업데이트 - * @param product - * @return - */ - public Map update(Map product) { - Map result = new HashMap<>(); - - Optional getDto = productRepository.findById(Long.parseLong(product.get("id"))); - - - if(!getDto.isEmpty()) { - ProductDto productDto = getDto.get(); - productDto.setName(product.get("name")); - productDto.setPrice(Integer.parseInt(product.get("price"))); - productDto.setFileUrl(product.get("fileUrl")); - - productRepository.save(productDto); - - result.put("id", Integer.toString(productDto.getId())); - result.put("name", productDto.getName()); - result.put("price", Integer.toString(productDto.getPrice())); - result.put("fileUrl", productDto.getFileUrl()); - - } else { - result.put("resultMsg", "상품 조회 결과가 없습니다."); - } - - return result; - } - - /** - * 상품 삭제 - * - * @param productId - */ - public void deleteById(Long productId) { - productRepository.deleteById(productId); - } - - - /** 상품명 유효성 검사 - * - * @param name - * @return - */ - public boolean check(String name) { - String[] swearWords = new String[] {"시발", "새끼", "개새끼", "병신" }; - String regExp = "^[가-힣a-zA-Z0-9\s]*$"; - String[] sign = {"\\(", "\\)" ,"\\[", "\\]", "\\+" ,"\\-", "\\&", "\\/", "\\_"}; - - // 최대 15자 - if(name.length() > 15) - return false; - - // 비속어 필터링 - for(int i=0; i new ImageUrl("http://www.naver.com/image")); + } +} diff --git a/src/test/java/shopping/api/entity/NameTest.java b/src/test/java/shopping/api/entity/NameTest.java new file mode 100644 index 0000000..9e5f609 --- /dev/null +++ b/src/test/java/shopping/api/entity/NameTest.java @@ -0,0 +1,24 @@ +package shopping.api.entity; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import shopping.domain.entity.Name; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class NameTest { + + @Test + @DisplayName("이름은 15자를 넘으면 안되고, 특수문자를 일부 허용한다.") + void constructorTest() { + try { + new Name("안녕하세요감사해요잘있어요다시만나요안녕하세요"); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + assertEquals("상품 명이 올바르지 않습니다.", e.getMessage()); + } + + } +} diff --git a/src/test/java/shopping/api/entity/ProductTest.java b/src/test/java/shopping/api/entity/ProductTest.java new file mode 100644 index 0000000..c95e40b --- /dev/null +++ b/src/test/java/shopping/api/entity/ProductTest.java @@ -0,0 +1,28 @@ +package shopping.api.entity; + + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import shopping.domain.entity.ImageUrl; +import shopping.domain.entity.Name; +import shopping.domain.entity.Price; +import shopping.domain.entity.Product; + +import static org.assertj.core.api.Assertions.*; + + +public class ProductTest { + + @Test + @DisplayName("상품은 이름, 가격, 이미지를 가지고 있어야 한다.") + void constructorTest() { + Product product = new Product(new Name("책"), new Price(2000), new ImageUrl("https://image.png")); + + assertThat(product.getName().getValue()).isEqualTo(new Name("책").getValue()); + assertThat(product.getPrice().getValue()).isEqualTo(new Price(2000).getValue()); + assertThat(product.getImageUrl().getValue()).isEqualTo(new ImageUrl("https://image.png").getValue()); + + } + + +} diff --git a/src/test/java/shopping/api/service/ProductServiceTest.java b/src/test/java/shopping/api/service/ProductServiceTest.java new file mode 100644 index 0000000..1bd230a --- /dev/null +++ b/src/test/java/shopping/api/service/ProductServiceTest.java @@ -0,0 +1,46 @@ +package shopping.api.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import shopping.api.entity.CreateProductRequest; +import shopping.domain.entity.ImageUrl; +import shopping.domain.entity.Name; +import shopping.domain.entity.Price; +import shopping.domain.entity.Product; + +import static org.assertj.core.api.Assertions.*; + +@SpringBootTest +public class ProductServiceTest { + + @Autowired + private ProductService productService; + + @Test + @DisplayName("상품을 조회한다.") + void findProductTest() { + Product product = 상품_생성("책",2000,"http://image.png"); + + Product actual = productService.findById(product.getId()); + + assertThat(actual.getName().getValue()).isEqualTo(product.getName().getValue()); + assertThat(actual.getPrice().getValue()).isEqualTo(product.getPrice().getValue()); + assertThat(actual.getImageUrl().getValue()).isEqualTo(product.getImageUrl().getValue()); + } + + + Product 상품_생성(String name, int price, String imageUrl) { + CreateProductRequest createProductRequest = new CreateProductRequest(new Name(name), new Price(price), new ImageUrl(imageUrl)); + + + Product savedProduct = productService.save(createProductRequest); + + assertThat(savedProduct.getName().getValue()).isEqualTo(name); + assertThat(savedProduct.getPrice().getValue()).isEqualTo(price); + assertThat(savedProduct.getImageUrl().getValue()).isEqualTo(imageUrl); + + return savedProduct; + } +}