发现若依的导入导出涉及到字典值、外键导出是一个Long值。然后想着是不是可以从redis中得到字典,从数据库得到数据。动态绑定起来
本着说做就做的动手能力。
从@Excel的枚举入手,加入两个枚举类型
/**
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/**
* 如果是外键,请设置类的路径值 (如: com.yz.service.impl.StudentServiceImpl)
*/
public String classType() default "";
继续写它的导入导出功能。导入导出功能在ExcelUtil中
添加字典、外键的导入实现 。在 public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception 这个方法中。修改实现
if (StringUtils.isNotNull(fieldType))
{
String propertyName = field.getName();
if (StringUtils.isNotEmpty(attr.targetAttr()))
{
propertyName = field.getName() + "." + attr.targetAttr();
}
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
{
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
}
else if (StringUtils.isNotEmpty(attr.dictType()))
{
// 根据类型跟名称字典id。表存的是id。
val = getDictValueByTypeAndLabel(String.valueOf(val), attr.dictType());
}
else if (StringUtils.isNotEmpty(attr.classType())){
// 根据类路径跟名称获得id,getClassIdByTypeAndName下面有写
val = getClassIdByTypeAndName(String.valueOf(val), attr.classType());
}
else if (!attr.handler().equals(ExcelHandlerAdapter.class))
{
val = dataFormatHandlerAdapter(val, attr);
}
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
{
PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
if (image == null)
{
val = "";
}
else
{
byte[] data = image.getData();
val = FileUtils.writeImportBytes(data);
}
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
接着是模板导出,public void setDataValidation(Excel attr, Row row, int column) 实现在这个方法里面。现在加入字典跟外键的导出
if(StringUtils.isNotEmpty(attr.dictType())) {//有字典 则取字典下拉
setXSSFValidation(sheet, DictUtils.getLabelArr(attr.dictType()), 1, 100, column, column);
}else if(StringUtils.isNotEmpty(attr.classType())) {//有外键 则取类的属性下拉,getClassLabelArr是新加的方法。下面有写
setXSSFValidation(sheet, getClassLabelArr(attr.classType()), 1, 100, column, column);
} else if (attr.combo().length > 0)// 如果设置了combo属性则本列只能选择不能输入
{
// 这里默认设了2-101列只能选择不能输入.
setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
}
上面这里对照着这个方法是能知道改动的地方的。
接着是数据导出。public List<T> importExcel(String sheetName, InputStream is, int titleNum) 实现在这个方法里面。
if (StringUtils.isNotNull(fieldType))
{
String propertyName = field.getName();
if (StringUtils.isNotEmpty(attr.targetAttr()))
{
propertyName = field.getName() + "." + attr.targetAttr();
}
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
{
val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
}
else if (StringUtils.isNotEmpty(attr.dictType()))
{
// 字典数据导出
// val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
val = getDictValueByTypeAndLabel(String.valueOf(val), attr.dictType());
}
else if (StringUtils.isNotEmpty(attr.classType())){
// 外键数据导出
val = getClassIdByTypeAndName(String.valueOf(val), attr.classType());
}
添加的方法
/**
* 根据指定的type ,value 获取 label
* @param value
* @param dictType
* @return
* @throws Exception
*/
public static String getDictLabelByTypeAndValue(String value,String dictType) throws Exception {
String label = value;
try {
label = DictUtils.getDictLabelByTypeAndValue(value, dictType, value);
} catch (Exception e) {
throw e;
}
return label;
}
/**
* 根据type,label 获取value
* @param propertyValue
* @param dictType
* @return
* @throws Exception
*/
public static Long getDictValueByTypeAndLabel(String propertyLabel, String dictType) throws Exception{
Long value = null;
try {
value = DictUtils.getDictValueByTypeAndLabel(propertyLabel, dictType, propertyLabel);
} catch (Exception e) {
throw e;
}
return value;
}
/**
* 根据type,名称 获取id
* @param
* @param classType
* @return
* @throws Exception
*/
public static Long getClassIdByTypeAndName(String propertyLabel, String classType) throws Exception{
Long value = null;
try {
// 通过反射获取类
Class clz = Class.forName(classType);
Object bean = SpringUtils.getBean(clz);
Method getIdByName = clz.getMethod("getOne", Wrapper.class);
QueryWrapper wrapper = new QueryWrapper();
wrapper.eq("name",propertyLabel);
Object invoke = getIdByName.invoke(bean, wrapper);
Class<?> aClass = invoke.getClass();
Method method = aClass.getMethod("getId");
value = (Long) method.invoke(invoke);
} catch (Exception e) {
throw e;
}
return value;
}
/**
* 通过反射获取单元格的值
* @param valueOf id
* @param classType 类的路径
* @return
*/
private String getDictNameAndValue(Long valueOf, String classType) throws Exception {
// 通过反射获取类
Class clz = Class.forName(classType);
Object bean = SpringUtils.getBean(clz);
Method getIdByName = clz.getMethod("getById", Serializable.class);
Object invoke = getIdByName.invoke(bean, valueOf);
Class<?> aClass = invoke.getClass();
Method method = aClass.getMethod("getName");
String value = (String) method.invoke(invoke);
return value;
}
/**
* 根据类的路径获取名称
* @param classType
* @return
* @throws Exception
*/
private String[] getClassLabelArr(String classType){
List<Object> objects = null;
try {
// 获取反射的class
Class clz = Class.forName(classType);
// 从启动类中得到bean;spring工具类 方便在非spring管理环境中获取bean
Object bean = SpringUtils.getBean(clz);
Method listMethod = clz.getMethod("list");
// 通过反射获取方法,方法调用得到一个list(因为调用list方法得到的一定是list)
objects = (List<Object>) listMethod.invoke(bean);
} catch (Exception e) {
e.printStackTrace();
}
// 数组长度即使集合的长度
List<String> result = new ArrayList<>();
// 遍历数组得到名称label,如果数据多的话。性能低,需优化
objects.forEach(obj -> {
Class<?> aClass = obj.getClass();
try {
Method method = aClass.getMethod("getName");
String value = (String) method.invoke(obj);
result.add(value);
} catch (Exception e) {
e.printStackTrace();
}
});
// 把String集合转成String数组返回出去
return result.toArray(new String[result.size()]);
}
然后是DictUtils的修改。在里面加入这些方法。
/**
* 根据指定的type ,value 获取 label
* @param value
* @param type
* @param defaultLabel 默认label
* @return
*/
public static String getDictLabelByTypeAndValue(String value, String type, String defaultLabel){
if (StringUtils.isNotBlank(type) && ObjectUtils.isNotNull(value)){
List<SysDictData> dataList = getDictCache(type);
for (SysDictData dict : dataList){
if (type.equals(dict.getDictType()) && value.equals(dict.getDictCode().toString())){
return dict.getDictLabel();
}
}
}
return defaultLabel;
}
/**
* 根据type,label 获取value
*
* @param label
* @param type
* @param defaultValue
* @return
*/
public static Long getDictValueByTypeAndLabel(String label,String type,String defaultValue) {
if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(label)){
for (SysDictData dict : getDictCache(type)){
if(type.equals(dict.getDictType()) && label.equals(dict.getDictLabel())) {
return dict.getDictCode();
}
}
}
return null;
}
/**
* 根据 type 将 lable组成 string数组
* @param type
* @return
*/
public static String[] getLabelArr(String type) {
String[] arr0 = new String[0];
if (StringUtils.isNotBlank(type)) {
List<SysDictData> dictList = getDictCache(type);
String[] strArr = new String[dictList.size()];
for (int i = 0 ; i < dictList.size() ; i ++) {
strArr[i] = dictList.get(i).getDictLabel();
}
return strArr;
}
return arr0;
}
差不多就可以了。使用的话
/**
* 交易方式id这个是字典值
*/
@Excel(name = "交易方式",dictType = "transaction_mode")
private Long tradeId;
/**
* 应用情况id,这个是外键(外键类型)
*/
@Excel(name = "应用情况",classType = "com.yz.service.impl.xxxImpl")
private Long usedId;