java 基于服务做统一数据导出

1.我们经常需要做数据的导出,但是,不同的业务场景只是数据不同,导出动作却又很多共性,为此,我们可以采用动静分离思想,将动作抽取出来作为一个服务,数据依赖于动作,就能用一套代码处理一些公共的东西了。

2.思路:如果只是将动作作为util,那每个服务都需要依赖该动作,服务与动作有高度的耦合性,我的思路是将动作抽取到基础(公共)服务里,该服务只是做特定的动作,数据从别的服务过来,加工后处理成特定的流,供其他服务调用

3.代码实现:

 

base服务里动作:FileImportExportController.java

import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;

import cn.togeek.service.FileImportExportService;

import java.util.List;
import java.util.Map;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/ftp")
@Api(tags = "统一文件导入导出")
@AllArgsConstructor
public class FileImportExportController {

   private final FileImportExportService fileImportExportService;

   @PostMapping("/export/xls")
   public byte[] exportFile(@RequestBody List<Map> data) throws Exception {
      return fileImportExportService.doExport(data);
   }

   @PostMapping("/import/xls")
   public List<Map> importFile(@RequestBody MultipartFile[] files) throws Exception {
      return fileImportExportService.doImport(files);
   }

}

 

service实现:FileImportExportService.java

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class FileImportExportService {

   public byte[] doExport(List<Map> data) throws IOException
   {
      ExcelWriter writer = ExcelUtil.getWriter();
      writer.write(data);
      IntStream.range(0, data.size()+1).forEach(x -> {
         writer.setRowHeight(x, 30);
      });
      IntStream.range(0, data.get(0).size()).forEach(j -> {
         writer.setColumnWidth(j, 40);
      });
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      writer.getWorkbook().write(outputStream);
      return outputStream.toByteArray();
   }

   public List<Map> doImport(MultipartFile[] files) {
      return Collections.emptyList();
   }
}

 

依赖服务:SpotBaseDataFeign.java(fengin方式调用)

import cn.togeek.common.domain.ElectricityRetailer;
import cn.togeek.common.domain.TradingUnit;
import cn.togeek.common.domain.Unit;
import cn.togeek.common.domain.UnitCost;
import cn.togeek.domain.base.InstalledGenerationCapacityInfo;
import cn.togeek.domain.base.UnitMarginalCost;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.core.io.Resource;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "spot-base-data", url = "${service.spot-base-data.url}", fallbackFactory = SpotBaseDataFeign.ApiBaseDataServiceFallbackFactory.class)
@RequestMapping("/spot-base-data")
public interface SpotBaseDataFeign {
  
   @PostMapping("/ftp/export/xls")
   byte[] exportFile(@RequestBody List<Map<Object,Object>> data);

   @Component
   static class ApiBaseDataServiceFallbackFactory extends FeignFallbackFactory<SpotBaseDataFeign> {
      @Override
      public SpotBaseDataFeign newHandler() {
         return new SpotBaseDataFeign() {

            @Override
            public byte[] exportFile(List<Map<Object,Object>> data) {
               return new byte[0];
            }
         };
      }
   }
}

 

使用:

public void exportMonthlyTargetSummary(YearMonth month) {
      List<Map<Object, Object>> data = this.getMonthlyTargetSummary(month);
      ExportUtil.doExport(spotBaseDataFeign.exportFile(transTargetSummaryToExportFormat(data)),"中标量汇总" + month.toString() + ".xls");
   }

 

util封装:

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class ExportUtil {

   private static OutputStream getResponseOutputStreamWithFileName(String fileName) throws IOException {
      ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
      HttpServletResponse response = attr.getResponse();
      response.setCharacterEncoding("utf-8");
      // 设置编码格式
      response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
      OutputStream outputStream = response.getOutputStream();
      return outputStream;
   }

   public static <T> void doExport(byte[] bytes, String fileName) {
      OutputStream outputStream = null;
      try {
         outputStream = ExportUtil.getResponseOutputStreamWithFileName(fileName);
         outputStream.write(bytes);
         outputStream.flush();
         outputStream.close();
      }
      catch(IOException e) {
         e.printStackTrace();
      }
   }
}

 

 补充:由于项目需要,部分数据需要做合并单元格处理,遂对处理进行升级

import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;

import cn.togeek.service.FileImportExportService;

import java.util.List;
import java.util.Map;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/ftp")
@Api(tags = "统一文件导入导出")
@AllArgsConstructor
public class FileImportExportController {

   private final FileImportExportService fileImportExportService;

   @PostMapping("/export/xls")
   public byte[] exportFile(@RequestBody Map<String,Object> originData) throws Exception {
      return fileImportExportService.doExport(originData);
   }

   @PostMapping("/import/xls")
   public List<Map> importFile(@RequestBody MultipartFile[] files) throws Exception {
      return fileImportExportService.doImport(files);
   }

}

  

