美文网首页工具使用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