java5 特征 泛型和反射技术的应用

java5 特征 泛型和反射技术的应用

1.报表应用

报表是需要联合查询的数据集,一般不会有对应的POJO类,如果手动封装字段那就太低效了.泛型和反射技术可以将报表数据通过几行代码写到VO集合中.

查询出的结果集往往不是POJO但为了方便我们使用VO来做

说明:
后台查询的结果集合: List<Map<String, Object>> 
行对象:Map<String, Object>  
String是POJO的字段名,Object是该列在当前行的单元格值. 
BeanUtils是org.apache.commons.beanutils提供的操作bean工具包.
//通过反射技术写入POJO</br>
for (int i = 0; i < list.size(); i++) {
				try {
					ProjectExeDetailVO pedv = new ProjectExeDetailVO();
					BeanUtils.populate(pedv, list.get(i));
					projectExeDetailVOs.add(pedv);
				} catch (Exception e) {
					e.printStackTrace();
                    throw new Exception(e);
				}
}

查看BeanUtils.populate()的源代码

public static void populate(Object bean, Map properties)
        throws IllegalAccessException, InvocationTargetException {
        BeanUtilsBean.getInstance().populate(bean, properties);
}

BeanUtilsBean中的populate()实现

public void populate(Object bean, Map properties)
        throws IllegalAccessException, InvocationTargetException {

        // Do nothing unless both arguments have been specified
        if ((bean == null) || (properties == null)) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug("BeanUtils.populate(" + bean + ", " +
                    properties + ")");
        }

        // Loop through the property name/value pairs to be set
        Iterator entries = properties.entrySet().iterator();
        while (entries.hasNext()) {

            // Identify the property name and value(s) to be assigned
            Map.Entry entry = (Map.Entry)entries.next();
            String name = (String) entry.getKey();
            if (name == null) {
                continue;
            }

            // Perform the assignment for this property
           setProperty(bean, name, entry.getValue());

        }

}

##########setProperty() 将目标值放入bean的name属性中
public void setProperty(Object bean, String name, Object value)
        throws IllegalAccessException, InvocationTargetException {

        // 写日志
        .....
        // 解析表达式来获取实际的bean
        .....

        // 计算出属性的数据类型
        .....
        // 将指定的值转换为属性所需的类型
        .....
        // 访问setter访问器设定值
        try {
          getPropertyUtils().setProperty(target, name, newValue);
        } catch (NoSuchMethodException e) {
            throw new InvocationTargetException
                (e, "Cannot set " + propName);
        }
    }

接下来就是将数据集合写入HSSFWorkbook对象输出给客户端

HSSFWorkbook对象是apache poi项目包里面的Excel顶级对象,我们的原材料包含:

属性
文件名
sheet标题
表头Map集合
数据集合
方法
写入到Excel输出到response中
public class Exceltools<T> {
	private String fname;// 文件名称
	private String sName;// sheet标题
	private Map<String, String> ziDuan;// 字段名称 ziDuan.put("0_fjh","房间号");属性前边的数字代表字段的先后顺序。
	private List<T> listData;// 数据集
	private HttpServletResponse response;

	public Exceltools(String fileName, String sheetName,
			Map<String, String> ziDuan, List<T> listData,
			HttpServletResponse response) {
		this.fname = fileName;
		this.sName = sheetName;
		this.ziDuan = ziDuan;
		this.listData = listData;
		this.response = response;
	}

	/**
	 * 将对象集合导出到Excel回客户端
	 * */
	public void writeToExcel() {
		Object[] keys = ziDuan.keySet().toArray();
		String[] ziDuanKeys = new String[keys.length];
		for (int k = 0; k < keys.length; k++) {
			String temp = keys[k].toString();
			int xuHao = Integer
					.valueOf(temp.substring(0, temp.indexOf("_", 0)));
			ziDuanKeys[xuHao] = temp.substring(temp.indexOf("_", 0) + 1);
		}
		OutputStream out = null;
		try {
			HSSFWorkbook wb = new HSSFWorkbook();
			HSSFSheet sheet = wb.createSheet(sName);
			HSSFRow row = sheet.createRow(0);
			for (int j = 0; j < ziDuanKeys.length; j++) {
				HSSFCell cell = row.createCell(j);
				// sheet表头,无论如何都要先打印表头
				sheet.setColumnWidth(j, 6000);
				cell.setCellValue(new HSSFRichTextString(ziDuan.get(j + "_"
						+ ziDuanKeys[j])));
			}
			for (int i = 0; i < listData.size(); i++) {
				HSSFRow row2 = sheet.createRow(i + 1);
				T obj = listData.get(i);
				for (int j = 0; j < ziDuanKeys.length; j++) {
					HSSFCell cell = row2.createCell(j);
					// 内容
					String ziDuanName = (String) ziDuanKeys[j];
					ziDuanName = ziDuanName.replaceFirst(
							ziDuanName.substring(0, 1),
							ziDuanName.substring(0, 1).toUpperCase());
					ziDuanName = "get" + ziDuanName;
					Class clazz = Class.forName(obj.getClass().getName());
					Method[] methods = clazz.getMethods();
					Pattern pattern = Pattern.compile(ziDuanName);
					Matcher mat = null;
					for (Method m : methods) {
						mat = pattern.matcher(m.getName());
						if (mat.find()) {
							Object shuXing = m.invoke(obj, null);
							if (shuXing != null) {
								cell.setCellValue(shuXing.toString());// 这里可以做数据格式处理
							} else {
								cell.setCellValue("");
							}
							break;
						}
					}
				}
			}
			response.setContentType("application/vnd.ms-excel;charset = utf-8");
			response.setHeader("Content-disposition", "attachment;filename="
					+ new String(sName.getBytes("GBK"), "ISO-8859-1")+".xlsx");
			out = response.getOutputStream();
			wb.write(out);// 写入File
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				try {
					out.flush();
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

后记

这样一个数据报表的导出就完成了.
除了使用反射,泛型等技术外,还用到了正则表达式的匹配.如果有不明白的地方,欢迎一起探讨,交换思想.QQ:185748383

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值