页面树结构
转至元数据结尾
转至元数据起始

1 概述

       Smartbi 默认提供可视化查询、SQL查询、存储过程查询等给客户使用,但这些查询均依赖于系统连接的关系数据源。有些项目存在一些特殊的数据源,例如文本文件或非结构化的数据,"Java查询"即是 Smartbi 产品提供给客户实现自定义数据结构的一种扩展方法。 

       Java 数据源不同于关系数据源和多维数据源之处为:它没有一个物理的数据库存储其字段和数据;但它可以通过Java类将任意一个含有数据的文件或报表通过解析后,在Smartbi中展现分析。

      为实现自定义数据结构的查询要求,系统提供接口类 IJavaQueryData 供实现Java查询扩展开发。需实现的接口方法说明如下:

IJavaQueryData接口说明
package com.freequery.metadata;
 
import java.util.List;
import java.util.Map;
import com.freequery.expression.Expression;
import com.freequery.querydata.GridData;
import com.freequery.report.OrderBy;
 
/**
 * Java查询实现接口
 */
public interface IJavaQueryData {
 /**
  * 声明该实现类支持计算字段
  */
  public interface ICalculateFieldSupport {
           public void addCalcField(String name, Expression exp);
  }
 
 /**
  * 声明该实现类支持排序
  */
  public interface IOrderSupport {
           public void setOrderBy(List<OrderBy> orderBy);
  }
 
 /**
  * 从保存的字符串中恢复配置信息
  * 
  * @param configStr
  *            配置字符串
  */
  public void loadConfigs(String configs);
 
 /**
  * 保存配置信息
  * 
  * @return 返回配置字符串
  */
  public String saveConfigs();
 
 /**
  * 获取Java查询需要的配置信息
  */
  public List<JavaQueryConfig> getConfigs();
 
 /**
  * 设置配置信息
  * 
  * @param key
  *            名称
  * @param value
  *            配置值
  */
  public void setConfigValue(String key, String value);
 
 /**
  * 设置配置信息
  */
  public void setConfigValues(Map<String, String> configValues);
 
 /**
  * 根据配置信息初始化Java查询对象
  */
  public void init();
 
 /**
  * 返回参数对象
  */
  public List<JavaQueryParameter> getParameters();
 
 /**
  * 返回Java查询的输出字段
  */
  public List<JavaQueryOutputField> getOutputFields();
 
 /**
  * 设置参数值
  */
  public void setParameterValue(String id, String value, String displayValue);
 
 /**
  * 返回总行数,返回Integer.MAX_VALUE表示未知总行数
  */
  public int getRowCount();
 
 /**
  * 获取指定行的数据
  */
  public GridData getGridData(int from, int count);
 
 /**
  * 关闭Java查询对象,关闭必要的资源
  */
  public void close();
}

2 示例说明

       以下部分说明如何在项目中进行Java查询的二次开发。

       1、打开服务器部署文件smartbi.war,解压后将smartbi.war\WEB-INF\lib\目录下的 smartbi-FreeQuery.jar、smartbi-Common.jar 包加入到扩展包项目的classpath中去。

       2、撰写Java查询对象类JavaQueryDemo.java,实现接口 IJavaQueryData

Java查询对象类
package bof.ext.JavaQuery;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import smartbi.net.sf.json.JSONObject;
import smartbi.util.StringUtil;
import smartbi.util.ValueType;
import smartbi.freequery.metadata.*;
import smartbi.freequery.querydata.CellData;
import smartbi.freequery.querydata.GridData;
/**
 * Java查询示例代码
 */
