栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java导入导出

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java导入导出

文章目录

方式一:采用easyexcel导入方式二:采用POI导入

方式一:采用easyexcel导入

1.需要导入的依赖

     
                com.alibaba
                easyexcel
                2.2.8
            

实体类代码:

@Data
@Entity  // 该注解声明一个实体类,与数据库中的表对应
@Table(name = "tb_user")  //表示当映射多个表时,指定表的表中的字段。默认值为主表的表名。
@ApiModel(description = "用户表")
public class User{
    //主键标识:表明该声明的属性字段和数据库的主键字段一一对应
    @Id
    //主键生成策略,不写意味着没有主键生成策略,也意味着是手动主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @ApiModelProperty(hidden = true)   //swagger注解
    private Integer id;
    @ApiModelProperty(value = "用户名")
    @ExcelProperty(index = 1)
    //unique
    //表示该字段是否为唯一标识,默认为false。如果表中有一个字段需要唯一标识,则既可以使用该标记,也可以使用@Table标记中的@UniqueConstraint。
    //nullable 表示该字段是否可以为null值,默认为true。
    // length  表示字段的长度,当字段的类型为varchar时,该属性才有效,默认为255个字符。
    @Column(name = "user_name", unique = true, nullable = false, length = 50)
    private String userName;
    @ApiModelProperty(value = "用户工号")
    @ExcelProperty(index = 2)
    @Column(name = "login_name", length = 20)
    private String loginName;

    @ApiModelProperty(value = "密码")
    @Column(name = "password", length = 50)
    private String password;

    @ApiModelProperty(value = "头像")
    @Column(name = "avatar", length = 100)
    private String avatar;

    @ApiModelProperty(value = "性别")
    @ExcelProperty(index = 3)
    @Column(name = "gender", nullable = false, length = 1)
    private String gender;

    @ApiModelProperty(value = "邮箱")
    @ExcelProperty(index = 4)
    @Column(name = "email", length = 50)
    private String email;

    @ApiModelProperty(value = "描述")
    @ExcelProperty(index = 7,value = "描述")
    @Column(name = "description")
    private String description;

    @ApiModelProperty(value = "所属公司")
    @ExcelProperty(index = 5,value = "所属公司")
    @Column(name = "company", length = 50)
    private String company;

    @ApiModelProperty(value = "职位")
    @ExcelProperty(index = 6,value ="职位")
    @Column(name = "position", length = 20)
    private String position;

    @ApiModelProperty(hidden = true)
    private Date createTime;

    @ApiModelProperty(hidden = true)
    private Date updateTime;
}

实现监听回调

public class PrtcpntInfoListener extends AnalysisEventListener {
    private static final Logger log = LoggerFactory.getLogger(PrtcpntInfoListener.class);
    private static int TOTAL_COUNT;

    
    private static final int BATCH_COUNT = 110000;
    List list = new ArrayList<>();
    private BatchLead batchLead;

    public PrtcpntInfoListener(BatchLead batchLead) {
        this.batchLead = batchLead;
    }

    
    @Override
    public void invoke(User data, AnalysisContext context) {
       log.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        // 每达到阈值,就去做批量入库,防止内存溢出
        if (list.size() >= BATCH_COUNT) {
            ThreadOperation.readExcel(list);
            TOTAL_COUNT += list.size();
            list.clear();
        }
    }

    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        //执行完让线程直接进入等待
         batchLead.save(list);
        TOTAL_COUNT += list.size();
        log.info("所有数据已入库完成,总计:{}条", TOTAL_COUNT);
    }


    public static void main(String[] args) {
        Long startTime = System.currentTimeMillis();
        ExcelReader excelReader = null;
        try {
            String filePath = "C:/Users/86135/Desktop/用户信息.xlsx";
            excelReader = EasyExcel.read(filePath, User.class, new PrtcpntInfoListener(new BatchLead())).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).headRowNumber(2).build();
            excelReader.read(readSheet);
        } finally {
            // 关闭资源
            if (excelReader != null) {
                excelReader.finish();
            }
        }
        log.info("总耗时:" + (System.currentTimeMillis() - startTime) / 1000 + "(s)");
    }
}

