Springboot+poi 를 사용 하여 백만 급 데 이 터 를 업로드 하고 처리 합 니 다 EXCEL
10970 단어 SpringbootpoiEXCEL
엑셀 업로드 에 대해 서 는 비교적 일반적인 방법 을 사용 하 는데 사실은 파일 업로드 와 같다.구체 적 인 소스 코드 는 다음 과 같다.
@PostMapping(value = "", consumes = "multipart/*", headers = "content-type=multipart/form-data")
public Map<String, Object> addBlacklist(
@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request
) {
//
String fileName = multipartFile.getOriginalFilename();
if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
return returnError(0," ");
}
String file = saveFile(multipartFile, request);
int result = 0;
try {
result = blacklistServcice.addBlackLists(file);
} catch (Exception e) {
e.printStackTrace();
}
return returnData(result);
}
private String saveFile(MultipartFile multipartFile, HttpServletRequest request) {
String path;
String fileName = multipartFile.getOriginalFilename();
//
String realPath = request.getSession().getServletContext().getRealPath("/");
String trueFileName = fileName;
// Excel
path = realPath + trueFileName;
File file = new File(path);
if (file.exists() && file.isFile()) {
file.delete();
}
try {
multipartFile.transferTo(new File(path));
} catch (IOException e) {
e.printStackTrace();
}
return path;
}
위의 소스 코드 에서 우 리 는 saveFile 방법 을 볼 수 있 습 니 다.이 방법 은 파일 을 서버 로 컬 에 저장 하 는 것 입 니 다.이렇게 하면 후속 파일 내용 의 읽 기 에 편리 하고 모든 내용 을 한 번 에 읽 지 않 아 도 대량의 메모 리 를 소모 할 수 있 습 니 다.물론 여기 더 좋 은 방법 이 있 으 면 댓 글로 알려 주세요.2 Excel 처리 도구 원본 코드
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;
/**
* XSSF and SAX (Event API)
*/
public abstract class XxlsAbstract extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
private int sheetIndex = -1;
private List<String> rowlist = new ArrayList<>();
public List<Map<String, Object>> dataMap = new LinkedList<>(); //
public int willSaveAmount; //
public int totalSavedAmount; //
private int curRow = 0; //
private int curCol = 0; //
private int preCol = 0; //
private int titleRow = 0; // , 0
public int rowsize = 0; //
//excel , sheet , , sheet , String
public abstract void optRows(int sheetIndex, int curRow, List<String> rowlist) throws SQLException;
// sheet, sheetId sheet , 1 ,1-3
/**
* @param filename
* @param sheetId sheetId sheet , 1 ,1-3
* @throws Exception
*/
public void processOneSheet(String filename, int sheetId) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
// rId2 found by processing the Workbook
// rId# rSheet# sheet
InputStream sheet2 = r.getSheet("rId" + sheetId);
sheetIndex++;
InputSource sheetSource = new InputSource(sheet2);
parser.parse(sheetSource);
sheet2.close();
}
public XMLReader fetchSheetParser(SharedStringsTable sst)
throws SAXException {
XMLReader parser = XMLReaderFactory.createXMLReader();
this.sst = sst;
parser.setContentHandler(this);
return parser;
}
public void endElement(String uri, String localName, String name) {
// SST
try {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx))
.toString();
} catch (Exception e) {
}
// v => , v SST
// rowlist ,
if (name.equals("v")) {
String value = lastContents.trim();
value = value.equals("") ? " " : value;
int cols = curCol - preCol;
if (cols > 1) {
for (int i = 0; i < cols - 1; i++) {
rowlist.add(preCol, "");
}
}
preCol = curCol;
rowlist.add(curCol - 1, value);
} else {
// row , , optRows()
if (name.equals("row")) {
int tmpCols = rowlist.size();
if (curRow > this.titleRow && tmpCols < this.rowsize) {
for (int i = 0; i < this.rowsize - tmpCols; i++) {
rowlist.add(rowlist.size(), "");
}
}
try {
optRows(sheetIndex, curRow, rowlist);
} catch (SQLException e) {
e.printStackTrace();
}
if (curRow == this.titleRow) {
this.rowsize = rowlist.size();
}
rowlist.clear();
curRow++;
curCol = 0;
preCol = 0;
}
}
}
}
3 분석 성공 후 데이터 처리먼저 우 리 는 소스 코드 를 보 여 준 후에 구체 적 으로 설명 할 것 이다.
public int addBlackLists(String file) throws ExecutionException, InterruptedException {
ArrayList<Future<Integer>> resultList = new ArrayList<>();
XxlsAbstract xxlsAbstract = new XxlsAbstract() {
//
@Override
public void optRows(int sheetIndex, int curRow, List<String> rowlist) {
/**
* 8000, 8000,
*
*/
if (this.willSaveAmount == 5000) {
//
List<Map<String, Object>> list = new LinkedList<>(this.dataMap);
Callable<Integer> callable = () -> {
int count = blacklistMasterDao.addBlackLists(list);
blacklistRecordMasterDao.addBlackListRecords(list);
return count;
};
this.willSaveAmount = 0;
this.dataMap = new LinkedList<>();
Future<Integer> future = executor.submit(callable);
resultList.add(future);
}
//
Map<String, Object> map = new HashMap<>();
map.put("uid", rowlist.get(0));
map.put("createTime", rowlist.get(1));
map.put("regGame", rowlist.get(2));
map.put("banGame", rowlist.get(2));
this.dataMap.add(map);
this.willSaveAmount++;
this.totalSavedAmount++;
}
};
try {
xxlsAbstract.processOneSheet(file, 1);
} catch (Exception e) {
e.printStackTrace();
}
//
if(xxlsAbstract.willSaveAmount != 0){
List<Map<String, Object>> list = new LinkedList<>(xxlsAbstract.dataMap);
Callable<Integer> callable = () -> {
int count = blacklistMasterDao.addBlackLists(list);
blacklistRecordMasterDao.addBlackListRecords(list);
return count;
};
Future<Integer> future = executor.submit(callable);
resultList.add(future);
}
executor.shutdown();
int total = 0;
for (Future<Integer> future : resultList) {
while (true) {
if (future.isDone() && !future.isCancelled()) {
int sum = future.get();
total += sum;
break;
} else {
Thread.sleep(100);
}
}
}
return total;
}
위의 소스 코드 에 대해 우 리 는 읽 은 EXCEL 데 이 터 를 데이터베이스 에 삽입 해 야 한 다 는 것 을 알 수 있 습 니 다.여기 서 데이터베이스 의 IO 를 줄 이 고 삽입 효율 을 높이 기 위해 우 리 는 5000 개의 일괄 삽입 을 사용 합 니 다(주의:데이터 양 이 너무 많 으 면 구 성 된 SQL 문 구 를 실행 할 수 없습니다).최종 실행 에 성공 한 삽입 결 과 를 얻 고 삽입 실행 이 느 려 야 합 니 다.자바 다 중 스 레 드 를 사용 한 Future 모드 는 비동기 방식 으로 최종 적 으로 J 실행 결 과 를 가 져 옵 니 다.
위의 실현 을 통 해 건물 주 테스트 에서 최종 백만 개의 데 이 터 를 얻 는 데 4 분 정도 걸 리 면 해결 할 수 있다.더 좋 은 방법 이 있다 면 댓 글 을 남 겨 주세요.
추가 지식:Java API SXSSFWorkbook Excel 대량 데이터 내 보 내기(백만 급)시간 초과 해결
이전에 간단 한 HSSFWorkbook 을 사용 하면 내 보 낸 데 이 터 를 초과 할 수 없습니다.
나중에 SXSSFWorkbook 으로 바 뀌 면 더 많은 것 을 내 보 낼 수 있 습 니 다.하지만...
그리고 제 이전 코드 는 모든 데 이 터 를 한꺼번에 찾 아 냈 고 몇 십 만 건 이 시간 을 초 과 했 습 니 다.
이전 코드 는 모든 결 과 를 한꺼번에 찾 아 냈 고 list 에는 수 십 만 개의 데이터 가 저장 되 어 있 었 다.기능 설계 의 문제 로 인해 나의 이 인 터 페 이 스 는 세 가지 기능 을 동시에 처리 해 야 한다.
게다가 SQL 조회 효율 문제 로 요청 시간 이 초과 되 었 습 니 다.
지금 은 더 많은 데 이 터 를 얻 기 위해 최 적 화 를 선택 할 수 밖 에 없다.최적화 조회 의 sql 은 여기 서 말 하지 않 고 내 보 내기 기능 의 최적화 만 말 합 니 다.
사실은 일괄 처리 조회 결과 입 니 다.
이렇게 하면 조회 속도 가 빨 라 지고 패 키 징 속도 도 빨 라 지 며 전체 속도 가 빨 라 지면 시간 초과 가 발생 하지 않 는 다 는 것 이 장점 이다.또한 페이지 별로 찾 아 낸 결 과 를 list 에 넣 으 면 JVM 메모리 가 너무 큰 상황 이 발생 하지 않 는 다.메모리 가 넘 쳐 시스템 이 무 너 지 는 것 을 피하 십시오.
다시 최적화:
위 에서 이렇게 하면 내 보 낼 수 있 지만 코드 가 아름 답지 않 습 니 다.
이렇게 하면 훨씬 간결 해 보인다.
경험 증,조회 패 키 징 EXCEL 7000 개 데이터 처리 1 초
이 글 은 Springboot+poi 를 사용 하여 백만 급 데 이 터 를 업로드 하고 처리 합 니 다.EXCEL 은 편집장 이 여러분 에 게 공유 한 모든 내용 입 니 다.참고 하 시기 바 랍 니 다.여러분 들 도 많이 응원 해 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.