项目介绍
该项目主要介绍基于快递信息的增删改查。
什么是MVC?
MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。
开发环境
-
运行环境:最好是java jdk 17,我们在这个平台上运行的。其他版本理论上也可以。
-
IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;
-
硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS;
-
数据库:MySql 5.7版本;
-
是否Maven项目:是
技术栈
-
后端:SpringBoot+Mysql+Thymeleaf模板引擎
-
前端:HTML+JavaScript+BootStrap
使用说明
-
使用idea的数据库,在mysql中创建对应名称的数据库,并导入项目的sql文件;
-
使用IDEA导入项目时,若为maven项目请选择maven;进去依赖添加完毕之后出现pom.xml的,即视为成功使用maven;
-
将项目中application.properties配置文件中的数据库配置改为自己的配置;
-
运行项目,输入localhost:8080/ 进入网页界面
技术要求
使用IDEA新建项目时,要选择Spring Initializr
选择Maven
建议JDK 17
添加以下五个依赖
思路过程
1. 搭建框架
2. model层
存放实体类;有收件人,电话号码,快递状态,一张表对应一个实体类,类属性同表字段相对应。
注:添加@Data用法,可帮我们省去实体类的get()和set()方法,节省时间。
代码展示:
package com.example.express.model;
import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
@Table(name = "express")
public class Express {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "person_name")
private String personName;
@Column(name = "person_number")
private String personNumber;
@Column(name = "state")
private String state;
}
3. Service层
业务层,service层的作用为完成功能设计。存放业务逻辑处理,不直接对数据库进行操作,有接口和接口实现类,提供controller层调用的方法。设计的功能主要有新增、更新、获取指定id的快递信息、删除指定ID的快递信息、分页、模糊查询快递信息。
代码展示:
package com.example.express.service;
import com.example.express.model.Express;
import org.springframework.data.domain.Page;
import java.util.List;
public interface ExpressService {
//获取所有快递
List<Express> getAllExpress();
//新增
void saveExpress(Express express);
//获取指定单号
Express getExpressByTd(long id);
//删除指定单号
void deleteExpressById(long id);
//分页
Page<Express> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection);
//根据收件人查询
List<Express> findByPersonName(String personName);
}
4. ExpressServiceImpl.java用来存放接口的实现类对接口函数进行实现。
代码展示:
package com.example.express.service;
import com.example.express.model.Express;
import com.example.express.repository.ExpressRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class ExpressServiceImpl implements ExpressService {
@Autowired
private ExpressRepository expressRepository;
@Override
public List<Express> getAllExpress(){
return expressRepository.findAll();
}
@Override
public void saveExpress(Express express){
this.expressRepository.save(express);
}
@Override
public Express getExpressByTd(long id) {
//调用数据访问层查找指定ID的员工,返回Optional对象
Optional<Express> optional = expressRepository.findById(id);
Express express = null;
//如果存在指定id的快递
if (optional.isPresent()){
//从Optional对象中获取快递对象
express = optional.get();
}else {
//否则抛出运行时异常
throw new RuntimeException("找不到快递单号:"+id);
}
return express;
}
@Override
public void deleteExpressById(long id){
this.expressRepository.deleteById(id);
}
@Override
public Page<Express> 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.expressRepository.findAll(pageable);
}
@Override
public List<Express> findByPersonName(String personName) {
List<Express> name = expressRepository.findAllByPersonName(personName);
return name;
}
}
5. Controller层
控制器层,controller层的功能为请求和响应控制。
controller层负责前后端交互,接受前端请求,调用service层,接收service层返回的数据,最后返回具体的页面和数据到客户端。
代码展示:
package com.example.express.controller;
import com.example.express.model.Express;
import com.example.express.service.ExpressService;
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 ExpressController {
@Autowired
private ExpressService expressService;
@GetMapping("/")
public String viewHomePage(Model model) {
return findPaginated(1, "personName", "asc", model);
}
/**
* 跳转
*/
@GetMapping("/showNewExpressForm")
public String showNewExpressForm(Model model){
Express express = new Express();
model.addAttribute("express", express);
return "new_express";
}
@GetMapping("/query{inpname}")
public String query(@PathVariable(value = "inpname") String inpame,Model model){
List<Express> listpersonnumber = expressService.findByPersonName(inpame);
model.addAttribute("listExpress",listpersonnumber);
return "index";
}
/**
* 添加
*/
@PostMapping("/saveExpress")
public String saveExpress(@ModelAttribute("express") Express express){
expressService.saveExpress(express);
return "redirect:/";
}
/**
* 更新跳转
*/
@GetMapping("/showFormForUpdate/{id}")
public String showFormForUpdate(@PathVariable(value = "id") long id,Model model){
Express express = expressService.getExpressByTd(id);
model.addAttribute("express", express);
return "update_express";
}
/**
* 删除
*/
@GetMapping("/deleteExpress/{id}")
public String deleteExpress(@PathVariable(value = "id") long id){
this.expressService.deleteExpressById(id);
return "redirect:/";
}
//获取分页数据
@GetMapping("/page/{pageNo}")
public String findPaginated(@PathVariable (value = "pageNo") int pageNo,
@RequestParam("sortField") String sortField,
@RequestParam("sortDir") String sortDir,
Model model) {
int pageSize = 5;
//分页查询
Page<Express> page = expressService.findPaginated(pageNo, pageSize, sortField, sortDir);
List<Express> listExpress = 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("listExpress", listExpress);
return "index";
}
}
6. repository层
-
调用ExpressRepository进行数据库操作。查询Express里面的personName对象;
-
select * from xxx中xxx也不是数据库里面真正的表名,而是对应的实体名;
-
补充:sql中的字段名也不是数据库中真正的字段名,而是实体的字段名。
代码展示:
package com.example.express.repository;
import com.example.express.model.Express;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface ExpressRepository extends JpaRepository<Express,Long> {
@Query("select g from Express g where g.personName like %:personName%")
List<Express> findAllByPersonName(@Param("personName") String personName);
}
7. 配置application.properties
本人使用的是远程数据库
代码展示:
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:mysql://(数据库ip):3306/express?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username=root
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
8. index.html部分页面展示
ps:html 的源码这里就不往上放了,大家感兴趣可自行摸索或私信我。
9. 使用BootStrap
进入到BootStrap官网中,选择符合主题或自己喜欢的样式,将他添加进html页面中的head标签中。
官网:BootStrap官网
难点及解决方法
难点
- 图片导入到 html 时,却在网页界面上不显示;使用其相对路径和绝对路径也都不显示;
解决方法
- 先使用 “…/static/img/p1.jpg” 方法法插入;点击浏览器预览
- 此时是正常显示的;
但注意看,这里有一个链接,可以看到是先项目名称才到后面的templates/index.html,之后我们的图片就应该
“http://localhost:63342/Express/src/main/resources/static/img/p1.jpg”
这样我们使用项目的时候localhost:8080才可以正常访问!
至此,问题就解决了。
效果展示
(1) 网页界面首页
(2) 增加快递信息
(3)更新
将张三更改为张四
(4)删除
将张四删除
(5) 查找——根据收件人的名字模糊查询
查询包含 “谢” 的收件人信息
(6) 分页(大于5行数据可显示页面)
总结
SpringBoot是一款非常优秀的框架,不仅提供了简化开发的工具和功能,还能帮助我们更好地理解和应用Spring框架。并且它还提供了一种快速、简单的方式来构建独立的、可执行的Spring应用程序。
通过学习我对Java应用程序的开发有了更深入的认识,也提升了自己的技能水平。我相信在未来的工作中,SpringBoot将会成为我们不可或缺的利器。
小伙伴们可以添加其他功能哦!
不合适的地方,望大牛指正。欢迎交流学习!