Author: 许亮
Create: 2015-11-8 0:08:41
开始本示例之前,有必要先阅读我先前发布的《SpringMVC与iReport(JasperReports) 5.6整合开发实例》这篇博文,只有熟悉了SpringMVC与iReport的整合基础之后,才能更容易上手本示例教程,因为本示例的重点在于iReport报表模板的设计。
开始之前,先来预览下最终的报表效果:
<!-- iReport JasperReports -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>5.6.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.2.2</version>
</dependency>
<!-- JFreeChart -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.19</version>
</dependency>
3.2.1 Person实体类
此模型类主要实现报表中的数据清单展示。
package com.pes_soft.example.model;
import java.util.ArrayList;
import java.util.List;
/** * iReport subDataset测试bean: Person实体类 * @Author 许亮 * @Create 2015-1-15 20:32:27 */
public class JavaBeanPerson {
private String name; // 姓名
private String sex; // 性别
private int age; // 年龄
private String hometown;// 籍贯
private String phone; // 电话号码
public JavaBeanPerson() {}
public JavaBeanPerson(String name, String sex, int age, String hometown, String phone) {
this.name = name;
this.sex = sex;
this.age = age;
this.hometown = hometown;
this.phone = phone;
}
// 此处省略字段的getter和setter
public static List<JavaBeanPerson> getList() {
List<JavaBeanPerson> list = new ArrayList<JavaBeanPerson>();
list.add(new JavaBeanPerson("Lily", "female", 22, "Hubei", "10086"));
list.add(new JavaBeanPerson("Macro", "male", 33, "Beijing", "13800000000"));
list.add(new JavaBeanPerson("Andy", "male", 44, "HongKong", "13812345678"));
list.add(new JavaBeanPerson("Linder", "female", 28, "Guangxi", "18677778888"));
list.add(new JavaBeanPerson("Jessie", "female", 26, "Gansu", "18219177720"));
return list;
}
}
3.2.2 颜色实体类
此模型类主要实现报表中的柱状图展示。
package com.pes_soft.example.model;
import java.util.ArrayList;
import java.util.List;
/** * iReport subDataset测试bean: 颜色实体类 * @Author 许亮 * @Create 2015-1-15 20:13:27 */
public class JavaBeanColor {
private String color; // 颜色名
private int count; // 计数
public JavaBeanColor() {}
public JavaBeanColor(String color, int count) {
this.color = color;
this.count = count;
}
// 此处省略字段的getter和setter
public static List<JavaBeanColor> getList() {
List<JavaBeanColor> list = new ArrayList<JavaBeanColor>();
list.add(new JavaBeanColor("Red", 36));
list.add(new JavaBeanColor("Green", 59));
list.add(new JavaBeanColor("Blue", 27));
list.add(new JavaBeanColor("Yellow", 8));
list.add(new JavaBeanColor("Gray", 19));
return list;
}
}
3.2.3 颜色实体类
此模型类主要实现报表中的柱状图展示。
package com.pes_soft.example.model;
import java.util.ArrayList;
import java.util.List;
/** * iReport subDataset测试bean: 水果实体类 * @Author 许亮 * @Create 2015-1-15 20:03:57 */
public class JavaBeanFruit {
private String name; // 水果名称
private int qty; // 数量
public JavaBeanFruit() {}
public JavaBeanFruit(String name, int qty) {
this.name = name;
this.qty = qty;
}
// 此处省略字段的getter和setter
public static List<JavaBeanFruit> getList() {
List<JavaBeanFruit> list = new ArrayList<JavaBeanFruit>();
list.add(new JavaBeanFruit("Apple", 40));
list.add(new JavaBeanFruit("Banana", 28));
list.add(new JavaBeanFruit("Orange", 37));
list.add(new JavaBeanFruit("Grape", 15));
list.add(new JavaBeanFruit("Pear", 21));
return list;
}
}
package com.pes_soft.example.ds;
import java.util.List;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRAbstractBeanDataSourceProvider;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
/** * iReport数据源封装 * @author 许亮 * @Create 2015-1-15 15:42:52 */
public class IReportDataSourceProvider extends JRAbstractBeanDataSourceProvider {
private List<?> dataList;
public IReportDataSourceProvider(Class<?> beanClass) {
super(beanClass);
}
public IReportDataSourceProvider(Class<?> beanClass, List<?> dataSourceList) {
super(beanClass);
this.dataList = dataSourceList;
}
public JRDataSource create(JasperReport report) throws JRException {
return new JRBeanCollectionDataSource(this.dataList);
}
public void dispose(JRDataSource dataSource) throws JRException {
this.dataList = null;
}
}
package com.pes_soft.example.ctrler;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.pes_soft.example.constant.IReportFormat;
import com.pes_soft.example.constant.IReportParam;
import com.pes_soft.example.ds.IReportDataSourceProvider;
import com.pes_soft.example.model.JavaBeanColor;
import com.pes_soft.example.model.JavaBeanFruit;
import com.pes_soft.example.model.JavaBeanPerson;
/** * Handles requests for the application home page. */
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/** * Simply selects the home view to render by returning its name. */
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
/** * 返回iReport报表视图 * @param model * @return */
@RequestMapping(value = "/report", method = RequestMethod.GET)
public String report(Model model) {
// 报表数据源
JRDataSource jrDataSourceMain_Person = null;
JRDataSource jrDataSourceSub_Color = null;
JRDataSource jrDataSourceSub_Fruit = null;
try {
IReportDataSourceProvider dataSourcePerson = new IReportDataSourceProvider(JavaBeanPerson.class, JavaBeanPerson.getList());
jrDataSourceMain_Person = dataSourcePerson.create(null);
IReportDataSourceProvider dataSourceColor = new IReportDataSourceProvider(JavaBeanColor.class, JavaBeanColor.getList());
jrDataSourceSub_Color = dataSourceColor.create(null);
IReportDataSourceProvider dataSourceFruit = new IReportDataSourceProvider(JavaBeanFruit.class, JavaBeanFruit.getList());
jrDataSourceSub_Fruit = dataSourceFruit.create(null);
} catch (JRException e) {
e.printStackTrace();
}
model.addAttribute("url", "/WEB-INF/jasper/MvcMultiDsCrossReportExample.jasper"); // 报表模板
model.addAttribute("format", IReportFormat.pdf.name()); // 报表输出格式
model.addAttribute("jrMainDataSource", jrDataSourceMain_Person); // 报表主数据源
model.addAttribute("jrColorDataSource", jrDataSourceSub_Color); // 报表子数据源1(柱状图[Bar Chart])
model.addAttribute("jrFruitDataSource", jrDataSourceSub_Fruit); // 报表子数据源2(饼图[Pie Chart])
return IReportParam.IREPORT_VIEW; // 对应jasper-defs.xml中的bean id
}
}
注意字段的类型与模型JavaBeanPerson.java中的字段类型保持一致。创建字段的过程就不赘述了,直接上图。
为报表创建两个参数,jrColorDataSource和jrFruitDataSource,此两参数最终会转换为报表的两个子数据源,分别作为柱状图和饼图的数据源。创建报表参数的操作如下:
然后将参数重命名为“jrColorDataSource”。
接下来需要设置该报表参数的两个属性:
◆ Parameter Class(参数类):net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
◆ Use as a prompt(是否弹出窗口以输入报表参数):去掉勾勾,即不弹出窗口
至此,报表参数jrColorDataSource创建完成。另一个参数jrFruitDataSource的创建过程亦与此相同。
为报表创建两个空的DataSet,分别重命名为subColorDataSet和subFruitDataSet。
给DataSet创建字段,字段名分别对应Java实体模型JavaBeanColor.java、JavaBeanFruit.java中的字段,注意字段数据类型的一致性。
在报表iReport报表设计器中,可以删除一些不需要的Band。这里特别要注意的是,像柱状图、饼图这些图表对象,只能放在“Summary” Band里面。
将组件面板中的“Chart”拖入到“Summary” Band里面,然后选择你想要的图表类型。这里先创建一个柱状图(Bar Chart)。
指定柱状图所使用的DataSet。在4.3步骤里创建的两个空的DataSet就在这里派上用场了。这里就直接指定柱状图使用“subColorDataSet”这个DataSet,剩下的一个“subFruitDataSet”就留作饼图的数据集合。
输入数据序列名称,这一步非必须,可以直接“下一步”跳过。
指定报表的Category(分类)和Value(值)。这里的Category即Y轴,Value即X轴。
同样的方法创建一个饼图。根据自己的需要,可以自由调整图表的尺寸。最终的报表模板效果如下:
回顾下报表模板的设计过程:
■ 创建了两个报表“Parameters(参数)”:jrColorDataSource和jrFruitDataSource,并且指定它们的“Parameter Class”为net.sf.jasperreports.engine.data.JRBeanCollectionDataSource。
■ 创建了两个空的“DataSet(数据集)”:subColorDataSet和subFruitDataSet,其中,
subColorDataSet对应Java实体模型JavaBeanColor.java,两者字段保持一致;
subFruitDataSet对应Java实体模型JavaBeanFruit.java,两者字段保持一致。
■ 创建了一个柱状图图表,指定使用的DataSet为“subColorDataSet”。
■ 创建了一个饼图图表,指定使用的DataSet为“subFruitDataSet”。
至此,报表模板的设计似乎已经完成,非也!如果此时编译报表模板,将得到的.jasper文件放入/WEB-INF/jasper/目录中,并不能得到想要的报表,原因是:创建了两个空的“DataSet(数据集)”。
我们一开始就创建了两个报表“Parameters(参数)”,那么接下来要做的就是:把报表“Parameters(参数)”赋值给两个空的“DataSet(数据集)”。
选中一个图表对象,右键菜单中点击“Chart Data”。
关键操作步骤为:
◆ 选择“Sub dataSet”为:subColorDataSet;
◆ 选择“Connection / DataSet Expression”为:Use datasource expression;
◆ 选择或设置上述表达式的值为:$P{jrColorDataSource},即其中一个报表“Parameters(参数)”。
这样就完成了报表“Parameters(参数)”到报表“DataSet(数据集)”的数据关联转换。饼图同样要如此设置。
编译报表模板,将得到的.jasper文件放入/WEB-INF/jasper/目录中,通过浏览器访问地址“http://localhost:8080/multids/report”查看报表(PDF格式)。如果能正常访问,说明你已经掌握了SpringMVC iReport多数据源交叉报表的的开发技术(至少本例中使用了三个不同的数据源,一个主数据源,两个子数据源)。
Eclipse中导入本实例时,若访问时出现404错误,可能需要设置项目的ContextPath。在项目属性中找到“Web Project Settings”,然后修改即可。
项目源码:mvc-ireport-multi-ds.rar