最後将会显示中文的文本Pdf,和SSM框架有关的知

2020-01-05 19:23 来源:未知

好,本篇开始讲解如何利用设计好的jasper报表来付诸应用,即在Web应用中如何调用jasper报表文件。
        首先运行Netbean IDE 6.8,并创建一个Web应用的工程。如何在Netbean IDE创建Web应用工程,包括如何使用Netbean IDE可以参考我写的《NetBeanIDE 6如何安装和使用》文章,这篇文章在我博客日志的”NetbeanIDE“分类中,时间是2007-12-04,如果需要可以去参考。

一。  下载ireport( 官方网站:http://ireport.sourceforge.net),本人下载ireport3.7.0。

Servlet基础学习

1、前言

写本文的主要原因是,之前写过一个开源软件,使用的报表技术是jasperreport+ireport,所以对它有一点印象,加上对国内fine某印象特别差,故此没有选择fine。和SSM框架有关的知识这里不做太多描述,我只详细解释和整合jasreport相关的部分,因为我也是初学SSM才一个月,框架部分实在是不敢误导人。

要要把jasper的包加入到/WEN-INF/lib中


一、JavaWEB开发的目录结构

--应用程序根目录/
  --WEB-INF目录:必须目录
    --web.xml:Web应用部署描述文件,必须目录
    --classes目录:存放字节码文件
    --lib目录:存放第三方类库文件
  --其他静态文件:HTML、CSS、JavaScript、图片等

2、jar包相关

jasperreport+ireport依赖的jar包有很多,可以自行网上搜索。比较重要的包有如下几个,我使用的是ireport5.1。

jasperreports-5.6.0.jar(这个对版本要求不是很高,5.1以上就可以)

groovy-1.8.3.jar(必须是1.8-2.0)

asm-3.3.1.jar(给别人搭的时候遇到的jar缺少问题,???黑人问号,我也不知道为什么要,反正你加就是了哪来那么多废话)

iText-2[1].1.7.jar(必须是这个版本之上)

还有其他的jar这里就不做阐述了,网上可以搜索到。

需要的类在ireport的安装目录下:

二。  搭建ireport+jasperreports java开发平台。将ireport3.7.0安装路径下

D:iReport-3.7.0 ireportmodulesext下的(jasperreports-3.7.jar,

iText-  2.1.0.jar,iTextAsian.jar,commons-logging-1.1.jar,commons-collections-3.2.1.jar,

commons- digester-1.7.jar,poi-3.2-FINAL-20081019.jar,groovy-all-1.5.5.jar)的jar包加入到 

java classPath下。其中各jar包的版本以你下载的ireport的ireportmodulesext路径下jar为准。

各jar包作用如下:

jasperreports-3.7.jar:该包的作用完成ireport中Preview按扭功能。通过该包可以通过java来ireport生成摸班 

(.jrxml或.jasper)填充数据源并导出pdf,excel,html等格式文件。

iText-2.1.0.jar:生成pdf所依赖的包。

iTextAsian.jar:支持pdf中文字体依赖的包。

groovy-all-1.5.5.jar:将.jrxml编译成.jasper.如果你不使用java编译,而使用ireport工具编译则无须导入该 包。

commons-digester-1.7.jar:解析.jrxml

poi-3.2-FINAL-20081019.jar:生成excel报表所依赖的jar

二、开发Java Web应用程序的流程

  1. 设计目录结构:根据具体业务需要,遵照规范的目录结构设计好Web应用程序的目录结构。
  2. 编写Web应用程序代码:编写业务逻辑所需的Java代码。
  3. 编写部署描述文件:把Servlet、初始化参数等定义到部署描述文件web.xml中。
  4. 编译代码:把编写好的Java源代码编译成字节码。
  5. 将Web应用程序打包:把整个Web应用程序打成jar包,以方便部署。
  6. 部署Web应用程序:把打好的War包部署到Web服务器上。
  7. 执行Web应用程序:启动Web服务器,利用客户端浏览器进行访问测试。
    注意:在具体的开发过程中,一般都会使用IDE工具,使用IDE工具进行Web应用程序开发时,只需要开发人员完成前三个步骤,其他步骤IDE工具可以自动完成。

Java Servlet是和平台无关的服务器组件,它运行在Servlet容器中。Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,Servlet和客户的通信采用"请求/响应"的模式。

3、Ireport相关

首先开发出一个报表并编译成.jasper文件,ireport有自带的这个功能,在.jrxml文件相同路径下就可以看到。ireport相关的文档有很多,请自行查阅。推荐使用5.1版本的ireport,其他版本不保证绝对能正常搭建成功。

iReport-3.7.3ireportmodulesext(如果为3.7.3):


三、手动部署JavaWeb应用程序

  • 把WebContent对应的根目录拷贝到webapps目录下,(可以改名helloworld)
  • 把程序中用到的*.class文件拷贝到classes目录中
  • 如果应用程序用到的有第三方jar包,则拷贝到lib目录中。

4、整合过程

首先需要一个dataSource,这里我发现一个想让我哭的事情,简书不能贴代码!!!,算了上图吧

永利平台娱乐 1

新建文件,reports.xml,为了方便,直接建在了WebContent底下。。。

永利平台娱乐 2

配置reportViewResolver和viewResolver,这里需要注意的是reportViewResolver的location需要时刚才配置的reports.xml的路径。文件名为:applicationContext-report.xml

永利平台娱乐 3

然后让加载刚才配置的applicationContext-report.xml

我这里设置的是自动加载,这一步就省略了。

永利平台娱乐 4

这里需要注意的是:spring mvc中的配置前缀和后缀你只能含泪注释掉了,如果不注释的话,报表的测试马上就会看见404了

永利平台娱乐 5

我只能新建一个文件供controller使用了,要不然你的别的view的后缀不能拼接上。不过这个是spring mvc的事情,不能脱题 - - 

永利平台娱乐 6

写controller,这里的return的view就是reports.xml中的beanID

永利平台娱乐 7

至此,SSM整合jasperreport的过程就完美收官了,接下来测试!!!

启动项目,

看到如下页面就代表成功了,我使用的是google浏览器

永利平台娱乐 8

不过这个文件后缀有点诡异,下载下来更改后缀为.pdf就可以正常打开了。后续我还会继续填坑的。不过简书的代码怎么贴请大家告诉我,第一次发帖不太懂

  • -

希望对大家有所帮助

jasperreports-3.7.3.jar
iText-2.1.7.jar
groovy-all-1.5.5.jar
commons-digester-1.7.jar
commons-collections-3.2.1.jar
commons-beanutils-1.8.2.jar


四、解决手动复制

  1. build path中修改default folder的默认路径,以后生成的*.class文件,可以自动输出到tomcat的webapps中。
  2. 如果不想手动复制WebContent目录,可以在webapps中新建catalina/localhost/**.xml文件
    xml文件的docBase指的是WebContent的物理路径,path="/",reloadable="true",reloadable:当修改了docBase下的classes目录下的class文件时,服务器重新加载class文件。

根据我的测试需要以上这些包,如果不够请在这个目录下寻找。


五、Servlet 容器:运行Servlet、JSP、Filter等的软件环境。

  1. 可以来创建Servlet,并调用Servlet 的相关生命周期方法。
  2. JSP, Filter, Listener, Tag...都是运行在Servlet容器中,并且相关的生命周期方法都是由Servlet容器来管理的。

在WEB-INF下新建文件夹 report,把ireport下生成的meeting_phone_list.jasper放到这个目录下

三。使用javaBean数据源开发子报表例子如下:

      第一步:创建主报表javaBean(货物)如下(set,get方法省列):

public class DailySales implements Serializable {

private static final long serialVersionUID = 1L;

     private String productNo;//货物代号

     private String productName;//货物名称

     private int number;

     private int money;//货物价格

     private int id;//货物唯一标识

     private List dailyZooms;//货物销售地区(子报表)

     public DailySales(String productNo, String productName, int number, int money,

List   dailyZooms) {

this.productNo = productNo;

this.productName = productName;

this.number = number;

this.money = money;

this.dailyZooms = dailyZooms;

}

}

六、Servlet 生命周期的方法:以下方法都是由Servlet容器负责调用

  • 构造器: 只被调用一次,只有第一次请求Servlet时,创建Servlet的实例,调用Constructor。这说明Servlet是单实例的!
  • init方法:只被调用一次,在创建好实例后立即被调用,用于初始化当前Servlet。
  • service:被多次调用,每次请求都会调用service方法,实际用于响应请求的。
  • destroy:只被调用一次,在当前Servlet所在的Web应用被卸载前调用,用于释放当前Servlet所占用的资源。

        其次,打开index.jsp文件,在其中填写如下代码:


七、 load-on-startup 参数:

  1. 配置在servlet节点中:
    <servlet>
        <servlet-name>helloServlet</servlet-name>
        <servlet-class>com.lucus.javaweb.HelloServlet</servlet-class>
        <!-- 可以指定Servlet被创建的时机 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
  1. load-on-startup:可以指定Servlet被创建的时机.若为负数,则在第一次请求时被调用,若为非负数,则在当前web应用被Servlet容器加载时创建实例,且数值越小越早被创建。
<form action="SReport" id="frmPrintView" name="frmPrintView" method="post" target="_blank">
            <input type="hidden" name="export_type" value="pdf">
            <input type="hidden" name="report" value="meeting_phone_list">
            <input type="hidden" name="meeting_name" value="江西省南昌市工业管理局">
            <input type="submit" value="打印">
</form>

        接下来,建立report.servlet的包,在此包下面建立SReport类,此类是一个Servlet类。修改其中processRequest方法。processRequest方法里的实现思路
        1)获取前台传入的参数,这些参数包括“export_type”(导出文件格式)、“report”(报表文件名)、“meeting_name”(会议名称)。
        2)填充报表。通过JasperFillManager类的fillReport方法来填充。
        3)依据导出文件格式要求不同产生不同的字节对象,可以支持的导出文件格式包括“pdf”、“excel”、“html”、“xml”。
        4)通过response对象向前台输出。
        其具体代码如下:

   第二步:创建子报表报表javaBean(货物销售地区)如下(set,get方法省列):

  public class DailyZoom implements Serializable {

    private String name;

    private BigDecimal amounts;

public DailyZoom(String name, BigDecimal amounts) {

永利平台娱乐,this.name = name;

this.amounts = amounts;

}

}

注意:如果在报表中需要排序则上述类必须实现Comparable接口,并实现其方法。

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        //设置字符集
        request.setCharacterEncoding("GBK");
        //获取导出文件类型
        String export_type=request.getParameter("export_type")==null?"pdf":(String)request.getParameter("export_type");
        //获取报表名
        String report_file=request.getParameter("report")==null?"":(String)request.getParameter("report");
        Hashtable ht=new Hashtable();
        java.util.Collection collection=null;
        //针对不同报表进行不同处理
        if(report_file.equals("meeting_phone_list")){
            System.out.println("当前报表名:"+report_file);
            String meeting_name=request.getParameter("meeting_name")==null?"":(String)request.getParameter("meeting_name");
            //将报表名取出,放入Map类对象中,方便之后传入报表
            ht.put("meeting_name", meeting_name);
            //BMeetingPhoneListDS为自定义的活动数据的类。
            BMeetingPhoneListDS mpl_ds=new BMeetingPhoneListDS();
            //获得数据,数据为java.util.Collection类型
            collection=mpl_ds.getCollection();
        }
        //因为是基于JavaBean数据源的,因此采用JRBeanCollectionDataSource类
        JRBeanCollectionDataSource ds=new JRBeanCollectionDataSource(collection);
        ServletOutputStream ouputStream =null;
        byte[] bReport=null;
        String err=null;
        try {
            StringBuffer sb=new StringBuffer("/WEB-INF/report/");
            sb.append(report_file);
            sb.append(".jasper");
            ServletContext application=this.getServletContext();
            String cd=application.getRealPath(sb.toString());
            System.out.println("当前路径:"+cd);
            JasperPrint jasperPrint = null;
            //将参数置入报表,参数包括报表文件路径、报表接收的传入参数(以Map类提供)、报表数据源
            jasperPrint = JasperFillManager.fillReport(cd, ht, ds);
            System.out.println("填充报表......");
            //依据导出文件格式不同,配置不同参数
            if(export_type.toLowerCase().equals("pdf")){
                bReport = JasperExportManager.exportReportToPdf(jasperPrint);
            }
            else{
                if(export_type.toLowerCase().equals("excel")){
                    JRXlsExporter exporter = new JRXlsExporter();
                    ByteArrayOutputStream oStream = new ByteArrayOutputStream();
                    exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
                    exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, oStream);
                    exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,Boolean.TRUE);
                    exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,Boolean.FALSE);
                    exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,Boolean.FALSE);
                    exporter.exportReport();
                    bReport= oStream.toByteArray();
                    oStream.close();
                }
                else{
                    if(export_type.toLowerCase().equals("html")){
                        JRHtmlExporter exporter = new JRHtmlExporter();
                        ByteArrayOutputStream oStream = new ByteArrayOutputStream();
                        exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN,Boolean.FALSE);
                        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
                        exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GBK");
                        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, oStream);
                        exporter.exportReport();
                        bReport= oStream.toByteArray();
                        oStream.close();
                    }
                    else{
                        bReport = JasperExportManager.exportReportToXml(jasperPrint).getBytes();
                    }
                }
              
              
            }
        }
        catch(Exception e){
            err=e.getMessage();
            System.out.println("制作报表失败!原因:"+err);
            bReport=null;
        }
        try{
            if(bReport!=null){
                //response.setContentType("application/octet-stream;charset=UTF-8");
                //将数据输出到客户端
                response.setContentType("application/pdf;charset=GBK");
                response.setCharacterEncoding("GBK");
                //设置客户端接收到的文件的文件名。
                String filename="222222.pdf";
                response.addHeader("Content-Disposition", "inline; filename="+filename);
                ouputStream = response.getOutputStream();
                response.setContentLength(bReport.length);
                ObjectOutputStream oos = new ObjectOutputStream(ouputStream);
                //oos.writeObject(jasperPrint);
                ouputStream.write(bReport, 0, bReport.length);
                oos.flush();
                oos.close();
            }
            else{
                PrintWriter pw=response.getWriter();
                pw.print(err);
                pw.close();
            }
          
        }
        catch(Exception e){
            System.out.println("输出报表失败!原因:"+e.getMessage());
        }
        finally {
            try{
                if(ouputStream!=null){
                    ouputStream.close();
                    ouputStream=null;
                }
            }
            catch(Exception e){
            }
          
        }
    }

protected void doPost(HttpServletRequest request, HttpServletResponse response)   
     throws ServletException, IOException {   
         processRequest(request, response);   
     }   


       上面我们实现了Servlet,但此次Servlet只是接受前端参数,并调用JasperReport的类实现产生报表文件,而数据的源部分需要我们自己编写完成。
        下面附上Servlet在Web.xml文件中的配置信息。


<servlet>
        <servlet-name>SReport</servlet-name>
        <servlet-class>report.servlet.SReport</servlet-class>
    </servlet>
<servlet-mapping>
        <servlet-name>SReport</servlet-name>
        <url-pattern>/SReport</url-pattern>
    </servlet-mapping>

 第三步:创建DailySalesFactory工厂类提供集合数据源如下:

public class DailySalesFactory {

private static DailySales[] data = { new DailySales(" 货号 1", " 物品1 ", 1, 1000, getDailyZoom()),

new DailySales(" 货号 2", " 物品 2", 2, 2000, getDailyZoom()),

new DailySales(" 货号 3", " 物品 3", 3, 3000, getDailyZoom()),

new DailySales(" 货号 4", " 物品 4", 4, 4000, getDailyZoom()),

new DailySales(" 货号 5", " 物品 5", 5, 5000, getDailyZoom()),

new DailySales(" 货号 6", " 物品 6", 6, 6000, getDailyZoom()),

new DailySales(" 货号 7", " 物品 7", 7, 7000, getDailyZoom()),

new DailySales(" 货号 8", " 物品 8", 8, 8000, getDailyZoom()),

new DailySales(" 货号 9", " 物品 9", 9, 9000, getDailyZoom()),

new DailySales(" 货号 10", " 物品 10", 10, 10000, getDailyZoom()) };

public static Object[] getBeanArray() {

return data;

}

public static Collection getBeanCollection() {

return Arrays.asList(data);

}

public static List getDailyZoom() {

List dailyZooms = new ArrayList();

dailyZooms.add(new DailyZoom("厦门", new BigDecimal(123.00)));

dailyZooms.add(new DailyZoom("南昌", new BigDecimal(456.00)));

return dailyZooms;

}

}

将上述创建的类设置到ireport3.7.0的classPath目录下(工具》选项》classPath),然后配置javaBean数据源如下:

  
        由上面的Servlet代码可以看到,在调用JasperFillManager.fillReport方法时,除了第一、二个参数外,我们的数据源需要转换成JRBeanCollectionDataSource类的对象,而JRBeanCollectionDataSource类又是由Collection构造而来。我们可以想到,为了还有很多的报表要基于此Servlet来实现,因此为了稍微通用点,我们首先来定义一个接口:



package report;
import java.util.ArrayList;
/**
*
* @author 伏虎
*/
public interface IDataSource<T> {
    public ArrayList<T> getCollection();
}

永利平台娱乐 9

        然后,定义一个Javabean用来实现POJO,相当于一条记录。



package report;
/**
*
* @author 伏虎
*/
public class CAddressList {
    private int id=0;
    private String name=null;
    private String post=null;
    private String sex=null;
    private String nationality=null;
    private String phone=null;
    private String unit=null;
    public String getUnit() {
        return unit;
    }
    public void setUnit(String unit) {
        this.unit = unit;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getNationality() {
        return nationality;
    }
    public void setNationality(String nationality) {
        this.nationality = nationality;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getPost() {
        return post;
    }
    public void setPost(String post) {
        this.post = post;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
  
}

永利平台娱乐 10

         在定义一个商业类来获取或者产生数据,我这里是通过此商业方法产生数据(因为做演示)

注意:(1)pdf中文设定:首先将iTextAsian.jar設置到classPath下.然後fonts path下勾選iTextAsian.jar路徑和jasperreports-extensions-3.5.3.jar路徑,最後将会显示中文的文本Pdf Font name is now deprecated:STSong-Light,pdfExcoding:UniGB-UCS2-V (Chinese Simplified)(V是从上往下显示,H是从左往右显示)。

package report;
import java.util.ArrayList;
import java.util.Random;
/**
*
* @author 伏虎
*/
public class BMeetingPhoneListDS implements IDataSource<CAddressList> {
    public ArrayList<CAddressList> getCollection() {
        Random r=new Random();
        int p=r.nextInt(25);
        int max=80;
        int step=p;
        int loop=0;
        int index=0;
        ArrayList<CAddressList> rtn = new ArrayList<CAddressList>();
        for (int i = 1; i <= max; i++) {
            CAddressList bean = new CAddressList();
            bean.setId(i);
            if(loop>step){
                index++;
                loop=0;
            }
            else{
                loop++;
            }
            bean.setUnit("工作单位"+index);
            bean.setName("姓名"+i);
            bean.setPost("岗位"+i);
            if((i % 2)==0){
                bean.setSex("女");
            }
            else{
                bean.setSex("男");
            }
            bean.setNationality("民族"+i);
            bean.setPhone("电话"+i);
            rtn.add(bean);
        }
        return rtn;
    }
}

         (2)上下和左右表格要对其,否则生成的excel会很乱。

         好到此,服务端的实现基本就完成了。
         现在运行,点击页面上的答应按钮就可以看到会弹出一个窗口并在其中显示报表。当然如果你导出的是pdf文件,则客户端要求安装Adobe的Reader阅读器。

         (3)Parameters,Fields,Variables区别:Parameters是保存从java外部传进来的参数,Fields是Sql或javaBean数据查询返回的字段,Variables是ireport计算或保存值的。

         (4)分页:强行分页可直接使用Break控件,程序控制分页(让它每显示20条就自动分页)在该print when expression里面写表达式,如下:new Boolean($V{total}.intValue() % 20 == 0)    total是数据总量

         (5)分組統計的報表.每一分組一頁(在ireport中***group foot1勾選start on a new page).

    第五步:使用数据源开发子报表如下:

永利平台娱乐 11

TAG标签:
版权声明:本文由永利平台娱乐发布于IT交流,转载请注明出处:最後将会显示中文的文本Pdf,和SSM框架有关的知