历史版本10 :WebService 程序数据集通过 JDBC 连接取数 返回文档
编辑时间: 内容长度:图片数:目录数: 修改原因:

目录:

1. 概述编辑

1.1 应用场景

在使用 WebService 作为项目的数据源时,希望报表中可以直接调用 WebService 数据源,而不是定义数据连接调用对应的数据库表,这样要怎么实现呢?

1.2 实现原理

在程序中访问 WebService 应用服务,将 WebService 返回的数据转为程序数据集,然后在设计器中调用。本文示例通过JDBC 连接直接访问 WebService 数据源取数。

2. 示例编辑

在 Axis2 工程中发布一个 WebService,然后编写一个 WebService 程序数据源,在设计器中定义为程序数据集使用。

2.1 准备 WebService 数据源

2.1.1 部署 axis2 服务器

若您已有搭建好的 axis2 服务器,请忽略此步骤。

1)用户自行下载并安装 JDK 和 Web 应用服务器来配置部署的环境,本文示例使用 Tomcat 服务器部署,所以部署前提前准备好了一个 Tomcat 服务器。

2)从 Axis2官网 下载 War 包,如下图所示:

1583829078420513.png

3)将下载的部署包解压,把部署包中的 axis2.war 移动到%Tomcat_Home%\webapps目录下。重启 Tomacat 服务器,该目录下自动生成一个文件夹 axis2。如下图所示:

1576142233239758.png

4)启动 Tomacat 服务器后,浏览器输入服务器访问网址可以访问即成功。如下使用本地服务器,浏览器访问 localhost:8080/axis2 ,出现部署成功页面,即部署成功。如下图所示:

注:访问 URL 需要根据服务器 IP、个人设置的 Tomcat 端口进行调整。

1576142430882991.png

2.1.2 编写 JDBC 取数类

在 Java 编辑器编写一个 JDBC 取数类,编译前,需要在 Java 工程环境中引入对应的 JDBC 数据库驱动,本文以 MySQL 数据库为例,所以首先需要引入 MySQL 的 JDBC 驱动。如何引入可参考:编译Java程序 

注:用户使用时,将代码中的数据库信息和数据查询语句更换为用户自己的数据库信息和查询语句。

Java 代码如下:

