导出组件(qilu-Export)介绍
导出组件(qilu-Export)介绍
超级导出是基于base开出的一朵花,其中的导出功能强大而隐秘,同时兼具扩展性,解决了我心中一个多年的愿望-----用查询功能写导出. 从这个中间件也可以看出,当底层被大量统一以后,会诞生出更多的中间件.这就是规范能带来的提升.
超级导出实现了一个单独的导出功能,对于controller或者service的直接复用.可以实现所见即导出,也可以手动实现各种导出功能.支持excel导出和CSV导出.
超级导出内部实现了一个强悍的数据转化工具,可以实现对list的增强操作,有了这个实现以后,结合qilu-mybatis生成的example代码,把原本需要使用多表关联的功能,转化为二次查询.
具体功能参考后台模板日志页面上的导出功能
依赖说明
<dependency>
<groupId>com.9istock.base</groupId>
<artifactId>qilu-export</artifactId>
<version>版本号</version>
</dependency>Controller的集成
springMVC配置
<aop:aspectj-autoproxy >
<aop:include name="exportAspect" />
</aop:aspectj-autoproxy>
<bean id="exportAspect" class="com.istock.base.export.annotation.ExporterAspect"></bean>controller集成
@Exporter(code="OpLog")
public @ResponseBody ApiBaseResponse<PageInfo<OperLogInfo>> search(ModelMap model , OperLogQuery query , PageInfo<OperLogInfo> pageInfo)在controller上,使用@Exporter的注解,注解的参数,就是导出的模板配置.
使用注解的方法中,返回值一定要是如下的2种,PageInfo或者List,如果入参中间存在PageInfo对象,超级导出会自动从第1页到最后一页的查询,并直接重写response.
注解中配置的code,就是导出模板的编号,导出模板的配置
发送的HTTP请求中,head中需要包含<header name="exportType">
- exportType=xls时,导出excel文件
- exportType=csv时,导出csv文件
详细示例,请看user的操作日志导出.
导出模板配置
导出配置主要是配置导出excel的每列的配置,以及导出过程中的callback
<bean name="loginNameTranslate" class="com.istock.union.user.translate.LoginNameTranslateCallback"></bean>
<bean name="opLogTemplate" class="com.istock.base.qiluExport.ExportTemplate">
<property name="fileName" value="opLog"></property>
<property name="limit" value="20"></property>
<property name="translateCallback">
<list>
<bean class="com.istock.base.qiluExport.ExportTranslateCallback">
<property name="orgiFiledName" value="operName"></property>
<property name="newFiledname" value="operUser"></property>
<property name="callback" ref="loginNameTranslate"></property>
</bean>
</list>
</property>
<property name="itemList">
<list>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="id"></property>
<property name="name" value="id"></property>
</bean>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="menuName"></property>
<property name="name" value="菜单名"></property>
</bean>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="functionName"></property>
<property name="name" value="功能名"></property>
</bean>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="method"></property>
<property name="name" value="方法"></property>
</bean>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="operName"></property>
<property name="name" value="操作人"></property>
</bean>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="status"></property>
<property name="name" value="操作结果"></property>
<property name="dicName" value="COMMON_STATUS"></property>
</bean>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="operUser.sex"></property>
<property name="name" value="性别"></property>
<property name="dicName" value="COMMON_SEX"></property>
</bean>
<bean class="com.istock.base.qiluExport.ExportTemplateItem">
<property name="fieldName" value="operUser.email"></property>
<property name="name" value="邮箱"></property>
</bean>
</list>
</property>
</bean>
<bean name="ExportRegister" class="com.istock.base.qiluExport.ExportRegister" factory-method="getInstance">
<property name="templateMap">
<map>
<entry key="OpLog" value-ref="opLogTemplate">
</entry>
</map>
</property>
</bean>导出模板说明
com.istock.base.export.ExportTemplate属性:
| 属性 | 说明 |
|---|---|
| fileName | 导出的文件前缀 |
| limit | 如果有分页参数,每次分页查询的数量 |
| translateCallback | 内置的数据翻译callback列表 |
| itemList | 导出的列的设置 |
com.istock.base.export.ExportTemplateItem属性:
| 属性 | 说明 |
|---|---|
| fieldName | 导出对象数据的属性名,支持数据嵌套,用”.”分割 |
| name | 导出excel列名 |
| dateFormat | 如果导出的列数据,类型为date,会触发解析日期格式的解析 |
| dicName | 如果导出的列是数据字典,这边需要配置数据字典的类型 |
| suffix | 数字的后缀,比如%,$ |
| defaultValue | 导出数据中,该列为null时候的填充值 |
| promt | Excel的提示信息 |
| height | Excel导出列的高度 |
| width | Excel导出列的宽度 |
com.istock.base.export.ExportTranslateCallback属性:
| 属性 | 说明 |
|---|---|
| orgiFieldName | 在原始数据里面的字段,传入callback进行翻译 |
| newFieldName | 翻译以后新的字段存储callback导出的数据 |
| callback | 执行callback的类 |
执行的callback类,一定要实现com.istock.base.export.data.TranslateCallback接口.
该接口会将数据集中的orginFieldName的数据整理成List,最终返回的map的key,就是以orginFieldName中的字段名,value就是翻译的内容,value可以是一个对象
手动导出
有的时候,不是需要对查询展示的数据进行导出,有时候需要单独编写导出程序.
使用com.istock.base.export.util.ExportUtils的exportExcel方法,可以实现手动导出
/**导出excel的通用方法
* 使用者只需要实现查询方法,查询的方法声明中,需要使用pageInfo对象进行分页
* @param searchService 注入的查询服务的实例
* @param targetMethod 需要调用的查询方法
* @param args 调用查询的参数
* @param os 输出流
* @param templateCode 导出excel的模板配置
* @return
*/
public static final ApiBaseResponse<String> exportExcel(Object searchService , Method targetMethod , Object[] args, OutputStream os , ExportTemplate template)只需要实现一个service方法,直接调用就可以实现excel的输出流.
超强的数据翻译
和数据字典类似,在导出过程中,往往还是需要数据翻译的功能,有的时候需要的功能会比数据字典更强,比如数据表中是userId,导出的时候需要使用userName.
在导出模板中,配置translateCallback,需要实现com.istock.base.export.data.TranslateCallback,这个接口就是为了导出过程中的数据翻译拦截.
/**翻译过程中的回调
* 使用codeList,进行数据库查询,查询的结果以code,name的方式存储在map里面
* @param codeList
* @return
*/
public Map<Object , Object> translate(List codeList);使用示例
List<Map> list = DataTranslateUtils.translate(pageInfo.getData(), "deptCode", "deptName", new DeptTranslateCallback());
list = DataTranslateUtils.translate(pageInfo.getData(), "tenantCode", "tenantName", new TenantTranslateCallback());
pageInfo.setData(list);上述代码,会使用pageInfo.getData()中的数据内容,转化为List<Map>结构的数据对象
将原本数据内容中的不同的deptCode,转化为callback中的入参,调用callback的translate方法,将对应的返回值的value,存储到deptName的一个属性里面.
上述的代码,如果在service里面,就意味着,这个service提供了复杂查询
上述的代码如果在一个controller的方法内,就意味着页面请求提供了翻译
结束语
当系统的底层被大量抽象统一以后,类似于qilu-export的导出功能可以做成一个统一的方式,简单又具备灵活性.这就是为什么要抽象,要统一的最主要原因.
我也相信,如果有机器人编程的时代来临,也注定是基于大量底层抽象和统一的基础上形成的.
