Spring Boot 数据导入导出与报表生成

Spring Boot 数据导入导出与报表生成

Spring Boot 数据导入导出与报表生成

在这里插入图片描述
24.1 学习目标与重点提示

学习目标:掌握Spring Boot数据导入导出与报表生成的核心概念与使用方法,包括数据导入导出的定义与特点、Spring Boot与数据导入导出的集成、Spring Boot与数据导入导出的配置、Spring Boot与报表生成的基本方法、Spring Boot的实际应用场景,学会在实际开发中处理数据导入导出与报表生成问题。
重点:数据导入导出的定义与特点Spring Boot与数据导入导出的集成Spring Boot与数据导入导出的配置Spring Boot与报表生成的基本方法Spring Boot的实际应用场景

24.2 数据导入导出概述

数据导入导出是Java开发中的重要组件。

24.2.1 数据导入导出的定义

定义:数据导入导出是指将数据从一个系统导入到另一个系统,或从一个系统导出到另一个系统的过程。
作用

  • 实现数据的迁移。
  • 实现数据的备份。
  • 实现数据的共享。

常见的数据导入导出格式

  • CSV:Comma-Separated Values,逗号分隔值格式。
  • Excel:Microsoft Excel格式。
  • JSON:JavaScript Object Notation,JavaScript对象表示法格式。
  • XML:eXtensible Markup Language,可扩展标记语言格式。

✅ 结论:数据导入导出是指将数据从一个系统导入到另一个系统,或从一个系统导出到另一个系统的过程,作用是实现数据的迁移、备份、共享。

24.2.2 数据导入导出的特点

定义:数据导入导出的特点是指数据导入导出的特性。
特点

  • 易用性:数据导入导出提供易用的编程模型。
  • 高效性:数据导入导出提供高效的数据处理。
  • 可扩展性:数据导入导出可以扩展到多个应用程序之间的数据通信。
  • 可靠性:数据导入导出提供可靠的数据传输。

✅ 结论:数据导入导出的特点包括易用性、高效性、可扩展性、可靠性。

24.3 Spring Boot与数据导入导出的集成

Spring Boot与数据导入导出的集成是Java开发中的重要内容。

24.3.1 集成Apache POI的步骤

定义:集成Apache POI的步骤是指使用Spring Boot与Apache POI集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 创建数据访问层。
  4. 创建业务层。
  5. 创建控制器类。
  6. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- Apache POI依赖 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的配置:

# 服务器端口 server.port=8080 # 数据库连接信息 spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # H2数据库控制台 spring.h2.console.enabled=true spring.h2.console.path=/h2-console 

实体类:

