java之json轉excel生成

背景
業務為實現自定義樣式excel的導出,常規的做法就是根據數據在代碼中進行類似模版的配置;這樣的體驗不是很好,只要用戶改變下樣式的設置不用代碼改動就能實現自定義excel的導出更加靈活。
以下是具體實現
pom依賴

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.17.2</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.17.2</version></dependency><!-- HTML解析 --><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.8.1</version></dependency>

控制器代碼

package com.longshare.microservice.file.support.service.impl;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.longshare.microservice.file.support.ProblemCode;
import com.longshare.microservice.file.support.config.FileUploadConfig;
import com.longshare.microservice.file.support.service.FileConvertService;
import com.longshare.microservice.file.support.service.FileInfoService;
import com.longshare.microservice.file.support.utils.FileUtils;
import com.longshare.rest.core.problem.ProblemSolver;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.*;
import java.util.*;
import java.util.stream.Collectors;import com.longshare.file.share.model.vo.FileInformation;
import org.springframework.web.multipart.MultipartFile;@Service
@Slf4j
public class FileConvertServiceImpl implements FileConvertService {private final String DEFAULT_SHEET_NAME = "Sheet1";private final String DEFAULT_FONT_NAME = "微軟雅黑";private final short DEFAULT_FONT_SIZE = 12;// 修復默認表頭背景色(原代碼"#"會導致解析錯誤)private final String DEFAULT_HEADER_BACKGROUND = "#F0F0F0";@Autowiredprivate FileInfoService fileInfoService;@Autowiredprivate FileUploadConfig fileUploadConfig;@Overridepublic FileInformation convertWithConfig(String configJson) throws Exception {log.info("字符串大小:{} 字符串KB:{} 字符串MB:{}",configJson.length(),configJson.length()/1024+"KB",configJson.length()/1024/1024+"");boolean addIndex = false;boolean sortAscending = true;String sortBy = "排序號";Config config = parseConfig(configJson);String filename = config.getFileName();String typeId = config.getTypeId();if (StringUtils.isBlank(typeId)) {throw ProblemSolver.client(ProblemCode.NOT_TYPE_ID).build();}String outputDir = "D:\\tmp\\microframe\\upload\\";
//        String outputDir = fileUploadConfig.getBasePath();log.info("outputDir:{}", outputDir);if (Objects.isNull(filename)) {filename = "configured_export";}File outputDirFile = new File(outputDir);if (!outputDirFile.exists()) {outputDirFile.mkdirs();}String outputPath = outputDir + File.separator + filename + ".xlsx";JSONArray dataArray = config.getExcelData();FileInformation fileInformation = new FileInformation();if (sortBy != null && !sortBy.isEmpty()) {sortDataArray(dataArray, sortBy, sortAscending);}Workbook workbook = new XSSFWorkbook();FileOutputStream fos = null;File tempFile = new File(outputPath);try {fos = new FileOutputStream(tempFile);Sheet sheet = workbook.createSheet(filename != null ? filename : DEFAULT_SHEET_NAME);HeaderConfig headerConfig = parseHeaderConfig(config.getHeader());writeDataToSheet(sheet, dataArray, headerConfig, addIndex);applyStyles(sheet, dataArray, headerConfig, addIndex);workbook.write(fos);log.info("Excel文件已生成:{}", outputPath);MultipartFile multipartFile = FileUtils.fileToMultipartFile(tempFile);log.info("multipartFile完成:{}", multipartFile.getOriginalFilename());fileInformation = fileInfoService.upload(multipartFile, null, typeId);log.info("上傳到文件中心完成---->:{}", fileInformation);} catch (Exception e) {log.error("處理Excel文件時發生錯誤: " + e.getMessage(), e);throw e;} finally {
//            if (fos != null) {
//                try {
//                    fos.close();
//                } catch (IOException e) {
//                    log.error("關閉文件流時發生錯誤: " + e.getMessage(), e);
//                }
//            }
//            if (tempFile.delete()) {
//                log.info("臨時文件已刪除: " + outputPath);
//            } else {
//                log.error("嘗試刪除臨時文件失敗");
//            }}return fileInformation;}@Overridepublic FileInformation htmlToWorld(MultipartFile multipartFile) {return null;}private static Config parseConfig(String configJson) throws Exception {try {boolean validJson = isValidJson(configJson);if (!validJson) {throw ProblemSolver.client(ProblemCode.NOT_JSON).build();}JSONObject configObj = JSON.parseObject(configJson);if (!configObj.containsKey("header") || !configObj.containsKey("excelData") || !configObj.containsKey("typeId")) {throw ProblemSolver.client(ProblemCode.NOT_TYPE_ID).build();}Config config = new Config();config.setHeader(configObj.getJSONObject("header"));config.setExcelData(configObj.getJSONArray("excelData"));config.setFileName(String.valueOf(configObj.get("fileName")));config.setTypeId(String.valueOf(configObj.get("typeId")));return config;} catch (Exception e) {log.error("解析配置文件失敗", e);throw new Exception("解析配置文件失敗: " + e.getMessage(), e);}}/*** 校驗字符串是否是有效的json字符串** @param jsonStr* @return*/public static boolean isValidJson(String jsonStr) {if (jsonStr == null || jsonStr.trim().isEmpty()) {return false;}jsonStr = jsonStr.trim();if (!(jsonStr.startsWith("{") && jsonStr.endsWith("}")) &&!(jsonStr.startsWith("[") && jsonStr.endsWith("]"))) {return false;}try {if (jsonStr.startsWith("{")) {JSON.parseObject(jsonStr);} else {JSON.parseArray(jsonStr);}return true;} catch (JSONException e) {return false;} catch (Exception e) {return false;}}private HeaderConfig parseHeaderConfig(JSONObject headerObj) {HeaderConfig headerConfig = new HeaderConfig();JSONObject normalSetting = headerObj.getJSONObject("normal_setting");if (normalSetting == null) {normalSetting = new JSONObject();}headerConfig.setNormalSetting(normalSetting);JSONObject customSetting = headerObj.getJSONObject("custom_setting");if (customSetting == null) {customSetting = new JSONObject();}headerConfig.setCustomSetting(customSetting);List<Map.Entry<String, Object>> sortedColumns = customSetting.entrySet().stream().sorted((e1, e2) -> {JSONObject conf1 = (JSONObject) e1.getValue();JSONObject conf2 = (JSONObject) e2.getValue();int index1 = conf1.getIntValue("index");int index2 = conf2.getIntValue("index");return Integer.compare(index1, index2);}).collect(Collectors.toList());List<String> columnOrder = new ArrayList<>();for (Map.Entry<String, Object> entry : sortedColumns) {columnOrder.add(entry.getKey());}headerConfig.setColumnOrder(columnOrder);return headerConfig;}private void writeDataToSheet(Sheet sheet, JSONArray dataArray, HeaderConfig headerConfig, boolean addIndex) {List<String> columnOrder = headerConfig.getColumnOrder();Set<String> allColumns = getAllColumnNames(dataArray);List<String> finalColumnOrder = new ArrayList<>();for (String col : columnOrder) {if (allColumns.contains(col)) {finalColumnOrder.add(col);}}for (String col : allColumns) {if (!finalColumnOrder.contains(col)) {finalColumnOrder.add(col);}}Row headerRow = sheet.createRow(0);headerRow.setHeightInPoints((float) Double.parseDouble(headerConfig.getNormalSetting().getString("header-row-height")));int colIndex = addIndex ? 1 : 0;if (addIndex) {Cell indexCell = headerRow.createCell(0);indexCell.setCellValue("索引");}for (String column : finalColumnOrder) {Cell cell = headerRow.createCell(colIndex++);cell.setCellValue(column);}for (int rowIndex = 0; rowIndex < dataArray.size(); rowIndex++) {Row dataRow = sheet.createRow(rowIndex + 1);colIndex = addIndex ? 1 : 0;if (addIndex) {Cell indexCell = dataRow.createCell(0);indexCell.setCellValue(rowIndex + 1);}JSONObject dataObj = dataArray.getJSONObject(rowIndex);for (String column : finalColumnOrder) {Cell cell = dataRow.createCell(colIndex++);if (dataObj.containsKey(column)) {Object value = dataObj.get(column);if (value != null) {setCellValue(cell, value);}}}}}/*** 應用樣式設置** @param sheet* @param dataArray* @param headerConfig* @param addIndex*/private void applyStyles(Sheet sheet, JSONArray dataArray, HeaderConfig headerConfig, boolean addIndex) {JSONObject normalSetting = headerConfig.getNormalSetting();JSONObject customSetting = headerConfig.getCustomSetting();List<String> columnOrder = headerConfig.getColumnOrder();Set<String> allColumns = getAllColumnNames(dataArray);List<String> finalColumnOrder = new ArrayList<>();for (String col : columnOrder) {if (allColumns.contains(col)) {finalColumnOrder.add(col);}}for (String col : allColumns) {if (!finalColumnOrder.contains(col)) {finalColumnOrder.add(col);}}int colOffset = addIndex ? 1 : 0;for (int i = 0; i < finalColumnOrder.size(); i++) {String columnName = finalColumnOrder.get(i);int colIdx = i + colOffset;JSONObject colConfig = customSetting.getJSONObject(columnName);if (colConfig == null) {colConfig = new JSONObject();}if (colConfig.containsKey("column_width")) {int pixelWidth = colConfig.getIntValue("column_width");double excelWidth = pixelWidth / 7.0;sheet.setColumnWidth(colIdx, (int) (excelWidth * 256));} else if (normalSetting.containsKey("width")) {int pixelWidth = normalSetting.getIntValue("width");double excelWidth = pixelWidth / 7.0;sheet.setColumnWidth(colIdx, (int) (excelWidth * 256));}}Row headerRow = sheet.getRow(0);if (headerRow != null) {for (int colIdx = 0; colIdx < finalColumnOrder.size(); colIdx++) {Cell headerCell = headerRow.getCell(colIdx + colOffset);if (headerCell != null) {applyHeaderCellStyle(headerCell.getSheet().getWorkbook(), headerCell, normalSetting);}}}for (int rowIdx = 1; rowIdx <= dataArray.size(); rowIdx++) {Row dataRow = sheet.getRow(rowIdx);if (dataRow != null) {for (int colIdx = 0; colIdx < finalColumnOrder.size(); colIdx++) {Cell cell = dataRow.getCell(colIdx + colOffset);if (cell != null) {String columnName = finalColumnOrder.get(colIdx);JSONObject colConfig = customSetting.getJSONObject(columnName);if (colConfig == null) {colConfig = new JSONObject();}applyDataCellStyle(cell.getSheet().getWorkbook(), cell, normalSetting, colConfig);}}}}}/*** 數據單元格樣式設置** @param workbook* @param cell* @param normalSetting* @param colConfig*/private void applyDataCellStyle(Workbook workbook, Cell cell, JSONObject normalSetting, JSONObject colConfig) {try {String fontName = normalSetting.containsKey("font-name") ?normalSetting.getString("font-name") : DEFAULT_FONT_NAME;short fontSize = DEFAULT_FONT_SIZE;if (normalSetting.containsKey("font-size")) {fontSize = (short) normalSetting.getIntValue("font-size");}boolean fontBold = normalSetting.containsKey("font-weight") &&"bold".equals(normalSetting.getString("font-weight"));Font font = workbook.createFont();font.setFontName(fontName);font.setFontHeightInPoints(fontSize);// POI 5.2.3使用setBold(boolean)替代setBoldweightfont.setBold(fontBold);if (normalSetting.containsKey("font-color")) {String fontColor = normalSetting.getString("font-color");
//                if (fontColor.startsWith("#")) {
//                    fontColor = fontColor.substring(1);
//                }try {if (workbook instanceof XSSFWorkbook) {byte[] rgb = getRgb(fontColor);if (rgb == null) {rgb = new byte[]{(byte) 0, (byte) 0, (byte) 0};}// POI 5.2.3 XSSFColor構造兼容處理((XSSFFont) font).setColor(new XSSFColor(rgb, null));}} catch (Exception e) {log.error("解析數據字體顏色失敗: " + fontColor, e);}}// 使用HorizontalAlignment枚舉替代CellStyle常量HorizontalAlignment hAlign;String align = colConfig.containsKey("column_align") ?colConfig.getString("column_align") : normalSetting.getString("align");switch (align) {case "center":hAlign = HorizontalAlignment.CENTER;break;case "right":hAlign = HorizontalAlignment.RIGHT;break;default:hAlign = HorizontalAlignment.LEFT;}CellStyle style = workbook.createCellStyle();style.setFont(font);style.setAlignment(hAlign);// 使用VerticalAlignment枚舉替代CellStyle常量style.setVerticalAlignment(VerticalAlignment.CENTER);if (normalSetting.containsKey("background-color")) {String bgColor = normalSetting.getString("background-color");try {if (workbook instanceof XSSFWorkbook) {byte[] rgb = getRgb(bgColor);if (rgb != null) {XSSFColor color = new XSSFColor(rgb, null);((XSSFCellStyle) style).setFillForegroundColor(color);// 使用FillPatternType枚舉替代CellStyle常量style.setFillPattern(FillPatternType.SOLID_FOREGROUND);}}} catch (Exception e) {log.error("解析數據背景顏色失敗: " + bgColor, e);}}style.setWrapText(normalSetting.getBoolean("line-wrap"));cell.setCellStyle(style);} catch (Exception e) {log.error("應用數據單元格樣式錯誤: " + e.getMessage(), e);}}/*** 更靈活的安全解析HTML顏色值為RGB數組** @param colorStr 顏色字符串,如 "#RRGGBB" 或 "#RGB"* @return RGB值數組 [R, G, B],解析失敗時返回 null*/public static byte[] getRgb(String colorStr) {if (colorStr == null || !colorStr.startsWith("#")) {
//            log.error("顏色值格式不正確: {}", colorStr);return null;}String hex = colorStr.substring(1); // 去掉 # 符號int length = hex.length();try {if (length == 6) {// 標準的情況 #RRGGBB 格式int r = Integer.parseInt(hex.substring(0, 2), 16);int g = Integer.parseInt(hex.substring(2, 4), 16);int b = Integer.parseInt(hex.substring(4, 6), 16);return new byte[]{(byte) r, (byte) g, (byte) b}; // 轉換為 byte 類型} else if (length == 3) {// 若存在簡寫 #RGB 格式,擴展為 #RRGGBBint r = Integer.parseInt(hex.substring(0, 1) + hex.substring(0, 1), 16);int g = Integer.parseInt(hex.substring(1, 2) + hex.substring(1, 2), 16);int b = Integer.parseInt(hex.substring(2, 3) + hex.substring(2, 3), 16);return new byte[]{(byte) r, (byte) g, (byte) b}; // 轉換為 byte 類型} else {log.error("不支持的顏色格式: {}", colorStr);return null;}} catch (NumberFormatException | StringIndexOutOfBoundsException e) {log.error("解析顏色值失敗: {}", colorStr, e);return null;}}private void applyHeaderCellStyle(Workbook workbook, Cell cell, JSONObject normalSetting) {try {String fontName = normalSetting.containsKey("header-font-name") ?normalSetting.getString("header-font-name") : DEFAULT_FONT_NAME;short fontSize = DEFAULT_FONT_SIZE;if (normalSetting.containsKey("header-font-size")) {fontSize = (short) normalSetting.getIntValue("header-font-size");}boolean fontBold = normalSetting.containsKey("header-font-weight") &&"bold".equals(normalSetting.getString("header-font-weight"));Font font = workbook.createFont();font.setFontName(fontName);font.setFontHeightInPoints(fontSize);// POI 5.2.3使用setBold(boolean)替代setBoldweightfont.setBold(fontBold);if (normalSetting.containsKey("header-font-color")) {String fontColor = normalSetting.getString("header-font-color");try {if (workbook instanceof XSSFWorkbook) {byte[] rgb = getRgb(fontColor);if (rgb == null) {//表頭字體黑色rgb = new byte[]{(byte) 0, (byte) 0, (byte) 0};}((XSSFFont) font).setColor(new XSSFColor(rgb, null));}} catch (Exception e) {log.error("解析表頭字體顏色失敗: " + fontColor, e);}}// 使用HorizontalAlignment枚舉替代CellStyle常量HorizontalAlignment hAlign;String align = normalSetting.getString("header-align");switch (align) {case "center":hAlign = HorizontalAlignment.CENTER;break;case "right":hAlign = HorizontalAlignment.RIGHT;break;default:hAlign = HorizontalAlignment.LEFT;}CellStyle style = workbook.createCellStyle();style.setFont(font);style.setAlignment(hAlign);// 使用VerticalAlignment枚舉替代CellStyle常量style.setVerticalAlignment(VerticalAlignment.CENTER);String bgColor = DEFAULT_HEADER_BACKGROUND;if (normalSetting.containsKey("header-background-color")) {bgColor = normalSetting.getString("header-background-color");}try {if (workbook instanceof XSSFWorkbook) {byte[] rgb = getRgb(bgColor);if (rgb == null) {//表頭白色背景rgb = new byte[]{(byte) 255, (byte) 255, (byte) 255};}XSSFColor color = new XSSFColor(rgb, null);((XSSFCellStyle) style).setFillForegroundColor(color);style.setFillPattern(FillPatternType.SOLID_FOREGROUND);} else {style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);}} catch (Exception e) {style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);}// POI 5.2.3使用BorderStyle枚舉替代short值BorderStyle borderStyle = BorderStyle.THIN; // 默認細邊框if (normalSetting.containsKey("header-border")) {int borderThick = normalSetting.getIntValue("header-border");// 根據數值映射邊框樣式(1=細,2=中,3=粗)switch (borderThick) {case 2:borderStyle = BorderStyle.MEDIUM;break;case 3:borderStyle = BorderStyle.THICK;break;default:borderStyle = BorderStyle.THIN;}}style.setBorderTop(borderStyle);style.setBorderBottom(borderStyle);style.setBorderLeft(borderStyle);style.setBorderRight(borderStyle);cell.setCellStyle(style);} catch (Exception e) {log.error("應用表頭單元格樣式錯誤: " + e.getMessage(), e);}}private void setCellValue(Cell cell, Object value) {if (value instanceof Number) {cell.setCellValue(((Number) value).doubleValue());} else if (value instanceof Boolean) {cell.setCellValue((Boolean) value);} else if (value instanceof Date) {cell.setCellValue((Date) value);} else {cell.setCellValue(value.toString());}}private Set<String> getAllColumnNames(JSONArray dataArray) {Set<String> columns = new LinkedHashSet<>();for (int i = 0; i < dataArray.size(); i++) {JSONObject obj = dataArray.getJSONObject(i);if (obj != null) {columns.addAll(obj.keySet());}}return columns;}private void sortDataArray(JSONArray dataArray, String sortBy, boolean sortAscending) {dataArray.sort((o1, o2) -> {JSONObject obj1 = (JSONObject) o1;JSONObject obj2 = (JSONObject) o2;Object val1 = obj1.get(sortBy);Object val2 = obj2.get(sortBy);if (val1 == null && val2 == null) {return 0;}if (val1 == null) {return sortAscending ? -1 : 1;}if (val2 == null) {return sortAscending ? 1 : -1;}if (val1 instanceof Comparable && val2 instanceof Comparable) {@SuppressWarnings("unchecked")int result = ((Comparable<Object>) val1).compareTo(val2);return sortAscending ? result : -result;}return sortAscending ? val1.toString().compareTo(val2.toString()) : val2.toString().compareTo(val1.toString());});}@Datapublic static class Config {private JSONObject header;private JSONArray excelData;private String fileName;private String typeId;}@Datapublic static class HeaderConfig {private JSONObject normalSetting;private JSONObject customSetting;private List<String> columnOrder;}public static void main(String[] args) throws Exception {/* ============ 1. 原始配置骨架(excelData 先留空數組) ============ */String baseJson = "{\n" +"  \"typeId\":\"10801\",\n" +"  \"fileName\":\"測試文件1\",\n" +"  \"header\":{\n" +"    \"normal_setting\":{\n" +"      \"align\": \"center\",\n" +"      \"font-name\":\"宋體\",\n" +"      \"font-size\": 12,\n" +"      \"font-weight\": \"\",\n" +"      \"font-color\": \"#333333\",\n" +"      \"background-color\": \"\",\n" +"      \"width\": 510,\n" +"      \"line-wrap\": true,\n" +"      \"header-align\": \"\",\n" +"      \"header-row-height\": 150,\n" +"      \"header-font-size\": 121,\n" +"      \"header-font-weight\": \"bold\",\n" +"      \"header-font-color\": \"#0f0f0f\",\n" +"      \"header-background-color\": \"#ADD8E6\"\n" +"    },\n" +"    \"custom_setting\":{\n" +"      \"序號\":{\"index\":3,\"column_align\":\"center\",\"column_width\":500},\n" +"      \"員工編號\":{\"index\":2,\"column_align\":\"left\",\"column_width\":50},\n" +"      \"姓名\":{\"index\":1,\"column_align\":\"center\",\"column_width\":50},\n" +"      \"年齡\":{\"index\":4,\"column_width\":50},\n" +"      \"部門\":{\"index\":5,\"column_align\":\"center\",\"column_width\":200},\n" +"      \"職位\":{\"index\":6,\"column_align\":\"center\",\"column_width\":100},\n" +"      \"薪資\":{\"index\":7,\"column_width\":100},\n" +"      \"績效評級\":{\"index\":8,\"column_width\":100},\n" +"      \"工作年限\":{\"index\":9,\"column_width\":100},\n" +"      \"入職日期\":{\"index\":10,\"column_width\":100},\n" +"      \"聯系電話\":{\"index\":11,\"column_align\":\"left\",\"column_width\":100},\n" +"      \"郵箱\":{\"index\":12,\"column_width\":100},\n" +"      \"工作地點\":{\"index\":13,\"column_width\":100},\n" +"      \"狀態\":{\"index\":14,\"column_align\":\"left\",\"column_width\":100}\n" +"    }\n" +"  },\n" +"  \"excelData\": %s\n" +"}";/* ============ 2. 單條數據模板 ============ */String singleRecord = "{\n" +"  \"排序號\": %d,\n" +"  \"員工編號\": \"E%03d\",\n" +"  \"姓名\": \"員工%d\",\n" +"  \"年齡\": %d,\n" +"  \"部門\": \"技術部\",\n" +"  \"職位\": \"工程師\",\n" +"  \"薪資\": %d,\n" +"  \"績效評級\": \"A\",\n" +"  \"工作年限\": %.1f,\n" +"  \"入職日期\": \"2022-01-01\",\n" +"  \"聯系電話\": \"138****%04d\",\n" +"  \"郵箱\": \"emp%03d@company.com\",\n" +"  \"工作地點\": \"北京\",\n" +"  \"狀態\": \"在職\"\n" +"}";/* ============ 3. 循環生成 N 條 ============ */int N = 5000;                       // 想壓多大就改多大List<String> list = new ArrayList<>(N);for (int i = 1; i <= N; i++) {list.add(String.format(singleRecord,i, i, i,20 + (i % 20),               // 年齡 20~398000 + (i * 10),             // 隨薪資遞增1.0 + (i % 10),              // 工作年限i % 10000, i));}/* ============ 4. 最終 JSON 字符串 ============ */String hugeJson = String.format(baseJson, list.toString());/* ============ 5. 調接口測試 ============ */FileConvertServiceImpl service = new FileConvertServiceImpl();FileInformation info = service.convertWithConfig(hugeJson);System.out.println("生成對象大小:" + hugeJson.length() / 1024 + " KB");}
}

