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

如何在OData Olingo Java处理器中支持Excel MIME类型$format参数?

在Olingo V4 + SpringBoot中处理Excel数据的Java示例

Olingo本身不直接支持Excel格式处理,需要结合Apache POI库来解析/生成Excel文件,以下是两种常见场景的代码示例:

场景1:导出OData实体为Excel格式

自定义处理器处理GET请求,将查询到的实体数据生成Excel文件返回给客户端。

依赖配置

在pom.xml中添加Apache POI依赖:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.5</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.5</version>
</dependency>

自定义集合处理器

继承ODataCollectionProcessor,重写readCollection方法实现Excel导出:

import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.processor.CollectionProcessor;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

// 假设你的业务实体类为Product
public class ExcelCollectionProcessor implements CollectionProcessor {

    private final ProductService productService;

    public ExcelCollectionProcessor(ProductService productService) {
        this.productService = productService;
    }

    @Override
    public void readCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo,
                               ODataSerializer serializer) throws ODataApplicationException {
        String acceptHeader = request.getHeaders().getHeader("Accept");
        // 判断客户端是否请求Excel格式
        if (acceptHeader != null && acceptHeader.contains("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
            try (Workbook workbook = new XSSFWorkbook()) {
                Sheet sheet = workbook.createSheet("Products");
                List<Product> products = productService.getAllProducts();

                // 创建表头
                Row headerRow = sheet.createRow(0);
                headerRow.createCell(0).setCellValue("ID");
                headerRow.createCell(1).setCellValue("商品名称");
                headerRow.createCell(2).setCellValue("价格");

                // 填充实体数据
                int rowNum = 1;
                for (Product product : products) {
                    Row row = sheet.createRow(rowNum++);
                    row.createCell(0).setCellValue(product.getId());
                    row.createCell(1).setCellValue(product.getName());
                    row.createCell(2).setCellValue(product.getPrice());
                }

                // 自动调整列宽
                for (int i = 0; i < 3; i++) {
                    sheet.autoSizeColumn(i);
                }

                // 将Workbook转为字节数组
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                workbook.write(outputStream);
                byte[] excelBytes = outputStream.toByteArray();

                // 设置响应头与响应体
                response.setHeader("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setHeader("Content-Disposition", "attachment; filename=\"Products.xlsx\"");
                response.setContent(excelBytes);
                response.setStatusCode(200);
            } catch (IOException e) {
                throw new ODataApplicationException("生成Excel文件失败", 500, null);
            }
        } else {
            // 非Excel请求,交给默认处理器返回JSON/XML格式
            // defaultCollectionProcessor.readCollection(request, response, uriInfo, serializer);
        }
    }

    // 其他未实现的方法可留空或提供默认实现
}

注册处理器到Olingo服务

在SpringBoot配置类中注册自定义处理器:

import org.apache.olingo.server.api.OlingoModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ODataConfig {

    @Bean
    public OlingoModule olingoModule(ProductService productService) {
        return new OlingoModule() {
            @Override
            public void configure(final OlingoServerBuilder builder) {
                builder.register(new ExcelCollectionProcessor(productService));
                // 注册元数据提供者、其他处理器等必要组件
                // ...
            }
        };
    }
}

场景2:导入Excel数据到OData服务

自定义处理器处理POST请求,解析上传的Excel文件并创建/更新OData实体。

自定义实体处理器

继承ODataEntityProcessor,重写createEntity方法实现Excel解析:

import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.IOException;
import java.io.InputStream;

public class ExcelEntityProcessor implements EntityProcessor {

    private final ProductService productService;

    public ExcelEntityProcessor(ProductService productService) {
        this.productService = productService;
    }

    @Override
    public void createEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException {
        String contentType = request.getHeaders().getHeader("Content-Type");
        // 判断请求体是否为Excel格式
        if (contentType != null && contentType.contains("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
            try (InputStream inputStream = request.getBody();
                 Workbook workbook = new XSSFWorkbook(inputStream)) {
                Sheet sheet = workbook.getSheetAt(0);
                // 跳过表头,从第2行开始读取数据
                for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                    Row row = sheet.getRow(i);
                    if (row == null) continue;

                    // 解析Excel行数据为Product实体
                    Product product = new Product();
                    product.setId((long) row.getCell(0).getNumericCellValue());
                    product.setName(row.getCell(1).getStringCellValue());
                    product.setPrice(row.getCell(2).getNumericCellValue());

                    // 保存实体到数据库
                    productService.saveProduct(product);
                }

                response.setStatusCode(201);
            } catch (IOException e) {
                throw new ODataApplicationException("解析Excel文件失败", 400, null);
            }
        } else {
            // 非Excel格式请求,交给默认处理器处理
            // defaultEntityProcessor.createEntity(request, response, uriInfo);
        }
    }

    // 其他未实现的方法可留空或提供默认实现
}

注意事项

  • 需确保Olingo元数据正确定义了目标实体类型(如Product)。
  • 处理Excel时要注意单元格类型转换,避免类型转换异常。
  • 如需支持老版本.xls格式,可替换为HSSFWorkbook。
  • 处理大文件时建议使用流式解析,避免内存溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 08:47:50