第一个 Spring boot API 开发范例。使用的元件有以下,开发使用 vscode 建立专案时透过工具进行建立非常的容易。这一个专案使用了 Mysql 进行 DB 连线,使用 JPA 的框架进行简易的 API 实现。
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
...
主要的资料夹结构
/springboot-crud/src/main/java/com/example/cch/crud$ tree
.
├── CrudApplication.java
├── controller # 靠近 UI 层
│ └── ProductController.java
├── model # 实体层,宣告一个领域
│ └── Product.java
├── repository # 有关 DB 的操作
│ └── ProductRepository.java
└── service # 业务逻辑
├── ProductService.java
└── ProductServiceImp.java
我们在 resource 资料夹下的 application.properties 档案进行关於 DB 连线的设置
# Mysql
# demo DB name
spring.datasource.url=jdbc:mysql://192.168.134.146:3306/crudb
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=springcrud
spring.datasource.password=123456
# Hibernate
# spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MYSQL
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
我们假设设计一个有关於产品的领域的实体,有个简单的主键 ID 和商品名称以及价格。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column()
private String name;
@Column()
private float price;
// ... get、set and constructor
}
建立实体後,需要操作 DB 以获得 DB 中的资料或是存储资料,简单的透过继层 JpaRepository
即可实现简易的 CRUD 操作。JpaRepository<Product, Long>
中 Product 是实体类它会对应 DB 中的栏位,Long
则是主键。
public interface ProductRepository extends JpaRepository<Product, Long>{
}
接这我们撰写业务逻辑,首先我们定义一个 Interface,分别是以下
public interface ProductService {
List<Product> getAllProduct(); //获取所有
void saveProduct(Product product); // 储存
Product getProductById(Long id); // 透过主键获取资料
void deleteProductById(Long id); // 删除资料
}
实现介面,也就是实现业务逻辑,简单来说就是把 DB 的操作逻辑写在这
@Service
public class ProductServiceImp implements ProductService {
@Autowired // 将 DB 的操作注入,这可以将其想像成是建构方法
private ProductRepository productRepository;
@Override
public List<Product> getAllProduct() {
// TODO Auto-generated method stub
return this.productRepository.findAll();
}
@Override
public void saveProduct(Product product) {
// TODO Auto-generated method stub
productRepository.save(product);
}
@Override
public Product getProductById(Long id) {
// TODO Auto-generated method stub
Optional<Product> optional = productRepository.findById(id);
Product product = null;
if (optional.isPresent()){
product = optional.get();
}
return product;
}
@Override
public void deleteProductById(Long id) {
// TODO Auto-generated method stub
this.productRepository.deleteById(id);
}
}
接着把靠近 UI 层部分就是 controller 进行实现,这边会使用 HTTP 的 Method 进行 CRUD 实现。
@RestController
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/products")
public List<Product> list() {
return productService.getAllProduct();
}
@GetMapping("/products/{id}")
public ResponseEntity<Product> get(@PathVariable(value = "id") Long id) {
// 这边的防呆其实可以拉到 Service 层进行
try {
Product product = productService.getProductById(id);
if (product == null){
return new ResponseEntity<Product>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Product>(product, HttpStatus.OK);
} catch (Exception e) {
// TODO: handle exception
return new ResponseEntity<Product>(HttpStatus.NOT_FOUND);
}
}
@PostMapping("/products")
public void add(@RequestBody Product product) {
productService.saveProduct(product);
}
@PutMapping("/products/{id}")
public ResponseEntity<?> update(@RequestBody Product product, @PathVariable(value = "id") Long id){
try {
Product existProduct = productService.getProductById(id);
if (existProduct == null){
return new ResponseEntity<Product>(HttpStatus.NOT_FOUND);
}
productService.saveProduct(product);
return new ResponseEntity<Product>(HttpStatus.OK);
} catch (Exception e) {
// TODO: handle exception
return new ResponseEntity<Product>(HttpStatus.NOT_FOUND);
}
}
@DeleteMapping("/products/{id}")
public void delete(@PathVariable(value = "id") Long id) {
productService.deleteProductById(id);
}
}
建立资料库和使用者
mysql> create user 'springcrud'@'%' identified by '123456';
Query OK, 0 rows affected (0.02 sec)
mysql> create database crudb;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on crudb.* to 'springcrud'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE product ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(45) NOT NULL, price FLOAT NOT NULL );
Query OK, 0 rows affected (0.04 sec)
mysql> show tables;
+-----------------+
| Tables_in_crudb |
+-----------------+
| product |
+-----------------+
1 row in set (0.01 sec)
mysql> SHOW COLUMNS FROM product;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(45) | NO | | NULL | |
| price | float | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
对映 controller 中 add 方法
$ curl -X POST -H "Content-Type: application/json" -d '{"name": "apple", "price": 189.8}' http://localhost:8080/products
mysql> use crudb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> SELECT * FROM product;
+----+-------+-------+
| id | name | price |
+----+-------+-------+
| 1 | apple | 189.8 |
+----+-------+-------+
1 row in set (0.00 sec)
对映 controller 中 list 方法
$ curl http://localhost:8080/products
[{"id":1,"name":"apple","price":189.8}]
$ curl -X POST -H "Content-Type: application/json" -d '{"name": "sony", "price": 120.86}' http://localhost:8080/products
$ curl -X POST -H "Content-Type: application/json" -d '{"name": "samsung", "price": 170.7}' http://localhost:8080/products
$ curl http://localhost:8080/products
[{"id":1,"name":"apple","price":189.8},{"id":2,"name":"sony","price":120.86},{"id":3,"name":"samsung","price":170.7}]
对映 controller 中 update 方法
$ curl -X PUT -H "Content-Type: application/json" -d '{"id": 1, "name": "iphone 12", "price": 999.7}' http://localhost:8080/products/1 -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> PUT /products/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 46
>
* upload completely sent off: 46 out of 46 bytes
< HTTP/1.1 200
< Content-Length: 0
< Date: Sun, 06 Dec 2020 13:28:07 GMT
<
* Connection #0 to host localhost left intact
$ curl http://localhost:8080/products
[{"id":1,"name":"iphone 12","price":999.7},{"id":2,"name":"sony","price":120.86},{"id":3,"name":"samsung","price":170.7}]
mysql> SELECT * FROM product;
+----+-----------+--------+
| id | name | price |
+----+-----------+--------+
| 1 | iphone 12 | 999.7 |
| 2 | sony | 120.86 |
| 3 | samsung | 170.7 |
+----+-----------+--------+
3 rows in set (0.01 sec)
当 id 不正确时回应 404
$ curl -X PUT -H "Content-Type: application/json" -d '{"id": 10, "name": "iphone 12", "price": 999.7}' http://localhost:8080/products/10 -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> PUT /products/10 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 47
>
* upload completely sent off: 47 out of 47 bytes
< HTTP/1.1 404
< Content-Length: 0
< Date: Sun, 06 Dec 2020 13:58:54 GMT
<
* Connection #0 to host localhost left intact
对映 controller 中 deleteProductById 方法
$ curl -X DELETE http://localhost:8080/products/1
mysql> SELECT * FROM product;
+----+---------+--------+
| id | name | price |
+----+---------+--------+
| 2 | sony | 120.86 |
| 3 | samsung | 170.7 |
+----+---------+--------+
2 rows in set (0.00 sec)
$ curl http://localhost:8080/products/
[{"id":2,"name":"sony","price":120.86},{"id":3,"name":"samsung","price":170.7}]
真的有点忙,文章内容都不是很完整,在麻烦见谅~~
这范例都在我github上
>>: [想试试看JavaScript ] 流程控制 if...else
网路钓鱼常被简称为网钓, 即攻击者透过伪装成正规的法人媒体, 以获得如使用者名称、密码和信用卡明细等...
前情提要 昨天实战了用 Python 向猫咪图片的 API 请求。使用者可以输入一个数字,让程序可以...
0x1 Laravel 资料库连接 请先确认 php.ini 的 pdo_pgsql extensi...
订阅patreon即可看到更多文章 https://www.patreon.com/wade3c ...
想知道我们在使用滑鼠操作电脑时作业系统在背後做了什麽事情吗? 又或者为什麽我们在写 C 语言时,老师...