需求.提供公共的可以按照一定条件查询出结果,并提供将查询结果全部下载功能(Excel、CSV、TXT),由于一次性查出结果放到内存会占用大量内存.需要支持分页模式查询出所有数据。

 

实现思路

  1.在公共的controller(BaseController)中增加下载方法

  2.支持自定义分页查询方式、自定义表头和查询结果属性对应

  

@ResponseBody
    @RequestMapping("/exportExcel.json")
    public void exportExcel(HttpServletRequest request, HttpServletResponse response, final DeductCurrentsQry qry) throws Exception {

        
        
        // 从零行开始导出
        qry.setStart(0);
        // 分页设置大一点,提高导出效率
        qry.setLimit(50);
        //开始导出数据 
        DownloadDataLoader<DeductCurrentVo> loader = new DownloadDataLoader<DeductCurrentVo>() {
            @Override
            protected List<DeductCurrentVo> getDownloadData(Integer pageNum) {
                // pageNum 初始值为0,在下载工具类中,通过对pageNum的自加,达到分页查询效果
                qry.setStart(pageNum * qry.getLimit());
                PageDataList<DeductCurrentVo> pageBean = getPageDataList(qry);
                return pageBean.getRows();
            }
        };
        String[] hearders = new String[] {"客户ID", "抵用券编号", "抵用券类型", "起投限制", "抵用券面值", "投资金额", "产品代码", "抵用券状态", "抵用券兑换码", "发放时间", "使用时间" };
        String[] fields = new String[] { "customerId", "id", "deductType", "minInvestAmount", "faceValueFormat", "investAmount", "productCode", "deductStatus", "deductSn", "createDatetimeFormat", "usedDatetimeFormat" };
        
        this.download(response,String.format("抵用券记录_%S.xls", DateUtil.dateStr(new Date())),
                        Arrays.asList(hearders), null, loader, Arrays.asList(fields));
    }
    

 

package com.wjs.common.web;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.httpclient.util.DateUtil;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import com.wjs.common.util.StringEscapeEditor;
import com.wjs.common.util.excel.ExcelUtils;

/**
 * 基础控制器
 * 
 * 其他控制器继承此控制器获得日期字段类型转换和防止XSS攻击的功能
 * 
 * @author Moon
 * 
 */