postman測試
在這里插入圖片描述
好了 至此 java之json轉excel生成 點點關注不迷路 老鐵們!!!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914885.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914885.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914885.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

新版本Cursor中配置自定義MCP服務器教程,附MCP工具開發實戰源碼

在 Cursor 中配置自定義 MCP 服務器&#xff1a;打造你的 AI 開發工具鏈 引言 隨著 AI 編程助手的普及&#xff0c;開發者們越來越希望能夠定制化自己的開發環境。Cursor 作為一款強大的 AI 編程編輯器&#xff0c;提供了 Model Context Protocol (MCP) 支持&#xff0c;新版本…

前端面試十二之vue3基礎

一、ref和reactive在 Vue 3 中&#xff0c;ref 和 reactive 是兩種主要的響應式數據創建方式&#xff0c;它們各有特點和適用場景。1.refref 主要用于創建單個值的響應式引用&#xff0c;通常用于基本類型數據&#xff0c;如數字、字符串等。使用 ref 創建的引用對象可以通過 .…

設計模式四:裝飾模式(Decorator Pattern)

裝飾模式是一種結構型設計模式&#xff0c;它允許你動態地給一個對象添加額外的職責&#xff0c;相比繼承更加靈活。1. 模式定義裝飾模式&#xff1a;動態地給一個對象添加一些額外的職責。就增加功能來說&#xff0c;裝飾模式相比生成子類更為靈活。2. 模式結構主要角色&#…

