前情提要:本例子的前端用的是vue、element-ui
1.导入依赖
<!--easyExcel开始-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
</dependency>
<!--easyExcel结束-->
<!-- mybatis-plus插件开始-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
<!-- mybatis-plus插件结束-->
2.将实体类与表进行规范
与excel表格的列对应起
实体类,ExcelProperty意思就是将实体类的变量与excel表格的列对应起来,容易理解。
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_dept")//表的名称
public class Dept implements Serializable {
@TableId(value = "deptNo",type = IdType.AUTO )
@ExcelProperty("编号")
private Integer deptNo;
@ExcelProperty("部门名称")
@ColumnWidth(10)
private String deptName;
@ExcelProperty("部门位置")
@ColumnWidth(10)
private String loc;
@ExcelProperty("图片")
@ColumnWidth(20)
@TableField("picPath")
private String picPath;
@ExcelProperty("图片名称")
@ColumnWidth(10)
private String picName;
}
3.编写接口和mapper.xml
dao层/mapper层
public interface DeptMapper {
/**
* 根据参数查询列表
* @param dept
* @return
*/
List<Dept> queryByParam(Dept dept);
/**
* 部门添加
* @param dept
* @return
*/
int add(Dept dept);
}
service和serviceimpl层
public interface DeptService {
/**
* 根据参数查询列表
* @param dept
* @return
*/
List<Dept> queryByParam(Dept dept);
/**
* 部门添加
* @param dept
* @return
*/
int add(Dept dept);
}
mapper.xml写sql语句的
<sql id="select">
select dept_no deptNo,dname deptName,loc,picpath picPath,picname picName from tb_dept
</sql>
<!-- 查询所有-->
<select id="queryByParam" resultType="com.aaa.entity.Dept">
<include refid="select"></include>
<where>
<if test="deptName!=null and deptName!=''">
dname like concat('%',#{deptName},'%')
</if>
<if test="loc!=null and loc!=''">
loc=#{loc}
</if>
</where>
</select>
<!-- 添加-->
<insert id="add">
insert into tb_dept(dname, loc,picpath,picname)
values (#{deptName}, #{loc},#{picPath},#{picName})
</insert>
4.监听器
DeptReadListener是一个关键的地方,这里其实就是导入的对象监听器
@Component//不在三层之内的,将该类交给Spring容器管理,使其成为组件
@Scope("prototype")// 设置该类的实例作用域为原型,每次获取实例都是一个新的对象
public class DeptReadListener extends AnalysisEventListener<Dept> {
// 依赖注入,将DeptService实例注入到该类中
@Resource
private DeptService deptService;
/**
* 构造方法,接收一个DeptService实例作为参数,并将其赋值给deptService成员变量
* @param deptService
*/
public DeptReadListener(DeptService deptService) {
this.deptService = deptService;
}
/**
* 重写invoke方法,在分析事件触发时调用该方法
* @param dept
* @param analysisContext
*/
@Override
public void invoke(Dept dept, AnalysisContext analysisContext) {
// 打印读取到的dept对象信息
System.out.println("读取到:"+dept);
// 调用deptService的add方法,将读取到的dept对象添加到数据库或其他存储中
deptService.add(dept);
}
/**
*重写doAfterAllAnalysed方法,在所有分析任务完成后调用该方法
* @param analysisContext
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// 打印读取完毕的信息
System.out.println("读取完毕!!!");
}
}
这段代码定义了一个名为DeptReadListener的类,它继承自AnalysisEventListener<Dept>。该类被交给Spring容器管理,并设置为原型作用域,每次获取实例都是一个新的对象。在构造方法中,将DeptService实例注入到该类中。继承AnalysisEventListener类的2个方法,invoke方法在分析事件触发时调用,用于处理读取到的dept对象,并将其添加到数据库或其他存储中。doAfterAllAnalysed方法在所有分析任务完成后调用,打印读取完毕的信息。
5.接着就是controller层
/**
* 查询所有
* @param dept
* @return
*/
@GetMapping("/queryByParam")
public Result queryByParam(Dept dept){
return success(deptService.queryByParam(dept));
}
/**
* 添加数据
* @param dept
* @return
*/
@PostMapping("/add")
public Result add(@RequestBody Dept dept){
return success(deptService.add(dept));
}
/**
* 导入的excel文件对象是MultipartFile类型的
* @param file
* @throws IOException
*/
@PostMapping("/import")
public void ExcelImport(MultipartFile file)throws IOException {
InputStream is = file.getInputStream();// 获取上传文件的输入流
DeptReadListener deptReadListener = new DeptReadListener(deptService);// 创建DeptReadListener对象,用于监听读取操作
EasyExcel.read(is,Dept.class,deptReadListener)//使用EasyExcel库开始读取Excel文件
.sheet(0)// 指定要读取的工作表索引为0,即第一个工作表
.headRowNumber(1)// 设置表头行号为1,表示数据从第二行开始读取
.doRead();// 执行读取操作
}
/**
* 导出
* @param response
* @throws IOException
*/
@GetMapping("/export")
public void ExcelExport(HttpServletResponse response)throws IOException {
// 查询部门数据
List<Dept> depts = deptService.queryByParam(null);
// 设置响应头信息,指定文件类型为Excel(.xlsx)和字符编码为UTF-8
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");//.xlsx格式
response.setCharacterEncoding("utf-8");
// 对文件名进行URL编码,将空格替换为%20,避免中文乱码问题
String fileName = URLEncoder.encode("部门数据", "UTF-8").replaceAll("\+", "%20");
// 设置响应头信息,指定下载文件的文件名和扩展名为.xlsx
response.setHeader("Content-disposition","attachment;filename="+fileName+".xlsx");
// 使用EasyExcel库将数据写入响应的输出流中,生成Excel文件
EasyExcel.write(response.getOutputStream())
.head(Dept.class)// 设置表头为Dept类的属性
.excelType(ExcelTypeEnum.XLSX)// 设置文件类型为Excel(.xlsx)
.sheet("部门数据")// 设置工作表名称为“部门数据”
.doWrite(depts);// 将查询到的部门数据写入Excel文件中
}
ExcelImport
这个方法接受一个MultipartFile类型的参数file,表示上传的Excel文件。它抛出了IOException异常,以便在发生输入输出错误时进行处理。
方法内部首先通过调用file.getInputStream()方法获取上传文件的输入流,并将其赋值给is变量。
接下来,创建了一个名为deptReadListener的DeptReadListener对象,该对象需要传入一个deptService参数。这个对象用于监听Excel文件的读取操作,并在读取完成后进行相应的处理。
然后,使用EasyExcel库的read方法开始读取Excel文件。read方法接受三个参数:输入流is、目标类Dept.class和监听器deptReadListener。它将Excel文件中的数据映射到Dept类的对象上,并通过调用deptReadListener对象的回调方法来处理读取结果。
在read方法之后,调用sheet(0)指定要读取的工作表索引为0,即第一个工作表。
接着,调用headRowNumber(1)设置表头行号为1,表示数据从第二行开始读取。
最后,调用doRead()方法开始执行读取操作。
总结起来,这段代码的作用是将上传的Excel文件的第一张工作表的数据导入到数据库中的Dept类对应的表中。
ExcelExport
这个方法使用了@GetMapping("/export")注解,表示它是一个处理HTTP GET请求的方法,请求路径为"/export"。它接受一个HttpServletResponse对象作为参数,用于设置响应头和响应内容。
在方法内部,首先通过调用deptService.queryByParam(null)方法查询部门数据,并将结果存储在名为depts的列表中。
接下来,通过调用response.setContentType()方法设置响应头信息,指定文件类型为Excel(.xlsx)和字符编码为UTF-8。然后,通过调用response.setCharacterEncoding()方法设置响应的字符编码为UTF-8。
为了确保中文文件名不出现乱码,使用URLEncoder.encode()方法对文件名进行URL编码,将空格替换为%20。然后,通过调用response.setHeader()方法设置响应头信息,指定下载文件的文件名为编码后的文件名,并指定文件扩展名为.xlsx。
最后,使用EasyExcel.write()方法将数据写入响应的输出流中,生成Excel文件。通过调用.head(Dept.class)方法设置表头为Dept类的属性,通过调用.excelType(ExcelTypeEnum.XLSX)方法设置文件类型为Excel(.xlsx),通过调用.sheet(`` "部门数据") 设置工作表名称为“部门数据”,通过调用.doWrite(depts);将查询到的部门数据写入Excel文件中。
6.前端代码编写
写在template里的div里边
下边的写在方法里边
7.测试
自行测试
结束语:参考文章SpringBoot集成EasyExcel实现excel的导入导出_springboot导入excel_Chenbaozeng的博客-CSDN博客
本文如有错误请指正!!!