HK仅輝 发表于 2022-2-21 13:23

java 使用线程把数据库导出为excel

本帖最后由 HK仅輝 于 2022-2-21 13:43 编辑

这是一个demo,内有不足请谅解


这个demo的主题是 使用EasyExcel把数据库导出为excel,多少条为一个excel文件,并把这些文件打包到一个固定位置,然后下载这个包文件
目前各种参数都是写死的,使用的是 生产消费者模式在一个队列中放数据,取数据

放一下关键代码
启动项目时启动一个线程
@Component//被spring容器管理
public class MyApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
      System.out.println("-------------->" + "项目启动,now=" + new Date());
      ExcelThread.startExcelThread();
    }
}
这是一个全局的阻塞队列
public class QueueUtil {
    public static BlockingQueue<Object> queue = new LinkedBlockingQueue<>();

    public static Object get() throws Exception{
//      return queue.poll(2, TimeUnit.SECONDS); //不阻塞
      return queue.take(); //阻塞
    }

    public static void put(Object obj) throws Exception{
      queue.put(obj);
    }
}

这是Controller   中的导出方法,传一个表名进来,条件可选

    @RequestMapping(value = {"/export/{tableName}"})
    public void export(@PathVariable String tableName ,String name){
//      System.out.println(tableName+"---"+name.length());user---0
      if (name.length()==0){
            service.exportZIP(tableName);
      }else {
            service.exportZIP(tableName, name);
      }
    }

这是Service这里往队列中存入数据

    public void exportZIP(String tableName){
      try {
            QueueUtil.put(tableName);
      }catch (Exception e){
            e.printStackTrace();
            System.out.println("存入数据失败");
      }

    }
    public void exportZIP(String tableName,String name){
      try {
            QueueUtil.put(tableName+":"+name);
      }catch (Exception e){
            e.printStackTrace();
            System.out.println("存入数据失败");
      }
    }

线程类在这把队列中的数据取出来
public class ExcelThread extends Thread{
    private static String PATH ="/file/";
    private static String ExcelName = "用户信息表";
    private static String TYPE = ".xlsx";
    //    @Value("${zip.name}")
    private static String ZIP_NAME = "用户信息";
    private static int SIZE = 5000 ;

    private BlockingQueue queue = QueueUtil.queue;
    public static ExcelThread excelThread = null;

    private FilesService filesservice = (FilesService) ApplicationContextUtil.getBean("filesServiceImpl");

    public static void startExcelThread(){
      if (excelThread==null){
            excelThread = new ExcelThread();
      }
      excelThread.start();
    }

    @Override
    public void run() {
      try {
            while (true) {
                String str = (String) QueueUtil.get(); //《============
                String[] split = str.split(":");
                zip(split);
            }
      } catch (Exception e) {
            e.printStackTrace();
      }
    }

    public void zip(String[] str) {
      OutputStream outputStream;
      ZipOutputStream zipOutputStream;
      Service service = (Service) ApplicationContextUtil.getBean(str+"ServiceImpl");
      long date = System.currentTimeMillis();
      ZIP_NAME += date;
      String path = System.getProperty("user.dir") + PATH + ZIP_NAME+".zip";
      filesservice.alter();
      int id = filesservice.save(new Files(ZIP_NAME,new Date(date)));
      try {
            outputStream = new FileOutputStream(path);
            zipOutputStream = new ZipOutputStream(outputStream);
            int count = 0;
            if (str.length>1){
                count = service.count(str);
            }else {
                count = service.count();
            }
            count = count/SIZE+(count%SIZE == 0 ?0:1);
            for (Integer i = 0; i < count; i++) {
                byte[] buf = new byte;

                List<User> userList;
                if (str.length>1){
                  userList = service.selectPage(i+1,5000,str);
                }else {
                  userList = service.selectPage(i+1,5000).getRecords();
                }

                byte[] content = new FileUtil().excelTableStream(userList).toByteArray(); //返回一个excel文件
                ByteArrayInputStream is = new ByteArrayInputStream(content);
                BufferedInputStream bis = new BufferedInputStream(is);

                zipOutputStream.putNextEntry(new ZipEntry(ExcelName+(i+1)+TYPE)); //压缩文件条目

                int len;
                while ((len = bis.read(buf)) > 0) {
                  zipOutputStream.write(buf, 0, len);
                }

                zipOutputStream.closeEntry();
                bis.close();
                is.close();

                zipOutputStream.flush();
                System.out.println(ExcelName+(i+1)+TYPE+"导出完成");
            }

            zipOutputStream.close();
            outputStream.close();

      } catch (Exception e) {
            e.printStackTrace();
      }finally {
         filesservice.updateState(id,PATH+ZIP_NAME+".zip");
      }
    }


    public static void main(String[] args) {
            Date now = new Date(); // 创建一个Date对象,获取当前时间
            // 指定格式化格式
            SimpleDateFormat f = new SimpleDateFormat("yyyy年MM月dd日 HH点mm分ss秒");
            System.out.println(f.format(now)); // 将当前时间袼式化为指定的格式
    }
}

把一个结果集生产一个excel
    public ByteArrayOutputStream excelTableStream(List<User> userList) {
      try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            EasyExcel.write(byteArrayOutputStream, User.class)
                  //.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) 自动列宽数字不起作用
                  .sheet("用户信息")
                  .doWrite(() -> {
                        // 查询数据
                        return userList;
                  });
            return byteArrayOutputStream;
      } catch (Exception e) {
            e.printStackTrace();
      }
      return null;
    }

先上效果图,在列表页面点击导出按钮,然后在一个文件表中添加一条数据,查看导出状态,完成后有一个下载地址

HK仅輝 发表于 2022-2-21 16:53

资料终结者 发表于 2022-2-21 15:45
学习一下,easyexcel好用还是poi好用

我也是学习,easyexcel比较小,没有poi全面,看你在什么地方用,

Davon 发表于 2022-2-21 15:04

6666我之前搞了个输出mysql数据库文档的,支持word、md、html格式

资料终结者 发表于 2022-2-21 15:45

学习一下,easyexcel好用还是poi好用

xiaoxiaohei1315 发表于 2022-4-11 22:19

学习一下,拿走了

freverlve 发表于 2022-10-29 10:01

666后期拿来用一下

jzx111 发表于 2022-11-8 11:12

界面是不是自己写的

chenxw138 发表于 2023-2-11 21:59

谢谢谢谢谢谢谢谢谢谢谢谢谢谢

adca 发表于 2023-3-24 07:56

学习一下,感谢分享

wangyou186 发表于 2023-6-25 08:58

Mark,留个脚印
页: [1] 2
查看完整版本: java 使用线程把数据库导出为excel