美文网首页工具使用springboot
封装导出功能(注解运用,底层是反射)

封装导出功能(注解运用,底层是反射)

作者: Raral | 来源:发表于2021-09-28 11:31 被阅读0次

封装导出功能(注解,反射)

  1. 工具类

/**
 * @description: 有关excel工具类
 */
public class ExcelsUtil<T> {
    private static final Logger log = LoggerFactory.getLogger(ExcelsUtil.class);

    /**
     * 转化的属性List
     * */
    public List converterExpList;

    /**
     * 转化的属性Map
     * */
    public Map converterExpMap;


    /**
     * 实体对象
     */
    public Class<T> clazz;

    public ExcelsUtil(Class<T> clazz)
    {
        this.clazz = clazz;
        this.converterExpList = new ArrayList();
        this.converterExpMap = new HashMap();
        this.initConverterExpList();
    }



    /**
     * @param response 响应
     * @param list 数据
     */
    public void exportExcel(HttpServletResponse response, List list) {
        ExcelWriter writer = null;
        Map<String, String> excelMap = this.createExcelField();
        try {
            writer = ExcelUtil.getWriter(true);
            for (String key : excelMap.keySet()) {
                writer.addHeaderAlias(key, excelMap.get(key));
            }
            writer.write(list, true);
            response.setContentType("application/force-download");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("test.xlsx", "UTF-8"));
            OutputStream out = response.getOutputStream();
            writer.flush(out);
            out.flush();
            out.close();
        } catch (Exception e) {
            log.error("劵管理导出异常:{}", JacksonUtils.obj2json(e));
        }

    }



    /**
     * 初始化转换字段
     * */
    private void initConverterExpList() {
        log.info("==excel导出初始化开始==");
        Map<String, String> map = new HashMap<>();
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        tempFields.stream().forEach(field -> {
            // 单注解
            if (field.isAnnotationPresent(Excel.class))
            {
                Excel attr = field.getAnnotation(Excel.class);
                if(!StrUtil.isBlankIfStr(attr.readConverterExp())) {
                    String key = field.getName();
                    this.converterExpList.add(key);
                    this.converterExpMap.put(key, attr.readConverterExp());
                }
            }
        });
        log.info("==excel导出初始化结束==");
    }

    /**
     * @param field 属性名
     * @return Boolean
     */
    public Boolean isConverterExpList(Field field) {
        return this.converterExpList.contains(field)? true : false;
    }

    /**
     * 配置excel导出模板所有定义字段
     *
     */
    private Map createExcelField() {
        log.info("==excel导出定义模板开始==");
        Map<String, String> map = new HashMap<>();
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        tempFields.stream().forEach(field -> {
            // 单注解
            if (field.isAnnotationPresent(Excel.class))
            {
                Excel attr = field.getAnnotation(Excel.class);

                String value = attr.name();
                String key = field.getName();
                map.put(key, value);
                if(StrUtil.isBlankIfStr(attr.readConverterExp())) {
                    this.converterExpList.add(key);
                }
            }
        });
        log.info("==excel导出定义模板结束:{}==", JacksonUtils.obj2json(map));
        return map;
    }

    /**
     * 过滤数据
     * @param list 需要过滤的原始数据
     * */
    public List filterData(List list) {
        log.info("==excel导出过滤数据开始==");
        Map<String, String> converterExpMap = this.converterExpMap;
        list.stream().forEach(item -> {
            Class aClass = item.getClass();
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field field : declaredFields) {
                if (field.isAnnotationPresent(Excel.class)) {
                    Excel annotation = field.getAnnotation(Excel.class);
                    if(StrUtil.isBlankIfStr(annotation.readConverterExp())) {
                        String name = field.getName();
                        String gm = this.converterMethod(name, 0);
                        try {
                            Method getMethod = aClass.getMethod(gm);
                            String value =(String) getMethod.invoke(item);
                            String expValue = this.reverseByExp(value, converterExpMap.get(name));
                            String sm = this.converterMethod(name, null);
                            Method setMethod = aClass.getMethod(sm, String.class);
                            setMethod.invoke(item, expValue);
                        } catch (Exception e) {
                            log.error("导出解析异常:{}", JacksonUtils.obj2json(e));
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        log.info("==excel导出过滤数据结束:{}==", JacksonUtils.obj2json(list));
        return list;
    }

    /**
     * 转换
     * */
    public String converterMethod(String name, Integer type) {
        String pre = type == null? "set" : "get";
        return pre + name.substring(0,1).toUpperCase() + name.substring(1);

    }

    /**
     * @param propertyValue 参数值
     * @param converterExp 翻译注解
     * @return 解析后值
     * @throws Exception
     */
    public String reverseByExp(String propertyValue, String converterExp) throws Exception
    {
        try
        {

            String[] convertSource = converterExp.split(",");
            for (String item : convertSource)
            {
                String[] itemArray = item.split("=");
                if (itemArray[0].equals(propertyValue))
                {
                    return itemArray[1];
                }
            }
        }
        catch (Exception e)
        {
            throw e;
        }
        return propertyValue;
    }


}

  1. 注解Excel


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {
    /**
     * 导出到Excel中的名字.
     */
    public String name() default "";

    /**
     * 日期格式, 如: yyyy-MM-dd
     */
    public String dateFormat() default "";

    /**
     * 读取内容转表达式 (如: 0=男,1=女,2=未知)
     */
    public String readConverterExp() default "";

    /**
     * 导出时在excel中每个列的高度 单位为字符
     */
    public double height() default 14;

    /**
     * 导出时在excel中每个列的宽 单位为字符
     */
    public double width() default 16;

    /**
     * 文字后缀,如% 90 变成90%
     */
    public String suffix() default "";

    /**
     * 当值为空时,字段的默认值
     */
    public String defaultValue() default "";

    /**
     * 提示信息
     */
    public String prompt() default "";

    /**
     * 设置只能选择不能输入的列内容.
     */
    public String[] combo() default {};

    /**
     * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
     */
    public boolean isExport() default true;

    /**
     * 另一个类中的属性名称,支持多级获取,以小数点隔开
     */
    public String targetAttr() default "";

    /**
     * 字段类型(0:导出导入;1:仅导出;2:仅导入)
     */
    Type type() default Type.ALL;

    public enum Type
    {
        ALL(0), EXPORT(1), IMPORT(2);
        private final int value;

        Type(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }
}

excels


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels {
    Excel[] value();
}

  1. DTO


@Setter
@Getter
@NoArgsConstructor
@ToString
public class GetCouponsTypeListReqDTO {
    /**
     * 券类型编号
     */
    private String atno;

    /**
     * 批量查询 券批次编号
     */
    private List<String> atnos;

    /**
     * 券类型名称
     * 如果请求参数是at_name,fastjson首先找at_name,没找到再赋值给atName
     */
    @JsonProperty(value = "at_name")
    private String atName;

    /**
     * 别名
     */
    private String alias;

    /**
     * 券类型
     * 01 折
     * 02 减
     * 03 返
     * 04 赠
     */
    @JsonProperty(value = "cny_type")
    private String cnyType;


    @JsonProperty(value = "plan_id")
    private String planId;

    /**
     * 状态
     *  state=1,进行中的券,查询条件  and act.end_time >= now()  and act.ing_num > 0
     */
    private Integer state;

    /**
     * 券商编号
     */
    private String ino;


    /**
     * 发券模式
     * 1 折上折 2优惠购 3 权益工具包 4 CPS 5 营销活动(仅入库不销售) 6 个人发放(仅入库不销售)7 分销发放(仅入库不销售)
     */
    @JsonProperty(value = "pool")
    private Integer pool;

    /**
     * CPS序号
     */
    @JsonProperty(value = "cps_no")
    private String cpsNo;

    /**
     * 仅入库不销售 1 是
     */
    @JsonProperty("no_sale")
    private Integer noSale;

    /**
     * 券有效期的开始时间,yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("start_time")
    private String startTime;
    /**
     * 券有效期的结束时间,yyyy-MM-dd HH:mm:ss
     */
    @JsonProperty("end_time")
    private String endTime;


    public void setAtno(String atno) {
        this.atno = atno;
        if(StrUtil.isNotBlank(atno)){
            String[] split = atno.replaceAll(",", ",").split(",");
            if(split == null || split.length == 0) return;
            List<String> strings = Arrays.asList(split);
            List<String> collects = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
            if(collects == null || collects.size() == 0) return;
            this.atnos = collects;
        }
    }
}

  1. controller
 @RequestMapping(value = "exportCoupon", method = RequestMethod.POST)
    public void exportCoupon(HttpServletRequest request,
                               HttpServletResponse response, @RequestBody ReqDTO<GetCouponsTypeListReqDTO> reqDTO) {
        GetCouponsTypeListReqDTO req = new GetCouponsTypeListReqDTO();
        List<AcctypeDTO> list = null;
        try {
            list = acctypeMapper.selectAccTypePage(req, 1, 2);
        } catch (Exception e) {
            log.error("劵管理导出,查询劵批次异常:{}", JacksonUtils.obj2json(e));
        }
        ExcelsUtil<AcctypeDTO> excelsUtil = new ExcelsUtil<>(AcctypeDTO.class);
        List resList = excelsUtil.filterData(list);
        excelsUtil.exportExcel(response, resList);
    }
  1. 前端请求(必须用原生的请求)
// 导出
function exportHandle() {

    var json = {
        "req_no": "123","method":"mgr.exportCoupon",
        "biz_params":JSON.stringify({'atno': param })
    };
    var biz_params = JSON.stringify(getParams(json))

    downLoadFile({
        data:biz_params,
        url: "http://xxx/mgr/exportCoupon"
        // url:biz_url
    })
}

function downLoadFile(options) {
    var sendData = options.data;
    var ajaxRequest = new XMLHttpRequest();
    ajaxRequest.responseType = 'arraybuffer';
    ajaxRequest.onreadystatechange = function () {
        if (ajaxRequest.readyState == 4 && ajaxRequest.status == 200) {
            // debugger;
            ajaxRequest.response.head

            var blob = new Blob([ajaxRequest.response], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
            var objectUrl = URL.createObjectURL(blob);
            var a = document.createElement("a");
            document.body.appendChild(a);
            a.style = "display: none";
            a.href = objectUrl;
            // a.download = fileName;
            a.download = "test.xlsx";
            a.click();
            document.body.removeChild(a);
        }
        else if (ajaxRequest.status == 409 || ajaxRequest.status == 500 || ajaxRequest.status == 204) {
        }
    }
    ajaxRequest.open("POST", options.url, true);
    ajaxRequest.setRequestHeader("Content-Type", "application/json");
    ajaxRequest.send(sendData);
}

相关文章

网友评论

    本文标题:封装导出功能(注解运用,底层是反射)

    本文链接:https://www.haomeiwen.com/subject/vknlnltx.html