目录
一、案例说明
二、数据库
三、案例源码
3.1、pom文件
3.2、Application.yml
3.3、项目结构
a)整体结构
b)Java代码部分
c)资源文件部分
3.4、业务功能的实现
1)配置类
2)实体类
3)Mapper文件
4)Service
5)Controller
6)视图
四、测试效果图
启动项目
浏览器访问
添加功能
修改
删除
附件:pom文件
一、案例说明
Idea 2022.3.3汉化版 、mysql 5.7 、 JDK 8
springboot + thymeleaf + restful + layui.css + bootstrap
图书表和出版社表为例,实现增删改查的功能。
该案例需要准备一些样式表:
layui官网
bootstrap的下载地址
bootstrap-select下载地址
bootstrap-table下载地址
(在bootstrap-select和bootstrap-table中也都是使用文件中dist目录下的文件)
commons-lang3的官方教程
commons-lang3的官方API
1. commons-lang3是Apache提供的一个java.lang包的增强版本,Lang3为java.lang API提供了许多帮助程序实用程序,特别是字符串操作方法,基本数值方法,对象反射,并发,创建和序列化以及系统属性。此外,它还包含对java.urti.Date的基本增强,以及一系列专用于构建方法的实用程序,例如hashCode,toString和equals。
2.提供了官方的API地址,可通过文档获取需要的支持。
二、数据库
Book表

Publish表

温馨小贴士:book 表中字段 pic 为图片路径(表中是图片名字和格式)。
在案例中使用到了文件(图片)上传。则需要注意的是:文件保存位置。
//将所有/upimg/的访问请求都拦截到指定目录
registry.addResourceHandler("/upimg/**").addResourceLocations("file:D://uploadImg//");
由于在配置类BeanConfig中配置了拦截器(👆),将所有/upimg/的访问请求都拦截到指定目录。
所以,需要根据指定目录存放文件(图片)。
本案例文件(图片)存放地址为:

没有文件夹的要根据自己的设置进行创建,并存放使用的图片。否则,项目运行无法加载图片。
三、案例源码
3.1、pom文件
1、需要加载各种所需依赖坐标。
2、构建资源。

target文件夹是项目编译之后的资源文件夹。该文件夹中存在的内容才可以被项目中读取使用。
如果target中没有所需要的文件资源时, 检查pom.xml文件中是否拥有以下配置:
src/main/java **/*.yml **/*.properties **/*.xml false src/main/resources **/*.css **/*.js **/*.html **/*.png **/*.jpg **/*.properties **/*.yml **/*.xml **/*.conf false
3.2、Application.yml
# 服务器设置: 端口号和访问路径
server:port: 8088servlet:context-path: /shq
# 数据源设置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/2101_files?serverTimezone=UTCusername: rootpassword: 123456thymeleaf:cache: falsesuffix: .htmlweb:resources:static-locations: classpath:/templates/,classpath:/static/image/
# 让控制台显示执行的SQL语句
logging:level:cn:shq:mapper: debug
# mybatis配置
mybatis:type-aliases-package: cn.shq.model # 别名configuration:auto-mapping-behavior: full #设置全自动映射use-column-label: true # 列标签代替字段名
#设置mapper的路径mapper-locations: classpath:cn/shq/mapper/*.xml
3.3、项目结构
a)整体结构

b)Java代码部分

c)资源文件部分
案例中所使用的CSS、JS文件需要从各个官网上下载(本文头部👆提供的有各个网址)。