@Controller
public class BaseController {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaseController.class);

    @InitBinder
    public void initBinder(ServletRequestDataBinder binder) {

        /**
         * 自动转换日期类型的字段格式
         */
        //        binder.registerCustomEditor(Date.class, new CustomDateEditor(
        //                        new SimpleDateFormat("yyyy-MM-dd"), true));

        /**
         * 防止XSS攻击
         */
        binder.registerCustomEditor(String.class, new StringEscapeEditor(true, false));
    }

    /**
     * http请求成功时调用
     * 
     * @return
     * 
     * @author chenchunhui
     */
    protected <T> JsonResult<T> success() {

        return this.success("操作成功", null);
    }

    /**
     * http请求成功时调用
     * 
     * @param data
     *        返回给前台的数据
     * @return 返回给前台的标准json对象
     */
    protected <T> JsonResult<T> success(T data) {

        return this.success("操作成功", data);
    }

    /**
     * http请求成功时调用
     * 
     * @param msg
     *        信息说明
     * @param data
     *        返回给前端的数据
     * @param <T>
     * @return 返回给前台的标准json对象
     * 
     * @author chenchunhui
     */
    protected <T> JsonResult<T> success(String msg, T data) {

        JsonResult<T> result = new JsonResult<T>(JsonResult.Status.SUCCESS, msg, data);
        if (LOGGER.isDebugEnabled()) {
            String logString = result.toString();
            if (logString.length() > 1024) {
                logString = logString.substring(0, 1024);
            }
            LOGGER.debug(logString);
        }
        return result;
    }

    /**
     * http请求失败时调用
     * 
     * @return 返回给前台的标准json对象
     * 
     * @author chenchunhui
     */
    protected <T> JsonResult<T> error() {

        return this.error("系统错误");
    }

    /**
     * http请求失败时调用
     * 
     * @param msg
     *        信息说明
     * @return 返回给前台的标准json对象
     * 
     * @author chenchunhui
     */
    protected <T> JsonResult<T> error(String msg) {

        JsonResult<T> result = new JsonResult<T>(JsonResult.Status.ERROR, msg);
        if (LOGGER.isInfoEnabled()) {
            String logString = result.toString();
            if (logString.length() > 1024) {
                logString = logString.substring(0, 1024);
            }
            LOGGER.info(logString);
        }
        return result;
    }

    
    
    
    /**
     * 分页下载数据获取类
     * @author Silver
     * @date 2017年3月16日 上午11:45:13 
     *
     * @param <T> 
     *
     */
    protected abstract class DownloadDataLoader<T> {

        /**
         * 分页下载属性值控制操作类
         * @param bean
         * @param propertyName
         * @param property
         * @return
         * @author Silver 
         * @date 2017年3月16日 上午11:45:45
         */
        protected String convertProperty(T bean, String propertyName, Object property) {
            return property == null ? "" : property.toString();
        }

        /**
         * 分页下载属性赋值
         * @param bean
         * @param propertyName
         * @return
         * @author Silver 
         * @date 2017年3月16日 上午11:46:37
         */
        protected Object getProperty(T bean, String propertyName) {
            try {
                return BeanUtils.getProperty(bean, propertyName);
            } catch (Throwable e) {
                LOGGER.info("bean:" + bean + ",Property:" + propertyName + e.getMessage(), e);
                return null;
            }
        }

        /**
         * 数据获取接口
         * @param pageNum -- 从0计数
         * @return
         * @throws Exception
         * @author Silver 
         * @date 2017年3月16日 上午11:47:07
         */
        protected abstract List<T> getDownloadData(Integer pageNum) throws Exception;
    };
    

    protected static interface Writer {
        public void write(Collection<String> row) throws IOException;
    }

    /**
     * Web下载文件
     * @param response httpResponse信息
     * @param fileName 文件名称,如果文件名称为空的情况默认【 日期.csv】格式
     * @param header 表头名称
     * @param columnWidth 列宽
     * @param loader    数据加载类
     * @param queryParam 如果有查询条件的传递
     * @param propertyNames
     * @throws Exception
     * @author Silver 
     * @date 2017年3月16日 上午11:47:31
     */
    protected <T> void download(HttpServletResponse response, String fileName, List<String> header, List<Integer> columnWidth, DownloadDataLoader<T> loader, List<String> propertyNames) throws Exception {

        if (StringUtils.isEmpty(fileName) || loader == null || CollectionUtils.isEmpty(propertyNames)) {
            throw new RuntimeException("参数错误。FileName:" + fileName + ",DataLoader:" + loader + ",PropertyName:" + propertyNames);
        }
        // 获取输出流,设置content-type等头域
        final OutputStream out = getResponseStream(response ,fileName);
        try {
            Writer writer = null;
            // 获取文件后缀名
            String extension = FilenameUtils.getExtension(fileName);
            // 如果是excel的后缀
            if ("xls".equalsIgnoreCase(extension) || "xlsx".equalsIgnoreCase(extension)) {
                Workbook workbook = new HSSFWorkbook();
                Sheet sheet = workbook.createSheet("sheet1");
                final List<Collection<String>> rows = new ArrayList<Collection<String>>();
                writer = new Writer() {
                    @Override
                    public void write(Collection<String> row) {
                        rows.add(row);
                    }
                };

                writeOutputStream(loader, propertyNames, writer);
                // 写入excel
                if (!ExcelUtils.setExcelInfo(sheet, columnWidth, header, rows)) {
                    throw new IOException("设置导出文件内容失败。");
                }
                
                workbook.write(out);
            } else if("csv".equalsIgnoreCase(extension)) {
                writer = new Writer() {

                    @Override
                    public void write(Collection<String> row) throws IOException {

                        String str = ExcelUtils.collectionToCsvString(row);
                        byte[] content = org.apache.commons.codec.binary.StringUtils.getBytesUnchecked(str + "\n",
                                        "GBK");
                        IOUtils.write(content, out);
                        out.flush();
                    }
                };
                // 写文件头
                writer.write(header);
                // 写文件
                writeOutputStream(loader, propertyNames, writer);
            }else{
                writer = new Writer() {

                    @Override
                    public void write(Collection<String> row) throws IOException {

                        IOUtils.write(org.apache.commons.codec.binary.StringUtils.getBytesUnchecked(row + "\n",
                                        "GBK"), out);
                        out.flush();
                    }
                };
                // 写文件头
                writer.write(header);
                // 写文件
                writeOutputStream(loader, propertyNames, writer);
            }
            out.flush();
        } finally {
            IOUtils.closeQuietly(out);
        }
    }
    
    /**
     * 获得输出流
     * 
     * @return
     * @throws IOException
     */
    protected OutputStream getResponseStream(HttpServletResponse response, String fileName) throws IOException {
        if (StringUtils.isEmpty(fileName)) {
            fileName = DateUtil.formatDate(new Date(), "yyyy-MM-dd_HH-mm-ss") + ".csv";
        }
        response.reset();


        String extension = FilenameUtils.getExtension(fileName);
        if("xlsx".equalsIgnoreCase(extension)){
            // 部分window版本生成后的xlsx打不开,默认改成xls打开
            fileName = fileName.substring(0, fileName.length() -1);
        }
        //设置响应编码
        response.setCharacterEncoding("UTF-8");
        //设置对应的contentType
        response.setContentType("application/x-download;charset=UTF-8");
//        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename="
                + new String(fileName.getBytes("gb2312"), "ISO-8859-1"));
        OutputStream out = response.getOutputStream();
        
        
        return out;
    }
    
    protected <T> void writeOutputStream(DownloadDataLoader<T> loader, List<String> propertyNames,
                    Writer writer) throws Exception {

                int pageNum = 0;
                int maxLenth = 102400;
                while (maxLenth-- > 0) {
                    // 分页获取数据
                    List<T> objList = null;
                    try {
                        objList = loader.getDownloadData(pageNum++);
                    } catch (Exception e) {
                        LOGGER.error("获得到处数据异常:{}",e.getMessage(), e);
                    }
                    if (CollectionUtils.isEmpty(objList)) {
                        break;
                    }
                    for (T bean : objList) {
                        if (bean == null) {
                            continue;
                        }
                        Collection<String> result = new ArrayList<String>();
                        // 遍历指定属性
                        for (String name : propertyNames) {
                            // 获得属性值
                            Object property = loader.getProperty(bean, name);
                            // 将属性值转换成字符串
                            String convertValue = loader.convertProperty(bean, name, property);
                            // 组装成row
                            result.add(convertValue);
                        }
                        if (CollectionUtils.isEmpty(result)) {
                            continue;
                        }
                        writer.write(result);
                    }
                }

            }
}
BaseController代码

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-12-20
  • 2022-02-06
  • 2021-12-29
  • 2022-12-23
  • 2022-01-08
猜你喜欢
  • 2022-02-21
  • 2021-06-08
  • 2022-12-23
  • 2021-07-20
  • 2022-01-24
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案