利用模板方法模式实现导出CSV文件功能

测试结果:

数据库表截图:

 导出cvs文件:

页面,导出按钮,导出js

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
<%-- 引入jQuery --%>
<script src="js/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
    $(function () {
        $('#exportCsv').bind("click", function(){
            var formElement=$("<form>");    // 定义一个form表单
            formElement.attr("style","display:none");
            formElement.attr("target","");
            formElement.attr("method","post");
            var contextPath = "${pageContext.request.contextPath}";
            formElement.attr("action", contextPath + "/item/export");

            /*var filterRules  = $("#purchaseDetail_datagrid").datagrid("options").filterRules;
            //把过滤条件传入
            var inputElement=$("<input>");
            inputElement.attr("type","hidden");
            inputElement.attr("name","filterRules");
            inputElement.attr("value",JSON.stringify(filterRules));
            formElement.append(inputElement);*/
            $("body").append(formElement);  // 将表单放置在web中
            /*inputElement=$("<input>");
            inputElement.attr("type","hidden");
            inputElement.attr("name","deptId");
            inputElement.attr("value",deptId);
            formElement.append(inputElement);*/
            formElement.submit();//表单提交
            return false;
        });
    })
</script>
</body>
    <a id="exportCsv" href="javascript:void(0)">导出CSV</a>
</html>

页面点击“导出cvs”按钮后,会在页面body中追加一个表单

controller

@RequestMapping(value = "/export")
@ResponseBody
public void export(@RequestParam Map<String, Object> params, Model model, HttpServletRequest request, HttpServletResponse resp) {
	itemService.export(params, request, resp);
}

 service

package com.alphajuns.ssm.service.impl;

import com.alphajuns.ssm.mybatis.ItemMapper;
import com.alphajuns.ssm.pojo.Item;
import com.alphajuns.ssm.service.ItemService;
import com.alphajuns.ssm.util.AbstractCsvHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class ItemServiceImpl extends AbstractCsvHelper implements ItemService {

    @Autowired
    private ItemMapper itemMapper;

    @Override
    public void export(Map<String, Object> params, HttpServletRequest request, HttpServletResponse resp) {
        exportCvs(params, request, resp);
    }

    @Override
    protected Map<String, String> getCsvHeader() {
        Map<String, String> header = new LinkedHashMap<String, String>();
        header.put("id", "类目ID");
        header.put("parent_id", "父类目ID");
        header.put("title", "分类名称");
        header.put("status", "状态");
        header.put("sort_order", "排列序号");
        header.put("is_parent", "是否为父类目");
        header.put("created", "创建时间");
        header.put("updated", "更新时间");
        return header;
    }

    @Override
    protected String getFilename() {
        Date date = new Date();
        DateFormat df=new SimpleDateFormat("yyyy-MM-dd");
        String time=df.format(date);
        return "分类详情_" + time + ".csv";
    }

    @Override
    protected List<Map<String, ?>> getCsvRecords(Map<String, Object> params) {
        List<Map<String, ?>> itemContentCategoryMapList = itemMapper.queryItemContentCategory(params);
        for(Map itemContentCategoryMap : itemContentCategoryMapList){
            // 状态
            String status = String.valueOf(itemContentCategoryMap.get("status"));
            String statusVal = "";
            if ("1".equals(status)) {
                statusVal =  "正常";
            } else if("2".equals(status)) {
                statusVal = "删除";
            }
            itemContentCategoryMap.put("status", statusVal);

            // 状态
            String isParent = String.valueOf(itemContentCategoryMap.get("is_parent")) ;
            String isParentVal = "";
            if ("1".equals(isParent)) {
                isParentVal =  "true";
            } else if("2".equals(isParent)) {
                isParentVal = "false";
            }
            itemContentCategoryMap.put("is_parent", statusVal);
        }
        return itemContentCategoryMapList;
    }

    @Override
    protected void prepareParams(Map<String, Object> params) {

    }
}

其中需要cvs的jar包,maven坐标

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-csv</artifactId>
  <version>1.4</version>
</dependency>

模板方法模式中,导出步骤位于抽象类的一个方法中,该方法中调用了抽象类中的抽象方法,该抽象方法的实现类位于子类中,这样根据导出可以根据需要,自定义表头,导出的数据

导出cvs模板类AbstractCsvHelper

package com.alphajuns.ssm.util;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.log4j.Logger;

/**
 * 导出csv的帮助类
 * @author warrenxia
 *
 */
public abstract class AbstractCsvHelper {
    /**
     * logger
     */
    private static Logger logger = Logger.getLogger(AbstractCsvHelper.class);