把静态文件放到static下面;把HTML文件放到templates下面;
3.4、业务功能的实现
1)配置类
BeasConfig.java
package cn.shq.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class BeanConfig extends WebMvcConfigurationSupport {/*** 拦截器* */@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {
// 自定义设置:指定程序中 路径为 /upimg/** 的文件,统统都到指定的Locations中去找(即 D://uploadImg//目录下去找)registry.addResourceHandler("/upimg/**").addResourceLocations("file:D://uploadImg//");
// 访问路径为/static/的请求,都到项目中static目录中。registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
// 在pom文件中 加载的各种前端文件 保存在resources/webjar目录下。
// 如果没有这一行代码的配置,则运行测试发现:没有样式表,找不到对应的样式文件。registry.addResourceHandler("/webjars/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX +"/META-INF/resources/webjars/");super.addResourceHandlers(registry);}/*** 添加restful支持*/@Beanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter() {HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();hiddenHttpMethodFilter.setBeanName("HiddenHttpMethodFilter");hiddenHttpMethodFilter.setMethodParam("_method");return hiddenHttpMethodFilter;}
}
2)实体类
Book.java
package cn.shq.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {private long bookId;private String bookName;private String author;private long price;private long pubId;/*** @DateTimeFormat:可以解决日期格式问题。* 因为页面传递过来的是String类型,而java中需要是Date类型。所以使用该注解可以进行类型转换。* 也可以使用另外一种方式实现类型转换:自己写一个日期格式转换类。* */@DateTimeFormat(pattern = "yyyy-MM-dd")private Date pubDate;private String pic;}
Publish.java
package cn.shq.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Publish {private long pubId;private String pubName;private String loc;}
BookVO.java
package cn.shq.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;import java.util.Date;@Data
@NoArgsConstructor
@AllArgsConstructor
public class BookVO {// book类中的属性private long bookId;private String bookName;private String author;private long price;private Date pubDate;private String pic;
// 👇 publish 出版社private Publish publish;
}
3)Mapper文件
BookMapper.java
package cn.shq.mapper;import cn.shq.model.Book;
import cn.shq.model.BookVO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;import java.util.List;
@Mapper
@Component
public interface BookMapper {// 查询全部List selectAll();// 添加int insert(Book book);// 删除 (根据编号进行删除)int del(Integer bookId);// 修改int update(Book book);// 条件查询 -----> 根据编号查找对应信息Book findByID(Integer bookId);}
BookMapper.xml
insert into book(bookName,pubId,pubDate,pic)values(#{bookName},#{pubId,jdbcType=INTEGER},#{pubDate,jdbcType=TIMESTAMP},#{pic}) delete from book where bookId = #{bookId} update book set bookName= #{bookName},pubId = #{pubId},pubDate = #{pubDate},pic = #{pic}where bookId = #{bookId}
PublishMapper.java
package cn.shq.mapper;import cn.shq.model.Publish;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;import java.util.List;@Mapper
@Component
public interface PublishMapper {@Select("select * from publish")List selectAll();
}
4)Service
BookService.java
package cn.shq.service;import cn.shq.model.Book;
import cn.shq.model.BookVO;import java.util.List;public interface BookService {// 查询全部List selectAll();// 添加int insert(Book book);// 删除 (根据编号进行删除)int del(Integer bookId);// 修改int update(Book book);// 条件查询 -----> 根据编号查找对应信息Book findByID(Integer bookId);
}
BookServiceImpl.java
package cn.shq.service.impl;import cn.shq.mapper.BookMapper;
import cn.shq.model.Book;
import cn.shq.model.BookVO;
import cn.shq.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
@Service
@Transactional
public class BookServiceImp implements BookService {@AutowiredBookMapper bookMapper;@Overridepublic List selectAll() {return bookMapper.selectAll();}@Overridepublic int insert(Book book) {return bookMapper.insert(book);}@Overridepublic int del(Integer bookId) {return bookMapper.del(bookId);}@Overridepublic int update(Book book) {return bookMapper.update(book);}@Overridepublic Book findByID(Integer bookId) {return bookMapper.findByID(bookId);}}
PublicServiceImpl.java
package cn.shq.service.impl;import cn.shq.mapper.PublishMapper;
import cn.shq.model.Publish;
import cn.shq.service.PublishService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
@Service
@Transactional
public class PublishServiceImpl implements PublishService {@AutowiredPublishMapper mapper;@Overridepublic List selectAll() {return mapper.selectAll();}
}
5)Controller
在控制器中使用到了图片的文件上传以及页面传递的日期格式,所以需要写一个工具类。
工具类BaseController.java
该工具类在本案例中放在util包中。
package cn.shq.util;import org.apache.commons.lang3.time.DateUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;import java.beans.PropertyEditorSupport;
import java.io.File;
import java.text.ParseException;
import java.util.Date;public class BaseController extends DateUtils {//定义真实的上传路径 : 案例中所用到的文件(图片)保存在改目录下。public final String REAL_PATH = "D:"+ File.separator+"uploadImg"+File.separator;//访问路径public final String VISIT_PATH = File.separator+"upimg"+File.separator;/*** 将前台传递过来的日期格式的字符串,自动转化为Date类型*/private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM","yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM","yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};/*** 日期型字符串转化为日期 格式*/public static Date parseDate(Object str) {if (str == null){return null;}try{return parseDate(str.toString(), parsePatterns);}catch (ParseException e){return null;}}@InitBinderpublic void initBinder(WebDataBinder binder){// Date 类型转换binder.registerCustomEditor(Date.class, new PropertyEditorSupport(){@Overridepublic void setAsText(String text){setValue(parseDate(text));}});}
}
控制器类BookController.java
package cn.shq.controller;import cn.shq.model.*;
import cn.shq.service.BookService;
import cn.shq.service.PublishService;
import cn.shq.util.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Controller
public class BookController extends BaseController {@AutowiredBookService bookService;@AutowiredPublishService publishService;// 应用的上下文路径,也可以称为项目路径@Value("${server.servlet.context-path}")String projName; // 将项目路径 注入到 projName中。/*** 查询全部* */@GetMapping("/books")public String books(Model model){List bs = bookService.selectAll();System.out.println("bs:"+bs);model.addAttribute("bs",bs);return "index";}/*** 文件上传* */@PostMapping("/doUpload")@ResponseBodypublic Map doUpload(MultipartFile photo) throws IOException {Map result = new HashMap<>();//判断是否为空if(null ==photo){result.put("type","error");result.put("msg","请选择上传的图片");return result;}//判断大小long size = photo.getSize();if(size > 2000000){result.put("type","error");result.put("msg","上传的图片超过限定大小,请上传2M以内的图片!");return result;}//拿到图片的后缀int index = photo.getOriginalFilename().lastIndexOf(".");String suffix = photo.getOriginalFilename().substring(index);//判断后缀是否是图片if(!".jpg,.jpeg,.png,.gif".toUpperCase().contains(suffix.toUpperCase())){result.put("type","error");result.put("msg","必须上传指定格式的图片.jpg,.jpeg,.png,.gif");return result;}//修改文件的名字String newFileName = System.currentTimeMillis()+""+suffix;//建立文件 ↓ 因为上面继承了工具类,则可以直接使用this表示。File file = new File(this.REAL_PATH,newFileName);//写入磁盘photo.transferTo(file);//把文件写入到指定的路径中;//返回给前端数据result.put("type","success");result.put("msg","上传成功!");result.put("fileName",newFileName);result.put("imgName",projName+File.separator+this.VISIT_PATH+newFileName);result.put("filePath",this.VISIT_PATH);return result;}/*** 添加* 1、点击添加按钮,先执行查询所有的出版社,然后跳往添加的页面。* 2、执行添加操作。* */@GetMapping("/toAdd")public String toAdd(Model model){List pubs = publishService.selectAll();model.addAttribute("pubs",pubs);return "add";}@PostMapping("/doAdd")public String doAdd(Book book){bookService.insert(book);return "redirect:/books";}//删除@GetMapping("/doDel/{bookId}")public String doDel(@PathVariable Integer bookId){bookService.del(bookId);return "redirect:/books";}/*** 修改:* 1、点击修改按钮,先根据ID查询到对应书籍的信息,和出版社信息,跳往修改页面。* 2、执行修改操作。* */@GetMapping("/toUpdate/{bookId}")public String toUpdate(@PathVariable Integer bookId,Model model){Book book = bookService.findByID(bookId);List pubs = publishService.selectAll();model.addAttribute("book",book);model.addAttribute("pubs",pubs);return "update";}@PutMapping("/doUpdate")public String doUpdate(Book book){bookService.update(book);return "redirect:/books";}
}
6)视图
index.html
首页
添加
图书编号 图书名称 出版社 出版日期 宣传页 操作 图书名称 出版社 出版日期 ![]()
删除修改
add.html
添加图书
update.html
修改界面
四、测试效果图
启动项目

