如何在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
相关产品推荐
相关产品推荐

