一、导入依赖
这里还是用了Apache的POI插件,现在一般的springboot解析excel基本都用它 。
<!-- 文件上传,解析文件需要的依赖-->
<!--poi对excel2007以上版本的支持-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
<!-- poi对excel2003以下版本的支持 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
二、前端实现
<button type="button" class="layui-btn layui-btn-normal layui-btn-radius" id="bookFileUpload">
<i class="layui-icon"></i>文件导入
</button>
layui.use('upload', function () {
var upload = layui.upload;
var layer = layui.layer;
// layer.msg('上传中', {icon: 16, time: 0,shade: 0.3});
//执行实例
var uploadInst = upload.render({
elem: '#bookFileUpload', //绑定元素
url: '/library/book/batchAddBooks/', //上传接口
exts: 'xlsx|xls', //限制文件类型
done: function (res) {
//上传完毕回调
if (res.code == '1') {
successMsg("导入成功");
} else {
errorMsg("导入失败" + res);
}
},
error: function (res) {
//请求异常回调
errorMsg("系统异常" + res);
}
});
});
说明一下,这里还是用了layui的框架去实现的,layui是我用过的前端框架里边坑相对较少的一个不错的简单并且很容易入门的框架。
三、后台逻辑
1.首先写一个用于导入数据的model实体类,对应数据库的一张表。
@Data
public class Book {
//主键id
private int bid;
//书名
private String bookname;
//作者
private String author;
//书的类型 武侠、言情等
private String booktype;
//出版社
private String publisher;
//出版时间
private String publicationdate;
//发行价格
private int price;
//发行状态
private String bookstate;
//备注
private String comment;
}
这里使用了lombok的插件工具,所以可以省去写setget方法,只需要@Data即可。
lombok的依赖,可用可不用,看你自己:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
2.接着写一下前端上传过来excel,后台的解析处理逻辑。
下面是重点:
package com.example.library.utils.fileUtiles;
import com.example.library.model.Book;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class ExcelUtils {
private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
//Map<String,Object> map = new HashMap<String, Object>();
private static final String XLS = "xls";
private static final String XLSX = "xlsx";
private final static String DATE_FORMAT = "yyyy-MM-dd";
public static Workbook getWorkbook(InputStream inputStream, String fileType) throws Exception {
Workbook workbook = null;
//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
if (fileType.equalsIgnoreCase(XLS)) {
//2003
workbook = new HSSFWorkbook(inputStream);
} else if (fileType.equalsIgnoreCase(XLSX)) {
//2007及以上
workbook = new XSSFWorkbook(inputStream);
}else {
throw new Exception("请上传excel文件!");
}
return workbook;
}
public static List<Book> readExcel(String fileName) {
Workbook workbook = null;
FileInputStream inputStream = null;
try {
// 获取Excel后缀名
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
// 获取Excel文件
File excelFile = new File(fileName);
if (!excelFile.exists()) {
logger.warn("指定的Excel文件不存在!");
}
// 获取Excel工作簿
inputStream = new FileInputStream(excelFile);
workbook = getWorkbook(inputStream, fileType);
// 读取excel中的数据
List<Book> resultDataList = parseExcel(workbook);
return resultDataList;
} catch (Exception e) {
logger.warn("解析Excel失败,文件名:" + fileName + " 错误信息:" + e.getMessage());
return null;
} finally {
try {
if (null != workbook) {
workbook.close();
}
if (null != inputStream) {
inputStream.close();
}
} catch (Exception e) {
logger.warn("关闭数据流出错!错误信息:" + e.getMessage());
return null;
}
}
}
public static List<Book> readExcel(MultipartFile file) {
Workbook workbook = null;
try {
//判断文件是否存在
if(null == file){
logger.warn("解析Excel失败,文件不存在!");
return null;
}
// 获取Excel后缀名
String fileName = file.getOriginalFilename();
if (fileName == null || fileName.isEmpty() || fileName.lastIndexOf(".") < 0) {
logger.warn("解析Excel失败,因为获取到的Excel文件名非法!");
return null;
}
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
// 获取Excel工作簿
workbook = getWorkbook(file.getInputStream(), fileType);
// 读取excel中的数据
List<Book> resultDataList = parseExcel(workbook);
return resultDataList;
} catch (Exception e) {
logger.warn("解析Excel失败,文件名:" + file.getOriginalFilename() + " 错误信息:" + e.getMessage());
return null;
} finally {
try {
if (null != workbook) {
workbook.close();
}
} catch (Exception e) {
logger.warn("关闭数据流出错!错误信息:" + e.getMessage());
return null;
}
}
}
private static List<Book> parseExcel(Workbook workbook) {
List<Book> resultDataList = new ArrayList<>();
//获取所有的工作表的的数量
int numOfSheet = workbook.getNumberOfSheets();
System.out.println(numOfSheet+"--->numOfSheet");
// 解析sheet,此处会读取所有脚页的行数据,若只想读取指定页,不要for循环,直接给sheetNum赋值,
// 脚页从0开始(通常情况Excel都只有一页,所以此处未进行进一步处理)
for (int sheetNum = 0; sheetNum < numOfSheet; sheetNum++) {
//获取一个sheet也就是一个工作本。
Sheet sheet = workbook.getSheetAt(sheetNum);
// 校验sheet是否合法
if (sheet == null) {
continue;
}
//获取一个sheet有多少Row
//int lastRowNum = sheet.getLastRowNum();
//if(lastRowNum == 0) {
// continue;
//}
// 获取第一行数据
int firstRowNum = sheet.getFirstRowNum();
Row firstRow = sheet.getRow(firstRowNum);
if (null == firstRow) {
logger.warn("解析Excel失败,在第一行没有读取到任何数据!");
}
// 解析每一行的数据,构造数据对象
int rowStart = firstRowNum + 1; //获取第几行
//获得当前行的列数
int rowEnd = sheet.getPhysicalNumberOfRows();
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row row = sheet.getRow(rowNum);
if (null == row) {
continue;
}
Book resultData = convertRowToData(row);
if (null == resultData) {
logger.warn("第 " + row.getRowNum() + "行数据不合法,已忽略!");
continue;
}
resultDataList.add(resultData);
}
}
return resultDataList;
}
private static String convertCellValueToString(Cell cell) {
String returnValue = null;
if(cell==null){
return returnValue;
}
//如果当前单元格内容为日期类型,需要特殊处理
String dataFormatString = cell.getCellStyle().getDataFormatString();
if(dataFormatString.equals("m/d/yy")){
returnValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue());
return returnValue;
}
switch (cell.getCellType()) {
case NUMERIC: //数字
Double doubleValue = cell.getNumericCellValue();
// 格式化科学计数法,取一位整数
DecimalFormat df = new DecimalFormat("0");
returnValue = df.format(doubleValue);
break;
case STRING: //字符串
returnValue = cell.getStringCellValue();
break;
case BOOLEAN: //布尔
Boolean booleanValue = cell.getBooleanCellValue();
returnValue = booleanValue.toString();
break;
case BLANK: // 空值
break;
case FORMULA: // 公式
returnValue = cell.getCellFormula();
break;
case ERROR: // 故障
break;
default:
break;
}
return returnValue;
}
private static Book convertRowToData(Row row) {
Book resultData = new Book();
Cell cell;
int cellNum = 0;
//获取书籍名称
cell = row.getCell(cellNum++);
String bookName = convertCellValueToString(cell);
if (null == bookName || "".equals(bookName)) {
// 书籍名称为空
resultData.setBookname(bookName);
} else {
resultData.setBookname(bookName);
}
// 获取书籍作者
cell = row.getCell(cellNum++);
String author = convertCellValueToString(cell);
if (null == author || "".equals(author)) {
// 书籍作者为空
resultData.setAuthor(author);
} else {
resultData.setAuthor(author);
}
// 获取书籍类型
cell = row.getCell(cellNum++);
String type = convertCellValueToString(cell);
if (null == type || "".equals(type)) {
// 书籍类型为空
resultData.setBooktype(type);
} else {
resultData.setBooktype(type);
}
//获取出版单位
cell = row.getCell(cellNum++);
String publisher = convertCellValueToString(cell);
if (null == publisher || "".equals(publisher)) {
// 出版单位为空
resultData.setPublisher(publisher);
} else {
resultData.setPublisher(publisher);
}
//获取出版时间
cell = row.getCell(cellNum++);
String publicationdate = convertCellValueToString(cell);
if (null == publicationdate || "".equals(publicationdate)) {
// 出版时间为空
resultData.setPublicationdate(publicationdate);
} else {
resultData.setPublicationdate(publicationdate);
}
//获取价格
cell = row.getCell(cellNum++);
String price = convertCellValueToString(cell);
if (null == price || "".equals(price)) {
// 价格为空
resultData.setPrice(Integer.parseInt(price));
} else {
resultData.setPrice(Integer.parseInt(price));
}
//获取借阅状态
cell = row.getCell(cellNum++);
String bookstate = convertCellValueToString(cell);
if (null == bookstate || "".equals(bookstate)) {
// 借阅状态为空
resultData.setBookstate(bookstate);
} else {
resultData.setBookstate(bookstate);
}
//获取备注
cell = row.getCell(cellNum++);
String comment = convertCellValueToString(cell);
if (null == comment || "".equals(comment)) {
// 备注为空
resultData.setComment(comment);
} else {
resultData.setComment(comment);
}
return resultData;
}
public void writeExcel(OutputStream outputStream){
Workbook wb = new SXSSFWorkbook(100);
//创建一个工作本
Sheet sheet = wb.createSheet("sheet");
//通过一个sheet创建一个Row
Row row = sheet.createRow(0);
for(int i =0;i<10;i++){
//通过row创建一个cell
Cell cell = row.createCell(i);
cell.setCellValue("这是第"+i+"个cell");
}
try {
wb.write(outputStream);
wb.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
3.最后写一下解析完成,存入数据库。
<insert id="insertUsers">
insert into user(username,sex,tel,institute,profession,classname,stuid,password,type)
values
<foreach collection="users" index="" item="item" separator=",">
(
#{item.username,jdbcType=VARCHAR}, #{item.sex,jdbcType=VARCHAR}, #{item.tel,jdbcType=VARCHAR},
#{item.institute,jdbcType=VARCHAR}, #{item.profession,jdbcType=VARCHAR},
#{item.classname,jdbcType=VARCHAR}, #{item.stuid,jdbcType=VARCHAR},
#{item.password,jdbcType=VARCHAR}, #{item.type,jdbcType=VARCHAR}
)
</foreach>
</insert>
三、页面效果
点击导入用户,选择excel文件即可。
四、可能会遇到的问题
因为springboot现在使用的poi的支持已经达到5.0以上版本了,但是他整合起来可能会出现一些小异常,虽然不影响我们正常使用,但是控制台会一直出现,也很烦,所以这里 给一个解决办法。
@Configuration
public class MyStandardJarScanner {
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
}
};
}
}
比较简单易学,网上也有很多教程,有需要的可以一起来交流一下,哈哈!!!
以上就是java进阶Springboot上传excel存入数据库步骤的详细内容,更多关于Springboot上传excel的资料请关注编程网其它相关文章!