浏览器访问
地址:http://localhost:8088/shq/books
效果:

添加功能


修改


删除

附件:pom文件
4.0.0 org.springframework.boot spring-boot-starter-parent 2.7.12 cn.shq springBoot_CRUD 0.0.1-SNAPSHOT springBoot_CRUD springBoot_CRUD 1.8 org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-web org.mybatis.spring.boot mybatis-spring-boot-starter 2.2.0 org.springframework.boot spring-boot-devtools runtime true mysql mysql-connector-java 8.0.25 org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.boot spring-boot-configuration-processor true org.webjars jquery 3.3.1 org.webjars layui 2.5.6 org.webjars bootstrap 4.5.2 org.webjars bootstrap-select 1.13.17 org.webjars bootstrap-datetimepicker 2.4.4 org.webjars bootstrap-table 1.16.0 org.webjars momentjs 2.24.0 org.apache.commons commons-lang3 3.9 tk.mybatis mapper-spring-boot-starter 2.1.5 com.alibaba druid 1.1.10 org.springframework.boot spring-boot-starter-jdbc src/main/java **/*.yml **/*.properties **/*.xml false src/main/resources **/*.css **/*.js **/*.html **/*.png **/*.jpg **/*.properties **/*.yml **/*.xml **/*.conf false org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok