项目中用的需要将原有的Excel表格中的数据上传到数据库中,参考了一些文章博客,目前主要采用的就是poi和阿里的easyexcel,这里对它们的好坏不做评价,根据个人习惯,这里我选择的是阿里的easyExcel。
官方文档给的内容已经非常详细了,这里我将整个开发的流程都展现一下,提供给大家参考。
点击跳转至官方文档
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.2.6version>
dependency>
主要就是为字段添加一个@ExcelProperty(index = 0, value = "xx")
注解 value 对应的是excel表格中的列名,这里index可用可不用,使用index是强制去匹配index所对应的列(和数组一样 index从0开始)不建议 index 和 name 同时用。
常用的注解,解释
@ExcelProperty
@ColumnWith 列宽
@ContentFontStyle 文本字体样式
@ContentLoopMerge 文本合并
@ContentRowHeight 文本行高度
@ContentStyle 文本样式
@HeadFontStyle 标题字体样式
@HeadRowHeight 标题高度
@HeadStyle 标题样式
@ExcelIgnore 忽略项
@ExcelIgnoreUnannotated 忽略未注解
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@TableName("tb_role")
@ApiModel(value = "住户信息", description = "")
public class ResidentDto implements Serializable {
@ExcelProperty(index = 0, value = "住户编号")
@TableId(value = "res_id", type = IdType.AUTO)
private Integer resId;
@ExcelProperty(index = 1, value = "住户名")
private String resName;
@ExcelProperty(index = 2, value = "性别")
private Integer resSex;
@ExcelProperty(index = 3, value = "手机号")
private String resPhone;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@ExcelProperty(index = 4, value = "入住小区时间")
private String resIntotime;
@ExcelProperty(index = 5, value = "状态")
@ApiModelProperty("0表示正常,1表示低风险,2表示高风险")
private Integer resStatus;
@ExcelProperty(index = 6, value = "备注")
private String resRemark;
}
public class ExcelListener extends AnalysisEventListener<ResidentDto> {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelListener.class);
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 5;
/**
* 实现业务逻辑的service
*/
private final ResidentService residentService;
/**
* 保存数据的集合
*/
List<ResidentDto> list = new ArrayList<ResidentDto>();
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param residentService
*/
public ExcelListener(ResidentService residentService) {
this.residentService = residentService;
}
@Override
public void invoke(ResidentDto data, AnalysisContext context) {
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
//这里才是数据继续数据库存储的重点
int batchResident = residentService.insertBatchResident(list);
if (batchResident < 1) {
LOGGER.info("数据保存异常,未知错误");
}
}
}
@Api(value = "文件上传", tags = "文件上传相关接口")
@RestController
@RequestMapping("/api/excel")
public class ExcelController {
public static Logger logger = LoggerFactory.getLogger(ExcelController.class);
@Resource
private ResidentService residentService;
@PostMapping("/uploadRes")
public Result upload(@RequestParam MultipartFile file) {
InputStream fileInputStream = null;
try {
fileInputStream = file.getInputStream();
} catch (IOException e) {
e.printStackTrace();
return Result.fail("上传文件异常");
}
try {
//调用EasyExcel.read然后去调用你写的监听器,随后去执行你写的Service
EasyExcel.read(fileInputStream, ResidentDto.class, new ExcelListener(residentService)).sheet().doRead();
return Result.ok("上传文件成功");
} catch (Exception e) {
e.printStackTrace();
}
return Result.fail("未知错误");
}
}
Service
/**
* 批量添加数据
*/
int insertBatchResident(List<ResidentDto> residentDtos);
ServiceImpl
/**
* 批量添加数据
*
* @param residentDtos
* @return
*/
@Override
public int insertBatchResident(List<ResidentDto> residentDtos) {
int batchResident = residentMapper.insertBatchResident(residentDtos);
return batchResident;
}
Mapper
int insertBatchResident(@Param("residentDtos") List<ResidentDto> residentDtos);
Mapper.Xml
<insert id="insertBatchResident">
insert into tb_resident(res_id, res_name, res_sex, res_phone, res_intotime,res_status, res_remark, res_photo)
values
<foreach collection="residentDtos" item="resident" index="index" separator=",">
(#{resident.resId}, #{resident.resName}, #{resident.resSex}, #{resident.resPhone}, #{resident.resIntotime},
#{resident.resStatus},#{resident.resRemark}, null)
foreach>
insert>
这里项目我采用的是LayUI的框架,直接引用了它本身的文件上传组件
<div class="layui-btn-container">
<button type="submit" class="layui-btn layui-btn-sm" lay-submit lay-filter="data-all"><i
class="layui-icon layui-icon-home">i>全部住户
button>
<button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn" lay-event="add"> 添加button>
<button class="layui-btn layui-btn-sm layui-btn-danger data-delete-btn" lay-event="delete"> 删除button>
<button class="layui-btn layui-btn-sm " id="upload">上传文件
button>
div>
//组件引用
layui.use(['form', 'table', 'miniPage', 'element', 'laydate', 'upload'], function () {
var $ = layui.jquery,
form = layui.form,
table = layui.table,
laydate = layui.laydate,
miniPage = layui.miniPage,
upload = layui.upload;
//文件上传操作
upload.render({
elem: '#upload' //绑定元素
, url: '/api/excel/uploadRes' //上传接口
, accept: 'file'
, size: 10240 // 最大上传限制,最大为10M
, done: function (res) {
//上传完毕回调
if (res.code == 200) {
layer.msg(res.msg, {icon: 6, time: 1000});
//页面刷新
parent.window.location.reload();
} else {
layer.msg(res.msg, {icon: 5, time: 1000});
}
}, error: function () {
//请求异常回调
}
});
);
目前正在学习中的小白,代码可能不够严谨,感谢大佬指正!如果可以为你带来帮助,荣幸之至!