分享
 
 
 

J2ee应用程序结合水晶报表:例程研究

王朝java/jsp·作者佚名  2007-09-01
窄屏简体版  字體: |||超大  

绪论

这篇文章,我们讨论j2ee应用程序结合水晶报表的经验,这个例子叫做“Task Workbench (TWB)”。这篇文章的目的是帮助大家评估在j2ee应用程序中使用水晶报表的优点和缺点。

TWB(www.taskworkbench.com)是提供工程和每日运作的实时信息的工作管理工具。它是一个web应用程序,jsp作为表示层,EJBs处理商业逻辑,CMP实体bean作为持久层映射到一个oracle数据库。

TWB帮助项目经理了解不同方法下项目花费时间和员工在每个项目上的消耗。当设计这个程序的时候,一个非常重要的需求就是提供给项目经理和项目管理人员一个高水平的项目成员和工程数据的视图。

图一: 显示一个员工的任务和每个任务花费的时间。

最初,我们用jsp创建报表。但是这个方法被证实太耗费时间,特别是创建联合报表的时候。所以开始寻找一个java报表解决方案。我们的基本要求是这个方案能够快速配置,并且轻松生成和修改报表,还有要容易整合到j2ee程序中。

我们选择水晶报表因为它完全满足我们的需求。它是一个成熟的、同类产品中处于领导地位的的工具。这是一个重要的考虑,因为我们希望我们的报表方案可以随着TWB一起成长。

实现

水晶报表被整合进TWB中有两个关键目的:第一是实现花费最小代价增加新报表和维护现有报表。第二个目的是转换到更复杂报表方案时,可以通过简单配置实现。

Crystal Java Reporting Component 有一个jsp标签库,提供创建基本报表的简单方法。我们决定使用自己的自定义jsp标签库,来使用Crystal Java Reporting Component显示报表。这个方法允许我们定制报表外观和报表参数,这样可以保持设计简单容易。

在jsp上唯一并且必须的java代码是一个为了得到一个显示在页面上的报表的实例而去访问工厂class的java方法。图二是一个可以请求报表的简单的jsp例子。Form传递必需的参数到view_report.jsp(图三)。

<%@ page import="com.ensemsys.twb.presentation.crystal.ReportParameter,

com.ensemsys.twb.presentation.crystal.ReportType"%>

<html>

<head>

<title>Report Viewer</title>

<link rel="stylesheet" href="style/main.css" type="text/css"/>

</head>

<body>

<h1>Simple Banked Hours Report</h1>

<p>Enter the date range for the report and click &quot;Submit&quot; to view

the report.</p>

<form method="post" action="view_report.jsp">

<input type="hidden" name="<%=ReportParameter.TYPE%>"

value="<%=ReportType.BANKED_TIME_SIMPLE%>"/>

<table>

<tr>

<td class="label">Start Date:</td>

<td>

<input type="text" name="<%=ReportParameter.START_DATE%>"

value="2003.06.30"/>

</td>

</tr>

<tr>

<td class="label">End Date:</td>

<td>

<input type="text" name="<%=ReportParameter.END_DATE%>"

value="2003.12.01"/>

</td>

</tr>

<tr>

<td>&nbsp;</td>

<td style="text-align: right">

<input type="submit" name="submitBtn" value="Submit"/>

</td>

</tr>

</table>

</form>

</body>

</html>

图二:simple_banked_time_report.jsp

<%@ page import="com.ensemsys.twb.presentation.crystal.ReportFactory,

com.ensemsys.twb.presentation.crystal.Report"%>

<%@ taglib uri="/simplereportviewer.tld" prefix="viewer" %>

<html>

<head>

<title>Report</title>

<link rel="stylesheet" href="style/main.css" type="text/css"/>

</head>

<body>

<%

// "CrystalEventTarget" is the report action name used by Crystal

final String REPORT_NAME = "CrystalEventTarget";

String reportName = (String) session.getAttribute( REPORT_NAME );

// refresh might have done via a report action

if ( reportName == null )

{

reportName = (String) request.getParameter( REPORT_NAME );

}

