头图

模板文件云存储管理 Sisyphus通过easyExcel实现模板文件的上传和下载,OSS云存储平台存储模板文件,对应的文件名存储在DUCC配置中心,技术架构如下图所示。
文件模板化管理系统.png

核心逻辑

条件结构流程图.png

技术组件

EasyExcel

简介

EasyExcel是一个基于Java的简单、省内存的读写Excel的阿里巴巴开源项目。在尽可能节约内存的情况下支持读写百M的Excel,Github:https://github.com/alibaba/easyexcelhttps://github.com/liurenjin/easypoi

更少的内存占用

easyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。通过一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。

底层源码

easyexcel-alibaba.png

简单使用

实体类

@Data
public class Hero {
    @ExcelProperty(value={"第一列"})
    private int id;
    @ExcelProperty(value={"第二列"})
    private String name;

}

监听类 HeroListener

public class HeroListener extends AnalysisEventListener<Hero> {

    Logger logger = LoggerFactory.getLogger(HeroListener.class);

    //每次读取100条数据就进行保存操作
    private static final int BATCH_COUNT = 100;
    //由于每次读都是新new UserInfoDataListener的,所以这个list不会存在线程安全问题
    List<Hero> list = new ArrayList<>();

    //这个组件是Spring中的组件,这边推荐两种方法注入这个组件
    //第一种就是提供一个UserInfoDataListener的构造方法,这个方法提供一个参数是UserInfoDataListener类型
    //另外一种方法就是将 UserInfoDataListener 这个类定义成 UserService 实现类的内部类(推荐这种方式)
    //private UserService userService;

    @Override
    public void invoke(Hero data, AnalysisContext analysisContext) {
        logger.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        logger.info("所有数据解析完成!");
    }

    private void saveData() {
        logger.info("{}条数据,开始存储数据库!", list.size());
        //保存数据
        //userService.save(list);
        logger.info("存储数据库成功!");
    }
}

Service层
下载一个excel

    @Override
    public void testExcelDownload(HttpServletResponse response) {
        try {
            List<Hero> stuInfo = this.heroDao.getAllHeroInfo();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("测试", "UTF-8");
//            String fileName = "测试";
            response.setHeader("Content-disposition", "attachment;filename="+fileName+".xlsx");
            EasyExcel.write(response.getOutputStream(),Hero.class)
                    .sheet("第一个sheet")
                    .doWrite(stuInfo);;

        } catch (Exception e) {
            logger.error("testExcelDownload error", e);
            e.printStackTrace();
        }

    }

对象存储OSS

简介

OSS是一个分布式的对象存储服务,提供的是一个Key-Value对形式的对象存储服务。用户可以根据Object的名称(Key)唯一的获取该Object的内容。相关的名词介绍如下:
Bucket
Bucket是一个用户用来管理所存储Object的存储空间。 每个用户可以拥有多个Bucket。Bucket的名称在OSS的范围内必须是全局唯一的,一旦创建之后无法修改名称。Bucket内部的Object数目是没有限制的。

Bucket对于用户来说是一个管理Object的单元,所有的Object都必须隶属于某个Bucket。Bucket有一些属性用来控制Region、Object的访问控制、Object的生命周期等,这些属性是作用在该Bucket下所有的Object上的,因此用户可以灵活创建不同的Bucket来完成不同的管理功能。

同一个Bucket内部的空间是扁平的,即没有文件系统的目录等概念,所有的Object都是直接隶属于其对应的Bucket。

Object
Object是OSS存储数据的基本单元,称为OSS的对象,也被称为OSS的文件。在本文中,Object,对象,文件指的都是同一个意思。 Object由元信息(Object Meta),用户数据(Data)和文件名(Key)组成。 Object由一个在Bucket内部唯一的Key来标示。Object Meta信息是一个键值对,表示了Object的一些属性,比如最后修改时间、大小等信息,同时用户也可以存储一些自定义的信息在Object Meta信息中。
Object在整个存储的生命周期内都是不可变的。一个Object的生命周期是从上传成功到被删除为止。重复上传同名的Object会导致老的Object被删除然后新的Object取而代之。因此在OSS中,不支持类似文件系统的修改部分内容等操作。

AccessKey
AccessKey,简称AK,指的是访问身份验证中用到的AccessKeyId和AccessKeySecret。 OSS通过使用AccessKeyId和AccessKeySecret对称加密的方法来验证某个请求的发送者身份。AccessKeyId用于标示用户,AccessKeySecret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,其中AccessKeySecret必须保密。

  • Bucket的拥有者申请的AccessKey。
  • 被Bucket的拥有者通过RAM授权第三方请求者的AccessKey。
  • 被Bucket的拥有者通过STS授权第三方请求者的AccessKey。