神經網絡常見激活函數 14-Mish函數

文章目錄Mish函數導函數函數和導函數圖像優缺點PyTorch 中的 Mish 函數TensorFlow 中的 Mish 函數Mish 論文 https://arxiv.org/pdf/1908.08681 函數導函數 Mish函數 Mish(x)x?tanh??(softplus(x))x?tanh??(ln??(1ex))\begin{aligned} \text{Mish}(x) & x \cdot \t…

LAMP遷移LNMP Nginx多站點配置全流程

文章目錄前言備份與停止服務nginx安裝與配置nginx 編譯安裝配置服務php-fpm多站點配置phf-fpm介紹多站點配置nginx 多站點配置nginx ssl 配置參考前言 之前服務器使用的是 LAMP環境&#xff0c;想充分利用服務器資源&#xff0c;再運行另外一個站點 在LAMP環境下應該是也可以…

Nginx屏蔽國外IP訪問

下載IP列表 # 下載到文件 wget http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest # 直接輸出到終端 curl -sSL https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest得到一份國內IP配置 # 原始IP列表格式&#xff1a;apnic|CN|ipv4|218.78.0.0|1310…

stl-string模擬

1.介紹主要進行cpp中string的模擬&#xff0c;方便我們更好的對stl進行使用&#xff0c;string沒有模板&#xff0c;我們將頭文件和函數寫在兩個不同的文件2.頭文件3.cpp文件如有問題&#xff0c;歡迎糾正&#xff01;

