模板文件云存储管理 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的操作形式:
- 平台上,首先创立本人的利用,而后在对应命名空间-配置环境-工作区新建对应的键值型配置参数,最初公布即可。
- 工程中,配置对应的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零碎中文件寄存地位