保存数据 JDBC直连方式

public class BatchLead {
    private static final Logger log = LoggerFactory.getLogger(BatchLead.class);
    int i = 0;

    public void save(List list) {
        System.out.println("保存="+list.size());
        Long startTime = System.currentTimeMillis();
        Connection conn = null;
        PreparedStatement pstmt = null;
        String sql = "insert into tb_user(user_name,login_name,password,avatar,gender,email,description,company,position)values(?,?,?,?,?,?,?,?,?)";
        conn = getConnection();
        try {
            conn.setAutoCommit(false);
            pstmt = conn.prepareStatement(sql);
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        for (User dataInfo : list) {
            try {
                pstmt.setString(1, dataInfo.getUserName());
                pstmt.setString(2, dataInfo.getLoginName());
                pstmt.setString(3, dataInfo.getPassword());
                pstmt.setString(4, dataInfo.getAvatar());
                pstmt.setString(5, dataInfo.getGender());
                pstmt.setString(6, dataInfo.getEmail());
                pstmt.setString(7, dataInfo.getDescription());
                pstmt.setString(8, dataInfo.getCompany());
                pstmt.setString(9, dataInfo.getPosition());
                pstmt.addBatch();
                i++;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        try {
            pstmt.executeBatch();
            conn.commit();
            conn.close();
            pstmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        log.info("批量入库,本次入库数据:{}条,耗时:{}(s)", list.size(), (System.currentTimeMillis() - startTime) / 1000);
    }

    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1:3306/localtest?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC",
                    "root", "root");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

或者使用mybatis,在覆盖doAfterAllAnalysed方法中调用

   @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        UserMapper userMapper = ApplicationContextProvider.getBean(UserMapper.class);
        userMapper.batchAddUser(list);
        TOTAL_COUNT += list.size();
        log.info("所有数据已入库完成,总计:{}条", TOTAL_COUNT);
    }

controller层调用:

  
    @PostMapping("/users/add")
    @ApiOperation(value = "批量导入")
    public ResultDTO saveBatchUser(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        if (!StrUtil.endWithAny(fileName, EXCEL_XLS, EXCEL_XLSX)) {
            return ResultDTO.error("只支持.xlsx与.xls格式的文件导入");
        }
        return  myUserService.saveBatchUser(file,fileName);
    }

service层代码:

  public ResultDTO saveBatchUser(MultipartFile multipartFile, String fileName) {
        Long startTime = System.currentTimeMillis();
        ExcelReader excelReader = null;
        File file = null;
        try {
            String[] filename = fileName.split("\.");
            file=File.createTempFile(filename[0], ".xlsx");
            multipartFile.transferTo(file);
            excelReader = EasyExcel.read(file, User.class, new PrtcpntInfoListener(new BatchLead())).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).headRowNumber(1).build();
            excelReader.read(readSheet);
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (excelReader != null) {
                excelReader.finish();
            }
           // file.deleteonExit();
        }
        log.info("总耗时:" + (System.currentTimeMillis() - startTime) / 1000 + "(s)");

        return ResultDTO.isSuccess();
    }

上面是单线程版
多线程保存数据库方式
先定义线程资源类

public class importThread implements Runnable {
    BatchLead batchLead;
    private List list;
    private CountDownLatch end;
    private MyUserMapper myUserMapper;

    public importThread(List list, CountDownLatch begin, CountDownLatch end, BatchLead batchLead) {
        this.list = list;
        this.end = end;
        this.batchLead = batchLead;
    }

  @Override
    public void run() {
        //这里三种方式选取一种
        //1.mybatis方式
        UserMapper userMapper = ApplicationContextProvider.getBean(UserMapper.class);
        userMapper.batchAddUser(list);
        //2.jpa方式
      //  MyUserMapper myUserMapper = ApplicationContextProvider.getBean(MyUserMapper.class);
      //  myUserMapper.saveAll(list);
        //3.JDBC直连
      //  batchLead.save(list);
      //  end.countDown();
    }
}

上面连接数据库如果使用mybatis方式,sql语句如下

     
        insert into tb_user(user_name,login_name,password,avatar,gender,email,description,company,position) values
        
            (#{item.userName},#{item.loginName},#{item.password},#{item.avatar},#{item.gender},#{item.email},#{item.description},#{item.company},#{item.position})
        
    

使用线程池

public class ThreadOperation {
    public static void readExcel(List list) {
        //一个线程处理数据数
        int count = 11000;
        // 开启的线程数
        int runSize = 10;
        // 存放每个线程的执行数据
        List newlist = null;
//        int corePoolSize,核心线程数
//        int maximumPoolSize,最大线程数
//        long keepAliveTime,线程空闲时最大存活时间
//        TimeUnit unit,最大存活时间单位
//        BlockingQueue workQueue,任务队列
//        ThreadFactory threadFactory,线程工厂用默认的即可
//        RejectedExecutionHandler handler)线程池和队列都满时的拒绝策略

        //创建一个线程池,数量和开启线程的数据量一样
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                runSize, runSize,  1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),
                new ThreadPoolExecutor.DiscardOldestPolicy());
                //并发容器,计数器,等待协同
        CountDownLatch end = new CountDownLatch(runSize);
        //循环创建线程
        for (int i = 0; i < runSize; i++) {
            //计算每个线程执行的数据
            if ((i+1)==runSize){
                newlist=list.subList((i*count),list.size());
            }else {
                newlist=list.subList((i*count),(i+1)*count);
            }
            //线程类 操作资源
            importThread mythead = new importThread(newlist, end,new BatchLead());
            //执行线程
            executor.execute(mythead);
        }
        try {
            end.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //执行完关闭线程池
        executor.shutdown();
    }
}

方式二:采用POI导入

依赖准备

             
                org.apache.poi
                poi
                3.9
            

            
                org.apache.poi
                poi-ooxml
                3.9
            

            
                org.apache.commons
                commons-lang3
                3.4
            

自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableExport {
     String fileName();
}


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableExportField {
     int colWidth() default  100;
     String colName();
}


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface importIndex {
     int index() ;
}

//pojo
@EnableExport(fileName = "XXX功能")
public class DataCheckExport {
    @EnableExportField(colName = "编码",colWidth = 90)
    @importIndex(index = 0)
    private String code;
    ....
    }

导入 、导出、 自定义表格颜色工具类

public class ExcelUtils {
    
    public static final  Map> ALL_SELECT_LIST_MAP = new HashMap> ();
        
        public static List parseExcelToList(File excel,Class clazz){
            List res = new ArrayList();
            // 创建输入流,读取Excel
            InputStream is = null;
            Sheet sheet = null;
            try {
                is = new FileInputStream(excel.getAbsolutePath());
                if (is != null) {
                    Workbook workbook = WorkbookFactory.create(is);
                    //默认只获取第一个工作表
                    sheet = workbook.getSheetAt(0);
                    if (sheet != null) {
                        int i = 2;
                        String values[] ;
                        Row row = sheet.getRow(i);
                        while (row != null) {
                            //获取单元格数目
                            int cellNum = row.getPhysicalNumberOfCells();
                            values = new String[cellNum];
                            for (int j = 0; j <= cellNum; j++) {
                                Cell cell =   row.getCell(j);
                                if (cell != null) {
                                    //设置单元格内容类型
                                    cell.setCellType(Cell.CELL_TYPE_STRING );
                                    //获取单元格值
                                    String value = cell.getStringCellValue() == null ? null : cell.getStringCellValue();
                                    values[j]=value;
                                }
                            }
                            Field[] fields = clazz.getDeclaredFields();
                            Object obj = clazz.newInstance();
                            for(Field f : fields){
                                if(f.isAnnotationPresent(importIndex.class)){
                                    importIndex annotation = f.getAnnotation(importIndex.class);
                                    int index = annotation.index();
                                    String useSetMethodName = annotation.useSetMethodName();
                                    if(!"".equals(useSetMethodName)){
                                        Object val = TypeUtils.cast(values[index],f.getType(),null);
                                        f.setAccessible(true);
                                        Method method = clazz.getMethod(useSetMethodName, new Class[]{f.getType(),Object.class});
                                        method.setAccessible(true);
                                        method.invoke(obj, new Object[]{f.get(obj),val});
                                    }else{
                                        f.setAccessible(true);
                                        Object val =TypeUtils.cast(values[index],f.getType(),null);
                                        f.set(obj,val);
                                    }
                                }
                            }
                            res.add(obj);
                            i++;
                            row=sheet.getRow(i);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return res;
        }

        
        public static List parseExcelToList(InputStream excel,Class clazz) throws IOException,
                InvalidFormatException,
                InstantiationException,
                IllegalAccessException,
                NoSuchMethodException,
                InvocationTargetException {
            List res = new ArrayList();
            // 创建输入流,读取Excel
            InputStream is = null;
            Sheet sheet = null;

            is = excel;
            if (is != null) {
                Workbook workbook = WorkbookFactory.create(is);
                //默认只获取第一个工作表
                sheet = workbook.getSheetAt(0);
                if (sheet != null) {
                    int i = 2;
                    String values[] ;
                    Row row = sheet.getRow(i);
                    while (row != null) {
                        //获取单元格数目
                        int cellNum = row.getPhysicalNumberOfCells();
                        values = new String[cellNum];
                        for (int j = 0; j <= cellNum; j++) {
                            Cell cell =   row.getCell(j);
                            if (cell != null) {
                                //设置单元格内容类型
                                cell.setCellType(Cell.CELL_TYPE_STRING );
                                //获取单元格值
                                String value = cell.getStringCellValue() == null ? null : cell.getStringCellValue();
                                values[j]=value;
                            }
                        }
                        Field[] fields = clazz.getDeclaredFields();
                        Object obj = clazz.newInstance();
                        for(Field f : fields){
                            if(f.isAnnotationPresent(importIndex.class)){

                                importIndex annotation = f.getAnnotation(importIndex.class);
                                int index = annotation.index();
                                Object value = values[index];
                                if(f.isAnnotationPresent(EnableSelectList.class)){

                                    value = getKeyByValue(ALL_SELECT_LIST_MAP.get(index),String.valueOf(value ) );

                                }
                                String useSetMethodName = annotation.useSetMethodName();
                                if(!"".equals(useSetMethodName)){
                                    Object val =TypeUtils.cast(value,f.getType(),null);
                                    f.setAccessible(true);
                                    Method method = clazz.getMethod(useSetMethodName, new Class[]{f.getType(),Object.class});
                                    method.setAccessible(true);
                                    method.invoke(obj, new Object[]{f.get(obj),val});
                                }else{
                                    f.setAccessible(true);
                                    Object val =TypeUtils.cast(value,f.getType(),null);
                                    f.set(obj,val);
                                }

                            }
                        }
                        res.add(obj);
                        i++;
                        row=sheet.getRow(i);
                    }
                }
            }

            return res;
        }

        
        public static void exportExcel(OutputStream outputStream, List  dataList, Class clazz, Map> selectListMap,String exportTitle){
            //创建一个Excel工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            //建立表
            HSSFSheet hssfsheet =  workbook.createSheet();

            hssfsheet.setDefaultRowHeight( ( short )(20*20) );
            //检查当前pojo是否允许导出
            if(clazz.isAnnotationPresent(EnableExport.class)) {
                EnableExport export = (EnableExport) clazz.getAnnotation(EnableExport.class);
                //获取所有标题名称
                List colNames =new ArrayList();
                //获取所有标题的背景颜色
                List colors =new ArrayList();
                //所有允许导出的字段
                List fieldList = new ArrayList();
                for(Field field : clazz.getDeclaredFields()){
                    if(field.isAnnotationPresent(EnableExportField.class)){
                        EnableExportField enableExportField = field.getAnnotation(EnableExportField.class);
                        colNames.add(enableExportField.colName());
                        colors.add(enableExportField.cellColor());
                        fieldList.add(field);
                    }
                }
                //设置每列的宽度
                for(int i=0;i colNames,List colors){
            //插入标题行
            hssfRow = hssfsheet.createRow(1);
            for (int i = 0; i < colNames.size(); i++) {
                hssfcell = hssfRow.createCell(i);
                hssfcell.setCellStyle(getTitleCellStyle(workbook,colors.get(i)));
                hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
                hssfcell.setCellValue(colNames.get(i));
            }
        }
        
        public static void createDataValidation(Sheet sheet, Map> selectListMap) {
            if(selectListMap!=null) {
                for(Map.Entry> entry:selectListMap.entrySet()  ){
                    Integer key = entry.getKey();
                    Map value = entry.getValue();
                    // 第几列校验(0开始)key 数据源数组value
                    if(value.size()>0) {
                        int i=0;
                        String[] valueArr = new String[value.size()];
                        for(Map.Entry ent :value.entrySet()){
                            valueArr[i] = ent.getValue();
                            i++;
                        }
                        CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(2, 65535, key, key);
                        DataValidationHelper helper = sheet.getDataValidationHelper();
                        DataValidationConstraint constraint = helper.createExplicitListConstraint(valueArr);
                        DataValidation dataValidation = helper.createvalidation(constraint, cellRangeAddressList);
                        //处理Excel兼容性问题
                        if (dataValidation instanceof XSSFDataValidation) {
                            dataValidation.setSuppressDropDownArrow(true);
                            dataValidation.setShowErrorBox(true);
                        } else {
                            dataValidation.setSuppressDropDownArrow(false);
                        }
                        dataValidation.setEmptyCellAllowed(true);
                        dataValidation.setShowpromptBox(true);
                        dataValidation.createpromptBox("提示", "只能选择下拉框里面的数据");
                        sheet.addValidationData(dataValidation);
                    }
                }
            }
        }
        
        private static String getKeyByValue(Map selectMap,String value){
            if(selectMap!=null){
                for(Map.Entry ent :selectMap.entrySet()){
                    if(value!=null&&value.equals(ent.getValue()))
                        return ent.getKey();
                }
            }else{
                return value;
            }
            return null;
        }


        
        private static boolean isNumeric(String str) {
            Pattern pattren =
                    Pattern.compile("[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");
            if (str != null && !"".equals(str.trim())) {
                Matcher matcher = pattren.matcher(str);
                if (matcher.matches()) {
                    if (!str.contains(".") && str.startsWith("0")) {
                        return false;
                    }
                    return true;
                }
            }
            return false;
        }

        
        private static void setCellValue(Object value,HSSFCell hssfcell,HSSFRow hssfRow,CellStyle cellStyle,int cellIndex) {
            String valueStr = String.valueOf(value);
            hssfcell =hssfRow.createCell(cellIndex );
            //暂时认为数字类型不会有下拉列表
            if (isNumeric(valueStr)) {
                hssfcell.setCellStyle(cellStyle);
                hssfcell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
                hssfcell.setCellValue(Double.valueOf(valueStr));
            } else {
                hssfcell.setCellStyle(cellStyle);
                hssfcell.setCellType(HSSFCell.CELL_TYPE_STRING);
                hssfcell.setCellValue(valueStr);
            }
        }
}
 

还可以自定义表格颜色,根据业务需要使用,定义一个枚举类存储需要的颜色。

public enum ColorEnum {
    RED("红色", HSSFColor.RED.index),
    GREEN("绿色", HSSFColor.GREEN.index),
    BLANK("白色", HSSFColor.WHITE.index),
    YELLOW("黄色", HSSFColor.YELLOW.index),
    BLUE("蓝色", HSSFColor.CORNFLOWER_BLUE.index);
    private String name;
    private short index;
    private ColorEnum( String name, short index) {
        this.name = name;
        this.index = index;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public short getIndex() {
        return index;
    }

    public void setIndex(short index) {
        this.index = index;
    }

}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号