This commit is contained in:
Jincheng Lu 2025-09-10 06:50:08 +08:00
parent eda045e55c
commit 17ba0a8226
12 changed files with 216 additions and 16 deletions

32
Readme.md Normal file
View File

@ -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

11
pom.xml
View File

@ -34,11 +34,22 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20250517</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@ -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";
}
}

View File

@ -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<Map<String,Object>> 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<Map<String, Object>> 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);
}
}
}

View File

@ -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) {

View File

@ -0,0 +1,7 @@
package com.ljc42.product.Exceptions;
public class ProductExitsException extends Exception{
public ProductExitsException(String message) {
super(message);
}
}

View File

@ -0,0 +1,7 @@
package com.ljc42.product.Exceptions;
public class ProductNotFoundException extends Exception{
public ProductNotFoundException(String message) {
super(message);
}
}

View File

@ -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;
}
}

View File

@ -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<Product, Long> {
boolean existsByName(String name);
Product findByName(String name);
}

View File

@ -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");
}
}
}

View File

@ -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

View File

@ -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;