JasperReports入门教程(二):中文打印


背景

上一篇中我们介绍了JasperReport的基本入门,也展示了一个报表。但是我们的示例都是使用的英文,如果我们把需要打印的数据改为中文会怎么样?下面我们就测试一下

  1. HashMap<String, Object> parameters = new HashMap<String, Object>();
  2. parameters.put("name", "小明");

预览的pdf界面会发现原来打印name的地方不显示任何数据了

为什么会出现这个问题呢?我们查找net.sf.jasperreports的jar包源码发现它并不包含中文的字体库。那么就好办了,我们只需要加上中文字体库就可以了。

给JasperReport Studio工具增加字体

1.我们可以在本地电脑的 C:\Windows\Fonts下找到你想要的字体文件,也可以使用我提供的字体文件微软雅黑msyh.ttf文件下载,提取码: bvmn

2.在JasperReport Studio工具的Window -> Preferences-> font 中add一个微软雅黑的字体

3.修改模板中需要显示中文的元素的字体为微软雅黑

给JasperReport增加扩展的字体资源文件

1.在resources资源文件下增加fonts.xml和msyh.ttf字体文件

  • fonts.xml配置微软雅黑的字体
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <fontFamilies>
  3. <fontFamily name="微软雅黑">
  4. <normal>jaspers/fonts/msyh.ttf</normal>
  5. <bold>jaspers/fonts/msyh.ttf</bold>
  6. <italic>jaspers/fonts/msyh.ttf</italic>
  7. <boldItalic>jaspers/fonts/msyh.ttf</boldItalic>
  8. <pdfEncoding>Identity-H</pdfEncoding>
  9. <pdfEmbedded>true</pdfEmbedded>
  10. <exportFonts>
  11. <export key="net.sf.jasperreports.html">'微软雅黑', Arial, Helvetica, sans-serif</export>
  12. <export key="net.sf.jasperreports.xhtml">'微软雅黑', Arial, Helvetica, sans-serif</export>
  13. </exportFonts>
  14. </fontFamily>
  15. </fontFamilies>

2.在resources资源文件下增加读取扩展字体的配置文件 jasperreports_extension.properties

  • jasperreports_extension.properties文件配置如下
  1. net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
  2. net.sf.jasperreports.extension.simple.font.families.dejavu=jaspers/fonts/fonts.xml

配置好的代码结构如下

3.访问地址 http://localhost:8080/test/jasper?type=pdf 可以看到中文打印出来了

实现原理

下面我们来分析下为什么需要按照上面来配置。因为JasperReport的jar包并未提供微软雅黑的字体的支持,所以我们需要通过提供的字体扩展的接口把我们需要的微软雅黑的字体在程序运行时可以读取到。

其中核心的类就是SimpleFontExtensionsRegistryFactory ,我们查看下这个类的源码

  1. public class SimpleFontExtensionsRegistryFactory implements ExtensionsRegistryFactory
  2. {
  3. public final static String SIMPLE_FONT_FAMILIES_PROPERTY_PREFIX =
  4. DefaultExtensionsRegistry.PROPERTY_REGISTRY_PREFIX + "simple.font.families.";
  5. public final static String PROPERTY_SIMPLE_FONT_FAMILIES_REGISTRY_FACTORY =
  6. DefaultExtensionsRegistry.PROPERTY_REGISTRY_FACTORY_PREFIX + "simple.font.families";
  7. @Override
  8. public ExtensionsRegistry createRegistry(String registryId, JRPropertiesMap properties)
  9. {
  10. List<PropertySuffix> fontFamiliesProperties = JRPropertiesUtil.getProperties(properties, SIMPLE_FONT_FAMILIES_PROPERTY_PREFIX);
  11. List<String> fontFamiliesLocations = new ArrayList<String>();
  12. for (Iterator<PropertySuffix> it = fontFamiliesProperties.iterator(); it.hasNext();)
  13. {
  14. PropertySuffix fontFamiliesProp = it.next();
  15. //String fontFamiliesName = fontFamiliesProp.getSuffix();
  16. String fontFamiliesLocation = fontFamiliesProp.getValue();
  17. //fontFamiliesLocations.addAll(SimpleFontExtensionHelper.getInstance().loadFontFamilies(fontFamiliesLocation));
  18. fontFamiliesLocations.add(fontFamiliesLocation);
  19. }
  20. return new FontExtensionsRegistry(fontFamiliesLocations);
  21. }
  22. }

这个类比较简单只有一个方法,这个createRegistry方法就是读取配置文件中net.sf.jasperreports.extension.simple.font.families开头的配置项的字体文件。

那么追溯这个createRegistry方法在什么地方使用的,可以追溯到类DefaultExtensionsRegistry中的instantiateRegistry方法

查看这个方法可以发现它是加载实现了ExtensionsRegistryFactory接口的某一个类,并且调用instantiateRegistry方法来读取的配置项,这里就是上面提到的SimpleFontExtensionsRegistryFactory 类。

继续向上追溯到类DefaultExtensionsRegistry中的loadRegistries方法,这个方法是加载所有的通过扩展注册进来配置,当然也包括通过扩展注册的字体。

这个方法的代码行较多,我就不贴出来了,那么我们关注下这个方法其中一行代码

List<ClassLoaderResource> extensionResources = loadExtensionPropertyResources();

这行代码是获取所有需要加载的配置文件资源,通过代码我们可以发现它最终是加载所有名称是jasperreports_extension.properties的文件,然后解析文件中的配置项并注册到JasperReport中

  1. protected List<ClassLoaderResource> loadExtensionPropertyResources()
  2. {
  3. return JRLoader.getClassLoaderResources(EXTENSION_RESOURCE_NAME);
  4. }
  5. /**
  6. * The name of property file resources that are used to load JasperReports
  7. * extensions.
  8. */
  9. public final static String EXTENSION_RESOURCE_NAME = "jasperreports_extension.properties";

