职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 420|回复: 1

JasperReport与spring集成的三种方式

[复制链接]
芷馨 发表于 2011-8-29 10:29 | 显示全部楼层 |阅读模式

最近要用JasperReport,试着和spring集成了一下,现总结如下:

spring提供了几种对应JasperReport的view,可以在spring的bean定义文件
中按需要定义好,在spring的controller中对报表数据进行填充,然后返回
ModelAndView就可以了,这样就和spring的MVC集成在一起了。
详细信息可以参看spring包中带的spring reference文档。

我是这么配置的,定义报表的ViewResolver:
Xml代码  
<bean id="reportViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">  
    <property name="order" value="1"/>  
    <property name="location" value="/WEB-INF/reports.xml"/>  
</bean>  

<bean id="reportViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
        <property name="order" value="1"/>
        <property name="location" value="/WEB-INF/reports.xml"/>
</bean>

spring可以定义多个ViewResolver,对于普通的jsp的view,还需要如下定义一个ViewResolver:
Xml代码  
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
</bean>  

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>

报表的ViewResolver中引用的reports.xml在后面会说到。

对于报表的数据的填充,我试验了三种方式如下:

1. 直接指定DataSource

可以在View的定义时,直接指定DataSource,这时我们就不需要再获取数据对
报表进行填充,报表会自动从DataSource获取数据库连接,然后通过报表定义
中的SQL语句获取数据。在reports.xml中是这样定义的:
Xml代码  
<bean id="datasourceCustomerReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView">  
    <property name="url" value="/pages/report/report1.jasper" />  
    <property name="jdbcDataSource" ref="dataSource" />  
</bean>  

<bean id="datasourceCustomerReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView">
        <property name="url" value="/pages/report/report1.jasper" />
        <property name="jdbcDataSource" ref="dataSource" />
</bean>
其中dataSource就是一般系统中定义的DataSource bean。spring refernce中
报表的ViewResolver用的是ResourceBundleViewResolver,View的定义是在一个
properties文件中完成的,但是我没找到在properties文件中指定jdbcDataSource
属性为一spring的bean(dataSource)的方法,所以用的是xml文件定义的方法。

这时controller的处理非常简单,没有获取数据的处理,代码如下:
  
@RequestMapping(value = "/datasourceCustomer", method = RequestMethod.POST)   
public ModelAndView datasourceCustomerReport(HttpServletRequest request) {   
    Map<String, String> model = new HashMap<String, String>();   
      
    //这段代码是按用户操作分别返回pdf和excel格式的报表   
    if (request.getParameter("excel") != null) {   
        model.put("format", "xls");   
    } else {   
        model.put("format", "pdf");   
    }   
      
    return new ModelAndView("datasourceCustomerReport", model);   
}  

@RequestMapping(value = "/datasourceCustomer", method = RequestMethod.POST)
public ModelAndView datasourceCustomerReport(HttpServletRequest request) {
        Map<String, String> model = new HashMap<String, String>();
       
        //这段代码是按用户操作分别返回pdf和excel格式的报表
        if (request.getParameter("excel") != null) {
                model.put("format", "xls");
        } else {
                model.put("format", "pdf");
        }
       
        return new ModelAndView("datasourceCustomerReport", model);
}

这种方法代码很简单,但是有一个问题,就是生成报表时的数据库操作,不在
spring的事务管理下,所以并不适用需要严格的事务管理的情况。

2. 通过的Hibernate Dao中获取数据

这种方式view的定义只要指定class和url就可以了,reports.xml中的定义如下:
Xml代码  
<bean id="customerReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView">  
    <property name="url" value="/pages/report/report1.jasper" />  
</bean>  

<bean id="customerReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView">
        <property name="url" value="/pages/report/report1.jasper" />
</bean>

这种方式是通过Hibernate Dao获取Collection类型的数据,然后保存在给View
的model中,Spring会自动寻找Collection类型的对象作为报表填充的数据。
Controller的代码如下:
  
@RequestMapping(value = "/customer", method = RequestMethod.POST)   
public ModelAndView customerReport(HttpServletRequest request) {   
    Map<String, Object> model = new HashMap<String, Object>();   
    List data = reportService.customerReport();   
    model.put("data", data);   
      
    ...   
      
    return new ModelAndView("customerReport", model);   
}  

@RequestMapping(value = "/customer", method = RequestMethod.POST)
public ModelAndView customerReport(HttpServletRequest request) {
        Map<String, Object> model = new HashMap<String, Object>();
        List data = reportService.customerReport();
        model.put("data", data);
       
        ...
       
        return new ModelAndView("customerReport", model);
}

其中reportService通过Hibernate Dao获取数据,Dao中代码如下:
  
@Override  
public List customerReport() {   
    Session session = sessionFactory.getCurrentSession();   
      
    return session.createCriteria(CustomerBaseInfo.class).list();   
}  

@Override
public List customerReport() {
        Session session = sessionFactory.getCurrentSession();
       
        return session.createCriteria(CustomerBaseInfo.class).list();
}

此时,我们可以在service层定义Transaction,保证了事务管理。

但这种方式也有感觉不好的地方,如果我只是需要某个表的某几个字段,但这种
方法会把所有字段的数据都取出来,这是一种对系统资源的浪费,所以我又试
验了第三种方法:

3. 通过JdbcTemplate Dao获取数据

这种方式View的定义和Controller中的处理没什么变化,Controller中也是通过
service获取数据,但是service是通过一个JdbcTemplate的Dao获取的数据,这个
Dao的代码如下:
  
public class ReportDaoImpl implements ReportDao {   
  
    private JdbcTemplate jdbcTemplate;   
  
    public void setDataSource(DataSource dataSource) {   
        this.jdbcTemplate = new JdbcTemplate(dataSource);   
    }   
  
    @Override  
    public List jdbcCustomerReport() {   
        return jdbcTemplate.queryForList("select name, listlaiyuan, yejie from customerbaseinfo");   
    }   
}  

public class ReportDaoImpl implements ReportDao {

        private JdbcTemplate jdbcTemplate;

        public void setDataSource(DataSource dataSource) {
                this.jdbcTemplate = new JdbcTemplate(dataSource);
        }

        @Override
        public List jdbcCustomerReport() {
                return jdbcTemplate.queryForList("select name, listlaiyuan, yejie from customerbaseinfo");
        }
}

通过这种方式,我们可以直接通过SQL语句或者存储过程灵活地获取数据,而且
由于HibernateTransactionManager能够检查到DataSource发起的数据库访问,所以
我们可以与系统中的其他Hibernate Dao一起用HibernateTransactionManager来
管理事务。

以上就是我试验的三种方式,三种方式各有侧重,可以根据具体情况选用。

以下附加上事务管理的定义:
Xml代码  
<bean id="transactionManager"  
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
    <property name="sessionFactory" ref="sessionFactory" />  
</bean>  
  
<tx:annotation-driven />  

<bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven />

以及JdbcTemplate Dao的定义
Xml代码  
<bean id="reportDao" class="daos.impl.ReportDaoImpl">  
    <property name="dataSource" ref="dataSource" />  
</bean>  

<bean id="reportDao" class="daos.impl.ReportDaoImpl">
        <property name="dataSource" ref="dataSource" />
</bean>

最后,希望各位大侠拍砖,呵呵

走就走吧 发表于 2011-8-29 10:30 | 显示全部楼层
推荐链接
见证又一个准百万富翁的诞生!
20-30万急聘多名天才Java/MTA软件工程师

3G培训就业月薪平均7K+,不3K就业不花一分钱!

您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-5-2 06:56 , Processed in 0.119567 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表