๋ชฉ์ฐจ
2022.12.03 ๋ด์ฉ ์ถ๊ฐ
์๋ ์ฝ๋์์๋ XSSFWorkbook์ ์ฌ์ฉํ๋๋ฐ, ์ค์ ์ด์์๋ฒ์์ ๋๋ Out Of Memory ์๋ฌ๋ฅผ ๊ฒฝํํ๋ค.
ํธ์ํ ์ฃผ๋ง์ ๋ณด๋ด๊ณ ์ถ๋ค๋ฉด ๊ผญ ๋ฐ๋์ ์๋ ๊ธ์ ์ฝ์ด๋ณด๊ณ SXSSFWorkbook์ ์ฌ์ฉํ์.
https://lotuus.tistory.com/153
ํต๊ณ API๋ฅผ ๋ง๋ค๋ค๋ณด๋ฉด
ํ๋ฉด์๋ ๊ฐ์ ๋ณด์ฌ์ฃผ์ด์ผํ๊ณ , ์์ ๋ค์ด๋ก๋๋ ๊ฐ๋ฅํด์ผํฉ๋๋ค ใ ใ
๋ํ์ ์ผ๋ก ์ฌ์ฉ๋๋ Apache Poi๋ฅผ ์ด์ฉํ์ฌ ์์ ๋ค์ด๋ก๋๋ฅผ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋น!
์์
UserPoint Entity
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserPoint {
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
@Column(name = "user_code")
private String userCode; //์ ์ ์ฝ๋
@Column(name = "user_name")
private String userName; //์ ์ ๋ช
@Column(name = "pay_cnt")
private Integer payCnt; //๊ฒฐ์ ๊ฑด์
@Column(name = "pay_sum")
private Long paySum; //๊ฒฐ์ ๊ธ์ก
}
StatsController
@RestController
@RequestMapping("/stats")
@RequiredArgsConstructor
public class StatsController {
private final StatsService statsService;
@GetMapping("/user/point")
public ResponseEntity getUsersPointStats(HttpServletResponse response, boolean excelDownload){
return ResponseEntity.ok(statsService.getUsersPointStats(response, excelDownload));
}
}
StatsService
@Service
@Transactional
@RequiredArgsConstructor
public class StatsService {
private final UserPointRepository userPointRepository;
private final ObjectMapper objectMapper;
public Object getUsersPointStats(HttpServletResponse response, boolean excelDownload) {
List<UserPoint> userPointList = userPointRepository.findAll();
List<Map> userPointMap = userPointList.stream()
.map(userPoint -> objectMapper.convertValue(userPoint, Map.class))
.collect(Collectors.toList());
return userPointMap;
}
}
API ์๋ต
์์ ๋ค์ด๋ก๋ ๊ตฌํ
build.gradle
//excel download : poi
implementation 'org.apache.poi:poi:5.2.2' // .xls ํ์ฅ์
implementation 'org.apache.poi:poi-ooxml:5.2.2' // .xlsx ํ์ฅ์
StatsService
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional
@RequiredArgsConstructor
public class StatsService {
private final UserPointRepository userPointRepository;
private final ObjectMapper objectMapper;
public Object getUsersPointStats(HttpServletResponse response, boolean excelDownload) {
List<UserPoint> userPointList = userPointRepository.findAll();
if(excelDownload){
createExcelDownloadResponse(response, userPointList);
return null; //์์ผ๋ฉด ์๋ฌ!
}
List<Map> userPointMap = userPointList.stream()
.map(userPoint -> objectMapper.convertValue(userPoint, Map.class))
.collect(Collectors.toList());
return userPointMap;
}
/**
* ์์
๋ค์ด๋ก๋ ๊ตฌํ ๐ฅ๐ฅ๐ฅ
*/
private void createExcelDownloadResponse(HttpServletResponse response, List<UserPoint> userPointList) {
try{
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("์ฌ์ฉ์ ํฌ์ธํธ ํต๊ณ");
//์ซ์ ํฌ๋งท์ ์๋ numberCellStyle์ ์ ์ฉ์ํฌ ๊ฒ์ด๋ค๋ค
CellStyle numberCellStyle = workbook.createCellStyle();
numberCellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0"));
//ํ์ผ๋ช
final String fileName = "์ฌ์ฉ์ ํฌ์ธํธ ํต๊ณ";
//ํค๋
final String[] header = {"๋ฒํธ", "์ ์ ์ฝ๋", "์ ์ ๋ช
", "๊ฒฐ์ ๊ฑด์", "๊ฒฐ์ ๊ธ์ก"};
Row row = sheet.createRow(0);
for (int i = 0; i < header.length; i++) {
Cell cell = row.createCell(i);
cell.setCellValue(header[i]);
}
//๋ฐ๋
for (int i = 0; i < userPointList.size(); i++) {
row = sheet.createRow(i + 1); //ํค๋ ์ดํ๋ก ๋ฐ์ดํฐ๊ฐ ์ถ๋ ฅ๋์ด์ผํ๋ +1
UserPoint userPoint = userPointList.get(i);
Cell cell = null;
cell = row.createCell(0);
cell.setCellValue(userPoint.getId());
cell = row.createCell(1);
cell.setCellValue(userPoint.getUserCode());
cell = row.createCell(2);
cell.setCellValue(userPoint.getUserName());
cell = row.createCell(3);
cell.setCellValue(userPoint.getPayCnt());
cell = row.createCell(4);
cell.setCellStyle(numberCellStyle); //์ซ์ํฌ๋งท ์ ์ฉ
cell.setCellValue(userPoint.getPaySum());
}
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8")+".xlsx");
//ํ์ผ๋ช
์ URLEncoder๋ก ๊ฐ์ธ์ฃผ๋๊ฒ ์ข๋ค!
workbook.write(response.getOutputStream());
workbook.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
API ์๋ต
excelDownload = false์ผ๋๋ json ๋ฐํ
excelDownload = true์ผ๋๋ ์์ ๋ค์ด๋ก๋
๊ฒฐ์ ๊ฑด์, ๊ฒฐ์ ๊ธ์ก์ ๋ณด๋ฉด
๋ณ๋ค๋ฅธ ์ฒ๋ฆฌ ์์ด๋ ๋ฌธ์์ด์ด ์๋ ์ซ์๋ก ์ฒ๋ฆฌ๋์ด์ ๋ฐ๋ก ์ฐ์ฐ์ด ๊ฐ๋ฅํ๋ค
( setCellValue(userPoint.getPayCnt().toString()) ์ผ๋ก ์ฒ๋ฆฌํด์ ์์ ๋ค์ด๋ก๋ํด๋ณด๋ฉด ์ซ์์ฐ์ฐ์ด ๋ถ๊ฐํ๋ค )
๋ํ ๊ฒฐ์ ๊ธ์ก์ ์ ์ฉํ ์ซ์ํฌ๋งท๋ ์ ์ ์ฉ๋์๋ค!
ํ๋ก ํธ์ชฝ์์๋ ์ด๋ป๊ฒ ํธ์ถํ์ง?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>excel</title>
</head>
<body>
<a href="http://localhost:8080/stats/user/point?excelDownload=true">ํฌ์ธํธ์ ๋ณด ์์
๋ค์ด๋ก๋</a>
</body>
</html>
aํ๊ทธ href ์์ฑ์ผ๋ก ์์ฒญ์ ๋ณด๋ด์ฃผ๋ฉด ๋ค์ด๋ก๋ ๊ฐ๋ฅํ๋ค!