使用回调方式写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

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

 

posted @ 2014-11-03 14:15  薛定谔的猫_  阅读(1301)  评论(3编辑  收藏  举报