You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何将服务类中的Excel操作共享方法迁移至工具类?

Problem Description

I have a service implementation class that handles Excel export functionality:

public class DataServiceImpl implements DataService {
    private static final String SHEET_TITLE = "export.permission.sheetTitle";
    private XSSFWorkbook workbook;
    private XSSFSheet sheet;
    private AtomicInteger rowCount;

    @Override
    public MultipartFile export() throws IOException {
        createSheet(SHEET_TITLE);
        // Omitted code for brevity
    }

    private void createSheet(String title) {
        workbook = new XSSFWorkbook();
        sheet = workbook.createSheet(title);
        rowCount = new AtomicInteger(0);
    }
}

I want to migrate methods like createSheet to a utility class since other similar classes need to use them. However, variables like workbook, sheet, and rowCount are used by other methods in this service class, so I'm unsure whether to pass these variables to the utility method and return them, or use another approach.

Additionally, I have these methods and need advice on whether to migrate them too:

private MultipartFile createMultipartFile(String title, String extension) throws IOException {
    File outputFile = File.createTempFile(TextBundleUtil.read(title), extension);
    workbook.write(outputStream);
    final FileInputStream input = new FileInputStream(outputFile);
    final String fileName = TextBundleUtil.read(title).concat(extension);
    return new MockMultipartFile(fileName, fileName, CONTENT_TYPE, IOUtils.toByteArray(input));
}

private static void writeTitles(Row row, List<String> titles, XSSFCellStyle style) {
    for (int i = 0; i < titles.size(); i++) {
        Cell cell = row.createCell(i);
        cell.setCellValue(titles.get(i));
        cell.setCellStyle(style);
    }
}

Solution

Let's break this down into manageable parts, focusing on clean state management and reusability:

1. Handling createSheet & State Variables (workbook, sheet, rowCount)

The core challenge here is that createSheet initializes state your service class relies on. Passing individual variables back and forth gets messy quickly—instead, create a context class to encapsulate all Excel-related state. This keeps your utility methods clean and makes state management consistent across multiple classes.

Step 1: Create an Excel Context Class

This class holds all the state variables and exposes getters (no setters to enforce immutability after initialization):

public class ExcelContext {
    private final XSSFWorkbook workbook;
    private final XSSFSheet sheet;
    private final AtomicInteger rowCount;

    public ExcelContext(XSSFWorkbook workbook, XSSFSheet sheet, AtomicInteger rowCount) {
        this.workbook = workbook;
        this.sheet = sheet;
        this.rowCount = rowCount;
    }

    // Getters for state variables
    public XSSFWorkbook getWorkbook() { return workbook; }
    public XSSFSheet getSheet() { return sheet; }
    public AtomicInteger getRowCount() { return rowCount; }
}

Step 2: Migrate createSheet to a Utility Class

Now your utility method can return the initialized ExcelContext, which your service class can store and use for other operations:

public class ExcelExportUtil {
    public static ExcelContext createSheet(String title) {
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet(title);
        AtomicInteger rowCount = new AtomicInteger(0);
        return new ExcelContext(workbook, sheet, rowCount);
    }
}

Step 3: Update Your Service Class

Replace the individual state variables with the context:

public class DataServiceImpl implements DataService {
    private static final String SHEET_TITLE = "export.permission.sheetTitle";
    private ExcelContext excelContext;

    @Override
    public MultipartFile export() throws IOException {
        excelContext = ExcelExportUtil.createSheet(SHEET_TITLE);
        // Use excelContext.getWorkbook(), excelContext.getSheet(), excelContext.getRowCount() in other methods
    }
}

2. Migrating the Other Methods

writeTitles: Definitely Migrate to Utility Class

This method is static already and only depends on its input parameters (no external state). It's perfect for a utility class:

public class ExcelExportUtil {
    // ... existing createSheet method

    public static void writeTitles(Row row, List<String> titles, XSSFCellStyle style) {
        for (int i = 0; i < titles.size(); i++) {
            Cell cell = row.createCell(i);
            cell.setCellValue(titles.get(i));
            cell.setCellStyle(style);
        }
    }
}

Call it directly from your service class:

ExcelExportUtil.writeTitles(row, titles, cellStyle);

createMultipartFile: Migrate to Utility Class (with Context)

This method depends on workbook, which is part of your ExcelContext. Pass the context to the utility method to keep it reusable:

public class ExcelExportUtil {
    // ... existing methods

    public static MultipartFile createMultipartFile(ExcelContext excelContext, String title, String extension, String contentType) throws IOException {
        String fileNamePrefix = TextBundleUtil.read(title);
        File outputFile = File.createTempFile(fileNamePrefix, extension);
        
        // Use try-with-resources to auto-close streams
        try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
            excelContext.getWorkbook().write(outputStream);
        }
        
        try (FileInputStream input = new FileInputStream(outputFile)) {
            String fileName = fileNamePrefix.concat(extension);
            return new MockMultipartFile(fileName, fileName, contentType, IOUtils.toByteArray(input));
        }
    }
}

Call it from your service:

MultipartFile file = ExcelExportUtil.createMultipartFile(excelContext, SHEET_TITLE, ".xlsx", CONTENT_TYPE);

Key Takeaways

  • Use a context class for stateful Excel operations: it avoids messy parameter lists and keeps related state organized.
  • Migrate stateless methods (like writeTitles) directly to the utility class—they're self-contained and easy to reuse.
  • Stateful methods (like createMultipartFile) can be migrated by passing the context or required state as parameters, ensuring they stay flexible across different service classes.

内容的提问来源于stack exchange,提问作者Jack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 19:52:47