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.tpcf.cn/news/914885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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 &…