importjavax.persistence.*;@Entity@Table(name ="product")publicclassProduct{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateString productId;privateString productName;privatedouble price;privateint sales;publicProduct(){}publicProduct(String productId,String productName,double price,int sales){this.productId = productId;this.productName = productName;this.price = price;this.sales = sales;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetProductId(){return productId;}publicvoidsetProductId(String productId){this.productId = productId;}publicStringgetProductName(){return productName;}publicvoidsetProductName(String productName){this.productName = productName;}publicdoublegetPrice(){return price;}publicvoidsetPrice(double price){this.price = price;}publicintgetSales(){return sales;}publicvoidsetSales(int sales){this.sales = sales;}@OverridepublicStringtoString(){return"Product{"+"id="+ id +",+ productId +'\''+",+ productName +'\''+", price="+ price +", sales="+ sales +'}';}}

Repository接口:

importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;@RepositorypublicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{}

Service类:

importorg.apache.poi.ss.usermodel.*;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importorg.springframework.web.multipart.MultipartFile;importjava.io.ByteArrayOutputStream;importjava.io.IOException;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;@ServicepublicclassProductService{@AutowiredprivateProductRepository productRepository;@TransactionalpublicvoidimportProducts(MultipartFile file)throwsIOException{List<Product> products =newArrayList<>();Workbook workbook =newXSSFWorkbook(file.getInputStream());Sheet sheet = workbook.getSheetAt(0);Iterator<Row> iterator = sheet.iterator();if(iterator.hasNext()){ iterator.next();// 跳过标题行}while(iterator.hasNext()){Row currentRow = iterator.next();Product product =newProduct(); product.setProductId(currentRow.getCell(0).getStringCellValue()); product.setProductName(currentRow.getCell(1).getStringCellValue()); product.setPrice(currentRow.getCell(2).getNumericCellValue()); product.setSales((int) currentRow.getCell(3).getNumericCellValue()); products.add(product);} productRepository.saveAll(products); workbook.close();}@Transactional(readOnly =true)publicbyte[]exportProducts()throwsIOException{List<Product> products = productRepository.findAll();Workbook workbook =newXSSFWorkbook();Sheet sheet = workbook.createSheet("Products");Row headerRow = sheet.createRow(0);Cell headerCell0 = headerRow.createCell(0); headerCell0.setCellValue("Product ID");Cell headerCell1 = headerRow.createCell(1); headerCell1.setCellValue("Product Name");Cell headerCell2 = headerRow.createCell(2); headerCell2.setCellValue("Price");Cell headerCell3 = headerRow.createCell(3); headerCell3.setCellValue("Sales");int rowNum =1;for(Product product : products){Row row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(product.getProductId()); row.createCell(1).setCellValue(product.getProductName()); row.createCell(2).setCellValue(product.getPrice()); row.createCell(3).setCellValue(product.getSales());}for(int i =0; i <4; i++){ sheet.autoSizeColumn(i);}ByteArrayOutputStream outputStream =newByteArrayOutputStream(); workbook.write(outputStream); workbook.close();return outputStream.toByteArray();}@TransactionalpublicProductaddProduct(Product product){return productRepository.save(product);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.HttpHeaders;importorg.springframework.http.MediaType;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjava.io.IOException;importjava.util.List;@RestController@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductService productService;@PostMapping("/import")publicResponseEntity<String>importProducts(@RequestParam("file")MultipartFile file){try{ productService.importProducts(file);returnResponseEntity.ok("数据导入成功");}catch(IOException e){ e.printStackTrace();returnResponseEntity.status(500).body("数据导入失败:"+ e.getMessage());}}@GetMapping("/export")publicResponseEntity<byte[]>exportProducts(){try{byte[] bytes = productService.exportProducts();HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")); headers.setContentDispositionFormData("attachment","products.xlsx"); headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");returnResponseEntity.ok().headers(headers).body(bytes);}catch(IOException e){ e.printStackTrace();returnResponseEntity.status(500).body(null);}}@PostMapping("/")publicProductaddProduct(@RequestBodyProduct product){return productService.addProduct(product);}@GetMapping("/")publicList<Product>getAllProducts(){return productService.getAllProducts();}}

应用启动类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassProductApplication{publicstaticvoidmain(String[] args){SpringApplication.run(ProductApplication.class, args);}@AutowiredprivateProductService productService;publicvoidrun(String... args){// 初始化数据 productService.addProduct(newProduct("P001","手机",1000.0,100)); productService.addProduct(newProduct("P002","电脑",5000.0,50)); productService.addProduct(newProduct("P003","电视",3000.0,80)); productService.addProduct(newProduct("P004","手表",500.0,200)); productService.addProduct(newProduct("P005","耳机",300.0,150));}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importorg.springframework.http.HttpEntity;importorg.springframework.http.HttpHeaders;importorg.springframework.http.HttpMethod;importorg.springframework.http.ResponseEntity;importorg.springframework.util.LinkedMultiValueMap;importorg.springframework.util.MultiValueMap;importorg.springframework.web.multipart.MultipartFile;importorg.springframework.web.multipart.commons.CommonsMultipartFile;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStream;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);Product savedProduct = restTemplate.postForObject("http://localhost:"+ port +"/api/products/", product,Product.class);assertThat(savedProduct).isNotNull();assertThat(savedProduct.getProductId()).isEqualTo("P006");}@TestvoidtestGetAllProducts(){List<Product> products = restTemplate.getForObject("http://localhost:"+ port +"/api/products/",List.class);assertThat(products).isNotNull();assertThat(products.size()).isGreaterThanOrEqualTo(5);}@TestvoidtestImportProducts()throwsIOException{File file =newFile("src/test/resources/products.xlsx");InputStream inputStream =newFileInputStream(file);MultipartFile multipartFile =newCommonsMultipartFile(inputStream);HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA);MultiValueMap<String,Object> body =newLinkedMultiValueMap<>(); body.add("file", multipartFile);HttpEntity<MultiValueMap<String,Object>> requestEntity =newHttpEntity<>(body, headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/api/products/import",HttpMethod.POST, requestEntity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("数据导入成功");}@TestvoidtestExportProducts(){ResponseEntity<byte[]> response = restTemplate.getForEntity("http://localhost:"+ port +"/api/products/export",byte[].class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).isNotNull();assertThat(response.getBody().length).isGreaterThan(0);}}

✅ 结论:集成Apache POI的步骤包括创建Spring Boot项目、添加所需的依赖、创建数据访问层、创建业务层、创建控制器类、测试应用。

24.4 Spring Boot与报表生成的基本方法

Spring Boot与报表生成的基本方法包括使用Apache POI、使用JasperReports、使用Excel模板。

24.4.1 使用JasperReports

定义:使用JasperReports是指Spring Boot与报表生成集成的基本方法之一。
作用

  • 实现报表生成。
  • 提高应用程序的性能。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- JasperReports依赖 --><dependency><groupId>net.sf.jasperreports</groupId><artifactId>jasperreports</artifactId><version>6.17.0</version></dependency><dependency><groupId>net.sf.jasperreports</groupId><artifactId>jasperreports-fonts</artifactId><version>6.17.0</version></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

Service类:

importnet.sf.jasperreports.engine.*;importnet.sf.jasperreports.engine.data.JRBeanCollectionDataSource;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.io.ByteArrayOutputStream;importjava.io.InputStream;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@ServicepublicclassReportService{@AutowiredprivateProductRepository productRepository;@Transactional(readOnly =true)publicbyte[]generateProductReport()throwsJRException{List<Product> products = productRepository.findAll();// 加载Jasper模板InputStream templateStream =getClass().getResourceAsStream("/reports/product-report.jasper");JasperReport jasperReport =(JasperReport)JRLoader.loadObject(templateStream);// 设置参数Map<String,Object> parameters =newHashMap<>(); parameters.put("Title","产品销售报表");// 设置数据源JRBeanCollectionDataSource dataSource =newJRBeanCollectionDataSource(products);// 生成报表JasperPrint jasperPrint =JasperFillManager.fillReport(jasperReport, parameters, dataSource);// 导出报表为PDFByteArrayOutputStream outputStream =newByteArrayOutputStream();JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);return outputStream.toByteArray();}}

控制器类:

importnet.sf.jasperreports.engine.JRException;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.HttpHeaders;importorg.springframework.http.MediaType;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjava.io.IOException;importjava.util.List;@RestController@RequestMapping("/api/products")publicclassProductController{@AutowiredprivateProductService productService;@AutowiredprivateReportService reportService;@GetMapping("/report")publicResponseEntity<byte[]>generateProductReport(){try{byte[] bytes = reportService.generateProductReport();HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.parseMediaType("application/pdf")); headers.setContentDispositionFormData("attachment","product-report.pdf"); headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");returnResponseEntity.ok().headers(headers).body(bytes);}catch(JRException e){ e.printStackTrace();returnResponseEntity.status(500).body(null);}}@PostMapping("/import")publicResponseEntity<String>importProducts(@RequestParam("file")MultipartFile file){try{ productService.importProducts(file);returnResponseEntity.ok("数据导入成功");}catch(IOException e){ e.printStackTrace();returnResponseEntity.status(500).body("数据导入失败:"+ e.getMessage());}}@GetMapping("/export")publicResponseEntity<byte[]>exportProducts(){try{byte[] bytes = productService.exportProducts();HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")); headers.setContentDispositionFormData("attachment","products.xlsx"); headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");returnResponseEntity.ok().headers(headers).body(bytes);}catch(IOException e){ e.printStackTrace();returnResponseEntity.status(500).body(null);}}@PostMapping("/")publicProductaddProduct(@RequestBodyProduct product){return productService.addProduct(product);}@GetMapping("/")publicList<Product>getAllProducts(){return productService.getAllProducts();}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importorg.springframework.http.HttpEntity;importorg.springframework.http.HttpHeaders;importorg.springframework.http.HttpMethod;importorg.springframework.http.ResponseEntity;importorg.springframework.util.LinkedMultiValueMap;importorg.springframework.util.MultiValueMap;importorg.springframework.web.multipart.MultipartFile;importorg.springframework.web.multipart.commons.CommonsMultipartFile;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStream;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);Product savedProduct = restTemplate.postForObject("http://localhost:"+ port +"/api/products/", product,Product.class);assertThat(savedProduct).isNotNull();assertThat(savedProduct.getProductId()).isEqualTo("P006");}@TestvoidtestGetAllProducts(){List<Product> products = restTemplate.getForObject("http://localhost:"+ port +"/api/products/",List.class);assertThat(products).isNotNull();assertThat(products.size()).isGreaterThanOrEqualTo(5);}@TestvoidtestImportProducts()throwsIOException{File file =newFile("src/test/resources/products.xlsx");InputStream inputStream =newFileInputStream(file);MultipartFile multipartFile =newCommonsMultipartFile(inputStream);HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA);MultiValueMap<String,Object> body =newLinkedMultiValueMap<>(); body.add("file", multipartFile);HttpEntity<MultiValueMap<String,Object>> requestEntity =newHttpEntity<>(body, headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/api/products/import",HttpMethod.POST, requestEntity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("数据导入成功");}@TestvoidtestExportProducts(){ResponseEntity<byte[]> response = restTemplate.getForEntity("http://localhost:"+ port +"/api/products/export",byte[].class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).isNotNull();assertThat(response.getBody().length).isGreaterThan(0);}@TestvoidtestGenerateProductReport(){ResponseEntity<byte[]> response = restTemplate.getForEntity("http://localhost:"+ port +"/api/products/report",byte[].class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).isNotNull();assertThat(response.getBody().length).isGreaterThan(0);}}

✅ 结论:使用JasperReports是指Spring Boot与报表生成集成的基本方法之一,作用是实现报表生成、提高应用程序的性能。

24.5 Spring Boot的实际应用场景

在实际开发中,Spring Boot数据导入导出与报表生成的应用场景非常广泛,如:

  • 实现产品信息的导入导出。
  • 实现用户信息的导入导出。
  • 实现订单信息的导入导出。
  • 实现产品销售报表的生成。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassProductApplication{publicstaticvoidmain(String[] args){SpringApplication.run(ProductApplication.class, args);}@AutowiredprivateProductService productService;publicvoidrun(String... args){// 初始化数据 productService.addProduct(newProduct("P001","手机",1000.0,100)); productService.addProduct(newProduct("P002","电脑",5000.0,50)); productService.addProduct(newProduct("P003","电视",3000.0,80)); productService.addProduct(newProduct("P004","手表",500.0,200)); productService.addProduct(newProduct("P005","耳机",300.0,150));}}@ServiceclassProductService{@AutowiredprivateProductRepository productRepository;@TransactionalpublicvoidimportProducts(MultipartFile file)throwsIOException{List<Product> products =newArrayList<>();Workbook workbook =newXSSFWorkbook(file.getInputStream());Sheet sheet = workbook.getSheetAt(0);Iterator<Row> iterator = sheet.iterator();if(iterator.hasNext()){ iterator.next();// 跳过标题行}while(iterator.hasNext()){Row currentRow = iterator.next();Product product =newProduct(); product.setProductId(currentRow.getCell(0).getStringCellValue()); product.setProductName(currentRow.getCell(1).getStringCellValue()); product.setPrice(currentRow.getCell(2).getNumericCellValue()); product.setSales((int) currentRow.getCell(3).getNumericCellValue()); products.add(product);} productRepository.saveAll(products); workbook.close();}@Transactional(readOnly =true)publicbyte[]exportProducts()throwsIOException{List<Product> products = productRepository.findAll();Workbook workbook =newXSSFWorkbook();Sheet sheet = workbook.createSheet("Products");Row headerRow = sheet.createRow(0);Cell headerCell0 = headerRow.createCell(0); headerCell0.setCellValue("Product ID");Cell headerCell1 = headerRow.createCell(1); headerCell1.setCellValue("Product Name");Cell headerCell2 = headerRow.createCell(2); headerCell2.setCellValue("Price");Cell headerCell3 = headerRow.createCell(3); headerCell3.setCellValue("Sales");int rowNum =1;for(Product product : products){Row row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(product.getProductId()); row.createCell(1).setCellValue(product.getProductName()); row.createCell(2).setCellValue(product.getPrice()); row.createCell(3).setCellValue(product.getSales());}for(int i =0; i <4; i++){ sheet.autoSizeColumn(i);}ByteArrayOutputStream outputStream =newByteArrayOutputStream(); workbook.write(outputStream); workbook.close();return outputStream.toByteArray();}@TransactionalpublicProductaddProduct(Product product){return productRepository.save(product);}@Transactional(readOnly =true)publicList<Product>getAllProducts(){return productRepository.findAll();}}@RestController@RequestMapping("/api/products")classProductController{@AutowiredprivateProductService productService;@AutowiredprivateReportService reportService;@GetMapping("/report")publicResponseEntity<byte[]>generateProductReport(){try{byte[] bytes = reportService.generateProductReport();HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.parseMediaType("application/pdf")); headers.setContentDispositionFormData("attachment","product-report.pdf"); headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");returnResponseEntity.ok().headers(headers).body(bytes);}catch(JRException e){ e.printStackTrace();returnResponseEntity.status(500).body(null);}}@PostMapping("/import")publicResponseEntity<String>importProducts(@RequestParam("file")MultipartFile file){try{ productService.importProducts(file);returnResponseEntity.ok("数据导入成功");}catch(IOException e){ e.printStackTrace();returnResponseEntity.status(500).body("数据导入失败:"+ e.getMessage());}}@GetMapping("/export")publicResponseEntity<byte[]>exportProducts(){try{byte[] bytes = productService.exportProducts();HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")); headers.setContentDispositionFormData("attachment","products.xlsx"); headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");returnResponseEntity.ok().headers(headers).body(bytes);}catch(IOException e){ e.printStackTrace();returnResponseEntity.status(500).body(null);}}@PostMapping("/")publicProductaddProduct(@RequestBodyProduct product){return productService.addProduct(product);}@GetMapping("/")publicList<Product>getAllProducts(){return productService.getAllProducts();}}// 测试类@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classProductApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestAddProduct(){Product product =newProduct("P006","平板",2000.0,70);Product savedProduct = restTemplate.postForObject("http://localhost:"+ port +"/api/products/", product,Product.class);assertThat(savedProduct).isNotNull();assertThat(savedProduct.getProductId()).isEqualTo("P006");}@TestvoidtestGetAllProducts(){List<Product> products = restTemplate.getForObject("http://localhost:"+ port +"/api/products/",List.class);assertThat(products).isNotNull();assertThat(products.size()).isGreaterThanOrEqualTo(5);}@TestvoidtestImportProducts()throwsIOException{File file =newFile("src/test/resources/products.xlsx");InputStream inputStream =newFileInputStream(file);MultipartFile multipartFile =newCommonsMultipartFile(inputStream);HttpHeaders headers =newHttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA);MultiValueMap<String,Object> body =newLinkedMultiValueMap<>(); body.add("file", multipartFile);HttpEntity<MultiValueMap<String,Object>> requestEntity =newHttpEntity<>(body, headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/api/products/import",HttpMethod.POST, requestEntity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("数据导入成功");}@TestvoidtestExportProducts(){ResponseEntity<byte[]> response = restTemplate.getForEntity("http://localhost:"+ port +"/api/products/export",byte[].class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).isNotNull();assertThat(response.getBody().length).isGreaterThan(0);}@TestvoidtestGenerateProductReport(){ResponseEntity<byte[]> response = restTemplate.getForEntity("http://localhost:"+ port +"/api/products/report",byte[].class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).isNotNull();assertThat(response.getBody().length).isGreaterThan(0);}}

输出结果

  • 访问http://localhost:8080/api/products/report:下载产品销售报表(PDF格式)。
  • 访问http://localhost:8080/api/products/import:上传产品信息Excel文件,导入数据。
  • 访问http://localhost:8080/api/products/export:下载产品信息Excel文件。

✅ 结论:在实际开发中,Spring Boot数据导入导出与报表生成的应用场景非常广泛,需要根据实际问题选择合适的导入导出格式和报表生成工具。

总结

本章我们学习了Spring Boot数据导入导出与报表生成,包括数据导入导出的定义与特点、Spring Boot与数据导入导出的集成、Spring Boot与数据导入导出的配置、Spring Boot与报表生成的基本方法、Spring Boot的实际应用场景,学会了在实际开发中处理数据导入导出与报表生成问题。其中,数据导入导出的定义与特点、Spring Boot与数据导入导出的集成、Spring Boot与数据导入导出的配置、Spring Boot与报表生成的基本方法、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。

Read more

Flutter 三方库 date_utils 的鸿蒙化适配指南 - 实现精准的业务日期计算、支持农历转换与分布式考勤场景下的时间逻辑编排实战

Flutter 三方库 date_utils 的鸿蒙化适配指南 - 实现精准的业务日期计算、支持农历转换与分布式考勤场景下的时间逻辑编排实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 date_utils 的鸿蒙化适配指南 - 实现精准的业务日期计算、支持农历转换与分布式考勤场景下的时间逻辑编排实战 前言 在进行 Flutter for OpenHarmony 的企业级 OA、日历或金融类应用开发时,原生的 DateTime 类虽然好用,但在处理复杂的业务日期逻辑(如:获取上月最后一天、计算两个日期间的工作日、农历转换等)时,往往需要编写大量繁琐的代码。date_utils 是一个功能完备的日期增强工具库。本文将介绍如何在鸿蒙端利用该库构建极致精准、业务友好的时间处理体系。 一、原直观解析 / 概念介绍 1.1 基础原理 date_utils 通过对 Dart 原生 DateTime 对象的封装和算法扩展,提供了一系列声明式的

By Ne0inhk
Node.js 下载安装与环境配置全流程(保姆级详解)| 图文详解,快速上手

Node.js 下载安装与环境配置全流程(保姆级详解)| 图文详解,快速上手

前言 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。它采用事件驱动、非阻塞式 I/O 模型,使得其在处理高并发任务时具有极高的效率。得益于这样的设计,Node.js 在 Web 开发、实时应用、微服务架构等场景中被广泛使用。 除了高性能,Node.js 还配备了功能强大的包管理器 npm(Node Package Manager)。npm 提供了丰富的开源库和工具,开发者可以轻松地安装、管理和共享代码,使开发过程更加高效。 一、下载安装 Node.js 1.下载安装包: * 访问 Node.js 官方下载页面。 通常页面会显示两个版本: 1. 长期维护版本(推荐)

By Ne0inhk
Spring Cloud与Dubbo架构哲学对决

Spring Cloud与Dubbo架构哲学对决

目录 摘要 🎯 开篇:别被"微服务"这个词忽悠了 🏗️ 架构哲学:两种完全不同的"世界观" 🎨 Spring Cloud:生态为王的全家桶 ⚡ Dubbo:专精RPC的特种兵 📊 性能对决:数据不说谎 🔧 核心原理:扒开看看里面啥样 🎯 Spring Cloud 2025.1.0的"虚拟线程革命" ⚡ Dubbo 3.0的Triple协议:对标gRPC 🚀 实战:从零搭建混合微服务架构 🏢 场景:电商平台(日均订单千万级) 📝 分步骤实现 步骤1:搭建Spring Cloud Gateway 步骤2:Dubbo核心服务实现 步骤3:Spring Cloud外围服务 步骤4:

By Ne0inhk
搭建前端开发环境标准步骤 安装 nvm Node.js pnpm 配置环境变量

搭建前端开发环境标准步骤 安装 nvm Node.js pnpm 配置环境变量

搭建前端开发环境标准步骤 安装 nvm Node.js pnpm 配置环境变量 1、下载 nvm * 国内下载: https://nvm.uihtm.com/ * 注意安装目录不要带空格 2、下载 Node.js nvm list available 查看nodejs有哪些版本 nvm install10.13.0 下载10.13.0版本 nvm use 10.13.0 切换到10.13.0版本 nvm list 查看已安装版本 3、配置 Node.js 3.1、设置淘宝镜像 设置淘宝镜像

By Ne0inhk