diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..0c9b849 --- /dev/null +++ b/Readme.md @@ -0,0 +1,32 @@ +## Java Implementation + +#### 运行方式 + +用./mvnw spring-boot:run运行 +h2 database在 localhost:8080/h2-console + +#### cURL测试 + +用cURL测试/api/v1/product/create +curl -X POST -H "Content-Type: application/json" --data '{"name":"product1","price":"1.0","stock":"5"}' http://localhost:8080/api/v1/product/create +返回 +{"code":201,"name":"product1","message":"Product created"} + +再次用cURL测试/api/v1/product/create使用相同的name +返回 +{"code":409,"message":"Product with the same name already exists"} + +用cURL测试/api/v1/product/{id} +curl -X GET -H "Content-Type: application/json" http://localhost:8080/api/v1/product/product1 +返回 +{"product":{"price":1.0,"name":"product1","stock":5},"code":200,"message":"Product retrieved"} +用cURL测试/api/v1/product/{id}使用不存在的name +返回 +{"code":404,"message":"Product not found"} + +#### 代码结构 +- controller: 接受请求parameters然后调用service +- service: 调用repository,处理业务逻辑。在必要时throw exception +- repository: 继承JpaRepository,和database交互存储数据 +- product: Model class +controller不直接调用repository,而是调用service负责业务逻辑。将来如要更改实现方式,只需更改service和repository,不用更改controller diff --git a/pom.xml b/pom.xml index b07ffb9..c590c1d 100644 --- a/pom.xml +++ b/pom.xml @@ -34,11 +34,22 @@ org.springframework.boot spring-boot-starter-data-jpa + + com.h2database + h2 + runtime + org.springframework.boot spring-boot-starter-web + + org.json + json + 20250517 + + org.springframework.boot spring-boot-starter-test diff --git a/src/main/java/com/ljc42/demo/Controller/HelloController.java b/src/main/java/com/ljc42/demo/Controller/HelloController.java deleted file mode 100644 index 41714ec..0000000 --- a/src/main/java/com/ljc42/demo/Controller/HelloController.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ljc42.demo; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class HelloController { - - @GetMapping("/") - public String hello() { - return "hello.json"; - } -} diff --git a/src/main/java/com/ljc42/product/Controller/ProductController.java b/src/main/java/com/ljc42/product/Controller/ProductController.java new file mode 100644 index 0000000..6aef2c6 --- /dev/null +++ b/src/main/java/com/ljc42/product/Controller/ProductController.java @@ -0,0 +1,61 @@ +package com.ljc42.product.Controller; + +import com.ljc42.product.Exceptions.ProductExitsException; +import com.ljc42.product.Exceptions.ProductNotFoundException; +import com.ljc42.product.Model.Product; +import com.ljc42.product.Service.ProductService; +import org.json.JSONObject; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; +import java.util.Objects; + +@RestController +public class ProductController { + + private final ProductService productService; + + public ProductController(ProductService productService) { + this.productService = productService; + } + + @GetMapping("/api/v1/product/{name}") + public ResponseEntity> getProducts(@PathVariable String name) { + try { + Product product = this.productService.getProductByName(name); + JSONObject jsonProduct = new JSONObject(); + jsonProduct.put("name", product.getName()); + jsonProduct.put("price", product.getPrice()); + jsonProduct.put("stock", product.getStock()); + JSONObject responseBody = new JSONObject(); + responseBody.put("code", 200); + responseBody.put("product", jsonProduct); + responseBody.put("message", "Product retrieved"); + return new ResponseEntity<>(responseBody.toMap(), HttpStatus.OK); + } catch (ProductNotFoundException e) { + JSONObject responseBody = new JSONObject(); + responseBody.put("code", 404); + responseBody.put("message", e.getMessage()); + return new ResponseEntity<>(responseBody.toMap(), HttpStatus.NOT_FOUND); + } + } + + @PostMapping("/api/v1/product/create") + public ResponseEntity> createProducts(@RequestBody Product product) { + try { + this.productService.createProduct(product); + JSONObject responseBody = new JSONObject(); + responseBody.put("code", 201); + responseBody.put("name", product.getName()); + responseBody.put("message", "Product created"); + return new ResponseEntity<>(responseBody.toMap(),HttpStatus.CREATED); + } catch (ProductExitsException e) { + JSONObject responseBody = new JSONObject(); + responseBody.put("code", 409); + responseBody.put("message", e.getMessage()); + return new ResponseEntity<>(responseBody.toMap(),HttpStatus.CONFLICT); + } + } +} diff --git a/src/main/java/com/ljc42/demo/DemoApplication.java b/src/main/java/com/ljc42/product/DemoApplication.java similarity index 72% rename from src/main/java/com/ljc42/demo/DemoApplication.java rename to src/main/java/com/ljc42/product/DemoApplication.java index 1fe392a..18d5a71 100644 --- a/src/main/java/com/ljc42/demo/DemoApplication.java +++ b/src/main/java/com/ljc42/product/DemoApplication.java @@ -1,10 +1,11 @@ -package com.ljc42.demo; +package com.ljc42.product; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) +//@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) +@SpringBootApplication() public class DemoApplication { public static void main(String[] args) { diff --git a/src/main/java/com/ljc42/product/Exceptions/ProductExitsException.java b/src/main/java/com/ljc42/product/Exceptions/ProductExitsException.java new file mode 100644 index 0000000..679f119 --- /dev/null +++ b/src/main/java/com/ljc42/product/Exceptions/ProductExitsException.java @@ -0,0 +1,7 @@ +package com.ljc42.product.Exceptions; + +public class ProductExitsException extends Exception{ + public ProductExitsException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ljc42/product/Exceptions/ProductNotFoundException.java b/src/main/java/com/ljc42/product/Exceptions/ProductNotFoundException.java new file mode 100644 index 0000000..e2cc804 --- /dev/null +++ b/src/main/java/com/ljc42/product/Exceptions/ProductNotFoundException.java @@ -0,0 +1,7 @@ +package com.ljc42.product.Exceptions; + +public class ProductNotFoundException extends Exception{ + public ProductNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/ljc42/product/Model/Product.java b/src/main/java/com/ljc42/product/Model/Product.java new file mode 100644 index 0000000..6b7daef --- /dev/null +++ b/src/main/java/com/ljc42/product/Model/Product.java @@ -0,0 +1,48 @@ +package com.ljc42.product.Model; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +@Entity +public class Product { + private @Id + @GeneratedValue Long id; + private String name; + private double price; + private int stock; + + public Product() { + + } + + public Product(String name, double price, int stock) { + this.name = name; + this.price = price; + this.stock = stock; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public int getStock() { + return stock; + } + + public void setStock(int stock) { + this.stock = stock; + } +} diff --git a/src/main/java/com/ljc42/product/Repository/ProductRepository.java b/src/main/java/com/ljc42/product/Repository/ProductRepository.java new file mode 100644 index 0000000..40e7a09 --- /dev/null +++ b/src/main/java/com/ljc42/product/Repository/ProductRepository.java @@ -0,0 +1,9 @@ +package com.ljc42.product.Repository; + +import com.ljc42.product.Model.Product; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProductRepository extends JpaRepository { + boolean existsByName(String name); + Product findByName(String name); +} diff --git a/src/main/java/com/ljc42/product/Service/ProductService.java b/src/main/java/com/ljc42/product/Service/ProductService.java new file mode 100644 index 0000000..b556f79 --- /dev/null +++ b/src/main/java/com/ljc42/product/Service/ProductService.java @@ -0,0 +1,31 @@ +package com.ljc42.product.Service; + +import com.ljc42.product.Exceptions.ProductNotFoundException; +import com.ljc42.product.Model.Product; +import com.ljc42.product.Repository.ProductRepository; +import com.ljc42.product.Exceptions.ProductExitsException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ProductService { + + @Autowired + private ProductRepository productRepository; + + public void createProduct(Product product) throws ProductExitsException{ + if(productRepository.existsByName(product.getName())) { + throw new ProductExitsException("Product with the same name already exists"); + } else { + this.productRepository.save(product); + } + } + + public Product getProductByName(String name) throws ProductNotFoundException { + if(productRepository.existsByName(name)) { + return productRepository.findByName(name); + } else { + throw new ProductNotFoundException("Product not found"); + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 2109a44..a02a06a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,7 @@ spring.application.name=demo +spring.h2.console.enabled=true +spring.datasource.url=jdbc:h2:mem:app +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/src/test/java/com/ljc42/demo/DemoApplicationTests.java b/src/test/java/com/ljc42/product/DemoApplicationTests.java similarity index 86% rename from src/test/java/com/ljc42/demo/DemoApplicationTests.java rename to src/test/java/com/ljc42/product/DemoApplicationTests.java index 944bac9..52a6935 100644 --- a/src/test/java/com/ljc42/demo/DemoApplicationTests.java +++ b/src/test/java/com/ljc42/product/DemoApplicationTests.java @@ -1,4 +1,4 @@ -package com.ljc42.demo; +package com.ljc42.product; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest;