1 自定义注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelTable {
    String value() default "";
}

2 使用在字段上

/**
* 使用举例
*/
public class User {

    //姓名
    @ExcelTable("姓名")
    private String name;

    //性别
    @ExcelTable("性别")
    private String sex;

    //年龄
    @ExcelTable("年龄")
    private String age;

}

3 导出excel表的工具类

/**
 * Excel导出工具类
 *
 * @author ellen
 * @version 1.0
 * @date 2018/11/11
 */
public class ExcelUtil {

    /**
     * @param list
     * @param sheetName
     * @param response
     * @param <T>
     * @throws Exception
     * @Description : 导出Excel(导出到浏览器,工作表的大小是2003支持的最大值)
     */
    public static <T> void listToExcel(List<T> list, String sheetName, HttpServletResponse response) throws Exception {
        listToExcel(list, sheetName, 65535, response);
    }

    /**
     * @param list
     * @param sheetName
     * @param response
     * @param <T>
     * @throws Exception
     * @Description : 导出Excel(导出到浏览器,可以自定义工作表的大小)
     */
    public static <T> void listToExcel(List<T> list, String sheetName, int sheetSize, HttpServletResponse response) throws Exception {

        //设置默认文件名为当前时间:年月日时分秒
        String fileName = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()).toString();
        //设置response头信息
        response.reset();
        //改成输出excel文件
        response.setContentType("application/vnd.ms-excel");
        //设置文件下载头
        response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");
        try {
            OutputStream out = response.getOutputStream();
            listToExcel(list, sheetSize, sheetName, out);
        } catch (Exception e) {
            e.printStackTrace();

            //如果是ExcelException,则直接抛出
            if (e instanceof CustomException) {
                throw (CustomException) e;
                //否则将其它异常包装成ExcelException再抛出
            } else {
                throw new CustomException("导出Excel失败");
            }
        }
    }

    /**
     * 一次导出全部
     *
     * @param list
     * @param sheetSize 每个工作表记录的最大数值
     * @param sheetName 每个工作表的名字
     * @param out       导出流
     * @param <T>
     * @throws Exception
     * @Description : 导出Excel(可以导出到本地文件系统,可自定义工作表大小)
     */
    public static <T> void listToExcel(List<T> list, int sheetSize, String sheetName, OutputStream out) throws Exception {

        if (list.size() == 0 || list == null) {
            throw new CustomException("数据源中没有任何数据");
        }
        //最大数值为65535
        if (sheetSize > 65535 || sheetSize < 1) {
            sheetSize = 65535;
        }

        //新建一个xls工作簿
        Workbook wb = new HSSFWorkbook();
        CreationHelper createHelper = wb.getCreationHelper();
        Sheet sheet = null;
        //如果数值太多,放到多个工作表中
        //计算一共有多少个工作表
        double sheetNum = Math.ceil(list.size() / new Integer(sheetSize).doubleValue());

        //多个工作表的情况
        for (int i = 0; i < sheetNum; i++) {

            if (sheetNum == 1) {
                //新建一个表
                sheet = wb.createSheet(sheetName);//表的名字是Excel不得超过31个字符
                fillSheet(list, sheet, 0, list.size() - 1);
            } else {
                //获取开始索引和结束索引
                int firstIndex = i * sheetSize;
                int lastIndex = (i + 1) * sheetSize - 1 > list.size() - 1 ? list.size() - 1 : (i + 1) * sheetSize - 1;

                sheet = wb.createSheet(sheetName + (i + 1));
                fillSheet(list, sheet, firstIndex, lastIndex);
            }

        }

        // Write the output to a file
        wb.write(out);
    }

    /**
     * 填充数据
     *
     * @param list
     * @param sheet      工作表插入
     * @param firstIndex 开始索引
     * @param lastIndex  结束索引
     * @param <T>
     * @throws Exception
     */
    private static <T> void fillSheet(List<T> list, Sheet sheet, int firstIndex, int lastIndex) throws Exception {
        Field[] fields = list.get(0).getClass().getDeclaredFields();
        //记录行数
        int rowNum = 0;
        //记录列数
        int cellNum = 0;
        Row row = sheet.createRow(0);
        row.setHeightInPoints(30);
        rowNum++;
        List<String> keylist = new ArrayList<>();
        for (Field field : fields) {

            Cell cell = row.createCell(cellNum);
            if (field.isAnnotationPresent(ExcelTable.class)) {
                ExcelTable excelRowName = field.getAnnotation(ExcelTable.class);
                cell.setCellValue(excelRowName.value());
                //保存到list
                keylist.add(field.getName());
                cellNum++;
            }

        }

        for (int index = firstIndex; index <= lastIndex; index++) {

            T object = list.get(index);
            Row row1 = sheet.createRow(rowNum);
            rowNum++;
            cellNum = 0;
            for (String string : keylist) {
                Field field = object.getClass().getDeclaredField(string);
                //设为可见
                field.setAccessible(true);
                Object value = field.get(object);
                Cell cell = row1.createCell(cellNum);

                //不需要做处理
                if (value != null) {
                    cell.setCellValue(value.toString());
                }

                cellNum++;
            }

        }
    }

    /**
     * 分工作表导出
     *
     * @param list
     * @param sheetSize 每个工作表的行数(不得超过65535)
     * @param sheetName 工作表的名称
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> Workbook CreateExcelWorkbook(List<T> list, int sheetSize, String sheetName) throws Exception {

        if (list.size() == 0 || list == null) {
            throw new CustomException("数据源中没有任何数据");
        }
        //最大数值为65535
        if (sheetSize > 65535 || sheetSize < 1) {
            throw new CustomException("sheetSize数值有误");
        }

        //新建一个xls工作簿
        Workbook wb = new HSSFWorkbook();
        CreationHelper createHelper = wb.getCreationHelper();
        Sheet sheet = null;

        //新建一个表
        sheet = wb.createSheet(sheetName);//表的名字是Excel不得超过31个字符
        fillSheet(list, sheet, 0, list.size() - 1);

        return wb;
    }

    /**
     * 添加数据
     *
     * @param list
     * @param sheetSize
     * @param sheetName
     * @param FilePath
     * @param <T>
     * @throws Exception
     */
    public static <T> void addListToExcel(List<T> list, int sheetSize, String sheetName, String FilePath) throws Exception {
        if (list.size() == 0 || list == null) {
            throw new CustomException("数据源中没有任何数据");
        }
        // 判断数据大小是否比最后一个表剩余的大小小,小的话可以直接在表中继续写,大的话在当前表中写完后继续在后面表中写
        //获得一个xls工作簿
        Workbook wb = returnWorkBookByFileName(FilePath);
        CreationHelper createHelper = wb.getCreationHelper();
        //获得最后一个工作表
        Sheet sheet = wb.getSheetAt(wb.getNumberOfSheets() - 1);
        //记录行数
        int rowNum = sheet.getLastRowNum();

        double sheetNum = 0;
        if (sheetSize > (65535 - sheet.getLastRowNum())) {
            // 判断当前表填满后还需要多少个表
            sheetNum = Math.ceil((list.size() - (65535 - sheet.getLastRowNum())) / new Integer(65535).doubleValue());
        }

        // 如果在当前表中可以能容纳list大小的数据
        if (sheetNum == 0) {
            ContinueToSheet(list, sheet, rowNum, 0, list.size() - 1);
        } else {
            int i = 0;
            // 将当前表填充完整
            ContinueToSheet(list, sheet, rowNum, 0, 65535 - sheet.getLastRowNum());
            i = 65535 - sheet.getLastRowNum();
            // 继续将新建表填充
            for (int index = 0; index < sheetNum; index++) {
                sheet = wb.createSheet(sheetName + (i + 1));
                ContinueToSheet(list, sheet, rowNum, i + 1, i + 65535);
                i += 65535;
            }
        }

        // Write the output to a file
        FileOutputStream fileOut = new FileOutputStream(FilePath);
        wb.write(fileOut);
        fileOut.close();
    }

    /**
     * @param list
     * @param sheet      工作表插入
     * @param beginIndex 开始索引
     * @param endIndex   结束索引
     * @param <T>
     * @throws Exception
     */
    private static <T> void ContinueToSheet(List<T> list, Sheet sheet, int rowNum, int beginIndex, int endIndex) throws Exception {
        Field[] fields = list.get(0).getClass().getDeclaredFields();

        // 获得最后一行
        Row row = sheet.getRow(rowNum);
        //记录列数
        int cellNum = 0;

        // 列数
        List<String> keylist = null;
        //  row.setHeightInPoints(30);
        keylist = new ArrayList<>();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelTable.class)) {
                ExcelTable excelRowName = field.getAnnotation(ExcelTable.class);
                //保存到list
                keylist.add(field.getName());
                cellNum++;
            }

        }

        for (int index = beginIndex; index <= endIndex; index++) {

            T object = list.get(index);
            Row row1 = sheet.createRow(rowNum);
            rowNum++;
            cellNum = 0;
            for (String string : keylist) {
                Field field = object.getClass().getDeclaredField(string);
                //设为可见
                field.setAccessible(true);
                Object value = field.get(object);
                Cell cell = row1.createCell(cellNum);
                if (value == null) {
                    cell.setCellValue(" ");
                } else {
                    //不需要做处理
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                }
                cellNum++;
            }

        }

    }

    /**
     * 通过文件输入流得到一个工作蒲
     *
     * @param is
     * @return
     * @throws IOException
     */
    private static HSSFWorkbook returnWorkBookByFileStream(InputStream is) throws IOException {
        HSSFWorkbook wb = null;
        wb = new HSSFWorkbook(is);
        return wb;
    }

    /**
     * 通过文件路径得到一个工作蒲
     *
     * @param FilePath
     * @return
     * @throws IOException
     */
    private static HSSFWorkbook returnWorkBookByFileName(String FilePath) throws IOException {
        InputStream inp = new FileInputStream(FilePath);
        return returnWorkBookByFileStream(inp);
    }

    /**
     * @param list
     * @param sheetName
     * @param <T>
     * @throws Exception
     * @Description : 导出Excel(可以导出到本地文件系统,工作表大小为2003支持的最大值)
     */
    public static <T> void listToExcel(List<T> list, String sheetName, OutputStream outputStream) throws Exception {
        listToExcel(list, 65535, sheetName, outputStream);
    }

    /**
     * @param list
     * @param sheetSize
     * @param sheetName
     * @param FilePath
     * @param <T>
     * @throws Exception
     */
    public static <T> void addListToExcel(List<T> list, int sheetSize, String sheetName, String FilePath, OutputStream out) throws Exception {

        if (list.size() == 0 || list == null) {
            throw new CustomException("数据源中没有任何数据");
        }
        //最大数值为65535
        if (sheetSize > 65535 || sheetSize < 1) {
            sheetSize = 65535;
        }

        //获得一个xls工作簿
        Workbook wb = returnWorkBookByFileName(FilePath);
        CreationHelper createHelper = wb.getCreationHelper();
        //获得最后一个工作表
        Sheet sheet = wb.getSheetAt(wb.getNumberOfSheets() - 1);

        //判断当前添加的表
        if (sheetSize > (65535 - sheet.getLastRowNum())) {

        }
        double sheetNum = Math.ceil((list.size() + sheet.getLastRowNum()) / new Integer(sheetSize).doubleValue());

        //多个工作表的情况
        for (int i = 0; i < sheetNum; i++) {

            if (sheetNum == 1) {
                //新建一个表
                //    sheet = wb.createSheet(sheetName);//表的名字是Excel不得超过31个字符
                addSheet(list, sheet, 0, list.size() - 1);
            } else {
                //获取开始索引和结束索引
                int firstIndex = i * sheetSize;
                int lastIndex = (i + 1) * sheetSize - 1 > list.size() - 1 ? list.size() - 1 : (i + 1) * sheetSize - 1;

                sheet = wb.createSheet(sheetName + (i + 1));
                fillSheet(list, sheet, firstIndex, lastIndex);
            }

        }

        // Write the output to a file
        FileOutputStream fileOut = new FileOutputStream(FilePath);
        wb.write(fileOut);
        fileOut.close();

    }


    /**
     * @param list
     * @param sheet      工作表插入
     * @param firstIndex 开始索引
     * @param lastIndex  结束索引
     * @param <T>
     * @throws Exception
     */
    private static <T> void addSheet(List<T> list, Sheet sheet, int firstIndex, int lastIndex) throws Exception {
        Field[] fields = list.get(0).getClass().getDeclaredFields();
        //记录行数
        int rowNum = sheet.getLastRowNum();
        //获得最后一行
        Row row = sheet.getRow(rowNum);
        //记录列数
        int cellNum = 0;


        //  row.setHeightInPoints(30);
        rowNum++;
        List<String> keylist = new ArrayList<>();
        for (Field field : fields) {

            Cell cell = row.createCell(cellNum);
            if (field.isAnnotationPresent(ExcelTable.class)) {
                ExcelTable excelRowName = field.getAnnotation(ExcelTable.class);
                cell.setCellValue(excelRowName.value());
                //保存到list
                keylist.add(field.getName());
                cellNum++;
            }

        }

        for (int index = firstIndex; index <= lastIndex; index++) {

            T object = list.get(index);
            Row row1 = sheet.createRow(rowNum);
            rowNum++;
            cellNum = 0;
            for (String string : keylist) {
                Field field = object.getClass().getDeclaredField(string);
                //设为可见
                field.setAccessible(true);
                Object value = field.get(object);
                Cell cell = row1.createCell(cellNum);
                if (value == null) {
                    cell.setCellValue(" ");
                } else {
                    cell.setCellValue(value.toString());
                }
                cellNum++;
            }

        }

    }

    public static Workbook addDate(List<T> list, int sheetSize, String sheetName, Workbook wb) {

        if (list.size() == 0 || list == null) {
            throw new CustomException("数据源中没有任何数据");
        }
        //最大数值为65535
        if (sheetSize > 65535 || sheetSize < 1) {
            sheetSize = 65535;
        }

        CreationHelper createHelper = wb.getCreationHelper();
        //获得最后一个工作表
        Sheet sheet = wb.getSheetAt(wb.getNumberOfSheets() - 1);

        //如果数值太多,放到多个工作表中
        //计算一共有多少个工作表
        double sheetNum = Math.ceil(list.size() + sheet.getLastRowNum() / new Integer(sheetSize).doubleValue());

        //多个工作表的情况
        for (int i = 0; i < sheetNum; i++) {

//            if(sheetNum == 1){
//                //新建一个表
//                //    sheet = wb.createSheet(sheetName);//表的名字是Excel不得超过31个字符
//                addSheet(list,sheet,0,list.size()-1);
//            }
//            else {
//                //获取开始索引和结束索引
//                int firstIndex=i * sheetSize;
//                int lastIndex=(i+1)*sheetSize-1>list.size()-1 ? list.size()-1 : (i+1)*sheetSize-1;
//
//                sheet = wb.createSheet(sheetName + (i+1));
//                fillSheet(list,sheet,firstIndex,lastIndex);
//            }
//
//
//        }
//
//        // Write the output to a file
//        FileOutputStream fileOut = new FileOutputStream(FilePath);
//        wb.write(fileOut);
//        fileOut.close();

        }

        return wb;
    }

}

4 简单使用实例

@Test
    public void testExcel() throws Exception {
        List<User> list = new ArrayList<User>();
        list.add(new User("zhangsan", "男", 11));
        list.add(new User("lisi", "男", 12));
        list.add(new User("wangwu", "男", 13));

        //本地导出
        FileOutputStream outputStream = new FileOutputStream("d:\\测试excel导出.xlsx");
        ExcelUtil.listToExcel(list, 65535, "user", outputStream);
        //浏览器导出
        ExcelUtil.listToExcel(list, "user", httpServletResponse);
    }

5 本地导出效果(浏览器导出参考实例)

java生成excel文件流返回给前端 java导出excel到浏览器_数据

附:maven添加poi依赖

<!-- poi依赖,excel表导出 -->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>3.17</version>
</dependency>