package service; //需定义包名为service,对应之后的文件夹名
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class MyService {
// 定义数据库连接参数
private static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; // 驱动
private static final String URL = "jdbc:mysql://localhost:3306/z"; // z为数据库名
private static final String USERNAME = "root"; // 用户名
private static final String PASSWORD = "123456"; // 密码
// 注册数据库驱动
static {
try {
Class.forName(DRIVER_CLASS_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 获取连接
private static Connection getConn() throws SQLException {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
}
// 关闭连接
private static void closeConn(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public List<String> get() throws SQLException { // 方法需要声明为public才能被访问
List<String> data = new ArrayList<>();
Connection connection = getConn();
Statement statement = connection.createStatement();
String sql = "select id,name from test"; // sql根据自己的需求定义
data.add("id name");
try {
if (statement != null) {
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
data.add(rs.getInt(1) + "  " + rs.getString(2).trim());
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (statement != null) {
statement.close();
}
closeConn(connection);
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
// 测试
public static void main(String[] args) {
List<String> list;
MyService service = new MyService();
Connection conn = null; // 声明连接conn
try {
conn = MyService.getConn(); // 获取连接conn
list = service.get(); // 获取数据
for (String s : list) {
System.out.println(s); // 展示获取的数据
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
closeConn(conn); // 关闭连接conn
}
}
}
}

代码编译通过后,可以看到从数据库中查询出的数据,如下图所示,查询出 test 表中的数据;同时编译通过后,将会在编译器对应工程文件存储路径下生成 MyService.class 类文件。

注:该代码如果出现错误,用户将无法在设计器中查看,只能在 Tomcat 中看到报错,所以连接之前可以先测试下代码是否能正常取数。

2.1.3 发布 WebService

1)新建 services.xml 文件并放在%Tomcat_Home%\webapps\axis2\META-INF目录下。services.xml 内容如下:

<service name="MyService">     <!--service名字可以自己定义-->
    <description>
        Web Service
    </description>
    <parameter name="ServiceClass">
        service.MyService      <!--对应包名和类名-->
    </parameter>
    <operation name="get" >    <!--函数名-->
        <messageReceiver  mep="http://www.w3.org/2004/08/wsdl/in-out"
        class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
    </operation>
</service>

2)打包 service 类。新建一个 WS 文件夹,里面再新建两个子文件夹 META-INFservice。如下图所示:

1576205273698351.png

将 1)中准备的 services.xml文件放到 META-INF 文件夹中;将 2.1.2 中生成的 JDBC 取数类 MyService.class 放在

service文件夹中。如下图所示:

1576205469433479.png

3)将 WS 文件夹打包生成 .aar 文件。在 Windows 控制台使用 cd 命令进入 WS 文件夹所在的目录,并输入如下命令生成 ws.aar 文件。如下图所示:

jar cvf ws.aar .

Snag_5922f64.png

在 WS 文件夹内即可看到 ws.aar 文件。如下图所示:

1576205960934118.png

4)调用 WebService。将 ws.arr 拷贝到%Tomcat_Home%\webapps\axis2\WEB-INF\services目录下,启动 Tomcat 后,就可以调用这个 WebService 了。

启动成功后,访问 http://localhost:8080/axis2/services/MyService?wsdl ,出现如下页面,即发布成功。

image2019-12-5_11-17-33.png

2.2 定义程序数据源

2.1 节准备好了 WebService 数据源,接下来可以直接在 JAVA 中定义程序数据源。直接通过 JDBC 取数 ,扩展 AbstractTableData,将获得的数据转为程序数据集。

2.2.1 准备编译环境

编译程序前,需先创建一个 Java 工程环境,并且需要一个 Java 编辑器,如 Eclipse 或 idea 。

在编辑器工程中导入 FineReport 工程 JAR 包。包括安装的报表工程

%FR_HOME%/lib下的所有的包,

%FR_HOME%/server/lib 下的所有包,

%FR_HOME%/webapps/webroot/WEB-INF/lib下的所有包,

还要引入 JDK 下的的 tools.jar,

还需要引入%AXIS_HOME%/web-inf/lib下面的 JAR 包,

从 Axis2官网 下载 bin 文件,解压后将 lib 文件夹中的 JAR 包引入 java 工程中。详细操作可参考:编译Java程序 

1583829853689238.png

2.2.2 编写 Java 程序

在编辑器中编写 Java 文件 WebServiceWSDLDataDemo.java, 完整代码可参见:

package com.fr.data;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.fr.general.data.TableDataException;
import com.fr.log.FineLoggerFactory;
import org.apache.axiom.om.*;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
public class WebServiceWSDLDataDemo extends AbstractTableData {
private String[][] data;
public WebServiceWSDLDataDemo() {
this.data = getWSDLData();
}
public int getColumnCount() throws TableDataException {
return data[0].length;
}
// 获取列的名称为数组中第一行的值
public String getColumnName(int columnIndex) throws TableDataException {
return data[0][columnIndex];
}
// 获取行数为数据的长度-1
public int getRowCount() throws TableDataException {
return data.length - 1;
}
// 获取值
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex + 1][columnIndex];
}
// 取数
private static String[][] getResults(OMElement element) {
if (element == null) {
return null;
}
Iterator iterator = element.getChildElements();
List<String> list = new ArrayList<>();
while (iterator.hasNext()) {
OMNode omNode = (OMNode) iterator.next();
if (omNode.getType() == OMNode.ELEMENT_NODE) {
OMElement omElement = (OMElement) omNode;
if (omElement.getLocalName().equals("return")) {
String temp = omElement.getText().trim();
list.add(temp);
}
}
}
String[] result1 = list.toArray(new String[list.size()]);
String results[][] = new String[result1.length][2]; // 这里的列数根据自己取出的列数而定,行数当然是有多少取多少
String b1, b2;
for (int i = 0; i < result1.length; i++) {
if (result1[i].length() != 0) {
b1 = result1[i].substring(0, result1[i].indexOf(" "));
b2 = result1[i].substring(result1[i].indexOf(" ") + 1);
results[i][0] = b1;
results[i][1] = b2;
}
}
return results;
}
// 获取连接并取数
private static String[][] getWSDLData() {
try {
String url = "http://localhost:8080/axis2/services/MyService?wsdl"; // 这里的url即为发布的WebService具体地址
EndpointReference targetEPR = new EndpointReference(url);
// 创建一个OMFactory,下面的namespace、方法与参数均需由它创建
OMFactory fac = OMAbstractFactory.getOMFactory();
// 命名空间namespace
OMNamespace omNs = fac.createOMNamespace("http://service", "a");
// 方法
OMElement method = fac.createOMElement("get", omNs); // 对应方法名
// 参数
Options options = new Options();
options.setTo(targetEPR);
options.setAction("http://service/get");
// 构建请求
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
// 发送请求
OMElement result1 = sender.sendReceive(method);
return getResults(result1);
} catch (org.apache.axis2.AxisFault e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
return null;
}
// 测试
public static void main(String[] args) {
String[][] result = getWSDLData();
if (result != null) {
int col = result[0].length;
for (String[] aResult : result) {
for (int j = 0; j < col; j++) {
System.out.print(aResult[j] + " ");
}
System.out.println();
}
}
}
}

2.2.3 编译Java文件

1)Java 文件编写完成后,在编译器中编译 WebServiceWSDLDataDemo.java ,编译通过后,Java 编辑器中会显示对应查询到的数据,同时将会在对应工程下生成 WebServiceWSDLDataDemo.class 类文件。如下图所示:

2)将编译好的 WebServiceWSDLDataDemo.class 文件拷贝到%FR_HOME%/webapps/webroot/WEB-INF/classes/com/fr/data文件夹下。如下图所示:

2.3 创建程序数据集

将 2.2.1 节下载的 %AXIS_HOME%/lib下面的 JAR 包(除了log4j 的 JAR,会冲突),拷贝到报表工程%FR_HOME%/webapps/webroot/WEB-INF/lib 下,拷贝成功后重启工程,即完成报表环境引用第三方 JAR 包。如将 JAR 包拷贝到设计器%FR_HOME%/webapps/webroot/WEB-INF/lib 下,拷贝成功后重启设计器。如下图所示:

1576216316803497.png

设计器打开后,新建模板,点击模板数据集下面的加号,选择「程序」数据集,在弹出的程序数据集对话框中,选择对应的 class 文件,如下图所示:

3.2 研发测试组 > WebService程序数据集--JDBC连接取数 > image2019-12-5_13-55-12.png

选定 class 文件后,点击保存后即完成了程序数据源配置。

2.4 使用程序数据集

配置好程序数据源后便可以使用自定义的程序数据集,与其他类型的数据集使用方法相同,可以通过拖拽方法实现单元格数据列绑定。如下图所示:

注:使用程序数据集时,axis 服务器为启动状态。