到这里我们应该理解上面配置文件jasperreports_extension.properties中的配置项的意义。

  1. ##这行配置项是说明需要使用哪个注册工厂类来解析下面的配置项
  2. net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
  3. ##这行配置是配置了需要加载的字体文件的位置,配合上面的```SimpleFontExtensionsRegistryFactory```类来加载字体文件。
  4. net.sf.jasperreports.extension.simple.font.families.dejavu=jaspers/fonts/fonts.xml

结束语

因为方便后续教程的演示,我们把公用的代码包括中文字体的支持都提起到一个公共的模块common,其他模块只引用即可使用,这样可以更好的专注本章节的代码。

本节代码和报表模板

JasperReports入门教程(二):中文打印的更多相关文章

  1. JasperReports入门教程(三):Paramters,Fields和Detail基本组件介绍

    JasperReports入门教程(三):Paramter,Field和Detail基本组件介绍 前言 前两篇博客带领大家进行了入门,做出了第一个例子.也解决了中文打印的问题.大家跟着例子也做出了de ...

  2. JasperReports入门教程(四):多数据源

    JasperReports入门教程(四):多数据源 背景 在报表使用中,一个页面需要打印多个表格,每个表格分别使用不同的数据源是很常见的一个需求.假如我们现在有一个需求如下:需要在一个报表同时打印所有 ...

  3. JasperReports入门教程(一):快速入门

    JasperReports入门教程(一):快速入门 背景 现在公司的项目需要实现一个可以配置的报表,以便快速的适应客户的需求变化.后来在网上查资料发现可以使用JasperReports + Jaspe ...

  4. 无废话ExtJs 入门教程二十一[继承:Extend]

    无废话ExtJs 入门教程二十一[继承:Extend] extjs技术交流,欢迎加群(201926085) 在开发中,我们在使用视图组件时,经常要设置宽度,高度,标题等属性.而这些属性可以通过“继承” ...

  5. 无废话ExtJs 入门教程二十[数据交互:AJAX]

    无废话ExtJs 入门教程二十[数据交互:AJAX] extjs技术交流,欢迎加群(521711109) 1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3C ...

  6. 无废话ExtJs 入门教程二[Hello World]

    无废话ExtJs 入门教程二[Hello World] extjs技术交流,欢迎加群(201926085) 我们在学校里学习任何一门语言都是从"Hello World"开始,这里我 ...

  7. mongodb入门教程二

    title: mongodb入门教程二 date: 2016-04-07 10:33:02 tags: --- 上一篇文章说了mongodb最基本的东西,这边博文就在深入一点,说一下mongo的一些高 ...

  8. SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1

    在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...

  9. PySide——Python图形化界面入门教程(二)

    PySide——Python图形化界面入门教程(二) ——交互Widget和布局容器 ——Interactive Widgets and Layout Containers 翻译自:http://py ...

随机推荐

  1. String是否相等、new的时候创建了几个对象等问题详解

    问题一 这段代码创建了几个对象? String str1 = new String("aa"); 答案是两个 "aa"对象和String对象 Java代码在编译 ...

  2. 【Springboot】实例讲解Springboot整合OpenTracing分布式链路追踪系统(Jaeger和Zipkin)

    1 分布式追踪系统 随着大量公司把单体应用重构为微服务,对于运维人员的责任就更加重大了.架构更复杂.应用更多,要从中快速诊断出问题.找到性能瓶颈,并不是一件容易的事.因此,也随着诞生了一系列面向Dev ...

  3. 双连通分量 Road Construction POJ - 3352

    @[双连通分量] 题意: 有一个 n 个点 m 条边的无向图,问至少添加几条边,能让该图任意缺少一条边后还能相互连通. 双连通分量定义: 在无向连通图中,如果删除该图的任何一个结点都不能改变该图的连通 ...

  4. 使用内部枚举类作为外部类的参数的Mybatis的参数该如何判断

    新写了一个接口,期望根据不同的参数来给数据库中不同的字段进行传值.这里使用了内部静态枚举类的方式进行传值,在写mybatis动态sql时,如果是普通对象,一般使用,那么使用枚举类,如何判断枚举类的值呢 ...

  5. springboot集成通用mapper详细配置

    通常,我们利用mybatis写持久层方法.要么按照传统定义mapper方法,定义xml文件的方式,全部手写.要么需要通过mybatis-generator逆向工程插件生成大量的xxxExample文件 ...

  6. Python数据库之数据库基本操作

    安装(基于centos) yum -y install mariadb mariadb-server # centos7版本 yum -y install mysql mysql-server #ce ...

  7. while实现2-3+4-5+6...+100 的和

    while实现2-3+4-5+6...+100 的和 可以看到规律为2-100内所有奇数都为减法,偶数为加法 设定变量 total=0: count=2 当count为偶数时与total相加,反则相减 ...

  8. Aircoinst 三层架构ASP.NET开源

    <注意! 本源码为我本人所写,可能有点烂.仅供学习使用,请勿进行商业用途~!> <本源码永久归于MineLSG 及 Aircoinst_慈 所拥有> 使用方法:直接拷贝 一.结 ...

  9. IOS部分APP使用burpsuite抓不到包原因

    曾经在ios12的时候,iphone通过安装burpsuite的ca证书并开启授权,还可以抓到包,升级到ios13后部分app又回到以前连上代理就断网的情况. 分析:ios(13)+burpsuite ...

  10. HDU1087:Super Jumping! Jumping! Jumping!(DP水题)

    Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...