基于MATLAB的極限學習機ELM的數據回歸預測方法應用

說明&#xff1a;這是一個機器學習實戰項目&#xff08;附帶數據代碼文檔&#xff09;&#xff0c;如需數據代碼文檔可以直接到文章最后關注獲取 或者私信獲取。 1.項目背景 在當今的數據驅動時代&#xff0c;準確且高效的預測模型對于解決復雜問題至關重要。極限學習機&#…

芯谷科技--雙四通道模擬/數字多路復用器74HC4052

在電子系統中&#xff0c;信號的多路復用與解復用是常見的需求&#xff0c;特別是在需要對多個信號源進行選擇和切換的場景中。芯谷科技推出的 74HC4052 雙四通道模擬/數字多路復用器/解復用器&#xff0c;以其高效、靈活的設計&#xff0c;為工程師提供了可靠的解決方案。產品…

基于MATLAB的極限學習機ELM的數據分類預測方法應用

說明&#xff1a;這是一個機器學習實戰項目&#xff08;附帶數據代碼文檔&#xff09;&#xff0c;如需數據代碼文檔可以直接到文章最后關注獲取 或者私信獲取。 1.項目背景 在現代數據挖掘與機器學習領域&#xff0c;面對日益復雜的數據結構和快速增長的數據量&#xff0c;開…