Region表示OSS的数据中心所在的区域,物理位置。Endpoint表示OSS对外服务的访问域名。

   从设计层面来说,将OSS映射为文件系统是非常低效的,也是不建议的做法。如果一定要挂载成文件系统的话,也尽量只做写新文件、删除文件、读取文件这几种操作。使用OSS应该充分发挥其优点,即海量数据处理能力,优先用来存储海量的非结构化数据,比如图片、视频、文档等。

OSS常见操作

创建Bucket
在上传文件(Object)到OSS之前,您需要创建一个用于存储文件的Bucket。Bucket具有各种配置属性,包括地域、访问权限以及其他元数据。

上传文件
Bucket创建完成后,可以通过多种方式上传不同大小的文件。

下载文件
文件上传完成后,可以将文件下载至浏览器默认路径或本地指定路径。

列举文件
当Bucket内存储了大量的文件后,可以选择列举Bucket内的全部或部分文件。

删除文件
当不再需要保留上传的文件时,可以手动删除单个或多个文件,也可以通过配置生命周期规则自动删除单个或多个文件。

DUCC配置中心

简介

DUCC为京东的一款配置中心产品,是在原来UCC的基础上升级的新一代配置中心,类似与apollo。采用长轮询拉取&定时拉取,相对的开源配置中心有spring-cloud-config、diamond、disconf和apollo
https://github.com/spring-cloud/spring-cloud-config
https://github.com/takeseem/diamond
https://github.com/knightliao/disconf
https://github.com/ctripcorp/apollo/
DUCC的操作方式:

  1. 平台上,首先创建自己的应用,然后在对应命名空间-配置环境-工作区新建对应的键值型配置参数,最后发布即可。
  2. 工程中,配置对应的DUCC资源管理器,添加ducc平台连接信息,具体使用时,通过key获取配置。

特点

  • 支持多环境(或称分组),分组可以合并
  • 内置强大的基于插件的数据绑定框架,支持多种类型等转换;
  • 支持Log4j、Log4j2、Logback的动态修改日记级别功能。
  • 支持Spring原生注解、支持自定义注解,客户端代码入侵性低
  • 支持客户端多配置源,支持自定义配置,如ZK、Consol扩展
  • 支持配置预案切换

部分代码分析

持续更新完善中
Pojo和PojoExcel 实体类

public class Pojo {
}

public class PojoExcel {
}

PojoListener 监听类

public class PojoListener extends AnalysisEventListener<PojoExcel> {

    private static final Logger LOGGER = LoggerFactory.getLogger(PojoListener.class);

    private List<PojoExcel>  dataList;

    public PojoListener() {
    }

    public PojoListener(List<PojoExcel> dataList) {
        this.dataList = dataList;
    }

    @Override
    public void invoke(PojoExcel data, AnalysisContext analysisContext) {
        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
        dataList.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        LOGGER.info("所有数据解析完成!");
    }
}

pojoExcelUtil 文件工具类

public static void writePojoExcel(List<PojoExcel> excelList, HttpServletResponse response, InputStream inputStream) throws Exception{
 EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).autoCloseStream(Boolean.TRUE).sheet().doFill(excelList);
}


public static List<PojoExcel> readPojoExcel(InputStream in){
    List<PojoExcel> dataList = new ArrayList<>();
    PojoListener listener =  new PojoListener(dataList);
    EasyExcel.read(in,PojoExcel.class, listener).sheet("上传落地页").doRead();
    return dataList;
}

Service层逻辑

//读取文件
List<KolTaskAccountHrefExcel> dataList = pojoExcelUtil.readPojoExcel(file.getInputStream());

//写出文件
String filename = duccResourceManager.getConfigValue(DuccConstant.POJO_FILENAME);//通过DUCC获取文件名
pojoExcelUtil.writePojoExcel(dataList, response, pojoOssService.getExcelFileFromOss("模板文件.xlsx"));
// 获取OSS文件
@Override
public InputStream getExcelFileFromOss(String fileName) {
    StorageObject Object = jingdongStorageService.bucket(excelBucketName).object(fileName).get();
    if (storageObject == null) {
        return null;
    }
    return storageObject.getInputStream();
}


//<property name="excelBucketName" value="${jss.bucketName.excel}"/>
//jss.bucketName.excel=OSS系统中文件存放位置

Charles6169
1 声望0 粉丝

路漫漫其修远兮 吾将上下而求索