项目中的需求:导出功能,且有些字段是需要通过数据库存储的数据字典来进行翻译转换。比如:企业类型,1=生产企业,2=配送企业,3=经营企业,等等。这些映射关系虽然变化频率很低,但也是动态存储在数据库中的。我们不希望将这些映射关系写死在Java代码中。
EasyExcel有个Converter功能,目前看来有两种实现方式:
一种是在@ExcelProperty注解中指定:
@ExcelProperty(value = "创建时间",index = 5,converter = DateTimeConverter.class)
private Date creTime;
一种是注册写处理器的方式,类似于:
public static void export(HttpServletResponse response, List rowList,String fileName,Class clazz,String sheetName) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), clazz)
.registerWriteHandler(new CustomCellWriteHandler())
.registerWriteHandler(your converter constructor)//这里可以继续添加其他的转换器或处理器
.sheet(sheetName).doWrite(rowList);
}
这两种方式各自有缺点:
注解方式:这种方式直接使用的话,无法动态维护映射关系。假设我们已经有了映射关系范围,无法通过构造器的方式注入到转换器中。
注册方式:这种注册方式是针对类型的全局转换器。比如我们将如下的转换器注册进去,它就会针对所有的Integer类型的字段,全部按照这个转换器里的规则,进行转换。而不是针对某个字段。
在我们的项目中,数据字典的翻译是很常见的,甚至通过一个ID去动态查询其他表的一个信息,也是极为常见的所以最好是能有一种方案,让我们比较灵活的翻译来自数据库的映射关系。
鉴于我们的项目使用的是Springboot,所以可以通过某种方式,获取到Spring容器中的数据库访问组件Bean(dao,或者我们自己封装的组件类)。
以下是我在项目中已经实现的一种方案。
先从网上找了一个通过Spring应用上下文获取Spring容器中bean的工具类:
@Component
public class SpringApplicationUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
/**
* 获取applicationContext
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringApplicationUtils.applicationContext == null) {
SpringApplicationUtils.applicationContext = applicationContext;
}
}
/**
* 通过name获取 Bean.
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
*
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
/**
* 获取指定类型的所有bean实例
*
* @param clazz
* @param <T>
* @return
*/
public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
Map<String, T> instances = getApplicationContext().getBeansOfType(clazz);
return instances;
}
}
然后定义我们的EasyExcel converter实现类,用于转换一个状态,将状态码转为可读性比较好的状态名称:
public class EnableStatusConverter implements Converter<Integer> {
private static Map<Integer,String> statusMap = null;
//baseService是项目中封装的一个组件类,间接调用dao中的方法,并对返回结果进行了处理封装
private BaseService baseService;
//懒汉模式构造器,将状态码映射关系注入进map中,不必每次都连接数据库进行查询
public EnableStatusConverter() {
baseService = SpringApplicationUtils.getBean(BaseService.class);
if (CollectionUtil.isEmpty(statusMap)){
statusMap = baseService.getItemMap(DictTypeConstants.D_ENABLE_STATUS);
}
}
@Override
public Class supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String enableStatusName = cellData.getStringValue();
for (Integer enableStatus : statusMap.keySet()) {
if(StringUtils.equalsStr(enableStatusName,statusMap.get(enableStatus))){
return enableStatus;
}
}
return null;
}
@Override
public CellData convertToExcelData(Integer enableStatus, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String enableStatusName = statusMap.get(enableStatus);
return new CellData(StringHelper.isEmpty(enableStatusName) ? "":enableStatusName);
}
}
然后是Excel Row对应的实体类,在@ExcelProperty注解中,converter属性指定转换器即可:
public class BzVaccKnowRowModel {
@ExcelProperty(value = "ID号",index = 0)
private Integer knowId;
@ExcelProperty(value = "知识标题",index = 1)
private String title;
@ExcelProperty(value = "浏览量",index = 2)
private Integer viewNum;
@ExcelProperty(value = "收藏量",index = 3)
private Integer collectNum;
@ExcelProperty(value = "状态",index = 4,converter = EnableStatusConverter.class)
private Integer enableStatus;
@ExcelProperty(value = "创建时间",index = 5,converter = DateTimeConverter.class)
private Date creTime;
}
其他的导出逻辑,并无其他不同,不再赘述。
直接上Excel导出结果:
状态列,即为本次翻译的主要对象。
来源:oschina
链接:https://my.oschina.net/alexjava/blog/4815040