復合機器人在生物制藥實驗室上下料搬運案例

在醫療行業的物料搬運環節&#xff0c;傳統的人工操作模式逐漸暴露出諸多弊端&#xff0c;成為制約企業發展的瓶頸。富唯智能通過引入先進的復合機器人技術&#xff0c;為醫療企業提供了高效、智能的上下料搬運解決方案&#xff0c;助力醫療行業實現自動化與智能化升級。?客戶…

嵌入式學習-PyTorch(7)-day23

損失函數的調用import torch from torch import nn from torch.nn import L1Lossinputs torch.tensor([1.0,2.0,3.0]) target torch.tensor([1.0,2.0,5.0])inputs torch.reshape(inputs, (1, 1, 1, 3)) target torch.reshape(target, (1, 1, 1, 3)) #損失函數 loss L1Loss…

用 Ray 跨節點調用 GPU 部署 DeepSeek 大模型,實現分布式高效推理

在大模型時代&#xff0c;單節點 GPU 資源往往難以滿足大模型&#xff08;如 7B/13B 參數模型&#xff09;的部署需求。借助 Ray 分布式框架&#xff0c;我們可以輕松實現跨節點 GPU 資源調度&#xff0c;讓大模型在多節點間高效運行。本文將以 DeepSeek-llm-7B-Chat 模型為例&…

