应用场景:在后台管理项目中经常会需要批量导入的功能,这个时候我们就可以用Excel表格完成数据的下载。
一、新建SpringBoot项目,并且配置数据库;
1、pom.xml 文件中导入依赖;
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>excel</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--SpringBoot依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
<!--SpringBoot集成WEB项目依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<!--表格上传和下载的解析jar包依赖-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!--连接Mysql采用的是mybatis-plus框架-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!--druid连接池依赖,mybatis框架连接数据库必备-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<!--mybatis-plus自动生成依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
<!--mysql核心依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
由于演示的是批量导入数据库,数据库选择的是关系型数据库Mysql,连接框架选用的比较火的mybatis-plus;
2、项目的resources文件建application.yaml配置文件:
spring:
datasource:
url: jdbc:mysql://localhost:3306/wolfcar?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
由于只是演示基本的功能,所以只配置连接池连接的基本四要素就可以,选用的Mysql是5版本的,高版本的driver-class-name:com.mysql.jdbc.cj.Driver。另外说下SpringBoot项目的配置文件加载顺序为:
bootstrap.yml(bootstrap.properties)用来在程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
bootstrap.yml 先于 application.yml 加载;
url:jdbc:mysql://安装mysql的IP地址:端口/要连接的数据库名称?后面为固定的字符串格式和时区设置;
3、Mysql内数据库表格准备;
在我们指定的数据库内创建一个deparment的表格作为演示表格:
sql语句如下:
CREATE TABLE `department` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sn` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
添加表格信息,sql语句如下:
INSERT INTO `wolfcar`.`department`(`name`, `sn`) VALUES ('安保部', 'ab');
INSERT INTO `wolfcar`.`department`(`name`, `sn`) VALUES ('行政部', 'xz');
INSERT INTO `wolfcar`.`department`(`name`, `sn`) VALUES ('保洁部', 'bj');
4、创建Deparment的实体类,利用@TableName的注解将实体类和数据库中的deparment表联系起来,实现代码如下:
//lombok注解,get,set方法、全参构造器,无参构造器,toString方法;
@Getter@Setter@AllArgsConstructor@NoArgsConstructor@ToString
//mybatis-plus中的@TableName注解,括号内填写数据库内要连接的表名即可映射;
@TableName("department")
public class Department {
//@TableId 对应表格的主键Id,类型跟我们的表格对应,选择自增;
@TableId(value = "id",type = IdType.AUTO)
private Long id;
//@TableField 实体类和数据库表的字段名字映射关系,非主键的字段都可以用这个注解;
@TableField("name")
private String dname;
@TableField("sn")
private String sn;
}
5、创建DeparmentMapper接口继承 BaseMapper<Department>;
mybatis-plus给我提供了封装好的操作数据库的接口~BaseMapper,我们只需要在项目中创建自己的Mapper接口之后继承BaseMapper,就可以操作Mysql数据库;
public interface DepartmentMapper extends BaseMapper<Department> {
}
进行到这里我们为了演示表格下载和上传的数据库方面的准备工作就进行的差不多了;
6、然后别忘记了SpringBoot项目中必不可少的启动类,也就是我们的主方法;
@SpringBootApplication
@MapperScan("你的mapper所在的包名")
//主方法内添加Mapper的扫描路径
public class ExcelRun {
public static void main(String[] args) {
SpringApplication.run(ExcelRun.class,args);
}
}
二、文件下载功能实现
1、前端网页(我的前端真的很差,所以只是用最简单的html文件来展示基本功能,所以没有模态框也没有别的炫炫的功能,并且为了方便演示,此项目为前后端一体项目),在resources文件夹内创建static文件夹,然后新建html文件,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下载</title>
</head>
<body>
<a href="/down">下载表格</a>
2、在项目中新建controller包,新建DeparmentController类;
@RestController
public class DepartmentController {
@Autowired
private IDepartmentService departmentService;
@GetMapping("/down")
public void downFile(HttpServletResponse resp) throws IOException {
/* resp.setHeader("Content-Disposition","attachment;filename=department.xls");
固定写法,作用为设定浏览器响应的方式为下载文件,我们只需要在filename=后面写上我们下载文件
的名字和格式就可以;*/
resp.setHeader("Content-Disposition","attachment;filename=department.xls");
/* controller层不进行复杂的业务逻辑处理,这里我们直接调用service中的方法;
当然这个方法也是我们自己写的,我们现在给方法一个名字就行;
我们希望得到的结果是Workbook类,然后写好controller层的逻辑后再去service创建方法和实现方法就可以*/
Workbook workbook = departmentService.getWork();
//这个也没啥好讲的,就是写入的固定操作代码,记住即可;
workbook.write(resp.getOutputStream());
}
}
controller层需要调用service层方法,所以下一步。。。。
3、service层先创建一个接口;
public interface IDepartmentService {
Workbook getWork();
}
4、然后创建一个接口的实现类;
@Service
public class DepartmentServiceImpl implements IDepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
public Workbook getWork() {
//创建一个excel表格
HSSFWorkbook sheets = new HSSFWorkbook();
//创建一个sheet表格(一个EXCEL文件内可以有多个sheet)
Sheet sheet = sheets.createSheet("employee");
//编辑表头
//新建行
Row headrow = sheet.createRow(0);
//行内的单元格内容
headrow.createCell(0).setCellValue("id");
headrow.createCell(1).setCellValue("部门名");
headrow.createCell(2).setCellValue("编号");
//操作mybatis-plus操作的QueryWrapper,由于是无条件查询所有,所以创建出来一个对象即可,不用写具体条件语句;
QueryWrapper<Department> queryWrapper = new QueryWrapper<Department>();
//调用方法从数据库中查询到我们想要的值
List<Department> list = departmentMapper.selectList(queryWrapper);
//遍历 list,将内容写入表格内;
for(int i =0 ;i<list.size();i++){
Department department = list.get(i);
Row row = sheet.createRow(i + 1);
row.createCell(0).setCellValue(department.getId());
row.createCell(1).setCellValue(department.getDname());
row.createCell(2).setCellValue(department.getSn());
}
return sheets;
}
截止到这里我们的文件下载功能就已经实现完成了;
三、文件上传和批量修改功能;
1、前端页面(同样寒酸的前端页面,原谅技术小白的我),接着之前的前端页面写;正常业务功能实现都需要给客户提供一个表格模板,客户下载之后按照模板写入数据,模板的下载方法可以参考之前我们的表格下载功能,只是减少了从数据库查询数据增加到表格的操作。当然如果有特殊格式的话,可以除了表头外再写一条模板数据方便客户编辑的时候参照或者格式化数据;当然在这里就不演示模板下载,主要是我有点忘记模态框的前端代码了~~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下载</title>
</head>
<body>
<a href="/down">下载表格</a>
<!-- 文件上传框 -->
<form action="/up" method="post" enctype="multipart/form-data">
<!--form表单中的enctype一定要修改成"multipart/form-data",否则controller层接收不到文件-->
<input type="file" name="file">
<input type="submit">
</form>
</body>
</html>
2、然后写我们的controller层;
@RestController
public class DepartmentController {
@Autowired
private IDepartmentService departmentService;
@GetMapping("/down")
public void downFile(HttpServletResponse resp) throws IOException {
/* resp.setHeader("Content-Disposition","attachment;filename=department.xls");
固定写法,作用为设定浏览器响应的方式为下载文件,我们只需要在filename=后面写上我们下载文件的名字和格式就可以;*/
resp.setHeader("Content-Disposition","attachment;filename=department.xls");
/* controller层不进行复杂的业务逻辑处理,这里我们直接调用service中的方法;
当然这个方法也是我们自己写的,我们现在给方法一个名字就行;
我们希望得到的结果是Workbook类,然后写好controller层的逻辑后再去service创建方法和实现方法就可以*/
Workbook workbook = departmentService.getWork();
//这个也没啥好讲的,就是写入的固定操作代码,记住即可;
workbook.write(resp.getOutputStream());
}
@PostMapping("/up")
public void upFile(MultipartFile file) throws IOException {
//写入数据库数据,正常需要给客户反馈一个执行结果,这里为了方便直接无返回值,大家写项目的时候别忘记美化;
departmentService.upFile(file);
}
}
3、完善我们的service层的代码;
public interface IDepartmentService {
Workbook getWork();
void upFile(MultipartFile file) throws IOException;
}
@Service
public class DepartmentServiceImpl implements IDepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
public Workbook getWork() {
//创建一个excel表格
HSSFWorkbook sheets = new HSSFWorkbook();
//创建一个sheet表格(一个EXCEL文件内可以有多个sheet)
Sheet sheet = sheets.createSheet("employee");
//编辑表头
//新建行
Row headrow = sheet.createRow(0);
//行内的单元格内容
headrow.createCell(0).setCellValue("id");
headrow.createCell(1).setCellValue("部门名");
headrow.createCell(2).setCellValue("编号");
//操作mybatis-plus查询操作的QueryWrapper,由于是无条件查询所有,所以创建出来一个对象即可,不用写具体条件语句;
QueryWrapper<Department> queryWrapper = new QueryWrapper<Department>();
//调用方法从数据库中查询到我们想要的值
List<Department> list = departmentMapper.selectList(queryWrapper);
//遍历 list,将内容写入表格内;
for(int i =0 ;i<list.size();i++){
Department department = list.get(i);
Row row = sheet.createRow(i + 1);
row.createCell(0).setCellValue(department.getId());
row.createCell(1).setCellValue(department.getDname());
row.createCell(2).setCellValue(department.getSn());
}
return sheets;
}
public void upFile(MultipartFile file) throws IOException {
//同样新建一个HSSFWorkbook对象,不同之前下载方法的是我们新建的对象要有内容~也就是我们前端传过来的文件;
//用MultipartFile的getInputStream()方法获得输入流作为HSSFWorkbook的构造参数得到我们想要的实例;
HSSFWorkbook sheets = new HSSFWorkbook(file.getInputStream());
//然后获得excel表的第一个sheet,这就是给客户提供模板的作用,因为如果客户自己创建表格,那么可能不知道把数据存在哪里~
HSSFSheet sheet = sheets.getSheetAt(0);
//获得sheet表的总行数;
int maxRow = sheet.getLastRowNum();
//操作mybatis-plus更新操作的UpdateWrapper,由于我们的添加也是无条件添加,所以不需要写具体条件语句;
UpdateWrapper wrapper = new UpdateWrapper();
//遍历每一行的数据,然后将值设置给Deparment的实例中,利用更新方法存储到数据库中;
for(int i =1;i<=maxRow;i++){
Row row = sheet.getRow(i);
departmentMapper.update(
new Department(
//(long)row.getCell(0).getNumericCellValue(),
// 由于我们数据库是设置的id主键自增,所以不要将id的值设置到实例的对象中,不然会覆盖原来的数据;
//这里留下注释主要是为了告诉大家,当我们用row.getCell(索引)方法获得对应的单元格然后想获得单元格内具体内容的时候:
//字符串内容直接用getStringCellValue(),数字类型用getNumericCellValue(),
// 而且getNumericCellValue()得到的类型是double类型,很多时候和我们的数据库常用的主键类型Long不符,需要强转;
null,
row.getCell(1).getStringCellValue(),
row.getCell(2).getStringCellValue()),wrapper);
截止到这里,SpringBoot项目如何用mybatis-plus连接数据库操作,还有表格下载和表格上传及批量新增工作就已经完成了,如果要批量修改的话只需要在遍历表格数据的时候设置QueryWrapper的条件即可;
文章仅供自己记录使用,如果bug和不对的地方欢迎指出,仅适用于小白新手;