public class JavaQueryDemo implements IJavaQueryData {
	private Map<String, JavaQueryConfig> configs = new LinkedHashMap<String, JavaQueryConfig>();
	private BufferedReader reader;
	private List<JavaQueryOutputField> outputFields;
	private int currentLine;
	public JavaQueryDemo() {
		// 增加一个名称为FileName的配置项
		addConfig("FileName", "文件名", "给定一个文件名", "test.csv", true);
		addConfig("Encoding", "编码", "编码方式", "GBK", true);
	}
	/**
	 * 获取Java查询需要的配置信息
	 */
	public List<JavaQueryConfig> getConfigs() {
		return new ArrayList<JavaQueryConfig>(configs.values());
	}
	/**
	 * 添加一个配置项
	 * 
	 * @param name
	 *            名称
	 * @param alias
	 *            别名
	 * @param desc
	 *            描述
	 * @param defaultValue
	 *            默认值
	 * @param notNull
	 *            是否允许为空
	 */
	private void addConfig(String name, String alias, String desc, String defaultValue,
			boolean notNull) {
		JavaQueryConfig p = new JavaQueryConfig();
		p.setName(name);
		p.setAlias(alias);
		p.setDesc(desc);
		p.setValue(defaultValue);
		p.setNotNull(notNull);
		configs.put(name, p);
	}
	/**
	 * 从保存的字符串中恢复配置信息
	 * 
	 * @param configStr
	 *            配置字符串
	 */
	public void loadConfigs(String configStr) {
		if (StringUtil.isNullOrEmpty(configStr))
			return;
		JSONObject obj = JSONObject.fromString(configStr);
		configs.get("FileName").setValue(obj.has("FileName") ? obj.getString("FileName") : null);
		configs.get("Encoding").setValue(obj.has("Encoding") ? obj.getString("Encoding") : null);
	}
	/**
	 * 保存配置信息
	 * 
	 * @return 返回配置字符串
	 */
	public String saveConfigs() {
		JSONObject json = new JSONObject();
		for (JavaQueryConfig config : configs.values())
			json.put(config.getName(), config.getValue());
		return json.toString();
	}
	/**
	 * 设置配置信息
	 * 
	 * @param key
	 *            名称
	 * @param value
	 *            配置值
	 */
	public void setConfigValue(String key, String value) {
		configs.get(key).setValue(value);
	}
	/**
	 * 设置配置信息
	 */
	public void setConfigValues(Map<String, String> configValues) {
		for (Entry<String, String> config : configValues.entrySet())
			configs.get(config.getKey()).setValue(config.getValue());
	}
	/**
	 * 根据配置信息初始化Java查询对象
	 */
	public void init() {
		try {
			ClassLoader c1=this.getClass().getClassLoader();
			reader = new BufferedReader(new InputStreamReader(c1.getResourceAsStream(configs.get(
					"FileName").getValue()), configs.get("Encoding").getValue()));
			String titleLine = reader.readLine();
			String[] fields = titleLine.split(",");
			outputFields = new ArrayList<JavaQueryOutputField>();
			for (String str : fields) {
				JavaQueryOutputField f = new JavaQueryOutputField();
				f.setId(str);
				f.setName(str);
				f.setAlias(str);
				f.setDataType(ValueType.STRING);
				outputFields.add(f);
			}
			currentLine = 0;
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException(e);
		} catch (FileNotFoundException e) {
			throw new IllegalArgumentException(e);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}
	/**
	 * 关闭Java查询对象,关闭必要的资源
	 */
	public void close() {
		try {
			if (reader != null) {
				reader.close();
				reader = null;
			}
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}
	/**
	 * 返回参数对象
	 */
	public List<JavaQueryParameter> getParameters() {
		return new ArrayList<JavaQueryParameter>();
	}
	/**
	 * 设置参数值
	 */
	public void setParameterValue(String id, String value, String displayValue) {
	}
	/**
	 * 返回Java查询的输出字段
	 */
	public List<JavaQueryOutputField> getOutputFields() {
		return outputFields;
	}
	/**
	 * 获取指定行的数据
	 */
	public GridData getGridData(int from, int count) {
		try {
			if (currentLine > from) {
				reader.close();
				ClassLoader c1=this.getClass().getClassLoader();
				reader = new BufferedReader(new InputStreamReader(c1.getResourceAsStream(configs.get(
						"FileName").getValue()), configs.get("Encoding").getValue()));
				reader.readLine();
				currentLine = 0;
			}
			while (currentLine < from) {
				reader.readLine();
				currentLine++;
			}
			List<List<CellData>> datas = new ArrayList<List<CellData>>();
			for (int i = 0; i < count; i++) {
				String line = reader.readLine();
				if (line == null)
					break;
				currentLine++;
				String[] fs = line.split(",");
				List<CellData> row = new ArrayList<CellData>();
				for (int j = 0; j < fs.length; j++) {
					CellData c = new CellData();
					c.setStringValue(fs[j]);
					row.add(c);
				}
				datas.add(row);
			}
			GridData d = new GridData();
			List<String> headers = new ArrayList<String>();
			for (JavaQueryOutputField f : outputFields)
				headers.add(f.getName());
			d.setStringHeaders(headers);
			d.setData(datas);
			return d;
		} catch (UnsupportedEncodingException e) {
			throw new IllegalArgumentException(e);
		} catch (FileNotFoundException e) {
			throw new IllegalArgumentException(e);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}
	/**
	 * 返回总行数,返回Integer.MAX_VALUE表示未知总行数
	 */
	public int getRowCount() {
		return Integer.MAX_VALUE;
	}
}

       3、在Smartbi中新建Java查询定义

       (1)登录Smartbi,在【数据连接】选择“Java数据源”、新建Java数据源 



(2)在刚才新建的"Java数据源"上右键"新建Java数据集对象",在类名中输入正确的Java查询实现类全名(如bof.ext.JavaQuery.JavaQueryDemo)并检测默认配置;

       3、再点击获取参数与结果集并保存;

       4、"保存"后就可以在"新建Java数据集"中使用。
       5、示例代码下载:JavaQuery.rar