目录
1.环境搭建:
1.1创建项目
依赖选择
1.2项目结构
a
1.3配置数据库
spring.datasource.url=jdbc:mysql://rm-cn-uqm37zs4a0.rwlb.rds.aliyuncs.com:3306/dbExam?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username= chenyun
spring.datasource.password= *******
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# for Spring Boot 2
# spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
# for Spring Boot 3
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQLDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto= update
#?????hibernate-sql
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
# 设置编码格式
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
2.Model层
package com.example.finalcameraproject.model;
import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
@Table(name = "camerar")
public class Camera {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "camera_name") // 照相机的名称
private String cameraName;
@Column(name = "brand") // 照相机品牌
private String brand;
@Column(name = "camera_ype") // 照相机类型
private String cameraType;
@Column(name = "state") // 照相机状态
private String state;
@Column(name = "rent")
private double rent; // 照相机租价
}
3.Repository层
import com.example.finalcameraproject.model.Camera;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CameraRepository extends JpaRepository<Camera, Long> {
Page<Camera> findByStateContainingIgnoreCase(String CameraState, Pageable pageable);
}
4.service层
4.1 接口
import com.example.finalcameraproject.model.Camera;
import org.springframework.data.domain.Page;
import java.util.List;
public interface CameraService {
//获取所有的相机
List<Camera> getAllCamera();
//新增/更新一个相机
void saveCamera(Camera employee);
//获取指定ID的相机
Camera getCameraById(long id);
//删除指定ID的相机
void deleteCameraById(long id);
//分页与搜索
Page<Camera> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection, String CameraState);
}
4.2实现接口
import com.example.finalcameraproject.model.Camera;
import com.example.finalcameraproject.repository.CameraRepository;
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 CameraServiceImpl implements CameraService{
@Autowired
private CameraRepository cameraRepository;
@Override
public List<Camera> getAllCamera() {
return cameraRepository.findAll();
}
@Override
public void saveCamera(Camera camera) {
this.cameraRepository.save(camera);
}
@Override
public Camera getCameraById(long id) {
//调用数据访问层查找指定ID的相机,返回Optional对象
Optional< Camera > optional = cameraRepository.findById(id);
Camera camera = null;
//如果存在指定id的相机
if (optional.isPresent()) {
//从Optional对象中获取员工对象
camera = optional.get();
} else {
//否则抛出运行时异常
throw new RuntimeException(" 找不到相机ID :: " + id);
}
return camera;
}
@Override
public void deleteCameraById(long id) {
this.cameraRepository.deleteById(id);
}
//分页、排序与搜索
@Override
public Page<Camera> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection, String CameraState) {
//设置排序参数,升序ASC/降序DESC?
Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name())
? Sort.by(sortField).ascending()
: Sort.by(sortField).descending();
// 判断相机状态是否为空,为空则设置默认值为""
CameraState = CameraState != null ? CameraState : "";
//根据页号/每页记录数/排序依据返回某指定页面数据。
Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
// 执行模糊查询并应用分页和排序参数
Page<Camera> cameraPage = cameraRepository.findByStateContainingIgnoreCase(CameraState, pageable);
return cameraPage;
}
}
5.controller层
import com.example.finalcameraproject.model.Camera;
import com.example.finalcameraproject.service.CameraService;
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 CameraController {
@Autowired
private CameraService cameraService;
@GetMapping("/")
public String viewHomePage(Model model) {
return findPaginated(1, "cameraName", "asc",null,
model);
}
@GetMapping("/showNewCameraForm")
public String showNewCameraForm(Model model) {
// create model attribute to bind form data
Camera camera = new Camera();
model.addAttribute("camera",camera);
return "new_camera";
}
@PostMapping("/saveCamera")
public String saveCamera(@ModelAttribute("camera") Camera camera) {
// save Camera to database
cameraService.saveCamera(camera);
return "redirect:/";
}
@GetMapping("/showFormForUpdate/{id}")
public String showFormForUpdate(@PathVariable(value = "id") long id, Model model) {
Camera camera = cameraService.getCameraById(id);
model.addAttribute("camera", camera);
return "update_camera";
}
@GetMapping("/deleteCamera/{id}")
public String deleteCamera(@PathVariable(value = "id") long id) {
this.cameraService.deleteCameraById(id);
return "redirect:/";
}
//获取分页数据
@GetMapping("/page/{pageNo}")
public String findPaginated(@PathVariable (value = "pageNo") int pageNo,
@RequestParam("sortField") String sortField,
@RequestParam("sortDir") String sortDir,
@RequestParam(required = false) String CameraState,
Model model) {
int pageSize = 5;//
Page<Camera> page = cameraService.findPaginated(pageNo, pageSize, sortField, sortDir, CameraState);
List<Camera> listCamera = 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("CameraState",CameraState);
model.addAttribute("listCamera", listCamera);
return "index";
}
}
6.视图层
6.1 主页面 index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"> <!-- 设置编码格式 -->
<title>Camera Management System</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
</head>
<body>
<div class="container my-2">
<h1>共享照相机管理平台</h1>
<a th:href = "@{/showNewCameraForm}" class="btn btn-primary btn-sm mb-3"> 添加相机 </a>
<!-- 搜索框 -->
<form class="form-inline my-2 my-3"
th:action="@{/page/{pageNo}(pageNo=${currentPage},sortField=${'id'},sortDir=${'asc'})}"
th:method="get">
<input name="pageNo" type="hidden" th:value="1"/>
<input name="sortField" type="hidden" th:value="id"/>
<input name="sortDir" type="hidden" th:value="asc"/>
<input class="four-column-mr-sm-2" name="CameraState" type="search" placeholder="查询相机状态"
aria-label="Search">
<button class="bth btn-outline-success my-2 my-sm-0" type="submit">搜索</button>
<table border="1" class = "table table-striped table-responsive-md">
</form>
<thead>
<tr>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=cameraName&sortDir=' + ${reverseSortDir}}">
相机名称</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=brand&sortDir=' + ${reverseSortDir}}">
相机品牌</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=cameraType&sortDir=' + ${reverseSortDir}}">
相机类型</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=state&sortDir=' + ${reverseSortDir}}">
相机状态</a>
</th>
<th>
<a th:href="@{'/page/' + ${currentPage} + '?sortField=rent&sortDir=' + ${reverseSortDir}}">
相机租金</a>
</th>
<th> 行动 </th>
</tr>
</thead>
<tbody>
<tr th:each="camera : ${listCamera}">
<td th:text="${camera.cameraName}"></td>
<td th:text="${camera.brand}"></td>
<td th:text="${camera.cameraType}"></td>
<td th:text="${camera.state}"></td>
<td th:text="${camera.rent}"></td>
<td> <a th:href="@{/showFormForUpdate/{id}(id=${camera.id})}" class="btn btn-primary">修改</a>
<a th:href="@{/deleteCamera/{id}(id=${camera.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">
Total Rows: [[${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}}">Next</a>
<span th:unless="${currentPage < totalPages}">Next</span>
</div>
<div class="col-sm-1" style="margin-left: 10px;">
<a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${totalPages}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">Last</a>
<span th:unless="${currentPage < totalPages}">Last</span>
</div>
</div>
</div>
</div>
</body>
</html>
6.2 新建相机页面 new_camera.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Camera Management System</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1>共享照相机管理系统</h1>
<hr>
<h2>添加相机</h2>
<form action="#" th:action="@{/saveCamera}" th:object="${camera}" method="POST">
<input type="text" th:field="*{cameraName}" placeholder="相机的名称" class="form-control mb-4 col-4">
<input type="text" th:field="*{brand}" placeholder="相机品牌" class="form-control mb-4 col-4">
<input type="text" th:field="*{cameraType}" 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="*{rent}" 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>
6.3修改相机界面 update_camera.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Camera Management System</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1>Camera Management System</h1>
<hr>
<h2>Update Camera</h2>
<form action="#" th:action="@{/saveCamera}" th:object="${camera}" method="POST">
<!-- Add hidden form field to handle update -->
<input type="hidden" th:field="*{id}" />
<input type="text" th:field="*{cameraName}" class="form-control mb-4 col-4">
<input type="text" th:field="*{brand}" class="form-control mb-4 col-4">
<input type="text" th:field="*{cameraType}" 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="*{rent}" 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>