service:

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class FileImportExportService {

   public byte[] doExport(Map<String,Object> originData) throws IOException
   {
      List<Object> data = ((List<Object>) originData.get("data"));
      ExcelWriter writer = ExcelUtil.getWriter();
      int currentRow = 0,containerSize = 0;
      if(originData.containsKey("merge")) {
         List<Map> mergeInfo = (List<Map>) originData.get("merge");
         for(Map map : mergeInfo) {
            Integer firstRow = (Integer) map.get("firstRow");
            Integer lastRow = (Integer) map.get("lastRow");
            Integer firstColumn = (Integer) map.get("firstColumn");
            Integer lastColumn = (Integer) map.get("lastColumn");
            Boolean isSetHeaderStyle = (Boolean) map.get("isSetHeaderStyle");
            Object value =  map.get("content");
            if(firstRow == lastRow && firstColumn == lastColumn) {
               writer.writeCellValue(firstColumn,firstRow,value);
            } else {
               //isSetHeaderStyle = isSetHeaderStyle==null?false:isSetHeaderStyle;
               writer.merge(firstRow,lastRow,firstColumn,lastColumn,value,false);
            }
            currentRow = currentRow<lastRow?lastRow:currentRow;
         }
         writer.setCurrentRow(++currentRow);
      }
      if(data.get(0) instanceof List) {
         containerSize = ((List<?>) data.get(0)).size();
         for(Object datum : data) {
            writer.writeRow(((List) datum));
         }
      } else if (data.get(0) instanceof Map) {
         containerSize = ((Map) data.get(0)).size();
         writer.write(data);
      } else {
         throw new IllegalArgumentException("无效果的参数");
      }

      IntStream.range(0, data.size()+currentRow).forEach(x -> {
         writer.setRowHeight(x, 30);
      });
      IntStream.range(0, containerSize).forEach(j -> {
         writer.setColumnWidth(j, 40);
      });
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      writer.getWorkbook().write(outputStream);
      return outputStream.toByteArray();
   }

   public List<Map> doImport(MultipartFile[] files) {
      return Collections.emptyList();
   }
}

 

调用:

import cn.togeek.common.domain.ElectricityRetailer;
import cn.togeek.common.domain.TradingUnit;
import cn.togeek.common.domain.Unit;
import cn.togeek.common.domain.UnitCost;
import cn.togeek.domain.base.InstalledGenerationCapacityInfo;
import cn.togeek.domain.base.UnitMarginalCost;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.core.io.Resource;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "spot-base-data", url = "${service.spot-base-data.url}", fallbackFactory = SpotBaseDataFeign.ApiBaseDataServiceFallbackFactory.class)
@RequestMapping("/spot-base-data")
public interface SpotBaseDataFeign {


   @PostMapping("/ftp/export/xls")
   byte[] exportFile(@RequestBody Map<String,Object> originData);

   @Component
   static class ApiBaseDataServiceFallbackFactory extends FeignFallbackFactory<SpotBaseDataFeign> {
      @Override
      public SpotBaseDataFeign newHandler() {
         return new SpotBaseDataFeign() {

            @Override
            public byte[] exportFile(Map<String,Object> originData) {
               return new byte[0];
            }
         };
      }
   }
}

 

使用:

 public void exportMonthlyTargetSummary(YearMonth month) {
      List<Map<Object, Object>> data = transTargetSummaryToExportFormat(this.getMonthlyTargetSummary(month));
      HashMap<String, Object> originData = new HashMap<>();
      originData.put("data",data.stream().map(x->x.values()).collect(Collectors.toList()));
      fillHeader(originData);
      ExportUtil.doExport(spotBaseDataFeign.exportFile(originData),"中标量汇总" + month.toString() + ".xls");
   }

 private void fillHeader(HashMap<String, Object> data) {
      List<Map> list = new ArrayList<>();
      list.add(new HashMap(){{
         put("firstRow",0);
         put("lastRow",1);
         put("firstColumn",0);
         put("lastColumn",0);
         put("content","日期");
         put("isSetHeaderStyle",true);
      }});
      list.add(new HashMap(){{
         put("firstRow",0);
         put("lastRow",0);
         put("firstColumn",1);
         put("lastColumn",8);
         put("content","广州公司");
         put("isSetHeaderStyle",true);
      }});
      list.add(new HashMap(){{
         put("firstRow",0);
         put("lastRow",0);
         put("firstColumn",9);
         put("lastColumn",16);
         put("content","清远公司");
         put("isSetHeaderStyle",true);
      }});
      list.add(new HashMap(){{
         put("firstRow",0);
         put("lastRow",0);
         put("firstColumn",17);
         put("lastColumn",24);
         put("content","韶关公司");
         put("isSetHeaderStyle",true);
      }});
      list.add(new HashMap(){{
         put("firstRow",0);
         put("lastRow",0);
         put("firstColumn",25);
         put("lastColumn",32);
         put("content","坪石公司");
         put("isSetHeaderStyle",true);
      }});
      list.add(new HashMap(){{
         put("firstRow",0);
         put("lastRow",0);
         put("firstColumn",33);
         put("lastColumn",40);
         put("content","区域合计");
         put("isSetHeaderStyle",true);
      }});
      IntStream.range(1,41).forEach(x->{
         int mode = x % 8;
         String content = "";
         switch(mode) {
            case 0:
               content = "实时偏差电量(万千瓦时)";
               break;
            case 1:
               content = "中长期电量(万千瓦时)";
               break;
            case 2:
               content = "日前中标电量(万千瓦时)";
               break;
            case 3:
               content = "日前现货电量(万千瓦时)";
               break;
            case 4:
               content = "全厂中长期覆盖率";
               break;
            case 5:
               content = "日前全电量加权均价(厘/千瓦时)";
               break;
            case 6:
               content = "实时电量(万千瓦时)";
               break;
            case 7:
               content = "实时全电量加权均价(厘/千瓦时)";
               break;
            default:
               break;
         }
         String finalContent = content;
         list.add(new HashMap(){{
            put("firstRow",1);
            put("lastRow",1);
            put("firstColumn",x);
            put("lastColumn",x);
            put("content", finalContent);
            put("isSetHeaderStyle",true);
         }});
      });
      data.put("merge",list);
   }

 

 

 
 
 
posted @ 2022-05-06 09:48  海的味道  阅读(302)  评论(0编辑  收藏  举报