快速了解 HTTPS

1. 引入 在 HTTP 協議 章節的 reference 段&#xff0c;曾提到過 HTTPS。這里對HTTPS進行詳細介紹。 HTTPS 是在 HTTP 的基礎上&#xff0c;引入了一個加密層 (SSL)。HTTP 是明文傳輸的 (不安全)。當下所見到的大部分網站都是 HTTPS 的。 起初是拜運營商劫持所賜&#xff08;…

mysql備份與視圖

要求:1.將mydb9_stusys數據庫下的student、sc 和course表&#xff0c;備份到本地主機保存為st_msg_bak.sql文件&#xff0c;然后將數據表恢復到自建的db_test數據庫中&#xff1b;2.在db_test數據庫創建一視圖 stu_info,查詢全體學生的姓名&#xff0c;性別&#xff0c;課程名&…

【數據結構】 鏈表 + 手動實現單鏈表和雙鏈表的接口(圖文并茂附完整源碼)

文章目錄 一、 鏈表的概念及結構 二、鏈表的分類 ?編輯 三、手動實現單鏈表 1、定義單鏈表的一個節點 2、打印單鏈表 3、創建新節點 4、單鏈表的尾插 5、單鏈表的頭插 6、單鏈表的尾刪 7、單鏈表的頭刪 8、單鏈表的查找 9、在指定位置之前插入一個新節點 10、在指…

