目录
前言
一、项目结构
二、创建项目、运行环境
三、配置数据库
四、Model
五、Repository
六、Service
1、接口类
2、实现类
七、Controller
八、Web页面
1、index
2、new_food
3、update_food
九、Web页面展示
十、总结
文章来源:https://www.uudwc.com/A/NxEPg/
前言
Spring是一个开源框架,可以轻松创建独立的、生产级的基于 Spring 的应用程序,它可以尽可能减少你的配置文件,而且它不仅仅局限于服务器端开发,任何Java应用都能在简单性、可测试性和松耦合性等方面从Spring中获益。
一、项目结构
二、创建项目、运行环境
三、配置数据库
四、Model
model是存放实体的类,类中定义了多个类属性,这里一共给了五个属性,分别是:name、type、state、price、quantity
package com.example.food.model;
import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
@Table(name = "Food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name")
private String name;
@Column(name = "type")
private String type;
@Column(name = "state")
private String state;
@Column(name = "price")
private String price;
@Column(name = "quantity")
private String quantity;
}
@GeneratedValue:为一个实体生成一个唯一标识的主键,在这里主键是id
@Column:标识实体类中属性与数据表中字段的对应关系。
@Data :可以提高代码的简洁性,并且自动装配get、set、toString、hashcoe、equals等方法。
@Table:一般用在pojo实体类的类名上,使用该注解后pojo类的属性会和对应的表字段做一个映射关系
五、Repository
Repository是接口层,相当于一个数据仓库,它可以用于底层数据的存取,在它的内部封装了数据查询和存储的逻辑。
package com.example.foodwork.repository;
import com.example.foodwork.model.Food;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface FoodRepository extends JpaRepository<Food, Long> {
List<Food> findAllByName(String name);
}
@Repository:将类识别为Bean,并将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。
六、Service
Service是业务逻辑层,由对应的存放接口类和存放接口实现类组成,不直接对数据库进行操作,为controller层提供调用的方法,在这里我写了增删查改以及分页的五个方法。
1、接口类
package com.example.foodwork.service;
import com.example.foodwork.model.Food;
import org.springframework.data.domain.Page;
import java.util.List;
public interface FoodService {
// 获取所有的商品
List<Food> getAllFood();
// 新增或更新一样商品
void saveFood(Food food);
// 获取指定ID的商品
Food getFoodById(long id);
// 删除指定ID的商品
void deleteFoodById(long id);
// 查找某样商品
List<Food> findByName(String name);
// 更新
void updateFood(Food food);
// 分页
Page<Food> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection);
}
2、实现类
package com.example.foodwork.service;
import com.example.foodwork.model.Food;
import com.example.foodwork.repository.FoodRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class FoodServiceImpl implements FoodService {
@Autowired
private FoodRepository foodRepository;
@Override
public List<Food> getAllFood(){
return foodRepository.findAll();
}
@Override
public void saveFood(Food food){
this.foodRepository.save(food);
}
@Override
public Food getFoodById(long id){
// 调用数据访问层查找指定ID的商品,返回Optional==(选择)对象
Optional<Food> optional = foodRepository.findById(id);
Food food = null;
// 如果存在指定id的商品
if (optional.isPresent()) {
// 从Optional对象中获取商品对象
food = optional.get();
} else {
// 否则抛出运行时异常
throw new RuntimeException("找不到商品ID :: " + id);
}
return food;
}
// 删除指定id的商品
@Override
public void deleteFoodById(long id){
this.foodRepository.deleteById(id);
}
@Override
public Page<Food> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection) {
//设置排序参数,升序ASC/降序DESC?
Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name())
? Sort.by(sortField).ascending()
: Sort.by(sortField).descending();
//根据页号/每页记录数/排序依据返回某指定页面数据。
Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
return this.foodRepository.findAll(pageable);
}
@Override
public List<Food> findByName(String name) {
List<Food> goodsNames = foodRepository.findAllByName(name);
return goodsNames;
}
@Override
public void updateFood(Food food) {
foodRepository.save(food);
}
}
@Service():在调用该service的时候只需要将该类注入接口中,表示给当前类命名一个别名,方便注入到其他需要用到的类中;不加的话,默认别名就是当前类名,但是首字母小写 。
@Override:重写,子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
七、Controller
控制层模块,它是一个控制器类,在HTTP请求中获取信息,提取参数,并将其分发给不同的处理服务(service层),进行前端请求的处理,向前端返回service层处理后的数据。
package com.example.foodwork.controller;
import com.example.foodwork.model.Food;
import com.example.foodwork.service.FoodService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
public class FoodController {
@Autowired
private FoodService foodService;
@GetMapping("/")
public String viewHomePage(Model model) { return findPaginated(1, "name", "asc", model); }
@GetMapping("/showFoodForm")
public String showFoodForm(Model model) {
Food food = new Food();
model.addAttribute("food", food);
return "new_super";
}
@PostMapping("/saveFood")
public String saveFood(@ModelAttribute("food") Food food) {
foodService.saveFood(food);
return "redirect:/";
}
@GetMapping("/showFormForUpdate/{id}")
public String showFormForUpdate(@PathVariable(value = "id") long id, Model model) {
Food foods = foodService.getFoodById(id);
model.addAttribute("food", foods);
return "update_super";
}
@GetMapping("/deleteFood/{id}")
public String deleteFood(@PathVariable(value = "id") long id) {
this.foodService.deleteFoodById(id);
return "redirect:/";
}
@GetMapping("/query{newName}")
public String query(@PathVariable(value = "newName") String newName, Model model) {
List<Food> listGoodsNumber = foodService.findByName(newName);
model.addAttribute("listFood", listGoodsNumber);
return "index";
}
//获取分页数据
@GetMapping("/page/{pageNo}")
public String findPaginated(@PathVariable(value = "pageNo") int pageNo,
@RequestParam("sortField") String sortField,
@RequestParam("sortDir") String sortDir,
Model model) {
int pageSize = 3;
Page<Food> page = foodService.findPaginated(pageNo, pageSize, sortField, sortDir);
List<Food> listFood = page.getContent();
model.addAttribute("currentPage", pageNo);
model.addAttribute("totalPages", page.getTotalPages());
model.addAttribute("totalItems", page.getTotalElements());
model.addAttribute("sortField", sortField);
model.addAttribute("sortDir", sortDir);
model.addAttribute("reverseSortDir", sortDir.equals("asc") ? "desc" : "asc");
model.addAttribute("listFood", listFood);
return "index";
}
}
@Autowired :对类成员变量、方法及构造函数进行标注,完成自动装配的工作
@GetMapping:用于处理请求方法的GET类型
八、Web页面
1、index
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta charset="ISO-8859-1">
<title>食品管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
<body>
<div class="container my-2">
<h1>商品列表</h1>
<a th:href="@{/showFoodForm}" class="btn btn-primary btn-sm mb-3"> 新增 </a>
<h1 class="text-primary"></h1>
<nav class="navbar navbar-light bg-light">
<form id="query-form" action="/query" method="get">
<h6 class="text-secondary">查找商品</h6><input type="text" id="name-input" name="inpname" placeholder="商品名">
<button type="button" class="btn btn-info"onclick="queryFood()">搜索</button>
</form>
<hr>
<a th:href="@{/}"> 回到商品列表</a>
<script>
function queryFood() {
var goodsName = document.getElementById("name-input").value;
var url = "/query" + encodeURIComponent(goodsName);
window.location.href = url;
}
</script>
</nav>
<table border="1" class="table table-striped table-responsive-md">
<thead>
<tr>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=goodsName&sortDir=' + ${reverseSortDir}}">
商品名称</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=price&sortDir=' + ${reverseSortDir}}">
商品类型</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=types&sortDir=' + ${reverseSortDir}}">
商品状态</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=types&sortDir=' + ${reverseSortDir}}">
商品价格</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=types&sortDir=' + ${reverseSortDir}}">
商品数量</a>
</th>
<th> 功能 </th>
</tr>
</thead>
<tbody>
<tr th:each="food : ${listFood}">
<td th:text="${food.name}"></td>
<td th:text="${food.type}"></td>
<td th:text="${food.state}"></td>
<td th:text="${food.price}"></td>
<td th:text="${food.quantity}"></td>
<td> <a th:href="@{/showFormForUpdate/{id}(id=${food.id})}" class="btn btn-primary">更新</a>
<a th:href="@{/deleteFood/{id}(id=${food.id})}" class="btn btn-danger">删除</a>
</td>
</tr>
</tbody>
</table>
<div th:if = "${totalPages > 1}">
<div class = "row col-sm-10">
<div class = "col-sm-3">
商品总数: [[${totalItems}]]
</div>
<div class = "col-sm-5">
<span th:each="i: ${#numbers.sequence(1, totalPages)}">
<a th:if="${currentPage != i}" th:href="@{'/page/' + ${i}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">[[${i}]]</a>
<span th:unless="${currentPage != i}">[[${i}]]</span>
</span>
</div>
<!--< <div class = "col-sm-1">–>-->
<!--< <a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${currentPage + 1}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">上一页</a>–>-->
<!--< <span th:unless="${currentPage < totalPages}">Next</span>–>-->
<!--< </div>–>-->
<!--< <div class="col-sm-1">–>-->
<!--< <a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${totalPages}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">下一页</a>–>-->
<!--< <span th:unless="${currentPage < totalPages}">Last</span>–>-->
<!--< </div>–>-->
<!-- </div>-->
</div>
</div>
</body>
</html>
2、new_food
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta charset="ISO-8859-1">
<title>食品管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>食品管理</h1>
<hr>
<h2>上架新商品</h2>
<form action="#" th:action="@{/saveFood}" th:object="${food}" method="POST">
<input type="text" th:field="*{name}" placeholder="名称" class="form-control mb-4 col-4">
<input type="text" th:field="*{type}" placeholder="类型" class="form-control mb-4 col-4">
<input type="text" th:field="*{state}" placeholder="状态" class="form-control mb-4 col-4">
<input type="text" th:field="*{price}" placeholder="价格" class="form-control mb-4 col-4">
<input type="text" th:field="*{quantity}" placeholder="数量" class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2"> 保存</button>
</form>
<hr>
<a th:href="@{/}"> 回到商品列表</a>
</div>
</body>
</html>
3、update_food
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta charset="ISO-8859-1">
<title>食品管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>食品管理</h1>
<hr>
<h2>更改商品</h2>
<form action="#" th:action="@{/saveFood}" th:object="${food}" method="POST">
<!-- Add hidden form field to handle update -->
<input type="hidden" th:field="*{id}" />
<input type="text" th:field="*{name}" class="form-control mb-4 col-4">
<input type="text" th:field="*{type}" class="form-control mb-4 col-4">
<input type="text" th:field="*{state}" class="form-control mb-4 col-4">
<input type="text" th:field="*{price}" class="form-control mb-4 col-4">
<input type="text" th:field="*{quantity}" class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2"> 更改</button>
</form>
<hr>
<a th:href="@{/}"> 返回到商品列表</a>
</div>
</body>
</html>
九、Web页面展示
列表页面:
添加页面:
更新页面:
十、总结
在这里简单的介绍了Springle Boot的增删查改,希望能给大家带来帮助,本人是个还在学习的小白,有不对的地方还请大家多多指点。文章来源地址https://www.uudwc.com/A/NxEPg/