    /**
     * 导出csv
     * @param params
     * @param request
     * @param resp
     */
    public void exportCvs(Map<String, Object> params, HttpServletRequest request, HttpServletResponse resp) {
        resp.setContentType("application/octet-stream");
        resp.setCharacterEncoding("GBK");
        int rows = 500;
        CSVFormat csvFormat = CSVFormat.DEFAULT;
        CSVPrinter csvPrinter = null;
        PrintWriter printWriter = null;
        try {
            String agent = (String)request.getHeader("USER-AGENT");
            if(agent != null && agent.toLowerCase().indexOf("firefox") > 0) {
                resp.setHeader("Content-Disposition","attachment; filename=" + new String(getFilename().getBytes("GB2312"),"ISO-8859-1"));
            } else {
                resp.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(getFilename(), "UTF-8"));
            }
            printWriter = resp.getWriter();
            csvPrinter = new CSVPrinter(printWriter, csvFormat);
            
            Map<String, String> header = getCsvHeader();
            insertHeader(header, csvPrinter);
            
            prepareParams(params);
            params.put("rows", rows);
            params.put("page", 1);
            //查询导出的数据
            List<Map<String,?>> mapList = getCsvRecords(params);
            int totalCount = 0;
            if(mapList!=null&&!mapList.isEmpty()){
                if (mapList.get(0).containsKey("TOTALCOUNT")) {
                    Number nTotalCount = (Number) mapList.get(0).get("TOTALCOUNT");
                    totalCount = nTotalCount.intValue();
                } else {
                    totalCount = mapList.size();
                }
            }
            // 设置最大导出数量
            String reportMaxRow = "20000";
            int intReportMaxRow = 5000;
            if(reportMaxRow!=null && !reportMaxRow.trim().equals("")){
                intReportMaxRow = Integer.parseInt(reportMaxRow.trim());
            }
            if(totalCount>intReportMaxRow){
                String errMsg = "不能导出大于"+intReportMaxRow+"条的数据,请缩小选择范围!";
                List<String> record = new ArrayList<String>();
                record.add(errMsg);
                csvPrinter.printRecord(record);
                throw new ReportBusinessException(errMsg);
            }
            insertRecords(mapList, header, csvPrinter);
            int totalPage = (int) Math.ceil((double)totalCount / rows);
            for (int i = 1; i < totalPage; i++) {
                params.put("page", i + 1);
                mapList = getCsvRecords(params);
                insertRecords(mapList, header, csvPrinter);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch(ReportBusinessException e){
            logger.error("报表导出异常",e);
            throw e;
        }
        catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                csvPrinter.flush();
                printWriter.flush();
                csvPrinter.close();
                printWriter.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    protected abstract Map<String, String> getCsvHeader();
     
    protected abstract String getFilename();
     
    protected abstract List<Map<String,?>> getCsvRecords(Map<String, Object> params);
     
    protected abstract void prepareParams(Map<String, Object> params);
     
    private void insertHeader(Map<String, String> header, CSVPrinter csvPrinter) throws IOException {
        csvPrinter.printRecord(header.values());
    }
     
    private void insertRecords(List<Map<String,?>> mapList, Map<String, String> header, CSVPrinter csvPrinter) throws IOException {
        for (Map<String, ?> map : mapList) {
            List<String> record = new ArrayList<String>();
            for (Entry<String, String> entry : header.entrySet()) {
                Object object = map.get(entry.getKey());
                if (object == null) {
                    record.add("");
                } else {
                    record.add(String.valueOf(object));
                }
            }
            csvPrinter.printRecord(record);
        }
    }
}

报表导出异常类

package com.alphajuns.ssm.util;

public class ReportBusinessException extends RuntimeException{

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1L;
    
     /**
       * 
       */
        private String errorCode;
        /**
       * 
       */
        private String message;

        /**
         * BusinessException
         * @param message message
       */
        public ReportBusinessException(String message) {
            this.message = message;
        }

        /**
         * BusinessException
         * @param errorCode errorCode
         * @param message message
       */
        public ReportBusinessException(String errorCode, String message) {
            this.message = message;
            this.errorCode = errorCode;
        }

        /**
         * BusinessException
         * @param message message
         * @param cause cause
       */
        public ReportBusinessException(String message, Throwable cause) {
            super(cause);
            this.message = message;
        }
        
        /**
         * BusinessException
         * @param errorCode errorCode, 
         * @param message message
         * @param cause cause
       */
        public ReportBusinessException(String errorCode, String message, Throwable cause) {
            super(errorCode, cause);
            this.errorCode = errorCode;
            this.message = message;
        }
        public String getErrorCode() {
            return this.errorCode;
        }

        public void setErrorCode(String errorCode) {
            this.errorCode = errorCode;
        }

        @Override
        public String getMessage() {
            return this.message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

}

mapper接口

List<Map<String,?>> queryItemContentCategory(Map<String, Object> params);

mapper.xml

<select id="queryItemContentCategory" resultType="map">
        select * from tb_content_category
    </select>
原文地址:https://www.cnblogs.com/alphajuns/p/13097527.html