zoukankan      html  css  js  c++  java
  • 使用回调方式写POI导入excel工具类

    场景是这样的:为了做一个excel导入的功能,为了尽可能的写一个通用的工具类,将与poi有关的东西都封装起来,以便以其他人员只用关心自己的业务,不用和poi打交道。

    写到最后,现在还是会有poi的东西暴漏出来一点,暴漏出来的这个应该是必须的。

    为了模拟这个场景,先写两个service方法,用于和数据库交互,存入从模板中读取的数据。代码如下:

    1.berthservice

    public class BerthService {
        public void update(){
            System.out.println("this is berth service");
        }
    }

    2.sensorservice

    public class SensorServices {
        public void update(Sensor sensor){
            //do services
            System.out.println("success update:"+sensor.getName());
        }
    }

    之所以要写两个service,是为了测试,对于同一个xls模板,是不是可以使用两次。

    然后需要写一个实体类,用于将模板中的数据存入其中,这里只写一个sensor的。

    3.sensor

    public class Sensor {
        private String name;
        private String age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    }

    上面的准备工作完毕,这里使用回调,需要一个接口,这里其实暴露出了POI里面的HSSFROW这个对象。

    public interface ExcelDataSetter {
        public Object setCellData(HSSFRow row);
    }

    然后就是最重要的工具类,传入上面的接口,这个用来读取xls文件,并且进行业务操作的,这里涉及到的都是关于POI的一些操作。

    public class ExcelUtil {
        //存放service
        private static List serviceList=new ArrayList();
    
        public static void readAndSetData(File file,ExcelDataSetter dataSetter, Object services){
    
            FileInputStream fileInputStream=null;
            try {
                fileInputStream=new FileInputStream(file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
    
            POIFSFileSystem fs= null;
            HSSFSheet hssfSheet=null;
            Object dataObj=null;
            List<Object> list=new ArrayList<Object>();
            Map map=null;
            try {
                fs = new POIFSFileSystem(fileInputStream);
                HSSFWorkbook wb=new HSSFWorkbook(fs);
                hssfSheet=wb.getSheetAt(0);  // 获取第一个Sheet页
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (hssfSheet!=null){
                for (int rowNum=2;rowNum<=hssfSheet.getLastRowNum();rowNum++){
                    HSSFRow row=hssfSheet.getRow(rowNum);
                    if (row==null){
                        continue;
                    }
                   //填充数据到对象中
                   dataObj= dataSetter.setCellData(row);
                   /*Sensor sensor= (Sensor) dataObj;
                   System.out.println("get sensor data:"+sensor.getName());
                   System.out.println("get sensor age:"+sensor.getAge());
                   services.update(sensor);*/
                   doServices(services,dataObj);
                }
            }
        }
    
        public static void doServices(Object o,Object dataObj){
                if (o instanceof SensorServices) {
                    Sensor sensor = (Sensor) dataObj;
                    ((SensorServices) o).update(sensor);
                }
                if (o instanceof BerthService) {
                    ((BerthService) o).update();
                }
        }
    
        public static void registeService(List list){
            serviceList=list;
        }
    
    }

    填充数据到对象中之后,调用doServices方法,与数据库进行交互。
    这里设计的不是很合理,因为可能会有很多个services方法,doServices里面,这里是写死的,然后根据类型来判断。之前是想设计一个registeService方法,其他人员采用的时候,先在这里注册一下自己的service,就不需要写死service了。这里如果有高手有比较合理的设计方式,请指教指教。

    写一个main方法,测试一下。

    public class Main {
        public static void main(String args[]){
            File file=new File("F:/G/test.xls");
            final Sensor sensor=new Sensor();
            //test sensor services
            SensorServices sensorservices=new SensorServices();
            //test berth services
            BerthService berthService=new BerthService();
    
           //注册service
           //SerivicesRegister register=new SerivicesRegister(sensorservices);
    
           ExcelUtil.readAndSetData(file, new ExcelDataSetter() {
                @Override
                public Sensor setCellData(HSSFRow row) {
                    sensor.setName(row.getCell(0).getStringCellValue());
                    sensor.setAge(row.getCell(1).getStringCellValue());
                    return sensor;
                }
            },sensorservices);
    
            //test berth services
            ExcelUtil.readAndSetData(file,new ExcelDataSetter() {
                @Override
                public Object setCellData(HSSFRow row) {
                    return null;
                }
            },berthService);
        }
    
    }

    读取的文件里面,有两行数据。

    运行main方法,在控制台,就会打印出service中的语句,模拟service的操作。sensor的service是读取该模板的内容并,berthservice纯粹是打印语句。

    控制台输出:

    success update:wll
    success update:zhangsan
    this is berth service
    this is berth service

    针对上面的设计问题,希望各位指教指教。

  • 相关阅读:
    SQL SERVER的检查点checkpoint
    MySQL备份说明
    声明对象和创建对象的区别
    getParameter的用法总结
    Jsp的九大对象,七大动作,三大指令
    为什么内部类访问的外部变量需要使用final修饰
    java synchronized详解
    网上选课系统需求说明书
    第三次作业
    第二次作业
  • 原文地址:https://www.cnblogs.com/juepei/p/4071128.html
Copyright © 2011-2022 走看看