Report report = null;

if ( reportName == null )

{

report = ReportFactory.newInstance( request );

reportName = report.getName();

session.setAttribute( REPORT_NAME, reportName );

session.setAttribute( reportName, report );

}

else

{

report = (Report) session.getAttribute( reportName );

}

%>

<viewer:viewer report="<%=report%>" />

</body>

</html>

图三:view_report.jsp

报表工厂类创建一个报表实例,用request参数来确定报表类型。这种方法巧妙的把商业逻辑通过一个方法(method)装入单独报表。在ReportFactory子集中,工厂方法对于复合报表来说是一个最好的解决办法-ReportFactory能够代表子集创建一个报表。

package com.ensemsys.twb.presentation.crystal;

import com.crystaldecisions.sdk.occa.report.data.Fields;

import com.crystaldecisions.sdk.occa.report.data.ParameterField;

import com.crystaldecisions.sdk.occa.report.data.ParameterFieldDiscreteValue;

import com.crystaldecisions.sdk.occa.report.data.Values;

import javax.servlet.ServletRequest;

import javax.servlet.jsp.JspException;

import java.sql.Date;

import java.text.DateFormat;

import java.text.ParseException;

import java.text.SimpleDateFormat;

/**

* Provides methods for creating an instance of a Report

* from the parameters in the request.

*/

public class ReportFactory

{

public static final DateFormat FORMAT =

new SimpleDateFormat( "yyyy.MM.dd" );

public static Report newInstance( ServletRequest request )throws JspException

{

String reportType = getParameter( request, ReportParameter.TYPE );

Report report = null;

// For brevity, only the simple report type is shown here

if ( reportType.equals( ReportType.BANKED_TIME_SIMPLE ) )

{

report = newSimpleBankedTimeReport( request );

}else

{

throw new InvalidReportTypeException( reportType );

}

return report;

}

图四:ReportFactory.java 基于form提交的参数创建一个实例

private static Report newSimpleBankedTimeReport( ServletRequest request )

throws JspException

{

Date startDate = getDateParameter( request, ReportParameter.START_DATE );

Date endDate = getDateParameter( request, ReportParameter.END_DATE );

Fields fields = new Fields();

ParameterField prevYearField = newDateField( "Prev Fiscal Year", startDate);

ParameterField reportDateField = newDateField( "Report Date", endDate );

fields.add( prevYearField );

fields.add( reportDateField );

return new Report( "protected/reports/bhr_simple_demo.rpt",

ReportType.BANKED_TIME_SIMPLE, fields );

}

public static ParameterField newDateField( String name, Date date )

{

ParameterField field = new ParameterField();

Values vals = new Values();

ParameterFieldDiscreteValue value = new ParameterFieldDiscreteValue();

field.setName( name );

value.setValue( date );

field.setReportName( "" );

value.setDescription( "" );

vals.add( value );

field.setCurrentValues( vals );

return field;

}

public static Date newDate( String s )

throws InvalidDateStringException

{

java.sql.Date date = null;

try{

date = new java.sql.Date( FORMAT.parse( s ).getTime() );

}

catch ( ParseException e )

{

throw new InvalidDateStringException( e );

}

return date;

}

protected static void assertHasParameter( ServletRequest request,

String name)

{

String parameter = request.getParameter( name );

if ( parameter == null || parameter.equals( "" ) )

{

throw new NoSuchParameterException( name );

}

}

图四:ReportFactory.java

protected static Date getDateParameter( ServletRequest request, String name )

throws JspException

{

String parameter = getParameter( request, name );

Date date = null;

try{

date = newDate( parameter );

}

catch ( InvalidDateStringException e )

{

throw new JspException( e );

}

return date;

}

protected static String getParameter( ServletRequest request, String name )

{

assertHasParameter( request, name );

return request.getParameter( name );

}

}

图四:ReportFactory.java

SimpleReportViewerTag.java 呈现报表,这个类使用水晶报表的API来完成画出报表的工作。这个类非常简单――它创建一个CrystalReportViewer实例,设置数据库连接信息和报表需要的参数,最后显示报表。对应的TLD,simplereportviewer.tld,在图六列出。

