数据导出的另类方案:
数据导出在很多系统中都是需要的,最常见的做法是点了下载按钮以后再查询数据库将数据转化为excel或者pdf文档。
先假定数据量比较小,没有做分页,如展现统计平台该类业务属于这种情况。
如果原始系统没有做导出,在后期再加上该功能的话,如此实现便比较麻烦
1:可能需要重新查询数据库,不能利用已经查询出的结构,如果统计是非常费时的操作,则显然浪费了不少时间去重复查询。
2:不再查询数据库,直接取上次的统计结果。但是这些统计结果可能在原始系统中存放在Request作用域因为作用域过期而无法获得,即使存放是在session中,因为原始系统中每个统计将其统计结果存放在session下的不同名字中,依然是不同的导出业务需要实现专门的类去读取这些统计结果生成相应的导出格式文件。即使是想办法在前端加上控制器依然是非常麻烦。
针对该中情况,为什么不在生成JSP时就生成excel"文档"呢?
如html中<td export="type=number★color=red★row=1★col=1★value=45" type="excel,pdf">45</td>表示的意思为:
需要在第一行第一列输出值"45",类型为number类型,颜色为red,并且在导出格式为excel,pdf时包含,其他文件格式不包含。那么这种才能使服务器解析这些数据呢,
这需要增加一个jsp标签,如
<log:export type="excel,cvs,pdf" linkVar="downLoadLink">
<table>
<tr>
<td><a href="${downLoadLink_excel}">excel</></td>
</tr>
<tr>
<td export="type=number★color=red★row=1★col=1★value=45" type="excel,pdf">45</td>
</tr>
</table>
</log:export>
其中的export标签继承自BodyTagSupport,这样才能得到标签体内执行后的数据(通过方法bodyContent.getString()),得到标签体内容后解析
export="type=number★color=red★row=1★col=1★value=45" type="excel,pdf"这些数据生成ExportBook对象,该对象中记录了每一行每一列的数据以及数据展现格式,将该对象存放在session中。export标签同时根据type生成下载报表的连接,不同类型的下载生成相应的连接地址,如downloadChart.do?type=excel,将这些连接地址存放在request以方便页面生成连接。当用户点击下载后,服务器根据下载类型调用该类型对应的格式生成器(因为不同类型的文档需要不同的实现),生成文档以后发送给客户端即可
标签代码范例:
public class ExportParserTag extends BodyTagSupport {
//支持的下载类型
private String type;
//指定下载连接存放名称前缀,真正的名字需要跟上下载类型,如downLoadLink_excel,downLoadLink_pdf。
private Strng linkVar;
public int doEndTag() throws JspException {
String content = bodyContent.getString();
ExportParser parser = new ExportParser();
try {
parser.parse(new StringReader(content));
pageContext.getSession().setAttribute("____Export", parser.getResult());
generateDownloadLink(pageContext.getOut());
pageContext.getOut().append(content);
} catch (IOException e) {
e.printStackTrace();
}
return super.doEndTag();
}
}
下载功能的Servlet范例代码:
private ExportFormaterRegister formaterRegister;
private void execute(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ExportParseResult parserResult = (ExportParseResult) request.getSession()
.getAttribute("____Export");
if (excel == null) {
request.setAttribute("message", "查询数据已经过期,请重新查询!");
request.getRequestDispatcher("/message.jsp?error").forward(request,
response);
return;
} else {
String type=getExportType(request);
IExportFormater formater=formaterRegister.getFormater(type);
if(formater){
//TODO 下载类型不支持
}
else{
formater.format(parserResult,response.getOutputStream());
}
}
}