`
modabobo
  • 浏览: 508493 次
文章分类
社区版块
存档分类
最新评论

Spring原理探索第一步-以excel导入为列探讨SpringIoc原理

 
阅读更多

问题描述

一个excel中有两个sheet页,第一个sheet页保存的是本月的数据,第二个sheet页保存的是次月的数据,两个sheet页中的数据都分别对应着数据库中不同的两张表,如何实现excel往数据库的导入呢。

问题分析

1 excel数据解析:
使用POI或者JXL
2 数据映射
因为两个sheet页分别对应着不同的两张表,就涉及挑数这个问题,要分别处理
3 数据保存:
用hibernate保存对象即可

解决方案

根据分析问题分析,我们很容易的就想到一种解决办法
本月sheet页:解析数据->数据映射->保存数据
次月sheet页:解析数据->数据映射->保存数据
要是在多个sheet页怎么办?继续如法炮制?

我的方案

首先解析可以单独抽出来,保存也可以单独抽出来,唯一增加的是数据映射。
基于此:我们首先构建数据解析的方法:
	/**
	 * 将excel读入到Map
	 *    key为sheet页名称,value为将exceld单元格解析成的二维数据
	 * @param file
	 * @return
	 */
	private static Map<String,String[][]> reader(File file){
		Map<String,String[][]> map=new HashMap<String,String[][]>();
		//可以根据sheet页名称作循环解析
		map.put("excelService4CurrentMonth", null);
		map.put("excelService4CNextMonth", null);
		return map;
	}

保存方法:我们就建立一个保存的service.
package com.springIoc.service;

import com.springIoc.mapper.IExcelMapper;
/**
 * excel服务类
 * @author Administrator
 *
 */
public class ExcelServer {
	/**excel封装类,作解耦合使用*/
	private IExcelMapper excelMapper;
	/**excel返回的二维数组*/
	private String[][] values;

	public String[][] getValues() {
		return values;
	}

	public void setValues(String[][] values) {
		this.values = values;
	}

	public IExcelMapper getExcelMapper() {
		return excelMapper;
	}

	public void setExcelMapper(IExcelMapper excelMapper) {
		this.excelMapper = excelMapper;
	}
	/**可以通过hibernate保存方法实现数组的保存*/
	public void save(String[][] values){
		Object obj=excelMapper.mappering(values);
		System.out.println(obj+"保存成功");
	}
	

}

可以看到上述代码中有个叫IExcelMapper的接口,他的作用就是把二维数组中的数据转化为hibernate可保存的对象。
具体怎么处理要看他的实现类了。本月的返回本月封装好的对象,次月返回次月封装好的对象。
package com.springIoc.mapper;
/**
 * excel映射接口
 * @author Administrator
 *
 */
public interface IExcelMapper {
	
	public abstract Object mappering(String[][] values);

}

他的实现类做的就是数据映射
package com.springIoc.mapper.impl;

import com.springIoc.mapper.IExcelMapper;

/**
 * 本月数据封装
 * @author yj.shi
 *
 */
public class ExcelMapper4CurrentMonth implements IExcelMapper{

	@Override
	public Object mappering(String[][] values) {
		System.out.println("本月数据封装");
		return "本月数据";
	}

}
在service中调用接口,是不是就实现了数据的解耦呢?service跟数据映射类(ExcelMapper4CurrentMonth)是不是就可以随便拆开用了。

实现解耦了,下一步要做的就是对应关系,我哪知道哪个servcie中的ExcelMapper是哪一个?也许我们可以自己写对应逻辑。不过我觉得可行的方案是利用Spring的Ioc思想。
控制翻转:不是我那个service要找哪个mapper了,而是我哪个mapper要找哪个service。不是你要找我,而是我要找你,这样你就不用写那复杂的对应关系了。从你要找变为去找你,你是不就轻松多了呢。
依赖注入:注入的是啥?是依赖引用对象的注入。IExcelMapper是个引用的声明,我怎么注入他要引用的对象呢?
很简单,写个properites文件,说明他们的对应关系。
#本月excel映射
excelMapper4CurrentMonth=com.springIoc.mapper.impl.ExcelMapper4CurrentMonth
#次月excel映射
excelMapper4NextMonth=com.springIoc.mapper.impl.ExcelMapper4NextMonth

excelService4CurrentMonth=com.springIoc.service.ExcelServer
excelService4CNextMonth=com.springIoc.service.ExcelServer

excelService4CurrentMonth.excelMapper=excelMapper4CurrentMonth
excelService4CNextMonth.excelMapper=excelMapper4NextMonth




有了对应关系。下一步就是怎么来处理了。spring是个容器,对象的创建,依赖关系的建立最好要交给sring容器去做。下面就写一个spring容器。
我们根据上边的properites写好映射类就行了。
package com.springIoc.container;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.beanutils.PropertyUtils;

/**
 * 相当于spring容器,用来保存bean
 * @author yj.shi
 *
 */
public class Container {
	private static Map<String,Object> map=new HashMap<String,Object>();
	public Container(){
		Properties properties=new Properties();
		InputStream in = null;
		try {
			
			in=Container.class.getClassLoader().getResourceAsStream("ioc.properties");
			properties.load(in);
			for(Map.Entry<Object, Object> entity:properties.entrySet()){
				String key=entity.getKey().toString();
				String value=entity.getValue().toString();
				mappeingBean(key,value);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	/**
	 * 对properties的内容进行映射
	 * @param key
	 * @param value
	 * @throws ClassNotFoundException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 */
	private void mappeingBean(String key,String value) throws InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException{
		String[] parts=key.split("\\.");
		if(parts.length==1){//对象创建
			map.put(parts[0],Class.forName(value).newInstance() );
		}else{//注入引用关系
			Object target=getBeanById(parts[0]);
			Object resource=getBeanById(value);
			PropertyUtils.setProperty(target, parts[1], resource);
		}
	}
	/**
	 * 通过key过去spring容器中的数据
	 * @param key
	 * @return
	 */
	public static Object getBeanById(String key){
		return map.get(key);
	}

}


好了,最后就写一下测试方法
package com.springIoc.test;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import com.springIoc.container.Container;
import com.springIoc.service.ExcelServer;

public class TestMain {
	@SuppressWarnings("static-access")
	public static void main(String[] args) {
		Container container=new Container();
		Map<String,String[][]> map=reader(null);
		for(String key:map.keySet()){
			ExcelServer service=(ExcelServer) container.getBeanById(key);
			service.save(map.get(key));
		}

	}
	/**
	 * 将excel读入到Map
	 *    key为sheet页名称,value为将exceld单元格解析成的二维数据
	 * @param file
	 * @return
	 */
	private static Map<String,String[][]> reader(File file){
		Map<String,String[][]> map=new HashMap<String,String[][]>();
		//可以根据sheet页名称作循环解析
		map.put("excelService4CurrentMonth", null);
		map.put("excelService4CNextMonth", null);
		return map;
	}
}

总结:springIoc的控制翻转,是角色的翻转,从我要主动找变为等待别人找我。找到我之后干什么,做的就是依赖注入,把我要的对象通过setter或者构造方法或者接口方式给我。这样既实现了类与类之间的解耦,又实现了依赖对象引用关系的建立。一举两得,轻松加愉快。
具体的实现就交给spring容器来做吧。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics