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. 【3D】PoseCNN姿态检测网络复现过程记录

    最近在研究室内6D姿态检测相关问题,计划在PoseCNN网络基础上进行改进实现.但是在第一步的复现过程中踩了无数的坑,最终成功运行了demo,但目前数据集train还是遇到了一些问题.有问题欢迎一起交 ...

  2. Python——五分钟理解函数式编程与闭包

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第9篇文章,我们来聊聊Python的函数式编程与闭包. 函数式编程 函数式编程这个概念我们可能或多或少都听说过,刚听 ...

  3. OpenWrite技术自媒体界的JVM一次编辑、随处发布

    原文 :https://mp.weixin.qq.com/s/KUtJ2dwhBRuJ2G_-PkQFEA 最懂你的科技自媒体管理平台 [实用小工具推荐]给科技或技术同学们推荐一款比较好用的工具,可以 ...

  4. 前端之jQuery基础篇

    jQuery 是一个 JavaScript 库. jQuery 极大地简化了 JavaScript 编程. jQuery 很容易学习. jQuery 安装 网页中添加 jQuery 可以通过多种方法在 ...

  5. docker 搭建keepalived+nginx高可用

    前言 最近工作 中 有用到keepalived,就想着 在 本地 搭建一套环境验证一下相关的功能.因为创建虚拟机比较麻烦,就借助  docker来搭建这样 一套 环境 ,顺带学习 巩固下docker的 ...

  6. IBN-Net: 提升模型的域自适应性

    本文解读内容是IBN-Net, 笔者最初是在很多行人重识别的库中频繁遇到比如ResNet-ibn这样的模型,所以产生了阅读并研究这篇文章的兴趣,文章全称是: <Two at Once: Enha ...

  7. 1039 Course List for Student (25分)

    Zhejiang University has 40000 students and provides 2500 courses. Now given the student name lists o ...

  8. PTA | 1010 一元多项式求导 (25分)

    设计函数求一元多项式的导数.(注:xn(n为整数)的一阶导数为n*xn-1.) 输入格式: 以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数).数字间以空格分隔. 输出格式: ...

  9. Linux搜索工具

                                                                Linux搜索工具 Search搜索工具 yum search all vim  ...

  10. 基于 HTML5 WebGL 的 水泥工厂可视化系统

    前言 如今的制造行业,基于数据进行生产策略制定与管理已经成为一种趋势,特别是 工业4.0 的浪潮下,数据战略已经成为很多制造企业的优先战略,而数据可视化以更直观的方式,帮助指导决策,成为数据分析传递信 ...