package com.ensemsys.twb.presentation.crystal;

import com.crystaldecisions.report.web.viewer.CrystalReportViewer;

import

com.crystaldecisions.reports.reportengineinterface.JPEReportSourceFactory;

import com.crystaldecisions.sdk.occa.report.data.ConnectionInfo;

import com.crystaldecisions.sdk.occa.report.data.ConnectionInfos;

import com.crystaldecisions.sdk.occa.report.data.Fields;

import com.crystaldecisions.sdk.occa.report.data.IConnectionInfo;

import com.crystaldecisions.sdk.occa.report.lib.ReportSDKExceptionBase;

import com.crystaldecisions.sdk.occa.report.reportsource.IReportSource;

import com.crystaldecisions.sdk.occa.report.reportsource.IReportSourceFactory2;

import com.ensemsys.twb.ApplicationProperties;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.TagSupport;

import java.util.Locale;

图五:SimpleReportViewerTag.java 被执行来显示一个报表。

/**

* Displays a Crystal report.

*/

public class SimpleReportViewerTag extends TagSupport

{

private Report report;

public Report getReport()

{

return report;

}

public void setReport( Report report )

{

this.report = report;

}

public int doEndTag() throws JspException

{

CrystalReportViewer viewer = newViewer( report );

try{

IReportSourceFactory2 rptSrcFactory = new JPEReportSourceFactory();

IReportSource reportSource =

(IReportSource) rptSrcFactory.createReportSource(

report.getReportFileName(), getLocale() );

viewer.setReportSource( reportSource );

viewer.setDatabaseLogonInfos( newDBConnectionInfos() );

viewer.setEnableLogonPrompt( false );

Fields fields = report.getFields();

if ( fields != null )

{

viewer.setParameterFields( fields );

viewer.setEnableParameterPrompt( false );

}

viewer.processHttpRequest(

(HttpServletRequest) pageContext.getRequest(),

(HttpServletResponse) pageContext.getResponse(),

pageContext.getServletConfig().getServletContext(),

pageContext.getOut() );

}

catch ( ReportSDKExceptionBase e )

{

throw new JspException( e );

}

finally

{

if ( viewer != null )

{

viewer.dispose();

}

}

return EVAL_PAGE;

}

图五:SimpleReportViewerTag.java

private Locale getLocale()

{

// generally you want to change this method

// to return the specific locale that your J2EE

// application is using

return pageContext.getRequest().getLocale();

}

private static ConnectionInfos newDBConnectionInfos()

{

ConnectionInfos infos = new ConnectionInfos();

IConnectionInfo con = new ConnectionInfo();

con.setUserName( ApplicationProperties.getJDBCUser() );

con.setPassword( ApplicationProperties.getJDBCPassword() );

infos.add( con );

return infos;

}

private static CrystalReportViewer newViewer( Report report )

{

CrystalReportViewer viewer = new CrystalReportViewer();

viewer.setName( report.getName() );

// set the viewer formatting and behaviour options

//viewer.setSeparatePages( false );

//viewer.setBestFitPage( true );

// ... and so on

return viewer;

}

}

图五:SimpleReportViewerTag.java

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE taglib

PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"

"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>

<tlib-version>1.0</tlib-version>

<jsp-version>1.2</jsp-version>

<short-name>Crystal Viewer Tag Library</short-name>

<description>Display a Crystal Report with paramters</description>

<tag>

<name>viewer</name>

<tagclass>

com.ensemsys.twb.presentation.crystal.SimpleReportViewerTag

</tag-class>

<body-content>JSP</body-content>

<attribute>

<name>report</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

</taglib>

图六:simplereportviewer.tld

应为TWB仅仅允许管理者查看报表,TWB现有的接口控制系统控制对报表的访问。将来,TWB可以要求更精细的访问控制-例如,用户可以在有限的条件下查看特定项目的报表。在这个案例中,为了到达这种访问标准,我们使用水晶报表的安全特性。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有