You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSP中渲染Crystal Report时从web.xml修改数据库连接的方法

解决Crystal Report在JSP渲染时动态修改数据库连接的问题

针对你的需求,这里提供两种实用的实现方案,适配你现有项目结构,帮你在报表渲染阶段从web.xml读取连接信息并替换设计时的固定连接:

方案一:通过web.xml上下文参数存储连接字符串

首先在你的web.xml中添加数据库连接相关的上下文参数,方便统一管理:

<!-- 新增数据库连接参数 -->
<context-param>
    <param-name>dbJdbcUrl</param-name>
    <param-value>jdbc:sqlserver://your-db-server:1433;databaseName=IntranetDBW</param-value>
</context-param>
<context-param>
    <param-name>dbUsername</param-name>
    <param-value>your-db-username</param-value>
</context-param>
<context-param>
    <param-name>dbPassword</param-name>
    <param-value>your-db-password</param-value>
</context-param>
<context-param>
    <param-name>dbDriverClass</param-name>
    <param-value>com.microsoft.sqlserver.jdbc.SQLServerDriver</param-value>
</context-param>

然后修改JSP代码,在打开报表后动态替换数据库连接:

<%@ page import= "com.crystaldecisions.report.web.viewer.*,com.crystaldecisions.sdk.occa.report.data.*" %>
<%@ page import="com.crystaldecisions.sdk.occa.report.lib.*"%>
<%@ page import="com.crystaldecisions.sdk.occa.report.*"%>
<%@page import="com.crystaldecisions.reports.sdk.*" %>
<%@page import="com.crystaldecisions.sdk.occa.report.exportoptions.*" %>
<%@page import="javax.servlet.ServletContext" %>
<%
// 从web.xml读取预配置的连接参数
ServletContext appContext = getServletConfig().getServletContext();
String jdbcUrl = appContext.getInitParameter("dbJdbcUrl");
String dbUser = appContext.getInitParameter("dbUsername");
String dbPwd = appContext.getInitParameter("dbPassword");
String driverClass = appContext.getInitParameter("dbDriverClass");

// 打开报表文件
String REPORT_NAME = "test_table.rpt";
ReportClientDocument reportClientDoc = new ReportClientDocument();
reportClientDoc.open(REPORT_NAME, 0);

// 获取报表的数据库控制器,用于修改连接
DatabaseController dbController = reportClientDoc.getDatabaseController();
IConnectionInfo originalConnInfo = dbController.getConnectionInfos(null).getConnectionInfo(0);

// 构建新的连接属性集合
PropertyBag newConnProps = new PropertyBag();
newConnProps.put("JDBC Connection String", jdbcUrl);
newConnProps.put("JDBC Driver Class Name", driverClass);
newConnProps.put("User ID", dbUser);
newConnProps.put("Password", dbPwd);
// 根据数据库类型补充其他必要属性,比如SQL Server需要的Server Name、Database Name
newConnProps.put("Server Name", jdbcUrl.split("://")[1].split(";")[0]);
newConnProps.put("Database Name", jdbcUrl.split("databaseName=")[1]);

// 更新连接信息
originalConnInfo.setAttributes(newConnProps);
originalConnInfo.setUserName(dbUser);
originalConnInfo.setPassword(dbPwd);

// 应用新连接到报表
dbController.setConnection(originalConnInfo, originalConnInfo, null, 0);

// 初始化报表查看器并渲染
CrystalReportViewer viewer = new CrystalReportViewer();
viewer.setOwnPage(true);
viewer.setOwnForm(true);
viewer.setPrintMode(CrPrintMode.ACTIVEX);
viewer.setReportSource(reportClientDoc.getReportSource());
viewer.processHttpRequest(request, response, appContext, null);
%>

方案二:利用已配置的容器数据源(推荐)

你已经在web.xml中配置了jdbc/IntranetDBW的资源引用,这种方式更安全(容器管理密码)且支持连接池,是生产环境的首选方案:

修改JSP代码如下:

<%@ page import= "com.crystaldecisions.report.web.viewer.*,com.crystaldecisions.sdk.occa.report.data.*" %>
<%@ page import="com.crystaldecisions.sdk.occa.report.lib.*"%>
<%@ page import="com.crystaldecisions.sdk.occa.report.*"%>
<%@page import="com.crystaldecisions.reports.sdk.*" %>
<%@page import="com.crystaldecisions.sdk.occa.report.exportoptions.*" %>
<%@page import="javax.naming.InitialContext" %>
<%@page import="javax.sql.DataSource" %>
<%@page import="java.sql.Connection" %>
<%
// 从容器中获取预配置的数据源
InitialContext ctx = new InitialContext();
DataSource dbSource = (DataSource) ctx.lookup("java:comp/env/jdbc/IntranetDBW");
Connection dbConn = dbSource.getConnection();

// 打开报表文件
String REPORT_NAME = "test_table.rpt";
ReportClientDocument reportClientDoc = new ReportClientDocument();
reportClientDoc.open(REPORT_NAME, 0);

// 修改报表连接
DatabaseController dbController = reportClientDoc.getDatabaseController();
IConnectionInfo originalConnInfo = dbController.getConnectionInfos(null).getConnectionInfo(0);

PropertyBag newConnProps = new PropertyBag();
newConnProps.put("Database DLL", "crdb_jdbc.dll"); // 对应JDBC驱动的DLL文件
newConnProps.put("JDBC Connection String", dbConn.getMetaData().getURL());
newConnProps.put("User ID", dbConn.getMetaData().getUserName());

originalConnInfo.setAttributes(newConnProps);
originalConnInfo.setUserName(dbConn.getMetaData().getUserName());

// 应用更新
dbController.setConnection(originalConnInfo, originalConnInfo, null, 0);

// 归还连接到连接池
dbConn.close();

// 渲染报表
CrystalReportViewer viewer = new CrystalReportViewer();
viewer.setOwnPage(true);
viewer.setOwnForm(true);
viewer.setPrintMode(CrPrintMode.ACTIVEX);
viewer.setReportSource(reportClientDoc.getReportSource());
viewer.processHttpRequest(request, response, getServletConfig().getServletContext(), null);
%>

关键注意事项

  • 连接类型匹配:确保动态设置的连接类型和报表设计时的类型一致(比如都是JDBC),否则会出现兼容性错误。
  • 属性适配:不同数据库的PropertyBag属性略有差异,比如Oracle和SQL Server的参数名称不同,需要根据你的数据库类型调整。
  • 资源释放:使用容器数据源时,务必关闭Connection对象,让连接归还到连接池,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Masum billah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:39:13