13、File, rich rendering,and email support
文件、富生成和email支持
This chapter covers
■ Handling file uploads
■ Creating PDF documents and charts
■ Sending emails with attachments
■ Customizing the UI with resource bundles
本章包括:
处理文件上传
建立PDF及图表
发送带有附件的emails
用资源包定制UI
Many people playing their first round of golf question why anyone would want to
torture themselves with such a maddening game, concluding that those who play it
are simply masochistic. But anyone who has experienced the triumph of sinking
the ball in the hole from the tee box, clearing a large water hazard, or just taking a
great swing understands that there’s something extremely gratifying about golf
once you get the hang of it. The same can be said about an application framework.
There’s a lot to learn at first and it can seem overwhelming. Then things click. Your
newfound ability makes the experience enjoyable and you get to do things you’ve
never experienced before.
很多人在玩第一回合高尔夫时会问为什么每个人会用这个疯狂的游戏来折磨自己,认为玩家都是受虐狂。但只有经历种种考验而得以入洞的人才会理解这种感受。对于应用框架也是一样。首先要有很多要学,看上去是排山倒海。随后事件有所变化,你新增的能力使经验有趣了,你要做些以前从未经历的事情。
You saw in the last chapter how Seam and JSF component libraries take the pain
out of using Ajax, making Ajax more accessible than ever. That’s just one example
of how Seam provides features that are both rewarding to develop and rewarding for
your customers and clients to use. In this chapter, you’ll learn how to do more fun and
enjoyable tasks in Seam, including handling file uploads, creating PDF documents,
rendering dynamic image data and charts, sending emails that include attachments,
and adding themes to your application. This sampling represents the set of features
that are quite often tossed out in the name of budget and time constraints. With
Seam, you discover that performing these tasks is a breeze. They’re all just variations
on what you have done so many times throughout this book.
上一章你看到了Seam 和JSF部件库解决了Ajax之痛,使其更易访问。这只是SEAM所提供的特性中的一个例子。既对开发有益也对用户有益。本章,你将学习如何从SEAM中找更多的乐子,包括处理文件上传,建立PDF文档,生成动态图像及图表,发送带有附件的邮件,向你的应用中加入主题。这个例子代表一套特性经常增加项目的预算及时间紧迫性。使用SEAM你发现这些都成了小菜一碟。所有这些只是你在本书所学的招术稍做变化。
Because several of the examples covered in this chapter work with raw file and
image data, you’ll begin by learning how to accept file uploads and how to serve them
back to the browser.
因为本章的一些例子要使用原文件和图像数据,你要开始学习如何接受文件上传并如何将其传回浏览器。
13.1 Uploading files and rendering dynamic images
How many times have you cringed at the requirement of processing an image upload
and having it rendered on a page in the application? The problem isn’t that the task is
impossible, but that it isn’t as straightforward as dealing with plain form data. In fact,
accepting file uploads in Java has a well-founded reputation for being notoriously difficult.
With Seam, it’s almost too easy. In this section, you’ll learn how to bind an
upload form element to a Seam component to accept an image and persist it to the
database. Then you’ll use Seam’s enhanced graphic component to turn that raw data
back into a dynamically rendered image.
上传文件和生成动态图像
有多少次你对上传图像并在应用的页面上重画感到为难?问题不在于不可能,而在于不像处理表单数据那样直接。事实上,在JAVA中接受上传恶名流传。对于SEAM来说,就太简单了。这一节,你会学习如何绑定一个上传表单元素到SEAM部件以接受一个图像并将其保存到数据库。随后你使用SEAM增强的图形部件来将其转化为动态重画的图像。
13.1.1 Accepting file uploads
Seam practically sacrifices itself to protect you from the nastiness of file uploads in Java,
reducing the task to a simple EL value binding expression—it’s that dramatic. There are
no buffers, stream reading, or multipart boundaries to worry about. All of that is handled
for you transparently by the MultipartFilter and the MultipartRequest it wraps
around the incoming servlet request. If you already have the SeamFilter configured,
you don’t have to do anything else to enable Seam’s file upload support.
接受文件上传
SEAM在文件上传上给了你坚强庇护,将任务简化成一个简单地EL值绑定表达式,太神了。不再有缓冲、读流,以及多边界需要担心。只是透明地在进入的servlet请求外包装上MultipartFilter 和MultipartRequest。如果你已有SeamFilter配置,除了启动SEAM文件上传支持,你不用做任何事。
SEAM’S FILE UPLOAD UI COMPONENT
Seam provides a UI input component, , for receiving file uploads
from a JSF form. The file data is passed through an EL value binding that references a
byte[] or InputStream property on a Seam component. The upload component can
also capture the content type of the file, the filename, and the file size and apply that
information to a Seam component along with the file data.
SEAM文件上传UI部件
SEAM提供了UI录入部件,,从JSF表单接受文件上传。文件的数据通过参考SEAM部件的byte[] 或InputStream属性的一个EL值绑定完成。上传部件也可以获得文件的内容类型、文件名、文件大小。
To demonstrate a file upload, we augment the registration form to allow members
to upload a profile image, or avatar. Two properties have to be added to the Golfer
entity, image and imageContentType, to capture the image data and content type,
respectively. The relevant parts of the Golfer entity class are shown here:
为演示一个文件上传,我们给注册表单加上参数,让会员上传一个图像。要加上两个属性到Golfer实体:image 和imageContentType,用来获得图像数据和内容类型。Golfer实体类型的相关部分显示如下:
I’ve decided to accept the file data as a byte[]. The lazy-fetch strategy prevents the
data from being loaded until the image data is requested, slightly reducing the memory
footprint.
我已决定接受文件数据为byte[]。延迟加载策略不会加载数据,直到图像数据被请求。给会员省了些周折。
The only remaining step is to add the upload field to the registration form and wire
it to the image and imageContentType properties on the Golfer entity. You also need
to set the enctype attribute on the
component tag to multipart/form-data.1This setting tells the browser to send the form data using multipart data streams. Failure
to make this adjustment will prevent the browser from sending the file data. An excerpt
of the registration form with these changes applied is shown here:
唯一剩下的步骤是增加上传字段到注册表单并将其连到Golfer实体的image 和imageContentType属性。你还要设置
部件标签上的enctype属性为multipart/form-data。这一设定告诉浏览器使用多个数据流发送表单数据。不做这一调整会阻止浏览器发送数据。带有这些变化的注册表单的一个节选如下:
You don’t have to make any changes to the RegisterAction class to accept the
uploaded image and have it stored in the database. The image data is bound to the
entity instance named newGolfer and automatically persisted to the database along
with the other fields on this entity. If you’re content with the image as it’s uploaded,
your work is done. However, it’s likely that you’ll want to put some limits on what the
user can upload.
你不用对RegisterAction类做任何变化来接受图像并存入数据库。图像数据被绑定到名为newGolfer的实体实例并跟随其它字段一起自动地保存到数据库,如果你满意于上传的图像,你的工作就完成了。不管怎样,你肯定还是希望对用户的上传加一些限制。
CONTROLLING WHAT GETS UPLOADED
The accept attribute on is used to specify a comma-separated list of
standard Multipurpose Internet Mail Extensions (MIME) types that can be uploaded.
The upload field in the registration form limits the acceptable file types to graphic
formats that Seam is capable of rendering dynamically. The use of wildcards is also
permissible. You could accept all image MIME types, for instance, using the pattern
image/*. Even with this restriction in place, though, you should still validate the file
type in the action method.
控制上传的内容
上的accept属性用于指定一个逗号分隔的列表,即可上传的标准Multipurpose Internet Mail Extensions (MIME)类型。注册表单的上传字段限制可接受的文件类型于SEAM可动态生成的图形格式。可以使用通配符。例如image/*,可以接受所有的MIME类型的图形。当带有这一限制,你仍然可以在action方法中让某类型生效。
Seam exposes two global settings on the built-in component named multipart-
Filter to control file uploads. The maxUploadSize property allows you to cap the size
(in bytes) of the file being uploaded. There’s no limit in the default configuration. You
use the createTempFiles property to control whether Seam uses a temporary file to
store the uploaded file data or whether the file data is held in memory, which is the
default. These two properties can be adjusted using component configuration as follows:
在名为multipartFilter的内建部件中,SEAM暴露两个全局设定,来控制文件上传。maxUploadSize属性让你设置被上传的文件的最大尺寸(bytes)。在默认配置中无限制。你使用createTempFiles属性控制是否SEAM使用临时文件来保存上传的文件数据,或是否文件被保存在内存中(默认)。两个属性可用部件描述调整如下:
While the maxUploadSize property puts a limit on file size of the uploaded profile
image, it doesn’t put restrictions on its dimensions. Once the profile image has
uploaded, it’s a good idea to scale it so that it doesn’t steal too much space on the
page when rendered.
当maxUploadSize属性设置文件尺寸,不是在设置分辨率。一旦文件已上传,最好调整其分辨率以免重画时占用太大的页面空间。
PROCESSING AN UPLOADED IMAGE
The uploaded image can be resized in the action method before the newGolfer
instance is persisted. The class org.jboss.seam.ui.graphicImage.Image, which is
bundled with the jboss-seam-ui.jar file, makes resizing and scaling images a cinch. Listing
13.1 shows the code added to the register() action method that manipulates the
uploaded image. This code is just a starting point. If you use it in your application,
you’ll likely want to make it more configurable by eliminating the hardcoded values
you see used here.
处理一个上传的图像
在newGolfer实例被保存前,上传的图像可以用action方法改变大小。位于jboss-seam-ui.jar中的类org.jboss.seam.ui.graphicImage.Image使得改变大小或分辨率变得很简单。表13.1显示了加下register() action方法中的代码。这个代码只是个起点,如果你在应用中使用,你最好不用这里看到的硬编码而多增加些配置。
Once you’ve accepted the raw file data into the database, you need to render it. After
all, what good would it be? Seam can render raw file data in addition to static files
read from the classpath and input streams, in any of the following ways:
■ As an image in a web page
■ As an image in a PDF document
■ Pushed to the browser to be downloaded
■ As an inline image in an email or as an email attachment
一旦你将收到的原文件加入数据库,你就需要重画它。SEAM可用下列方式重画原文件数据。
作为页面上的图像
作为PDF文档中的图像
发到将被下载的浏览器
作为email的内嵌图像或作为附件
Let’s begin by exploring how to render the raw image data in a web page using Seam’s
enhanced graphic UI component. As the chapter progresses, you’ll learn about the
other ways to use the raw file data listed here. These additional options build on this
initial lesson in that they’re merely variations on the graphic UI component.
让我们开始浏览如何使用SAAM增强的图形UI部件在WEB页面重画原图像。随着本章深入,你会学到使用原文件的其它方式。开篇中的这些附加选择只是图形UI部件上的少许变化。
13.1.2 Rendering images from raw data
The Seam UI component set includes an enhanced graphic component capable of operating
on a dynamically generated image. Seam’s graphic component,
Image>, is an extension of the standard JSF graphic component, . In
addition to the features supported by the standard component, Seam’s version has support
for rendering raw image data and performing image transformations.
从原数据生成图像
SEAM UI部件设置包括一个增强的图形部件可以动态生成图像。SEAM的图形部件是标准JSF图形部件的扩展。SEAM的版本已支持生成原图数据和进行图像变形。
RENDERING DYNAMIC IMAGES WITH SEAM’S ENHANCED GRAPHIC UI COMPONENT
The standard tag only accepts a string value or an EL value expression
that resolves to a string value. This value is used to serve a static graphic resource
from the web application context (e.g., /img/golfer.png). The tag
supports a much broader range of Java types resolved from an EL value expression.
Table 13.1 lists the supported dynamic Java types from which the
can read image data and the image MIME types that the component can handle.
用SEAM增强的图形UI部件生成动态图像
标准的标签只接受一个串值或一个EL值表达式以解析一个串值。这个值用于WEB应用上下文的静态图形资源(如: /img/golfer.png)。标签支持更宽范围的JAVA类型来从EL值表达式中解析。表13.1列出了支持的动态类型,其可读图像数据及部件可以处理的图像MIME类型。
Like the component, the produces a standard
HTML element. The difference is that Seam generates a random filename
for the image, which is used in the src attribute of the tag and served by the
SeamResourceServlet. If you don’t want the filename to be random, you can specify
a fixed filename in the fileName attribute. You don’t need to put the extension of
the image in the filename; Seam appends the extension automatically according to
image type.
类似于部件,产生一个标准的HTML 元素。不同是SEAM生成一个随机的文件名,其被用于 标签的src属性,由SeamResourceServlet来支持。如何你不想用随机的文件名,可以在fileName属性指定一个固定的文件名。你不需要在文件名中使用图像的扩展名,SEAM会依图像的类型而自动加上。
You should recognize that one of the supported Java types listed in table 13.1 is
byte[], which is the property type that holds the golfer’s profile image. Let’s use the
component tag to display the profile image uploaded during the
registration process on the golfer’s profile page. The image data is specified in the
value attribute. A fallback image is used if the golfer doesn’t have a profile image.
The golfer’s username is used as the filename of the image to produce a URL that
remains stable and thus allows the browser to cache the image. Finally, alternate text is
provided for browsers that can’t render images:
你应该认识到表13.1中一个支持的JAVA类型是byte[],这是保存球员简介图象的属性类型。让我们使用部件标签来显示简介图象,它是在球员简介页面的注册过程中上传的。图像数据用value属性指定。一个故障图像用于球员没有简介图像的情况。球员的用户名用作图像的文件名来产生一个URL以保持稳定,并可让浏览器缓冲图像。最终的替代文字用于当浏览器无法生成图像之时:
In this example, we display image data retrieved from the database. However, you can
also use a Seam component to create an image using Java 2D. The image can be prepared
in a Seam component, converted to one of the accepted Java types listed in table 13.1,
and then bound to the tag. But before you venture into Java 2D, you
may be able to leverage one of the basic image transformations that Seam provides.
本例,我们显示从数据库中检索出的图像数据。你也可以使用SEAM部件的Java 2D来建立图像。图像可在SEAM部件中准备,转化成表13.1接受的JAVA类型,然后绑定到标签。但在你进入Java 2D之前,你也许可以使用SEAM提供的基本的图像变形。
IMAGE TRANSFORMATIONS
Given that the component loads image data into memory, it stands
to reason that the image can be transformed prior to being rendered. One of three
transformation component tags can be nested within to apply
transformations to the image using Java 2D, which are listed in table 13.2. Each component
tag accepts one or more parameters that control how the transformation is
applied. These transformations are the same as those provided by the Image class
from the Seam API introduced in section 13.1.
图像变形
假定部件加载图像数据到内存,这代表图像可以在重画前变形。三个变形部件标签之一可以被嵌套于以使用Java 2D对图像变形,其列于表13.2。每个部件标签接受一个或多个参数来控制如何应用变形。这些变形与第13.1节引入的SEAM API图像类一样。
The golfer’s profile image is reduced to a reasonable size when it’s initially uploaded.
But it may be necessary to scale it even further to create a thumbnail for personalizing
a review or comment that the golfer posts somewhere on the site, as shown here:
在最初上传时,球员简介图像被缩小到合理的大小。但可能需要进一步缩小以产生一个缩略图用于个人的检查或球员可能在站点的某处发布评论用到。
You can easily create your own transformation component by implementing the
interface org.jboss.seam.ui.graphicImage.ImageTransform. This interface has
one method, applyTransform(), which accepts the Image type from the Seam API
that you worked with in section 13.1. To make your component available to JSF, you
have to go through the song and dance of setting up a JSF component. If you’re
going to do so, check out the source code in the Seam UI module and have a good
JSF reference close by such as JavaServer Faces in Action (Manning, 2004) or Pro JSF and
Ajax (Apress, 2006). To save yourself time, take advantage of the Ajax4jsf Component
Development Kit (CDK).
通过实现接口org.jboss.seam.ui.graphicImage.ImageTransform,你可以简单地建立你自己的变形部件。这个接口有一个方法applyTransform(),从第13.1节要用的SEAM API接受Image类型。为了让JSF能用你的部件,你必须设置JSF部件。如果你想这样做,参考Seam UI模块的源码,或JSF参考,如JavaServer Faces in Action (Manning, 2004) or Pro JSF and Ajax (Apress, 2006)。为了节省你的时间,可利用Ajax4jsf 部件开发工具包(CDK)。
You’ll have the opportunity to visit the tag again when you learn
how to send emails with Seam in section 13.4. There’s an equivalent graphic component
for embedding dynamic images in a PDF document. Speaking of PDF, it’s time to
move away from HTML and explore how to create PDF documents dynamically.
第13.4节,当你学习用SEAM发送emails时,你还会有机会见到标签。有一个等效的图形部件来在PDF中嵌入动态图像。说到PDF,再在是该离开HTML而浏览如何动态建立PDF文档。
13.2 PDF generation with iText
You may be wondering, “What can an application framework do to help me create PDF
documents?” After all, most other frameworks provide a halfhearted integration
attempt by only helping you serve the PDF to the browser, leaving the work of creating
the PDF up to you. Well, with Seam, the answer to this question is plenty.
用iText生成PDF
你也许想知道,“应用框架可做什么来帮我建立PDF?”毕竟,大多其它框架提供了不认真的集成,只将PDF发送到浏览器,让将建立PDF的工作留给了你。使用SEAM,它会帮你很多。
You see, Seam goes well beyond just playing matchmaker between the browser and
the PDF renderer. In Seam, creating and serving a PDF is handled just like any other JSF
view. Seam provides a set of UI component tags that generate PDF content. When the
template is processed, the view handler serves a PDF document to the browser, generated
by the open source (LGPL/MPL) iText Java-PDF library, rather than an HTML document.
SEAM在浏览器和PDF生成器方面不只是充当媒人。在SEAM中,建立和使用PDF和其它JSF view一样。Seam提供一套UI部件标签生成PDF文档。当模板被处理时,view处理器将PDF文档发送到浏览器,其由开源的iText Java-PDF库生成,不再是HTML文档。
The PDF component tags extend from the tag handler in the Facelets API, so you
must use Facelets to generate PDF documents in this way. To enable PDF support in your
application, you need to add two files to the application classpath: itext.jar and jbossseam-
pdf.jar (both of which you’ll find in the lib folder of projects generated with seamgen).
You can then begin using the PDF component tags in your Facelets templates.
PDF部件标签从Facelets API的标签处理器扩展而来,这样,你必须使用Facelets来生成PDF文档。要在应用中启用对PDF的支持,你需要增加两个文件到应用的类路径。itext.jar 和jbossseampdf.jar(这两个你都能在seam-gen生成的项目中发现)。随后你就可以在Facelets 模板中使用PDF部件标签。
13.2.1 Laying out a PDF with UI components
A Facelets template that renders a PDF document uses as the root tag.
Aside from the new root tag and the accompanying palette of PDF tags, there’s no difference
in how you develop it compared to any other Facelets template. You can use
Facelets and Seam composition tags (e.g., , ), nonrendering
JSF component tags (e.g., , ), and JSF component
tags that produce HTML to build the JSF UI component tree. Since the PDF
template is rendered by JSF just like any other JSF view, you can front-load the request
with Seam’s page-oriented controls (page actions, page parameters, and page restrictions).
That’s a pretty powerful combination. Notice that nowhere in that description
did I mention Java. In this scenario, we want to avoid the use of Java to reuse our Facelets
knowledge to create dynamic views. There’s no need to step into a Java API to perform
this work.
用UI部件规则PDF
生成PDF文档的Facelets模板使用作为根标签。除了新的根标签和伴随的PDF标签模板,与其它用Facelets模板的开发没有什么不同。你可以使用Facelets和Seam部件标签(例如, , ),非重画JSF部件标签(例如, , ),产生HTML的JSF部件标签来建立JSF UI部件树。既然PDF模板是由其它JSF view一样地重画,你可以用SEAM的面向页面的控制来做请求的前加载(页面actions,页面参数和页面限制)。这是很强大的组合。注意在描述中我没有提JAVA,在这一场景,我想避免使用JAVA来重用我们的Facelets知道来建立动态views。不需要进入Java API来做这一工作。
For the most part, the PDF component tags map one to one with the functionality
provided by iText. An iText PDF document rendered through Seam consists of paragraphs,
images, headers, footers, chapters, sections, tables, lists, bar codes, and even
Swing components. You can customize the font size, font color, and background color
on most elements. Some limitations exist, but the PDF component tags should be sufficient
for all but the most complex requirements.
对于大多情况,PDF部件标签与iText提供的功能形成一对一的映射。一个iText PDF文档通过SEAM生成来组成段落、图像、标题、注脚、章节、小节、表、列表、条形码、甚至Swing部件。你可以对大多元素定制字体大小、颜色、背景色。有一些限制存在,但PDF部件可以满足大多的复杂需求。
Rather than itemize each and every tag in the PDF component palette, I provide a
comprehensive example that puts many of the tags to use. This approach will give you
real-world experience with the PDF tags, which you can supplement by consulting the
reference documentation for the specifics of each tag. In this example, we generate a
scorecard in PDF format for a golf course. The scorecard is the grid of holes and tee
sets that you use to record the number of strokes you took on each hole. It’s fairly
complex to render, but also aesthetically pleasing. Thus, I guarantee that this will be a
rewarding experience.
不是在PDF部件模板中分列每一个标签,我提供了一个全面的例子用到了所有标签。这种方式给了你PDF标签的真实的体验,你可以另外对每个去参考文档。在这个例子中,我们有球场用PDF格式生成一个分数卡。分数卡用洞和tee sets的格子来记录你在每个洞上的杆数。生成起来很复杂,但审美快乐。所以我保证这是个很有价值的经验。
SETTING UP FOR THE SCORECARD
To display the full scorecard for a course, it’s necessary to use all the entities in the
golf course model: Facility, Course, Hole, TeeSet, and Tee. The associations
between these entities are configured to be lazy loaded. However, as you’ve learned,
it’s best to avoid lazy loading in cases when using it wouldn’t be efficient. For instance,
rendering the scorecard would cause a large number of lazy associations to be
crossed, in turn causing a lot of queries. To optimize, we want to use a page action to
eagerly fetch all the necessary data in a single query and then make that data available
to the Facelets template. The Scorecard component, shown in listing 13.2, handles
this preload logic in the load() method. The abundance of join fetch clauses in the
JPQL that’s executed in this method represents the eager fetching of the associations.
设计计分卡
为了显示一个回合的全部记分卡,你需要使用球场模型的所有实体:Facility, Course, Hole, TeeSet, 和Tee。这些实体间的关联被配置成延迟加载。如你所学,这里最好避开延迟加载,以防使用它时无效。例如生成计分卡将会遇到大量的延迟加载,从而会导致大量的查询。为了优化,我们要使用一个页面action来立即在一个请求中抓取所有需要的数据随后在整个Facelets模板中可用。Scorecard部件,显示于列表13.2,在load()中处理这个提前加载的逻辑。在这个方法执行产生的JPQL语句中大量的join fetch分句表明了相关的立即抓取。
The Scorecard component also provides a handful of utility methods needed to
render portions of the scorecard. The implementation details aren’t important to this
discussion, so the method bodies are hidden (you can see them in the book’s source
code). The use of the terms out and in represent the two halves of the golf course. Out
is the first nine holes, leading away from the clubhouse. In is the back nine holes,
returning to the clubhouse. The methods getTeesOut() and getTeesIn() are
invoked from the Facelets template using a parameterized value expression.
Scorecard部件也提供很多实用的方法来生成计分卡的一些部分。实现细节不是本节的重点,所以方法体被隐藏了(你可以到本书的源码中看)。词汇out 和in球场的两半,Out是前9个洞,是远离方向的,In则是回来的9个。方法getTeesOut() and getTeesIn()使用带参的表达式从Facelets模板调用。
A scorecard is complex and so is the Facelets template needed to generate it. We get
there in two phases. In the first phase, we get our feet wet with a simple PDF report.
记分卡很复杂,所以Facelets模板需要生成它。我们用两个阶段。第一阶段,我们先看看简单的PDF支持。
A BASIC PDF REPORT
The first step is to create the Facelets template exportCourseInfo.xhtml, shown in listing
13.3. This template renders basic information about a course and the facility logo.
Notice that the root of the template is and that the template declares
the following namespace, which imports the PDF UI component tags:
基本PDF报告
第一步是建立Facelets模板,exportCourseInfo.xhtml,如列表13.3。这个模板生成关于球场及设施logo的基本信息。注意模板的根是,模板声明了如下名字空间,其导入了PDF UI部件标签:
p:xmlns="http://jboss.com/products/seam/pdf"
Next, we connect a page action to this view ID to preload the scorecard data, defined
in the exportCourseInfo.page.xml descriptor:
下面我连接一个页action到这个view ID来预加载计分卡数据,被定义在exportCourseInfo.page.xml描述文件:
The page action isn’t a prerequisite for rendering a PDF, but it’s relevant in this scenario.
页面action不是生成PDF的前提条件,但与这一场景相关。
如你在列表13.3中所见,建立PDF文档用费什么事。标签通知view处理器初始化一下新的iText PDF文档。如果单独使用,这个标签会产生一个空文档并发向浏览器。标签可以使用多种可选属性,你可以调整PDF文档的属性,如
title, subject, author,keywords, 和creator。你也可以改变页面的方向和尺寸。默认为A4,这里改为了LETTER。
生成PDF时,iText文档被优化,也可以使用RTF or HTML格式。你可以通过type属性来设置输出格式,其接受三上值:pdf, rtf, 和html。这时的输出格式通过请求参数type控制(如果存在的话)。
NOTE
The RTF and HTML output formats support the same features as PDF
with the exception of tables, images, and inline HTML. If any of these
features are present in the template, they’re ignored when the document
is rendered.
RTF 和HTML输出格式支持PDF同样的特性,一点例外是表、图像、行内HTML。如果任何这些特性出现在模板,当页面重画时,它们会被忽略。
来看文档的内容,模板包括一个图像,三个段落、一个强调列表。标签与标签工作类似。可以从表13.1的JAVA类型中读出图像,可以应用图像变形。这里的减小图像的大小到96像素,标签也有内建的尺寸功能。标签应用font设定到所有文档标签,直到遇到另一个标签改变为新的设定。所有行内文本必须用标签括起,否则输出会怪怪的(,, 和不是这样)。你也可以在一段段落文字中使用标签来改变单个词或词组的字体样式。
NOTE
There are some cases when the font settings aren’t inherited by a nested
tag. For instance, if you use a around a and
then use the to customize the contents of a , the
font settings from the outer tag—such as font size—aren’t inherited,
forcing you to have to apply them again on the nested tag. Expect this to
be fixed in the future.
有些时候字体设置没有被嵌套的标签继承。例如,如果你在
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/21802202/viewspace-1027644/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/21802202/viewspace-1027644/