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

外围逻辑

技术组件

EasyExcel

简介

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

更少的内存占用

easyExcel能大大减少占用内存的次要起因是在解析Excel时没有将文件数据一次性全副加载到内存中,而是从磁盘上一行行读取数据,一一解析。通过一行一行的解析模式,并将一行的解析后果以观察者的模式告诉解决(AnalysisEventListener)。

底层源码

简略应用

实体类

@Datapublic 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文件@Overridepublic 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零碎中文件寄存地位