springboot 导出数据到 excel
泛域名ssl证书 239元1年送1个月、单域名39元1年,Sectigo(原Comodo证书)全球可信证书,强大的兼容性,高度安全性,如有问题7天内可退、可开发票
加微信VX 18718058521 备注SSL证书
【腾讯云】2核2G4M云服务器新老同享99元/年,续费同价
问题来源:
前一段时间公司的项目有个导出数据的需求,要求能够实现全部导出也可以多选批量导出(虽然不是我负责的,我自己研究了研究),我们的项目是xboot前后端分离系统,后端的核心为SpringBoot 2.2.6.RELEASE,因此今天我主要讲述后端的操作实现,为了简化需求,我将需要导出的十几个字段简化为5个字段,导出的样式模板如下:
实现步骤:
打开一个你平时练习使用的springboot的demo,开始按照以下步骤加入代码进行操作。
1.添加maven依赖
1 2 3 4 5 6 | <!--Excel--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version> 3.11 </version> </dependency> |
poi-ooxml是一个excel表格的操作工具包,处理的单页数据量也是百万级别的,因此我们选择的是poi-ooxml.
2.编写excel工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.List; public class ExcelUtil { /** * 用户信息导出类 * @param response 响应 * @param fileName 文件名 * @param columnList 每列的标题名 * @param dataList 导出的数据 */ public static void uploadExcelAboutUser(HttpServletResponse response,String fileName,List<String> columnList,<br>List<List<String>> dataList){ //声明输出流 OutputStream os = null ; //设置响应头 setResponseHeader(response,fileName); try { //获取输出流 os = response.getOutputStream(); //内存中保留1000条数据,以免内存溢出,其余写入硬盘 SXSSFWorkbook wb = new SXSSFWorkbook( 1000 ); //获取该工作区的第一个sheet Sheet sheet1 = wb.createSheet( "sheet1" ); int excelRow = 0 ; //创建标题行 Row titleRow = sheet1.createRow(excelRow++); for ( int i = 0 ;i<columnList.size();i++){ //创建该行下的每一列,并写入标题数据 Cell cell = titleRow.createCell(i); cell.setCellValue(columnList.get(i)); } //设置内容行 if (dataList!= null && dataList.size()> 0 ){ //序号是从1开始的 int count = 1 ; //外层for循环创建行 for ( int i = 0 ;i<dataList.size();i++){ Row dataRow = sheet1.createRow(excelRow++); //内层for循环创建每行对应的列,并赋值 for ( int j = - 1 ;j<dataList.get( 0 ).size();j++){ //由于多了一列序号列所以内层循环从-1开始 Cell cell = dataRow.createCell(j+ 1 ); if (j==- 1 ){ //第一列是序号列,不是在数据库中读取的数据,因此手动递增赋值 cell.setCellValue(count++); } else { //其余列是数据列,将数据库中读取到的数据依次赋值 cell.setCellValue(dataList.get(i).get(j)); } } } } //将整理好的excel数据写入流中 wb.write(os); } catch (IOException e) { e.printStackTrace(); } finally { try { // 关闭输出流 if (os != null ) { os.close(); } } catch (IOException e) { e.printStackTrace(); } } } /* 设置浏览器下载响应头 */ private static void setResponseHeader(HttpServletResponse response, String fileName) { try { try { fileName = new String(fileName.getBytes(), "ISO8859-1" ); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } response.setContentType( "application/octet-stream;charset=UTF-8" ); response.setHeader( "Content-Disposition" , "attachment;filename=" + fileName); response.addHeader( "Pargam" , "no-cache" ); response.addHeader( "Cache-Control" , "no-cache" ); } catch (Exception ex) { ex.printStackTrace(); } } } |
网上的excel的工具类有很多,但很多并不是你复制过来就能直接使用的,因此需要我们深究其原理,这样可以应对不同的场景写出属于我们自己的合适的代码,这里就不一一解释了,代码中注释加的很清楚,有不懂的可以留言评论。
3.编写controller,service,serviceImpl,dao,entity
3.1 entity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.hibernate.annotations.Where; import javax.persistence.*; import java.math.BigDecimal; @Data @Entity @Where (clause = "del_flag = 0" ) @Table (name = "t_scf_item_data" ) public class ItemData{ private static final long serialVersionUID = 1L; @Id @TableId @ApiModelProperty (value = "唯一标识" ) private String id = String.valueOf(SnowFlakeUtil.getFlowIdInstance().nextId()); @ApiModelProperty (value = "创建者" ) @CreatedBy private String createBy; @CreatedDate @JsonFormat (timezone = "GMT+8" , pattern = "yyyy-MM-dd HH:mm:ss" ) @DateTimeFormat (pattern = "yyyy-MM-dd HH:mm:ss" ) @ApiModelProperty (value = "创建时间" ) private Date createTime; @ApiModelProperty (value = "项目编号" ) private String itemNo; @ApiModelProperty (value = "项目名称" ) private String itemName; @ApiModelProperty (value = "删除标志 默认0" ) private Integer delFlag = 0 ; } |
3.2 dao
1 2 3 4 5 6 7 8 9 10 11 12 | import cn.exrick.xboot.modules.item.entity.ItemData; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface ItemDataDao{ @Query (value = "select a.item_no,a.item_name,concat(a.create_time),a.create_by from t_scf_item_data a where a.del_flag = 0 limit 5" ,nativeQuery = true ) List<List<String>> findAllObject(); @Query (value = "select a.item_no,a.item_name,concat(a.create_time),a.create_by from t_scf_item_data a where a.del_flag = 0 and a.id in ?1 limit 5" ,nativeQuery = true ) List<List<String>> findByIds(List<String> idList); } |
3.3 service
1 2 3 4 5 6 | import javax.servlet.http.HttpServletResponse; import java.util.List; public interface TestService { void exportExcel(List<String> idList, HttpServletResponse response); } |
3.4 serviceImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import cn.exrick.xboot.common.utils.ExcelUtil; import cn.exrick.xboot.modules.item.dao.ItemDataDao; import cn.exrick.xboot.modules.item.service.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Transactional @Service public class TestServiceImpl implements TestService { @Autowired private ItemDataDao itemDataDao; @Override public void exportExcel(List<String> idList, HttpServletResponse response) { List<List<String>> dataList = new ArrayList<>(); if (idList == null || idList.size() == 0 ){ dataList = itemDataDao.findAllObject(); } else { dataList = itemDataDao.findByIds(idList); } List<String> titleList = Arrays.asList( "序号" , "项目编码" , "项目名称" , "创建时间" , "创建人" ); ExcelUtil.uploadExcelAboutUser(response, "apply.xlsx" ,titleList,dataList); } } |
3.5 controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import cn.exrick.xboot.modules.item.service.TestService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; @Slf4j @RestController @RequestMapping ( "/test" ) public class TestController { @Autowired private TestService testService; @RequestMapping (value = "/exportExcel" , method = RequestMethod.POST) @ApiOperation (value = "导出excel" ,produces= "application/octet-stream" ) public void exportCorpLoanDemand( @RequestBody Map<String,List<String>> map, HttpServletResponse response){ ; log.info( "测试:{}" ,map); testService.exportExcel(map.get( "list" ),response); } } |
4.测试
测试的话可以使用swagger或者postman,甚至你前端技术足够ok的话也可以写个简单的页面进行测试,我是用的是swaager进行的测试,下面就是我测试的结果了:
如果你觉得这篇博客有用,请点个赞再走吧。