场景是这样的:为了做一个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
针对上面的设计问题,希望各位指教指教。