Go語言時間控制:定時器技術詳細指南

1. 定時器基礎&#xff1a;從 time.Sleep 到 time.Timer 的進化為什么 time.Sleep 不夠好&#xff1f;在 Go 編程中&#xff0c;很多人初學時會用 time.Sleep 來實現時間控制。比如&#xff0c;想讓程序暫停 2 秒&#xff0c;代碼可能是這樣&#xff1a;package mainimport (&q…

C# 轉換(顯式轉換和強制轉換)

顯式轉換和強制轉換 如果要把短類型轉換為長類型&#xff0c;讓長類型保存短類型的所有位很簡單。然而&#xff0c;在其他情況下&#xff0c; 目標類型也許無法在不損失數據的情況下容納源值。 例如&#xff0c;假設我們希望把ushort值轉化為byte。 ushort可以保存任何0~65535的…

淺談自動化設計最常用的三款軟件catia,eplan,autocad

筆者從上半年開始接觸這三款軟件&#xff0c;掌握了基礎用法&#xff0c;但是過了一段時間不用&#xff0c;發現再次用&#xff0c;遇到的問題短時間解決不了&#xff0c;忘記的有點多&#xff0c;這里記錄一下&#xff0c;防止下次忘記Elpan:問題1QF01是柜安裝板上的一個部件&…

網絡編程7.17

練習&#xff1a;服務器&#xff1a;#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include &…