知识库

推荐内容

快逸做的更好

产品优势

您的位置: 首页 > 报表技术分享 > 快逸报表不同数据集的写日志需求

快逸报表不同数据集的写日志需求

背景描述
某客户要求记录访问报表查询的sql语句、访问人、访问时间等信息。之前我给出过相应实现,但客户在使用过程中发现添加了其他数据集类型以后,该实现方式似乎无法达到需求效果。

本文将在《将报表sql和参数输出到xml文件中》基础上完成对使用不同数据集的报表写日志的需求。

实现
先准备带有参数模板的报表,在发布报表的jsp中指定计算监听类,如:calculateListener=”listener.CalcListenerWriteSql2″

CalcListenerWriteSql2.java介绍:

1、 public void afterCalculate()

(1) 计算监听类计算后方法,首先判断context中是否存有参数,因为在翻页的时候context会丢失,导致context找不到的错误。

Map map = context.getAllParamMap();

Iterator iter = map.entrySet().iterator();

if(!iter.hasNext()){

System.out.println(“context里啥都没有啦~~”);

}else{ //执行下面的写日志操作

(2) 初始化一个map,用于存储数据集名和数据集sql(完整不带问号的sql)。

Map dsMap = new HashMap ();// 初始化存放数据集名,数据sql的map

(3) 再在该方法中获取数据集元对象以及数据集个数,通过循环数据集个数获取数据集名和通过getDsSql()方法获取数据集sql。

DataSetMetaData dsmd = report.getDataSetMetaData(); // 获取数据集元对象

int dsNum = dsmd.getDataSetConfigCount(); // 获取数据集个数

循环数据集个数,判断每个数据集的类型(这里只判断SQL和存储过程类型),对每种类型给予不同的处理

if(dsc instanceof SQLDataSetConfig){//sql数据集

System.out.println(“SQLDataSetConfig->”+dsName);

sdsc = (SQLDataSetConfig)dsc;

newSql = getDsSql(sdsc);

//Map中数据格式:key=数据集名;value=完整sql

dsMap.put(dsName, newSql);

}else if(dsc instanceof ProcDataSetConfig){//存储过程数据集

System.out.println(“ProcDataSetConfig->”+dsName);

pdsc = (ProcDataSetConfig)dsc;

dsMap.put(dsName, pdsc.getSQL());//直接将调用存储过程语句存入MAP

}

(4) 最后map及必要信息传给操作xml的方法,本例中xml文件都是以当前年月命名,若无该该文件则创建,否则修改,以达到每月创建使用一个xml的目的。

createXML(dsMap,raqName,userID,now,currYM);//创建xml

modifyXML(dsMap,raqName,userID,now,currYM);//修改xml

2、 public String getDsSql(SQLDataSetConfig sdsc)

根据传递过来的SQLDataSetConfig对象获取对应数据集sql(原始sql,带问号的),该方法通过getParam()将sql中问号与参数值对应,最后返回一个完整的sql字符串。

3、 public Map getParam(SQLDataSetConfig sdsc)

本方法先判断报表数据集的参数类型,经Expression计算参数表达式值,最后将参数位置和参数值存到map中返回。

Expression exp = new Expression(context, paramExp);

Object afterCalcObj = exp.calculate(context, false);

4、 public void createXML(Map map,String raqName,String userID,String now,String currYM)

创建xml方法(本例使用dom4j操作xml,使用时需导入dom4j的包)。其中创建时需考虑到xml文件编码、汉字乱码以及特殊符号转码等问题。

5、 public void modifyXML(Map map,String raqName,String userID,String now,String currYM)

修改xml方法。实现类似创建,注意同4。

附源程序:

package listener;

import java.sql.Date;

import java.sql.Time;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.math.*;

import org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import org.dom4j.io.OutputFormat;

import org.dom4j.io.SAXReader;

import org.dom4j.io.XMLWriter;

import com.runqian.report4.ide.base.DataSetTypes;

import com.runqian.report4.model.expression.Expression;

import com.runqian.report4.usermodel.AbstractCalculateListener;

import com.runqian.report4.usermodel.DataSetConfig;

import com.runqian.report4.usermodel.DataSetMetaData;

import com.runqian.report4.usermodel.ProcDataSetConfig;

import com.runqian.report4.usermodel.SQLDataSetConfig;

import com.sun.jmx.snmp.Timestamp;

public class CalcListenerWriteSql2 extends AbstractCalculateListener {

public void beforeCalculate() throws Exception {

}

public void afterCalculate() throws Exception {

Map map = context.getAllParamMap();

Iterator iter = map.entrySet().iterator();

if(!iter.hasNext()){

System.out.println(“context里啥都没有啦~~”);

}else{

/**获取数据集名称和sql部分**/

Map dsMap = new HashMap ();// 初始化存放数据集名,数据sql的map

DataSetMetaData dsmd = report.getDataSetMetaData(); // 获取数据集元对象

int dsNum = dsmd.getDataSetConfigCount(); // 获取数据集个数

System.out.println(“ds个数—————->”+dsNum);

DataSetConfig dsc = null;

String dsName = “”;

SQLDataSetConfig sdsc = null;

ProcDataSetConfig pdsc = null;

for (int i = 0; i < dsNum; i++) {

String newSql = "";// 不带问号的sql

dsc = dsmd.getDataSetConfig(i);

dsName = dsc.getName();// 取数据集名字

if(dsc instanceof SQLDataSetConfig){//sql数据集

System.out.println("SQLDataSetConfig->“+dsName);

sdsc = (SQLDataSetConfig)dsc;

newSql = getDsSql(sdsc);

//Map中数据格式:key=数据集名;value=完整sql

dsMap.put(dsName, newSql);

}else if(dsc instanceof ProcDataSetConfig){//存储过程数据集

System.out.println(“ProcDataSetConfig->”+dsName);

pdsc = (ProcDataSetConfig)dsc;

dsMap.put(dsName, pdsc.getSQL());

}

}

/**获取报表名称,登录人ID,访问报表时间等信息**/

String raqName = (String)request.getAttribute(“raqName”);//报表名称

String userID = (String)request.getAttribute(“userID”);//用户ID

DateFormat df_now = DateFormat.getDateTimeInstance();

String now = df_now.format(new Date(System.currentTimeMillis()));//访问该报表时间

//*****************【可能需要修改部分开始】————————–//

/**判断是要新生成xml,还是读取本月的**/

String currDate = “”;//当前年月日

String firstDay = “”;//每月第一天

String currYM = “”;//当前月份

//判断当前日期是不是每月一号

String[] temp = now.split(” “);//空格分割出日期、时间

String[] date = temp[0].split(“-”);//-号分隔出年月日

for(int i=0;i

currDate += (date[i]+"-");

firstDay += (date[i]+"-");

}

currDate += date[date.length-1];

firstDay += "1";

currYM += (date[0]+"-");

currYM +=(date[1]);

String xmlPath = request.getRealPath("\\")+"reportInfo"+File.separator+currYM+".xml";

File f = new File(xmlPath);

if(!f.exists()){//以年月命名的xml文件不存在,需要创建XML

System.out.println(currYM+".xml不存在,正在创建……");

createXML(dsMap,raqName,userID,now,currYM);//创建xml

System.out.println("创建XML结束!");

}else{//否则,以年月命名的xml文件存在,读取xml追加信息

System.out.println(currYM+".xml已存在,正在修改……");

modifyXML(dsMap,raqName,userID,now,currYM);//修改xml

//createXML(dsMap,raqName,userID,now,currYM);

System.out.println("修改XML结束!");

}

//----------------【可能需要修改部分结束】************************/

}

}

/**

* 获取处理后sql语句,即不带问号的完整sql

* @param sdsc

* @return

* @throws Exception

*/

public String getDsSql(SQLDataSetConfig sdsc) throws Exception{

String finalSql = "";//处理好的sql,返回

Map paramMap = getParam(sdsc);//取该数据集参数值

String sql = sdsc.getSQL();// 取数据集sql

String[] sqlArr = sql.split(“\\u003F”);// split问号,问号需要转义

for(int j=0;j

finalSql = finalSql+sqlArr[j]+paramMap.get(j);

}

finalSql = finalSql + sqlArr[sqlArr.length-1];

return finalSql;

}

/**

* 此方法用于获取该数据集的所有参数,将其位置和值存在map中

* @param sdsc

* @return

* @throws Exception

*/

public Map getParam(SQLDataSetConfig sdsc)throws Exception{

Map paramMap = new HashMap ();// 存放参数值和参数位置

int paramNum = sdsc.getParamCount();// 取每个数据集中参数个数

for (int j = 0; j < paramNum; j++) {

String paramExp = sdsc.getParamExp(j); // 取每个数据集中参数表达式

// System.out.println("第" + j + "个参数:" + paramExp);

Expression exp = new Expression(context, paramExp);

// System.out.println("参数计算前!");

Object afterCalcObj = exp.calculate(context, false);

// System.out.println("参数计算后!");

/** 判断参数类型* */

// 字符串

if (afterCalcObj instanceof String) {

// System.out.println("第" + j + "个参数类型:字符串!");

paramMap.put(j, "'" + afterCalcObj.toString() + "'");// 字符串则拼单引号和值进去

// 以下是数值型

} else if (afterCalcObj instanceof Integer) {

// System.out.println("第" + j + "个参数类型:整数!");

paramMap.put(j, afterCalcObj.toString());//

} else if (afterCalcObj instanceof Short) {

// System.out.println("第" + j + "个参数类型:短整数!");

paramMap.put(j, afterCalcObj.toString());//

} else if (afterCalcObj instanceof Long) {

// System.out.println("第" + j + "个参数类型:长整数!");

paramMap.put(j, afterCalcObj.toString());//

} else if (afterCalcObj instanceof BigInteger) {

// System.out.println("第" + j + "个参数类型:大整数!");

paramMap.put(j, afterCalcObj.toString());//

} else if (afterCalcObj instanceof Float) {

// System.out.println("第" + j + "个参数类型:单精度!");

} else if (afterCalcObj instanceof Double) {

// System.out.println("第" + j + "个参数类型:双精度!");

paramMap.put(j, afterCalcObj.toString());//

} else if (afterCalcObj instanceof BigDecimal) {

// System.out.println("第" + j + "个参数类型:数值!");

paramMap.put(j, afterCalcObj.toString());//

// 以下是日期型

// ******************【可能要修改的部分开始】--------------------------------

// 此处采用oracle的to_date函数将字符串转为日期类型,使用者需根据自身数据库情况采用对应的函数和日期格式

} else if (afterCalcObj instanceof Date) {

// System.out.println("第" + j + "个参数类型:日期!");

DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

String paramMapValue = "to_date('"

+ df.format(afterCalcObj) + "','yyyy-MM-dd')";// 需要修改行

paramMap.put(j, paramMapValue);

} else if (afterCalcObj instanceof Time) {

// System.out.println("第" + j + "个参数类型:时间!");

DateFormat df = new SimpleDateFormat("hh:mm:ss");

String paramMapValue = "to_date('"

+ df.format(afterCalcObj) + "','hh:mm:ss')";// 需要修改行

paramMap.put(j, paramMapValue);

} else if (afterCalcObj instanceof Timestamp) {

// System.out.println("第" + j + "个参数类型:日期时间!");

DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

String paramMapValue = "to_date('"

+ df.format(afterCalcObj)

+ "','yyyy-MM-dd hh:mm:ss')";// 需要修改行

paramMap.put(j, paramMapValue);

// ------------------【可能要修改的部分结束】********************************

// 布尔值

} else if (afterCalcObj instanceof Boolean) {

// System.out.println("第" + j + "个参数类型:布尔值!");

System.out.println("参数类型为布尔值,若使用请修改程序!");

// 组类型

} else if (afterCalcObj instanceof ArrayList) {

ArrayList al_afterCalcObj = (ArrayList)afterCalcObj;

Object element = al_afterCalcObj.get(0);//取ArrayList里一个元素,看是什么类型

if(element instanceof String){//字符串

String paramMapValue="";

for(int i=0;i

paramMapValue = "'"+al_afterCalcObj.get(i)+"','";

}

paramMapValue = paramMapValue +al_afterCalcObj.get(al_afterCalcObj.size()-1)+"'";

// System.out.println("字符串组处理后:"+paramMapValue);

paramMap.put(j, paramMapValue);

}else{//其他类型,不需要加单引号的,由于日期组没有意义,所以不做判断

String paramMapValue="";

for(int i=0;i

paramMapValue = al_afterCalcObj.get(i)+",";

}

paramMapValue = paramMapValue +al_afterCalcObj.get(al_afterCalcObj.size()-1);

// System.out.println("其他组类型处理后:"+paramMapValue);

paramMap.put(j, paramMapValue);

}

}

}

return paramMap;

}

/**

* 根据相关信息创建XML文件,文件名为yyyy-MM.xml

* @param map 存放数据集名和sql

* @param raqName 报表名

* @param userID 用户ID

* @param now 当前日期时间

* @param currYM 当前年月

*/

public void createXML(Map map,String raqName,String userID,String now,String currYM){

Document document = DocumentHelper.createDocument(); //创建文档实例

document.addComment(“create time:”+now);//添加注释:文档创建时间

Element root = document.addElement(“messageRoot”);//创建根元素messageRoot

//catalogElement.addProcessingInstruction(“target”,”text”);

Element message = root.addElement(“message”);//根节点上添加message元素

Element time=message.addElement(“time”);//message节点上添加time元素

time.setText(now);//设置time元素文本

Element user_id = message.addElement(“userID”);

user_id.setText(userID);

Element raq_name = message.addElement(“raqName”);

raq_name.setText(raqName);

//遍历HashMap,取key-数据集名;value-sql

Iterator iter = map.entrySet().iterator();

while (iter.hasNext()) {

Map.Entry entry = (Map.Entry) iter.next();

String key = entry.getKey().toString();

String value = entry.getValue().toString();

Element sql = message.addElement(“sql”);//message上添加sql元素

sql.addAttribute(“dsName”,key);//数据集名放到 sql节点的dsName属性中

sql.setText(value);//sql内容放到sql节点内容中

}

try{

String realPath = request.getRealPath(“”);

if(!”\\”.equals(realPath.trim().charAt(realPath.length()-1))){

realPath += “\\”;

}

//***************【可能需要修改部分开始】—————–//

//xml文件名当前年月;文件目录在应用根目录的reportInfo下,可修改

String xmlPath = realPath +”reportInfo\\”+currYM+”.xml”;

new File(realPath+”reportInfo”).mkdir();//创建reportInfo目录

//—————【可能需要修改部分结束】*****************//

OutputFormat format = OutputFormat.createPrettyPrint();

format.setEncoding(“utf-8″);//设置xml编码

/**重要:此处需使用FileOutputStream防止中文乱码*/

//XMLWriter output = new XMLWriter(new FileWriter( new File(xmlPath)),format);

XMLWriter output = new XMLWriter(new FileOutputStream( new File(xmlPath)),format);

/**重要:避免xml内容被转义*/

//output.setEscapeText(false);

output.write( document );

output.close();

}

catch(IOException e){System.out.println(e.getMessage());}

}

/**

* 用于向现有xml文件中追加信息

* @param map

* @param raqName

* @param userID

* @param now

* @param currYM

*/

public void modifyXML(Map map,String raqName,String userID,String now,String currYM){

//取应用真实路径

String realPath = request.getRealPath(“”);

if(!”\\”.equals(realPath.trim().charAt(realPath.length()-1))){

realPath += “\\”;

}

//***************【可能需要修改部分开始】—————–//

//xml文件名当前年月;文件目录在应用根目录的reportInfo下,可修改

String inputXml = realPath +”reportInfo\\”+currYM+”.xml”;

//—————【可能需要修改部分结束】*****************//

SAXReader saxReader = new SAXReader();

try {

Document document = saxReader.read(inputXml);//读入xml

Element root = document.getRootElement();//取根节点

Element message = root.addElement(“message”);//根节点上添加message元素

Element time=message.addElement(“time”);//message节点上添加time元素

time.setText(now);//设置time元素文本

Element user_id = message.addElement(“userID”);

user_id.setText(userID);

Element raq_name = message.addElement(“raqName”);

raq_name.setText(raqName);

//遍历HashMap,取key-数据集名;value-sql

Iterator iter = map.entrySet().iterator();

while (iter.hasNext()) {

Map.Entry entry = (Map.Entry) iter.next();

String key = entry.getKey().toString();

String value = entry.getValue().toString();

Element sql = message.addElement(“sql”);//message上添加sql元素

sql.addAttribute(“dsName”,key);//数据集名放到 sql节点的dsName属性中

sql.setText(value);//sql内容放到sql节点内容中

}

OutputFormat format = OutputFormat.createPrettyPrint();

/**重要:此处需使用FileOutputStream防止中文乱码*/

//XMLWriter output = new XMLWriter(new FileWriter( new File(xmlPath)),format);

XMLWriter output = new XMLWriter(new FileOutputStream( new File(inputXml)),format);

/**重要:避免xml内容被转义*/

//output.setEscapeText(false);

output.write( document );

output.close();

} catch (DocumentException de) {

de.printStackTrace();

} catch(IOException ioe){

ioe.printStackTrace();

}

}
}

本文标签: