23. View technologies
视图技术
23.1 Introduction
介绍
One of the areas in which Spring excels is in the separation of view technologies from the rest of the MVC framework. For example, deciding to use Groovy Markup Templates or Thymeleaf in place of an existing JSP is primarily a matter of configuration. This chapter covers the major view technologies that work with Spring and touches briefly on how to add new ones. This chapter assumes you are already familiar with Section 22.5, “Resolving views” which covers the basics of how views in general are coupled to the MVC framework.
领域的其中一部分在spring的excel中是从其他的mvc框架中分离开的视图技术。例如,决定市一宫Groovy标记模板或Thymeleaf用于替换已有的JSP是主要的一个配置问题。这一章节覆盖的主要的视图技术配合spring来使用和生产简单的对于如何使用和添加一个新的技术。这一章节假设你已经熟悉了章节22.5,“解析视图”包含了基本的视图解析和在mvc框架中的配置。
23.2 Thymeleaf
Thymeleaf is a good example of a view technology fitting perfectly in the MVC framework. Support for this integration is not provided by the Spring team but by the Thymeleaf team itself.
Thymeleaf是一个很好的例子对于视图技术适合在mvc框架中使用。支持集成Thymeleaf的功能不是由spring小组提供的而是Thymeleaf本身提供的。
Configuring Thymeleaf for Spring usually requires a few beans defined, like a ServletContextTemplateResolver, a SpringTemplateEngine and a ThymeleafViewResolver. Please refer to the Thymeleaf+Spring documentation section for more details.
对于spring来配置Thymeleaf需要一些bean的定义,例如ServletContextTemplateResolver、SpringTemplateEngine和ThymeleafViewResolver。请参考ThymeleafViewResolver的文档来了解更多的细节。
23.3 Groovy Markup Templates
The Groovy Markup Template Engine is another view technology, supported by Spring. This template engine is a template engine primarily aimed at generating XML-like markup (XML, XHTML, HTML5, …??), but that can be used to generate any text based content.
Groovy标记模板引擎是另一个视图技术,支持spring。这个模板引擎是一个模板疫情用于生成类似xml的标记(XML、XHTML、HTML5等),但是可以使用生成任何基于文本的内容。
This requires Groovy 2.3.1+ on the classpath.
他要求2.3.1以上的Groovy版本在classpath中。
23.3.1 Configuration
配置
Configuring the Groovy Markup Template Engine is quite easy:
配置Groovy标记模板引擎是十分简单的:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.groovy();
}
@Bean
public GroovyMarkupConfigurer groovyMarkupConfigurer() {
GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer();
configurer.setResourceLoaderPath("/WEB-INF/");
return configurer;
}
}
The XML counterpart using the MVC namespace is:
xml的部分使用mvc的命名空间是:
23.3.2 Example
Unlike traditional template engines, this one relies on a DSL that uses the builder syntax. Here is a sample template for an HTML page:
不像传统的模板引擎,依赖于DSL使用构建器语法。这是一个样例对于一个HTML页面:
yieldUnescaped ''
html(lang:'en') {
head {
meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"')
title('My page')
}
body {
p('This is an example of HTML contents')
}
}
23.4 Velocity & FreeMarker
Velocity and FreeMarker are two templating languages that can be used as view technologies within Spring MVC applications. The languages are quite similar and serve similar needs and so are considered together in this section. For semantic and syntactic differences between the two languages, see the FreeMarker web site.
Velocity和FreeMarker是两个模板语言可以被使用作为模板技术在spring的mvc应用中。语言是相似的并且服务相似需要和因此在一起被考虑在这个章节中。对于语法和语义关于两者的不同,见FreeMarker的网站。
[Note]
注意
As of Spring Framework 4.3, Velocity support has been deprecated due to six years without active maintenance of the Apache Velocity project. We recommend Spring’s FreeMarker support instead, or Thymeleaf which comes with Spring support itself.
在spring的框架4.3中,Velocity支持已经被废弃由于六年没有更新Apache的Velocity工程。我们建议使用spring的FreeMarker支持作为替代。
23.4.1 Dependencies
依赖
Your web application will need to include velocity-1.x.x.jar or freemarker-2.x.jar in order to work with Velocity or FreeMarker respectively and commons-collections.jar is required for Velocity. Typically they are included in the WEB-INF/lib folder where they are guaranteed to be found by a Java EE server and added to the classpath for your application. It is of course assumed that you already have the spring-webmvc.jar in your 'WEB-INF/lib' directory too! If you make use of Spring’s 'dateToolAttribute' or 'numberToolAttribute' in your Velocity views, you will also need to include the velocity-tools-generic-1.x.jar
你的web应用将需要包括velocity-1.x.x.jar或freemarker-2.x.jar以便可以使用Velocity或FreeMarker并且Velocity需要commons-collections.jar。通常他们需要放在WEB-INF/lib目录下这样才可以被JavaEE服务器发现并添加到你应用中的classpath中。当然假设你已经有了spring-webmvc.jar在你的库目录中。如果你在Velocity视图中使用spring的'dateToolAttribute'或'numberToolAttribute',你也需要包括velocity-tools-generic-1.x.jar。
23.4.2 Context configuration
上下文配置
A suitable configuration is initialized by adding the relevant configurer bean definition to your '*-servlet.xml' as shown below:
一个适当的配置被添加到相关的配置的bean的定义中定义在'*-servlet.xml'中展示如下:
[Note]
注意
For non web-apps add a VelocityConfigurationFactoryBean or a FreeMarkerConfigurationFactoryBean to your application context definition file.
对于非web应用添加VelocityConfigurationFactoryBean或FreeMarkerConfigurationFactoryBean到你定义的上下文中。
23.4.3 Creating templates
创建模板
Your templates need to be stored in the directory specified by the *Configurer bean shown above. This document does not cover details of creating templates for the two languages - please see their relevant websites for information. If you use the view resolvers highlighted, then the logical view names relate to the template file names in similar fashion to InternalResourceViewResolver for JSP’s. So if your controller returns a ModelAndView object containing a view name of "welcome" then the resolvers will look for the /WEB-INF/freemarker/welcome.ftl or /WEB-INF/velocity/welcome.vm template as appropriate.
你的模板需要被存储在目录中定义通过*Configurer的bean展示如上。这个文档不需要包括创建模板的细节对于两种语言————请参考他们相关的网站信息。如果你使用视图解析高亮,然后逻辑视图名相对于模板文件名以相同的风格对于InternalResourceViewResolver用于JSP。因此如果你的控制器返回一个ModelAndView的object包含一个视图名为“welcome”那么解析器将查找/WEB-INF/freemarker/welcome.ftl或/WEB-INF/velocity/welcome.vm模板根据需要。
23.4.4 Advanced configuration
高级配置
The basic configurations highlighted above will be suitable for most application requirements, however additional configuration options are available for when unusual or advanced requirements dictate.
基本配置高亮如上将适用于大部分应用的需求,然而额外的配置选项对于一般的或高级的需求也是有效的。
velocity.properties
This file is completely optional, but if specified, contains the values that are passed to the Velocity runtime in order to configure velocity itself. Only required for advanced configurations, if you need this file, specify its location on the VelocityConfigurer bean definition above.
这个文件是可选的,但是如果定义,包含在其中的值将传递给运行时的Velocity用于配置Velocity本身。只有需要高级的配置,如果你需要这个文件,定义它的位置在VelocityConfigurer的bean定义中如下:
Alternatively, you can specify velocity properties directly in the bean definition for the Velocity config bean by replacing the "configLocation" property with the following inline properties.
作为替代,你可以直接定义Velocity的属性文件在bean的定义中为了Velocity的配置通过替换"configLocation"属性根据下面内置的属性。
org.apache.velocity.runtime.resource.loader.FileResourceLoader
Refer to the API documentation for Spring configuration of Velocity, or the Velocity documentation for examples and definitions of the 'velocity.properties' file itself.
参考API文档有关spring对于Velocity的配置或Velocity文档中的示例和定义'velocity.properties'文件本身。
FreeMarker
FreeMarker 'Settings' and 'SharedVariables' can be passed directly to the FreeMarker Configuration object managed by Spring by setting the appropriate bean properties on the FreeMarkerConfigurer bean. The freemarkerSettings property requires a java.util.Properties object and the freemarkerVariables property requires a java.util.Map.
FreeMarker的'Settings'和'SharedVariables'可以直接传递给FreeMarker配置的object通过spring来管理,设置响应的bean属性在FreeMarkerConfigurer的bean上。freemarkerSettings属性需要一个java.util.Properties类型的object并且freemarkerVariables属性需要一个java.util.Map类型。
See the FreeMarker documentation for details of settings and variables as they apply to the Configuration object.
见FreeMarker文档中有关设置的细节和变量作为他们应用于Configuration的object。
23.4.5 Bind support and form handling
绑定支持和表达处理
Spring provides a tag library for use in JSP’s that contains (amongst other things) a
spring提供了标签库用于JSP中可以包含(在其他的内容中)一个
The bind macros
绑定宏命令
A standard set of macros are maintained within the spring-webmvc.jar file for both languages, so they are always available to a suitably configured application.
一个标准的宏命令集合包含在spring-webmvc.jar中对于两种语言,因此他们可以使用在响应的配置应用中。
Some of the macros defined in the Spring libraries are considered internal (private) but no such scoping exists in the macro definitions making all macros visible to calling code and user templates. The following sections concentrate only on the macros you need to be directly calling from within your templates. If you wish to view the macro code directly, the files are called spring.vm / spring.ftl and are in the packages org.springframework.web.servlet.view.velocity or org.springframework.web.servlet.view.freemarker respectively.
一些宏命令定义在spring的库中可以作为内部(私有)但是不是这样的范围存在于宏命令的定义标记了所有的宏命令对于调用代码是可见的及用户模板。下面的章节关注于你需要使用的宏命令会直接被调用在你的模板中。如果你希望直接看到宏命令代码,文件spring.vm / spring.ftl在org.springframework.web.servlet.view.velocity或org.springframework.web.servlet.view.freemarker的包中。
Simple binding
简单的绑定
In your HTML forms (vm / ftl templates) which act as a form view for a Spring MVC controller, you can use code similar to the following to bind to field values and display error messages for each input field in similar fashion to the JSP equivalent. Example code is shown below for the personFormV/personFormF views configured earlier:
在你的html表单中(vm / ftl templates)扮演一个表单视图的角色对于spring的mvc的控制器,你可以使用相似的代码对于下面的绑定来绑定域值和显示错误信息对于每个输入域在相同的JSP领域。样例代码展示在下面对于personFormV/personFormF视图配置:
...
...
<#import "/spring.ftl" as spring/>
...
...
#springBind / <@spring.bind> requires a 'path' argument which consists of the name of your command object (it will be 'command' unless you changed it in your FormController properties) followed by a period and the name of the field on the command object you wish to bind to. Nested fields can be used too such as "command.address.street". The bind macro assumes the default HTML escaping behavior specified by the ServletContext parameter defaultHtmlEscape in web.xml
#springBind / <@spring.bind>需要一个“path”参数包含你的命令object(他将是“command”除非你改变在你的FormController属性中)在一定时间之后对于命令object你希望绑定。内置的域可以被使用作为"command.address.street"。绑定宏命令假设默认的HTML逃逸行为更为定义在ServletContext参数defaultHtmlEscape中在web.xml中。
The optional form of the macro called #springBindEscaped / <@spring.bindEscaped> takes a second argument and explicitly specifies whether HTML escaping should be used in the status error messages or values. Set to true or false as required. Additional form handling macros simplify the use of HTML escaping and these macros should be used wherever possible. They are explained in the next section.
宏命令的选项表单名为#springBindEscaped / <@spring.bindEscaped>接收第二个参数并明确定义当HTML逃逸应当被使用在状态错误信息和错误值中。设置为true或false是必须的。额外的表单简单的处理宏命令通过使用HTML逃逸并且这些宏命令应当根据可能来使用。这会在后面的章节中解释。
Form input generation macros
对于输入生成宏命令
Additional convenience macros for both languages simplify both binding and form generation (including validation error display). It is never necessary to use these macros to generate form input fields, and they can be mixed and matched with simple HTML or calls direct to the spring bind macros highlighted previously.
额外的方便的宏命令对于两种语言简单包括绑定和表单生成(包括验证错误展示)。有必要使用这些宏命令来生成表单输入域和他们可以混合并匹配简单的HTML或直接调用spring绑定的宏命令。
The following table of available macros show the VTL and FTL definitions and the parameter list that each takes.
下面的表格展示了宏命令对于VTL和FTL定义和参数列表。
Table 23.1. Table of macro definitions
宏命令定义表
macro 宏命令 |
VTL definition |
FTL definition |
message (output a string from a resource bundle based on the code parameter) 消息(输出一个字符串来自资源基于代码参数) |
#springMessage($code) |
<@spring.message code/> |
messageText (output a string from a resource bundle based on the code parameter, falling back to the value of the default parameter) messageText(输出一个字符串来自资源基于代码参数,失败输出默认值) |
#springMessageText($code $text) |
<@spring.messageText code, text/> |
url (prefix a relative URL with the application’s context root) url(前缀是一个相关的URL对于应用上下文的根) |
#springUrl($relativeUrl) |
<@spring.url relativeUrl/> |
formInput (standard input field for gathering user input) formInput(标准的输入域用于获取用户的输入) |
#springFormInput($path $attributes) |
<@spring.formInput path, attributes, fieldType/> |
formHiddenInput * (hidden input field for submitting non-user input) formHiddenInput * (隐藏输入域用于提交非用户的输入) |
#springFormHiddenInput($path $attributes) |
<@spring.formHiddenInput path, attributes/> |
formPasswordInput * (standard input field for gathering passwords. Note that no value will ever be populated in fields of this type) formPasswordInput * (标准的输入域用于手机密码。注意这个域允许空值) |
#springFormPasswordInput($path $attributes) |
<@spring.formPasswordInput path, attributes/> |
formTextarea (large text field for gathering long, freeform text input) formTextArea(大文本域用于收集较长、且自由的文本输入) |
#springFormTextarea($path $attributes) |
<@spring.formTextarea path, attributes/> |
formSingleSelect (drop down box of options allowing a single required value to be selected) formSingleSelect (下拉框对于可选项允许单选) |
#springFormSingleSelect( $path $options $attributes) |
<@spring.formSingleSelect path, options, attributes/> |
formMultiSelect (a list box of options allowing the user to select 0 or more values) formMultiSelect (选项列表允许用户选择0个或多个值) |
#springFormMultiSelect($path $options $attributes) |
<@spring.formMultiSelect path, options, attributes/> |
formRadioButtons (a set of radio buttons allowing a single selection to be made from the available choices) formRadioButtons (一个单选按钮的集合允许单个选择对于多个选项中) |
#springFormRadioButtons($path $options $separator $attributes) |
<@spring.formRadioButtons path, options separator, attributes/> |
formCheckboxes (a set of checkboxes allowing 0 or more values to be selected) formCheckboxes (一个多选框允许0或多个被选择) |
#springFormCheckboxes($path $options $separator $attributes) |
<@spring.formCheckboxes path, options, separator, attributes/> |
formCheckbox (a single checkbox) formCheckbox (一个简单的复选框) |
#springFormCheckbox($path $attributes) |
<@spring.formCheckbox path, attributes/> |
showErrors (simplify display of validation errors for the bound field) showErrors (简单展示验证错误用于绑定域) |
#springShowErrors($separator $classOrStyle) |
<@spring.showErrors separator, classOrStyle/> |
In FTL (FreeMarker), these two macros are not actually required as you can use the normal formInput macro, specifying ' hidden’ or ' `password’ as the value for the `fieldType parameter.
在FTL(FreeMarker),这两个宏命令不是必须的你可以使用正常的输入宏命令,定义“hidden”或“password”作为值用于fieldType参数。
The parameters to any of the above macros have consistent meanings:
参数用于上面的宏命令包含相应的意义:
path: the name of the field to bind to (ie "command.name")
路径:域的名字绑定到(例如,"command.name")
options: a Map of all the available values that can be selected from in the input field. The keys to the map represent the values that will be POSTed back from the form and bound to the command object. Map objects stored against the keys are the labels displayed on the form to the user and may be different from the corresponding values posted back by the form. Usually such a map is supplied as reference data by the controller. Any Map implementation can be used depending on required behavior. For strictly sorted maps, a SortedMap such as a TreeMap with a suitable Comparator may be used and for arbitrary Maps that should return values in insertion order, use a LinkedHashMap or a LinkedMap from commons-collections.
选项:一个Map对于所有可选值可以选择来自输入域。map的key代表值将被返回给表单并且绑定命令object。map的object存储key是标签展示在表单中对于用户并且可能和相应的值不同对于表单。通常这样map被提供作为引用通过控制器。任何map实现可以被独立使用对于需要的行为。对于严格存储的map,一个SortedMap例如TreeMap有响应的比较强可以被使用用于任意数量的map应当按照插入的顺序来返回,使用LinkedHashMap或LinkedMap来自commons-collections。
separator: where multiple options are available as discreet elements (radio buttons or checkboxes), the sequence of characters used to separate each one in the list (ie "
").
分隔符:多个选项可以作为元素(单选按钮或复选框),字符的顺序用于分隔每个在列表中(例如
)。
attributes: an additional string of arbitrary tags or text to be included within the HTML tag itself. This string is echoed literally by the macro. For example, in a textarea field you may supply attributes as 'rows="5" cols="60"' or you could pass style information such as 'style="border:1px solid silver"'.
属性:一个额外的字符串对于任意的标签或文本包括在HTML标签本身。字符串是重复遍历的通过宏命令。例如,在一个文本域你可以提供属性作为'rows="5" cols="60"'或者你可以传递格式信息例如'style="border:1px solid silver"'。
classOrStyle: for the showErrors macro, the name of the CSS class that the span tag wrapping each error will use. If no information is supplied (or the value is empty) then the errors will be wrapped in tags.
classOrStyle:用于展示错误的宏命令,CSS类的名字分隔标签包裹每个使用的错误。如果没有信息被提供(或值为空)则错误将被包裹在标签中。
Examples of the macros are outlined below some in FTL and some in VTL. Where usage differences exist between the two languages, they are explained in the notes.
宏命令的例子是一部分在FTL和一部分在VTL。她们的使用不同,并且在注意中进行了说明。
Input Fields
输入域
...
Name:
#springFormInput("command.name" "")
#springShowErrors("
" "")
The formInput macro takes the path parameter (command.name) and an additional attributes parameter which is empty in the example above. The macro, along with all other form generation macros, performs an implicit spring bind on the path parameter. The binding remains valid until a new bind occurs so the showErrors macro doesn’t need to pass the path parameter again - it simply operates on whichever field a bind was last created for.
formInput宏命令使用了path属性(command.name)和额外的属性参数其中在上面的例子中是空的。宏命令,对于其他的表单生成宏命令,展示了严格的字符串绑定在路径参数上。绑定保留了验证直到新的绑定发生因此showErrors宏命令不需要再次传递路径————他简单的操作了最后一次创建的域绑定。
The showErrors macro takes a separator parameter (the characters that will be used to separate multiple errors on a given field) and also accepts a second parameter, this time a class name or style attribute. Note that FreeMarker is able to specify default values for the attributes parameter, unlike Velocity, and the two macro calls above could be expressed as follows in FTL:
showErrors宏命令使用了一个分隔参数(字符将被使用用于分隔多个错误对于给定的域)和接受第二个参数,这一次类名或格式属性。注意FreeMarker可以默认定义值对于属性参数,不像Velocity和两个宏命令调用可以展示在下面的FTL中:
<@spring.formInput "command.name"/>
<@spring.showErrors "
"/>
Output is shown below of the form fragment generating the name field, and displaying a validation error after the form was submitted with no value in the field. Validation occurs through Spring’s Validation framework.
输出被展示如下对于表单部分生成name域,并且展示一个验证错误在表单之后被提交空值在域中。验证错误发生通过spring的验证框架。
The generated HTML looks like this:
生成的html展示如下:
Name:
required
The formTextarea macro works the same way as the formInput macro and accepts the same parameter list. Commonly, the second parameter (attributes) will be used to pass style information or rows and cols attributes for the textarea.
formTextarea宏命令相同的方式工作类似于formInput宏命令并且接受相同的参数列表。通常,第二个参数(属性)将被使用用于传递格式信息或行和列的属性对于文本域。
Selection Fields
选择域
Four selection field macros can be used to generate common UI value selection inputs in your HTML forms.
四个选择域宏命令可以被使用用于生成通用UI值选择输入在你的html表单中:
formSingleSelect
formMultiSelect
formRadioButtons
formCheckboxes
Each of the four macros accepts a Map of options containing the value for the form field, and the label corresponding to that value. The value and the label can be the same.
四个宏命令中的每一个接收一个选项的Map包含的值就是表单域,并且标签对应相应的值。值和标签可以是相同的。
An example of radio buttons in FTL is below. The form backing object specifies a default value of 'London' for this field and so no validation is necessary. When the form is rendered, the entire list of cities to choose from is supplied as reference data in the model under the name 'cityMap'.
有一个关于选择按钮在FTL中的例子如下。表单返回object定义了一个默认值对于'London'在这个域中并且不需要验证。当表单被处理,整个城市的列表来选择作为引用的数据在'cityMap'的模型下。
...
Town:
<@spring.formRadioButtons "command.address.town", cityMap, ""/>
This renders a line of radio buttons, one for each value in cityMap using the separator "". No additional attributes are supplied (the last parameter to the macro is missing). The cityMap uses the same String for each key-value pair in the map. The map’s keys are what the form actually submits as POSTed request parameters, map values are the labels that the user sees. In the example above, given a list of three well known cities and a default value in the form backing object, the HTML would be
解析单行的单选按钮,每个值在cityMap中使用分隔符。没有额外的属性是必须的(宏命令的最后一个参数是抛弃的)。cityMap使用相同的字符串用于每个key-value值对在map中。map中key实际是表单提交的作为POST请求参数,map的value是用户看到的标签。在上面的例子中,给定了一个列表有三个已知的城市和一个默认值在表单的object中,则Html看起来是这样的
Town:
London
Paris
New York
If your application expects to handle cities by internal codes for example, the map of codes would be created with suitable keys like the example below.
如果你的应用期望处理内部的城市例如,code的map被创建使用合适的key类似于下面的例子。
protected Map referenceData(HttpServletRequest request) throws Exception {
Map cityMap = new LinkedHashMap();
cityMap.put("LDN", "London");
cityMap.put("PRS", "Paris");
cityMap.put("NYC", "New York");
Map m = new HashMap();
m.put("cityMap", cityMap);
return m;
}
The code would now produce output where the radio values are the relevant codes but the user still sees the more user friendly city names.
代码将产生输出当单选值是相关的代码但是用户依然看到更多友善的城市的名字。
Town:
London
Paris
New York
HTML escaping and XHTML compliance
html逃逸和xhtml承诺
Default usage of the form macros above will result in HTML tags that are HTML 4.01 compliant and that use the default value for HTML escaping defined in your web.xml as used by Spring’s bind support. In order to make the tags XHTML compliant or to override the default HTML escaping value, you can specify two variables in your template (or in your model where they will be visible to your templates). The advantage of specifying them in the templates is that they can be changed to different values later in the template processing to provide different behavior for different fields in your form.
默认使用表单宏命令如上将导致在html标签中html4.01承诺和使用默认的html逃逸定义在你的web.xml中使用通过spring的绑定支持。为了使得标签xhtml承诺或覆盖默认的html逃逸值,你可以定义两个变量在你的模板中(或你的模型中将对你的模板可见)。在模板中定义的优点是她们可以被改变为不同值在模板处理并提供对于表单域中不同域的不同的行为。
To switch to XHTML compliance for your tags, specify a value of 'true' for a model/context variable named xhtmlCompliant:
为了切换xhtml承诺对于你的标签,定义值为true用于模型或上下文变量名字为xhtmlCompliant:
# for Velocity..
#set($springXhtmlCompliant = true)
<-- for FreeMarker -->
<#assign xhtmlCompliant = true in spring>
Any tags generated by the Spring macros will now be XHTML compliant after processing this directive.
通过spring的宏命令生成的任何标签将被作为xhtml承诺在他们直接被处理之后。
In similar fashion, HTML escaping can be specified per field:
在相似的情况,html逃逸可以定义在每个域中:
<#-- until this point, default HTML escaping is used -->
<#assign htmlEscape = true in spring>
<#-- next field will use HTML escaping -->
<@spring.formInput "command.name"/>
<#assign htmlEscape = false in spring>
<#-- all future fields will be bound with HTML escaping off -->
23.5 JSP & JSTL
Spring provides a couple of out-of-the-box solutions for JSP and JSTL views. Using JSP or JSTL is done using a normal view resolver defined in the WebApplicationContext. Furthermore, of course you need to write some JSPs that will actually render the view.
spring提供了一组外部的解决方案对于JSP和JSTL视图。使用JSP或JSTL被完成使用一个默认的视图解析定义在WebApplicationContext。此外,当然你需要写一些JSP来实际解析视图。
[Note]
注意
Setting up your application to use JSTL is a common source of error, mainly caused by confusion over the different servlet spec., JSP and JSTL version numbers, what they mean and how to declare the taglibs correctly. The article How to Reference and Use JSTL in your Web Application provides a useful guide to the common pitfalls and how to avoid them. Note that as of Spring 3.0, the minimum supported servlet version is 2.4 (JSP 2.0 and JSTL 1.1), which reduces the scope for confusion somewhat.
设置你的应用来使用JSTL是一个普通的错误源,主要由于混合了不同的servlet,JSP和JSTL版本数字,他们意味着如何正确的定义taglibs。文章How to Reference and Use JSTL in your Web Application提供了一个有用的指南对于常见的错误以及如何避免这些错误。注意由于spring的3.0,最小支持的Servlet版本是2.4(JSP2.0和JSTL1.1)将减小错误的范围。
23.5.1 View resolvers
视图解析
Just as with any other view technology you’re integrating with Spring, for JSPs you’ll need a view resolver that will resolve your views. The most commonly used view resolvers when developing with JSPs are the InternalResourceViewResolver and the ResourceBundleViewResolver. Both are declared in the WebApplicationContext:
就像作为任何视图技术你和spring进行集成,对于JSP你需要一个视图解析器来解析你的视图。最常用的使用视图解析器当部署JSP是InternalResourceViewResolver和ResourceBundleViewResolver。他们都定义在WebApplicationContext中:
# And a sample properties file is uses (views.properties in WEB-INF/classes):
welcome.(class)=org.springframework.web.servlet.view.JstlView
welcome.url=/WEB-INF/jsp/welcome.jsp
productList.(class)=org.springframework.web.servlet.view.JstlView
productList.url=/WEB-INF/jsp/productlist.jsp
As you can see, the ResourceBundleViewResolver needs a properties file defining the view names mapped to 1) a class and 2) a URL. With a ResourceBundleViewResolver you can mix different types of views using only one resolver.
就像你看到的,ResourceBundleViewResolver需要一个属性文件定义视图名匹配类和一个URL。对于ResourceBundleViewResolver你可以混合不同类型的视图使用解析器。
The InternalResourceBundleViewResolver can be configured for using JSPs as described above. As a best practice, we strongly encourage placing your JSP files in a directory under the 'WEB-INF' directory, so there can be no direct access by clients.
InternalResourceBundleViewResolver可以被配置用于使用JSP描述如上。由于最好的联系,我们强烈鼓励替换你的JSP文件在'WEB-INF'文件夹中,因此他们不能直接通过客户端来访问。
23.5.2 'Plain-old' JSPs versus JSTL
原始JSP和JSTL比较
When using the Java Standard Tag Library you must use a special view class, the JstlView, as JSTL needs some preparation before things such as the I18N features will work.
当使用Java标准的标签库,你必须使用特定的视图类,JstlView作为JSTL需要一些准备在例如为了I18N特性正常工作。
23.5.3 Additional tags facilitating development
额外的标签部署
Spring provides data binding of request parameters to command objects as described in earlier chapters. To facilitate the development of JSP pages in combination with those data binding features, Spring provides a few tags that make things even easier. All Spring tags haveHTML escaping features to enable or disable escaping of characters.
spring提供了数据绑定对于请求参数对于命令object作为描述在之前的章节。为了便于JSP页面的部署对于这些数据绑定特性,spring提供了一些标签使得事情更加简单。所有的spring标签有html逃逸特性来允许或关闭逃逸的字符。
The tag library descriptor (TLD) is included in the spring-webmvc.jar. Further information about the individual tags can be found in the appendix entitled ???.
标签库描述符(TLD)包括在spring-webmvc.jar。更多的信息关于独立的标签可以找到在附录中。
23.5.4 Using Spring’s form tag library
使用spring表单的标签库
As of version 2.0, Spring provides a comprehensive set of data binding-aware tags for handling form elements when using JSP and Spring Web MVC. Each tag provides support for the set of attributes of its corresponding HTML tag counterpart, making the tags familiar and intuitive to use. The tag-generated HTML is HTML 4.01/XHTML 1.0 compliant.
由于版本2.0,spring提供了一个复杂的数据绑定集合标签用于处理元素当使用JSP和spring的web的mvc时。每个标签提供了支持用于他猛相应的html标签的属性集,使得标签更加容易使用。标签生成html是HTML4.01或XMLHTML1.0承诺。
Unlike other form/input tag libraries, Spring’s form tag library is integrated with Spring Web MVC, giving the tags access to the command object and reference data your controller deals with. As you will see in the following examples, the form tags make JSPs easier to develop, read and maintain.
不像其他的表单或输入标签库,spring的表单标签库是集成在spring的web的mvc中,给定了标签访问命令object和引用数据来处理。因此你看到在下面的例子中,表单标签使得JSP更加方便开发、阅读和维护。
Let’s go through the form tags and look at an example of how each tag is used. We have included generated HTML snippets where certain tags require further commentary.
查看表单标签查找每个标签的使用。我们包括生产HTML片段当确定的标签要求更多的评论。
Configuration
配置
The form tag library comes bundled in spring-webmvc.jar. The library descriptor is called spring-form.tld.
表单标签库来自spring-webmvc.jar中。库描述符名字为spring-form.tld。
To use the tags from this library, add the following directive to the top of your JSP page:
为了使用来自这些库,添加下面的内容在你的JSP页面的头部:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
where form is the tag name prefix you want to use for the tags from this library.
当来自标签名前缀你希望使用来自这个库中。
The form tag
表单标签
This tag renders an HTML 'form' tag and exposes a binding path to inner tags for binding. It puts the command object in the PageContext so that the command object can be accessed by inner tags. All the other tags in this library are nested tags of the form tag.
这个标签解析html的form标签并暴露一个绑定路径对于内部标签的绑定。他放入了命令object在PageContext因此命令object可以访问通过内部的标签。所有的其他标签在这个库中是嵌入到表单标签的。
Let’s assume we have a domain object called User. It is a JavaBean with properties such as firstName and lastName. We will use it as the form backing object of our form controller which returns form.jsp. Below is an example of what form.jsp would look like:
假设我们有一个主object名字为User。他是一个JavaBean使用了属性例如firstName和lastName。我们将使用他作为表单object对于我们的表单来自控制器返回form.jsp。下面是一个例子对于form.jsp类似于:
First Name: | |
Last Name: | |
|
The firstName and lastName values are retrieved from the command object placed in the PageContext by the page controller. Keep reading to see more complex examples of how inner tags are used with the form tag.
firstName和lastName值是返回来命令object存在于PageContext通过页面控制器。保证读取看到更加复杂的例子对于内部标签如何使用对于表单标签。
The generated HTML looks like a standard form:
为了生成HTML类似于一个标准的表单:
The preceding JSP assumes that the variable name of the form backing object is 'command'. If you have put the form backing object into the model under another name (definitely a best practice), then you can bind the form to the named variable like so:
之前的JSP假设变量名对于表单是'command'。如果你有放入表单objectDAO模型中以另一个名(定义了一个最好的),你可以绑定表单对于这个命名变量通过:
First Name: | |
Last Name: | |
|
The input tag
输入标签
This tag renders an HTML 'input' tag using the bound value and type='text' by default. For an example of this tag, see the section called “The form tag”. Starting with Spring 3.1 you can use other types such HTML5-specific types like 'email', 'tel', 'date', and others.
这个标签解析作为HTML的输入标签使用绑定值和type='text'作为默认。对于这个标签的例子,见章节名字为“The form tag”。开始于spring3.1你可以使用类型例如特定的html5类型例如'email'、'tel'、'date'等等。
The checkbox tag
复选框标签
This tag renders an HTML 'input' tag with type 'checkbox'.
这个标签解析html的输入标签当类型为'checkbox'时。
Let’s assume our User has preferences such as newsletter subscription and a list of hobbies. Below is an example of the Preferences class:
假设我们的用户有选择例如时事通信订阅和一个爱好列表。下面是一个列子有关选择类:
public class Preferences {
private boolean receiveNewsletter;
private String[] interests;
private String favouriteWord;
public boolean isReceiveNewsletter() {
return receiveNewsletter;
}
public void setReceiveNewsletter(boolean receiveNewsletter) {
this.receiveNewsletter = receiveNewsletter;
}
public String[] getInterests() {
return interests;
}
public void setInterests(String[] interests) {
this.interests = interests;
}
public String getFavouriteWord() {
return favouriteWord;
}
public void setFavouriteWord(String favouriteWord) {
this.favouriteWord = favouriteWord;
}
}
The form.jsp would look like:
form.jsp是这样的:
Subscribe to newsletter?: | |
Interests: |
Quidditch: Herbology: Defence Against the Dark Arts:
|
Favourite Word: |
Magic:
|
There are 3 approaches to the checkbox tag which should meet all your checkbox needs.
这是三个方法用于复选框标签当处理你的复选框需求时。
Approach One - When the bound value is of type java.lang.Boolean, the input(checkbox) is marked as 'checked' if the bound value is true. The value attribute corresponds to the resolved value of the setValue(Object) value property.
方式一,当绑定值是java.lang.Boolean类型,复选框的输入标记作为选中如果值为true时。值属性相当于解析setValue(Object)的值属性。
Approach Two - When the bound value is of type array or java.util.Collection, the input(checkbox) is marked as 'checked' if the configured setValue(Object) value is present in the bound Collection.
方式二,当绑定值是java.util.Collection类型,复选框的输入标记为选中如果setValue(Object)值在集合中。
Approach Three - For any other bound value type, the input(checkbox) is marked as 'checked' if the configured setValue(Object) is equal to the bound value.
方式三,对于其他的值类型,复选框输入标记为选中如果配置setValue(Object)和绑定值相同时。
Note that regardless of the approach, the same HTML structure is generated. Below is an HTML snippet of some checkboxes:
注意上面任意的一种方法,相同的html结构被生成。下面是有关复选框的html片段:
Quidditch:
Herbology:
Defence Against the Dark Arts:
What you might not expect to see is the additional hidden field after each checkbox. When a checkbox in an HTML page is not checked, its value will not be sent to the server as part of the HTTP request parameters once the form is submitted, so we need a workaround for this quirk in HTML in order for Spring form data binding to work. The checkbox tag follows the existing Spring convention of including a hidden parameter prefixed by an underscore ("_") for each checkbox. By doing this, you are effectively telling Spring that "the checkbox was visible in the form and I want my object to which the form data will be bound to reflect the state of the checkbox no matter what".
你不期望看到额外的隐藏域在每个复选框之后。当一个在html页面中的复选框没有被选中,他的值将不会被发送DAO服务器作为http请求参数的一部分来自表单的提交,因此我们需要一个工作区用于这种在html中用于spring的表单数据绑定到work中。复选框标签符合已有的spring规范包括隐藏参数通过前缀是下划线对于每个复选框。通过这样做,你可以有效的告诉spring“复选框是可见的在表单中并且我希望我的object对于表单数据的绑定反应了复选框的状态”。
The checkboxes tag
复选框标签
This tag renders multiple HTML 'input' tags with type 'checkbox'.
这个标签解析多个html输入标签对于类型'checkbox'。
Building on the example from the previous checkbox tag section. Sometimes you prefer not to have to list all the possible hobbies in your JSP page. You would rather provide a list at runtime of the available options and pass that in to the tag. That is the purpose of the checkboxes tag. You pass in an Array, a List or a Map containing the available options in the "items" property. Typically the bound property is a collection so it can hold multiple values selected by the user. Below is an example of the JSP using this tag:
构建例子来自之前的复选框标签。有时你希望有列出所有的在你的JSP页面中的爱好。你希望提供一个运行时列表对于可用的选项和传递给标签。这个是复选框标签的目的。你可以传递一个数组,一个列表或一个map包含每个可选项在"items"属性中。通常绑定手续ing是一个结合一次他可以保存多个值来提供给用户选择。下面是一个JSP使用这个标签的例子:
Interests: |
<%-- Property is of an array or of type java.util.Collection --%>
|
This example assumes that the "interestList" is a List available as a model attribute containing strings of the values to be selected from. In the case where you use a Map, the map entry key will be used as the value and the map entry’s value will be used as the label to be displayed. You can also use a custom object where you can provide the property names for the value using "itemValue" and the label using "itemLabel".
这个例子假设"interestList"是一个列表用于模型属性包含字符串值对于选中的表单。在这个例子中你使用一个map,map的key将使用作为值并且map的值将使用作为标签用于展示。你也可以使用一个自定义的object当你可以提供属性名对于值使用"itemValue"和标签使用"itemLabel"。
The radiobutton tag
单选框标签
This tag renders an HTML 'input' tag with type 'radio'.
这个标签解析一个html的输入标签对于类型是'radio'。
A typical usage pattern will involve multiple tag instances bound to the same property but with different values.
一个通常的使用模式将调用多个标签实例绑定到相同的属性但是值是不同的。
Male:
Female:
The radiobuttons tag
单选标签
This tag renders multiple HTML 'input' tags with type 'radio'.
这个标签解析多个html输入标签如果类型是'radio'。
Just like the checkboxes tag above, you might want to pass in the available options as a runtime variable. For this usage you would use the radiobuttons tag. You pass in an Array, a List or a Map containing the available options in the "items" property. In the case where you use a Map, the map entry key will be used as the value and the map entry’s value will be used as the label to be displayed. You can also use a custom object where you can provide the property names for the value using "itemValue" and the label using "itemLabel".
就像上面的复选框标签,你可以传递可选的选项作为运行时变量。对于这种使用方式你可以使用单选标签。你传递一个数组、一个列表或一个map包含可选的选项在"items"属性中。如果你使用一个map,map的key将使用作为值并且map的值将使用作为标签来显示。你也可以使用一个自定义object当你可以提供属性名对于值使用"itemValue"和标签使用"itemLabel"。
The password tag
密码框标签
This tag renders an HTML 'input' tag with type 'password' using the bound value.
这个标签解析html输入标签当类型是'password'时使用绑定值。
Please note that by default, the password value is not shown. If you do want the password value to be shown, then set the value of the 'showPassword' attribute to true, like so.
请注意,密码值是不可见的。如果你希望密码值可见,需要设置'showPassword'属性为true,如下。
The select tag
选择标签
This tag renders an HTML 'select' element. It supports data binding to the selected option as well as the use of nested option and options tags.
这个标签解析html的选择元素。他支持数据绑定对于选择项目作为使用内部的选项和选择标签。
Let’s assume a User has a list of skills.
我们假设用户有一个技能列表。
If the User’s skill were in Herbology, the HTML source of the 'Skills' row would look like:
如果用户的技能列表是Herbology,html关于'Skills'行的值看起来是这样的:
The option tag
选项标签
This tag renders an HTML 'option'. It sets 'selected' as appropriate based on the bound value.
这个标签解析html的option。他根据绑定值设置'selected'。
If the User’s house was in Gryffindor, the HTML source of the 'House' row would look like:
如果用户的家在Gryffindor,html关于家的源码行看起来是这样的:
The options tag
选项标签
This tag renders a list of HTML 'option' tags. It sets the 'selected' attribute as appropriate based on the bound value.
这个标签解析html的option标签列表。他根据绑定值设置'selected'属性。
If the User lived in the UK, the HTML source of the 'Country' row would look like:
如果用户住在UK,html解析国家的源码看来是这样的:
As the example shows, the combined usage of an option tag with the options tag generates the same standard HTML, but allows you to explicitly specify a value in the JSP that is for display only (where it belongs) such as the default string in the example: "-- Please Select".
由于上面的例子的展示,组合使用option变迁对于option标签生成相同的标准的html,但是允许你来指定JSP的值只用于显示()例如默认的字符串在例子中是:"-- Please Select"。
The items attribute is typically populated with a collection or array of item objects. itemValue and itemLabel simply refer to bean properties of those item objects, if specified; otherwise, the item objects themselves will be stringified. Alternatively, you may specify a Map of items, in which case the map keys are interpreted as option values and the map values correspond to option labels. If itemValue and/or itemLabel happen to be specified as well, the item value property will apply to the map key and the item label property will apply to the map value.
item属性通常是一个集合或item的object数组,itemValue和itemLabel简单引用了item的object的bean的属性,如果指定的话;此外,item的object将是直接的。作为替代,你可以定义一个item的map,map的key可以使作为选项值并且map的值相对于选项标签。如果itemValue和itemLabel都指定,item值属性将应用于map的key并且item标签属性将应用于map值。
The textarea tag
文本框标签
This tag renders an HTML 'textarea'.
这个标签解析html中的'textarea'。
The hidden tag
隐藏标签
This tag renders an HTML 'input' tag with type 'hidden' using the bound value. To submit an unbound hidden value, use the HTML input tag with type 'hidden'.
这个标签解析html中input标签类型是'hidden'使用绑定值。为了提交非绑定值,使用html输入标签且类型是'hidden'。
If we choose to submit the 'house' value as a hidden one, the HTML would look like:
如果我们选择提交'house'值作为隐藏域,html看起来是这样的:
The errors tag
错误标签
This tag renders field errors in an HTML 'span' tag. It provides access to the errors created in your controller or those that were created by any validators associated with your controller.
这个标签解析html中span标签中的错误。他提供了访问在你控制器中创建的错误或通过验证器关联你的控制器创建的错误。
Let’s assume we want to display all error messages for the firstName and lastName fields once we submit the form. We have a validator for instances of the User class called UserValidator.
让我们假设希望展示所有的错误信息对于firstName和lastName域当我们提交表单时。我们有一个验证器对于User类的实例名字为UserValidator。
public class UserValidator implements Validator {
public boolean supports(Class candidate) {
return User.class.isAssignableFrom(candidate);
}
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required.");
}
}
The form.jsp would look like:
这个form.jsp看起来是这样的:
First Name: | ||
Last Name: | ||
|
If we submit a form with empty values in the firstName and lastName fields, this is what the HTML would look like:
如果我们提交一个表单附带是空值在firstName和lastName的域中,则html看起来是这样的:
What if we want to display the entire list of errors for a given page? The example below shows that the errors tag also supports some basic wildcarding functionality.
如果我们希望展示整个错误列表对于给定的页面怎么办?下面的例子展示了错误标签也支持一些基本的通配符功能。
path="*" - displays all errors
展示所有的错误
path="lastName" - displays all errors associated with the lastName field
展示所有的错误相关于lastName域
if path is omitted - object errors only are displayed
如果路径被省略————object错误被展示
The example below will display a list of errors at the top of the page, followed by field-specific errors next to the fields:
下面的例子展示了一个错误列表在页面的顶部,符合特定的域紧挨着域:
First Name: | ||
Last Name: | ||
|
The HTML would look like:
html看起来是这样的:
HTTP Method Conversion
http方法规范
A key principle of REST is the use of the Uniform Interface. This means that all resources (URLs) can be manipulated using the same four HTTP methods: GET, PUT, POST, and DELETE. For each method, the HTTP specification defines the exact semantics. For instance, a GET should always be a safe operation, meaning that is has no side effects, and a PUT or DELETE should be idempotent, meaning that you can repeat these operations over and over again, but the end result should be the same. While HTTP defines these four methods, HTML only supports two: GET and POST. Fortunately, there are two possible workarounds: you can either use JavaScript to do your PUT or DELETE, or simply do a POST with the 'real' method as an additional parameter (modeled as a hidden input field in an HTML form). This latter trick is what Spring’s HiddenHttpMethodFilter does. This filter is a plain Servlet Filter and therefore it can be used in combination with any web framework (not just Spring MVC). Simply add this filter to your web.xml, and a POST with a hidden _method parameter will be converted into the corresponding HTTP method request.
一个REST使用的关键原则是对于同一接口的使用。这意味着所有的资源可以操作使用相同的四个HTTP方法:GET、PUT、POST和DELETE。对于每个方法,http规范定义了额外的语义。因此,一个GET应当是一个安全的操作,意味着他没有额外的意义和一个PUT或DELETE应当是幂等的,意味着你可以重复这些操作,但是最后结果是相同的。当http定义这四个方法,html只支持GET和POST。幸运的是,有两个可行的工作区:你可以使用JavaScript来处理你的PUT或DELETE,或简单的提交POST使用真正的方法作为额外的参数(方法作为隐藏输入域在html表单中)。这就是HiddenHttpMethodFilter做的。这个过滤器是一个普通的Servlet过滤器并且他可以被使用配合任何web框架(不只是springMvc)。简单的添加这个过滤器到你的web.xml中并且一个POST请求配合隐藏方法参数将转换到响应的http方法请求。
To support HTTP method conversion the Spring MVC form tag was updated to support setting the HTTP method. For example, the following snippet taken from the updated Petclinic sample
为了支持http的方法转换对于spring的mvc的表单标签被更新用于支持设置http方法。例如,下面的片段来自更新后的Petclinic案例
This will actually perform an HTTP POST, with the 'real' DELETE method hidden behind a request parameter, to be picked up by the HiddenHttpMethodFilter, as defined in web.xml:
这将应用于http的post,使用真正的DELETE方法隐藏在一个请求参数之后,通过HiddenHttpMethodFilter来处理,定义在web.xml中:
The corresponding @Controller method is shown below:
相应的@Controller方法展示如下:
@RequestMapping(method = RequestMethod.DELETE)
public String deletePet(@PathVariable int ownerId, @PathVariable int petId) {
this.clinic.deletePet(petId);
return "redirect:/owners/" + ownerId;
}
HTML5 Tags
HTML5标签
Starting with Spring 3, the Spring form tag library allows entering dynamic attributes, which means you can enter any HTML5 specific attributes.
使用spring3,spring的表单标签库允许全部的动态属性,意味着你可以使用任意的html5定义的属性。
In Spring 3.1, the form input tag supports entering a type attribute other than 'text'. This is intended to allow rendering new HTML5 specific input types such as 'email', 'date', 'range', and others. Note that entering type='text' is not required since 'text' is the default type.
在spring3.1中,表单输入标签支持输入一个类型属性而不只是text。他允许html5定义输入类型例如'email'、'date'、'range'等等。注意输入type='text'不是必须的自从'text'是默认的类型。
23.6 Script templates
脚本模板
It is possible to integrate any templating library running on top of a JSR-223 script engine in web applications using Spring. The following describes in a broad way how to do this. The script engine must implement both ScriptEngine and Invocable interfaces.
这是可行的集成任何模板库在JSR223脚本引擎上运行在web应用中使用spring。下面描述了许多方法来实现这些。脚本引擎必须实现ScriptEngine和Invocable接口。
It has been tested with:
他已经被测试通过:
Handlebars running on Nashorn
Mustache running on Nashorn
React running on Nashorn
EJS running on Nashorn
ERB running on JRuby
String templates running on Jython
23.6.1 Dependencies
依赖
To be able to use script templates integration, you need to have available in your classpath the script engine:
为了使用脚本模板集成,你需要在你的classpath中定义脚本引擎:
Nashorn Javascript engine is provided builtin with Java 8+. Using the latest update release available is highly recommended.
Nashorn脚本引擎提供了对于Java8的支持。推荐使用最新的更新版本。
Rhino Javascript engine is provided builtin with Java 6 and Java 7. Please notice that using Rhino is not recommended since it does not support running most template engines.
Rhino的JavaScript引擎内置提供支持Java6和Java7。请注意使用Rhino不被推荐因为他不支持运行大部分模板引擎。
JRuby dependency should be added in order to get Ruby support.
JRuby依赖应当被添加用于获得Ruby支持。
Jython dependency should be added in order to get Python support.
Jython依赖应当被添加用于获得Python支持。
You should also need to add dependencies for your script based template engine. For example, for Javascript you can use WebJars to add Maven/Gradle dependencies in order to make your javascript libraries available in the classpath.
你应当需要添加依赖用于你的脚本基于模板引擎。例如,对于JavaScript你可以使用WebJars来添加到Maven/Gradle依赖中用于使得你的javascript库可以在你的classpath中可见。
23.6.2 How to integrate script based templating
如何集成基于模板的脚本
To be able to use script templates, you have to configure it in order to specify various parameters like the script engine to use, the script files to load and what function should be called to render the templates. This is done thanks to a ScriptTemplateConfigurer bean and optional script files.
为了允许使用脚本引擎,你需要配置用于指定不同的参数让脚本引擎来使用,脚本文件被加载并且功能将被调用用于解析模板。这么做是为了ScriptTemplateConfigurer的bean和可选的脚本文件。
For example, in order to render Mustache templates thanks to the Nashorn Javascript engine provided with Java 8+, you should declare the following configuration:
例如,为了解析Mustache模板对于Nashorn的JavaScript引擎提供通过Java8以上,你应当定义下面的配置:
@Configuration
@EnableWebMvc
public class MustacheConfig extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.scriptTemplate();
}
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("mustache.js");
configurer.setRenderObject("Mustache");
configurer.setRenderFunction("render");
return configurer;
}
}
The XML counterpart using MVC namespace is:
xml配对的使用mvc的命名空间是:
The controller is exactly what you should expect:
容器中明确定义了你期望的:
@Controller
public class SampleController {
@RequestMapping
public ModelAndView test() {
ModelAndView mav = new ModelAndView();
mav.addObject("title", "Sample title").addObject("body", "Sample body");
mav.setViewName("template.html");
return mav;
}
}
And the Mustache template is:
并且Mustache模板是这样的:
{{body}}
The render function is called with the following parameters:
解析功能被调用通过下面的参数:
String template: the template content
Map model: the view model
String url: the template url (since 4.2.2)
Mustache.render() is natively compatible with this signature, so you can call it directly.
Mustache.render()是一个本地的方法签名,因此你可以直接调用。
If your templating technology requires some customization, you may provide a script that implements a custom render function. For example, Handlerbars needs to compile templates before using them, and requires a polyfill in order to emulate some browser facilities not available in the server-side script engine.
如果你的模板技术需要一些自定义,你可以提供一个脚本实现一个自定义的解析功能。例如,Handlerbars需要编译模板在使用他们之前,并且需要一个polyfill用于处理一些浏览器工具不支持服务端的脚本引擎。
@Configuration
@EnableWebMvc
public class MustacheConfig extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.scriptTemplate();
}
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("polyfill.js", "handlebars.js", "render.js");
configurer.setRenderFunction("render");
configurer.setSharedEngine(false);
return configurer;
}
}
[Note]
注意
Setting the sharedEngine property to false is required when using non thread-safe script engines with templating libraries not designed for concurrency, like Handlebars or React running on Nashorn for example. In that case, Java 8u60 or greater is required due to this bug.
设置sharedEngine属性为false是被要求的当使用非线程安全的脚本引擎对于模板库并且没有支持并发,类似于Handlebars或React运行在Nashorn上例如。因此,Java8u60或更高级的版本要求由于这个bug。
polyfill.js only defines the window object needed by Handlebars to run properly:
polyfill.js是只定义了window的object需要通过Handlebars来运行的:
var window = {};
This basic render.js implementation compiles the template before using it. A production ready implementation should also store and reused cached templates / pre-compiled templates. This can be done on the script side, as well as any customization you need (managing template engine configuration for example).
这个基本的render.js实现编译了模板在使用它之前。一个产品实现应当保存和重用缓存模板/提前编译的模板。这可以通过脚本方面来实现,并且你需要的自定义(例如管理模板引擎配置)
function render(template, model) {
var compiledTemplate = Handlebars.compile(template);
return compiledTemplate(model);
}
Check out Spring script templates unit tests (java, resources) for more configuration examples.
检查spirng的脚本模板单元测试(java、resources)用于多的配置案例。
23.7 XML Marshalling View
xml的Marshaller的视图
The MarshallingView uses an XML Marshaller defined in the org.springframework.oxm package to render the response content as XML. The object to be marshalled can be set explicitly using MarhsallingView’s `modelKey bean property. Alternatively, the view will iterate over all model properties and marshal the first type that is supported by the Marshaller. For more information on the functionality in the org.springframework.oxm package refer to the chapter Marshalling XML using O/X Mappers.
MarshallingView使用了一个xml的Marshaller定义在org.springframework.oxm包中用于解析作为xml的响应内容。object用于marshalled可以明确设置使用MarhsallingView的modelKey的bean属性。作为替代,视图将迭代所有模板属性和排列第一个类型通过Marshaller的支持。对于更多功能的信息在org.springframework.oxm包中引用了章节“Marshalling XML using O/X Mappers”。
23.8 Tiles
标题
It is possible to integrate Tiles - just as any other view technology - in web applications using Spring. The following describes in a broad way how to do this.
可以集成标题————就像其他的视图技术————在使用spring的web应用中。下面描述了如何来实现:
[Note]
注意
This section focuses on Spring’s support for Tiles v3 in the org.springframework.web.servlet.view.tiles3 package.
这个章节关注于spring的支持对于标签v3在org.springframework.web.servlet.view.tiles3包中。
23.8.1 Dependencies
依赖
To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher and its transitive dependencies to your project.
为了允许使用标题,你可以添加依赖在标题版本3.0.1或更高并且他会传递依赖到你的项目中。
23.8.2 How to integrate Tiles
如何继承标题
To be able to use Tiles, you have to configure it using files containing definitions (for basic information on definitions and other Tiles concepts, please have a look at http://tiles.apache.org). In Spring this is done using the TilesConfigurer. Have a look at the following piece of example ApplicationContext configuration:
为了使用标题,你必须配置他使用文件包含定义(对于基本的信息定义和其他的标题内容,请参考http://tiles.apache.org)。在spring中使用了TilesConfigurer。参考下面的应用上下文配置的案例:
As you can see, there are five files containing definitions, which are all located in the 'WEB-INF/defs' directory. At initialization of the WebApplicationContext, the files will be loaded and the definitions factory will be initialized. After that has been done, the Tiles includes in the definition files can be used as views within your Spring web application. To be able to use the views you have to have a ViewResolver just as with any other view technology used with Spring. Below you can find two possibilities, the UrlBasedViewResolver and the ResourceBundleViewResolver.
你也看到,这里有五个文件内容定义,所有都位于'WEB-INF/defs'文件夹中。一个WebApplicationContext的初始值,文件将被加载并且定义工厂将被初始化。在所有都完成以后,标题包括在定义文件中可以被使用作为视图在你的spring的web应用中。为了允许使用视图你需要一个ViewResolver对于其他的视图技术通过使用spring。下面你可以发现两个UrlBasedViewResolver和ResourceBundleViewResolver。
You can specify locale specific Tiles definitions by adding an underscore and then the locale. For example:
你可以定义本地的标题定义通过添加一个底线和位置。例如:
With this configuration, tiles_fr_FR.xml will be used for requests with the fr_FR locale, and tiles.xml will be used by default.
使用这样的配置,tiles_fr_FR.xml将被使用用于请求fr_FR并且tiles.xml将被默认使用。
[Note]
注意
Since underscores are used to indicate locales, it is recommended to avoid using them otherwise in the file names for Tiles definitions.
自从线下被使用用于指定位置,建议避免使用这些在Tiles定义的文件名中。
UrlBasedViewResolver
The UrlBasedViewResolver instantiates the given viewClass for each view it has to resolve.
UrlBasedViewResolver实例化给定viewClass对于每个解析的视图。
ResourceBundleViewResolver
The ResourceBundleViewResolver has to be provided with a property file containing viewnames and viewclasses the resolver can use:
ResourceBundleViewResolver用于提供属性文件包括视图名和视图类可以用于解析:
...
welcomeView.(class)=org.springframework.web.servlet.view.tiles3.TilesView
welcomeView.url=welcome (this is the name of a Tiles definition)
vetsView.(class)=org.springframework.web.servlet.view.tiles3.TilesView
vetsView.url=vetsView (again, this is the name of a Tiles definition)
findOwnersForm.(class)=org.springframework.web.servlet.view.JstlView
findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp
...
As you can see, when using the ResourceBundleViewResolver, you can easily mix different view technologies.
因此你可以看到,当使用ResourceBundleViewResolver,你可以简单的混合不同的视图技术。
Note that the TilesView class supports JSTL (the JSP Standard Tag Library) out of the box.
注意TilesView类支持JSTL(JSP标准标签库)。
SimpleSpringPreparerFactory and SpringBeanPreparerFactory
As an advanced feature, Spring also supports two special Tiles PreparerFactory implementations. Check out the Tiles documentation for details on how to use ViewPreparer references in your Tiles definition files.
作为一个高级的特性,spring也支持两个特殊的Tiles的PreparerFactory实现。检查Tiles的文档来了解细节关于如何使用ViewPreparer在你的Title定义文件中。
Specify SimpleSpringPreparerFactory to autowire ViewPreparer instances based on specified preparer classes, applying Spring’s container callbacks as well as applying configured Spring BeanPostProcessors. If Spring’s context-wide annotation-config has been activated, annotations in ViewPreparer classes will be automatically detected and applied. Note that this expects preparer classes in the Tiles definition files, just like the default PreparerFactory does.
指定SimpleSpringPreparerFactory来处理ViewPreparer实例基于特定的预处理类,应用spring的容器回调作为应用配置spring的BeanPostProcessors。如果spring的上下文访问注解配置已经被激活,ViewPreparer类中的注解将自动被探测和应用。注意这期望预处理类在Title定义文件,就像默认的PreparerFactory所实现的。
Specify SpringBeanPreparerFactory to operate on specified preparer names instead of classes, obtaining the corresponding Spring bean from the DispatcherServlet’s application context. The full bean creation process will be in the control of the Spring application context in this case, allowing for the use of explicit dependency injection configuration, scoped beans etc. Note that you need to define one Spring bean definition per preparer name (as used in your Tiles definitions).
指定SpringBeanPreparerFactory来操作特定的预处理名来代替类,获得相应的spring的bean来自DispatcherServlet’s的应用上下文。全部的bean创建程序将在spring应用的控制上下文中,允许使用明确的依赖注入配置、范围bean等等。注意你需要定义spring的bean定义对于每个预处理名字(同时也适用在你的Title定义中)
value="org.springframework.web.servlet.view.tiles3.SpringBeanPreparerFactory"/> 23.9 XSLT XSLT is a transformation language for XML and is popular as a view technology within web applications. XSLT can be a good choice as a view technology if your application naturally deals with XML, or if your model can easily be converted to XML. The following section shows how to produce an XML document as model data and have it transformed with XSLT in a Spring Web MVC application. XSLT是一个转换语言用于XML并且用于在web应用中的视图技术。XSLT可以是一个好的选择作为视图技术如果你的应用自然处理了XML,或如果你的模型可以简单的转换为XML。下面的章节展示了如何生产XML文档作为模型数据并且使用XSLT来转换在spring的web的mvc应用中。 23.9.1 My First Words 我的第一个单词 This example is a trivial Spring application that creates a list of words in the Controller and adds them to the model map. The map is returned along with the view name of our XSLT view. See Section 22.3, “Implementing Controllers” for details of Spring Web MVC’s Controller interface. The XSLT Controller will turn the list of words into a simple XML document ready for transformation. 这个例子是一个不重要的spring应用创建了一个单词列表在控制器和添加model的map。map是返回我们XSLT视图的视图名。见章节22.3,“实现控制器”对于spring的web的mvc的细节控制器接口。XSLT控制器将单词列表转换为简单的xml文档用于转换。 Bean definitions bean定义 Configuration is standard for a simple Spring application. The MVC configuration has to define a XsltViewResolver bean and regular MVC annotation configuration. 配置是标准的用于简单的spring应用。mvc配置已经定义了一个XsltViewResolver的bean和普通的mvc注解配置。 @EnableWebMvc @ComponentScan @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Bean public XsltViewResolver xsltViewResolver() { XsltViewResolver viewResolver = new XsltViewResolver(); viewResolver.setPrefix("/WEB-INF/xsl/"); viewResolver.setSuffix(".xslt"); return viewResolver; } } And we need a Controller that encapsulates our word generation logic. 并且我们需要一个控制压缩我们单词的生成逻辑。 Standard MVC controller code 标准的mvc控制器代码 The controller logic is encapsulated in a @Controller class, with the handler method being defined like so… 控制器逻辑是密封在@Controller类中,并且定义了处理方法如下。 @Controller public class XsltController { @RequestMapping("/") public String home(Model model) throws Exception { Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element root = document.createElement("wordList"); List for (String word : words) { Element wordNode = document.createElement("word"); Text textNode = document.createTextNode(word); wordNode.appendChild(textNode); root.appendChild(wordNode); } model.addAttribute("wordList", root); return "home"; } } So far we’ve only created a DOM document and added it to the Model map. Note that you can also load an XML file as a Resource and use it instead of a custom DOM document. 因此我们只要创建一个DOM文档并添加到Model的map中。注意你可以加载一个xml文件作为资源并且使用它来代替自定义的DOM文档。 Of course, there are software packages available that will automatically 'domify' an object graph, but within Spring, you have complete flexibility to create the DOM from your model in any way you choose. This prevents the transformation of XML playing too great a part in the structure of your model data which is a danger when using tools to manage the domification process. 当然,这些软件包是可用的并且将自动'domify'一个object的graph,但是在spring你可以完成方便的创建DOM来自你的模型中通过任何你选择的方式。这避免了xml的转换来承担很大的结构部分对于你的模型数据,因此是危险的当你使用工具来管理domification的处理。 Next, XsltViewResolver will resolve the "home" XSLT template file and merge the DOM document into it to generate our view. 然后,XsltViewResolver将解析“home”的XSLT模板文件并且管理DOM文档用于生成我们的视图。 Document transformation 文档转换 Finally, the XsltViewResolver will resolve the "home" XSLT template file and merge the DOM document into it to generate our view. As shown in the XsltViewResolver configuration, XSLT templates live in the war file in the 'WEB-INF/xsl' directory and end with a "xslt" file extension. 最后,XsltViewResolver将解析“home”的XSLT模板文件并且合并DOM文档用于生成我们的视图。由展示的XsltViewResolver配置,XSLT模板存在于war文件中在'WEB-INF/xsl'目录并且最后使用了xslt的文件后缀。
This is rendered as:
这个解析是:
23.10 Document views (PDF/Excel)
23.10.1 Introduction
介绍
Returning an HTML page isn’t always the best way for the user to view the model output, and Spring makes it simple to generate a PDF document or an Excel spreadsheet dynamically from the model data. The document is the view and will be streamed from the server with the correct content type to (hopefully) enable the client PC to run their spreadsheet or PDF viewer application in response.
返回一个html页面不是最好的方式对于用户的视图模型输出,并且spring使得他更加简单对于生成PDF文档或一个Excel的动态sheet对于模型数据。文档是一个视图并且将直接来自服务器使用的正确的内容类型用于允许客户端PC来执行他们的spreadsheet或PDF视图应用。
In order to use Excel views, you need to add the 'poi' library to your classpath, and for PDF generation, the iText library.
为了使用Excel视图,你需要添加poi库到你的classpath中,并且对于PDF生成你需要iText库。
23.10.2 Configuration and setup
配置和设置
Document based views are handled in an almost identical fashion to XSLT views, and the following sections build upon the previous one by demonstrating how the same controller used in the XSLT example is invoked to render the same model as both a PDF document and an Excel spreadsheet (which can also be viewed or manipulated in Open Office).
文档基于视图被处理以确定的形式对于XSLT视图,并且遵循章节构建前面的内容通过证明如何相同的控制器使用在XSLT例子中被调用用于解析相同的模型作为一个PDF文档和Excel的spreadsheet(可以作为视图或管理在Open Office中)。
Document view definitions
文档视图定义
First, let’s amend the views.properties file (or xml equivalent) and add a simple view definition for both document types. The entire file now looks like this with the XSLT view shown from earlier:
首先,让我们修改views.properties文件(或xml文件)并且添加一个简单的视图定义对于文档类型。全部的文件使用XSLT视图展现在前面:
home.(class)=xslt.HomePage
home.stylesheetLocation=/WEB-INF/xsl/home.xslt
home.root=words
xl.(class)=excel.HomePage
pdf.(class)=pdf.HomePage
If you want to start with a template spreadsheet or a fillable PDF form to add your model data to, specify the location as the 'url' property in the view definition
如果你希望开始一个模板spreadsheet或一个可填充的PDF模板用于添加你的模型数据,定义'url'属性中的位置在视图的定义中。
Controller code
控制器代码
The controller code we’ll use remains exactly the same from the XSLT example earlier other than to change the name of the view to use. Of course, you could be clever and have this selected based on a URL parameter or some other logic - proof that Spring really is very good at decoupling the views from the controllers!
我们将使用的控制器代码明确保留了相同的来自之前的XSLT的例子用于改变我们使用的视图。当然,你可以聪明并且有选择的基于URL参数或一些其他的逻辑————证明spring真的是一个很好的用于处理来自控制器的视图。
Subclassing for Excel views
用于Excel视图的子类
Exactly as we did for the XSLT example, we’ll subclass suitable abstract classes in order to implement custom behavior in generating our output documents. For Excel, this involves writing a subclass of org.springframework.web.servlet.view.document.AbstractExcelView (for Excel files generated by POI) or org.springframework.web.servlet.view.document.AbstractJExcelView (for JExcelApi-generated Excel files) and implementing the buildExcelDocument() method.
恰好我们对于XSLT模板所做的,我们的子类适用于抽象类用于实现自定义的行为对于生成我们的输出文档。对于Excel,这调用了org.springframework.web.servlet.view.document.AbstractExcelView子类的书写(对于POI生成的Excel文件)或org.springframework.web.servlet.view.document.AbstractJExcelView(用于JExcelApi生成的Excel文件)并且实现buildExcelDocument方法。
Here’s the complete listing for our POI Excel view which displays the word list from the model map in consecutive rows of the first column of a new spreadsheet:
这里是一个全部的列表对于我们的POI的Excel视图来展示单词列表来自模型map在一个新的spreadsheet列中的连续的行:
package excel;
// imports omitted for brevity
public class HomePage extends AbstractExcelView {
protected void buildExcelDocument(Map model, HSSFWorkbook wb, HttpServletRequest req,
HttpServletResponse resp) throws Exception {
HSSFSheet sheet;
HSSFRow sheetRow;
HSSFCell cell;
// Go to the first sheet
// getSheetAt: only if wb is created from an existing document
// sheet = wb.getSheetAt(0);
sheet = wb.createSheet("Spring");
sheet.setDefaultColumnWidth((short) 12);
// write a text at A1
cell = getCell(sheet, 0, 0);
setText(cell, "Spring-Excel test");
List words = (List) model.get("wordList");
for (int i=0; i < words.size(); i++) {
cell = getCell(sheet, 2+i, 0);
setText(cell, (String) words.get(i));
}
}
}
And the following is a view generating the same Excel file, now using JExcelApi:
并且下面是一个视图生成相同的Excel文件,现在使用JExcelApi:
package excel;
// imports omitted for brevity
public class HomePage extends AbstractJExcelView {
protected void buildExcelDocument(Map model, WritableWorkbook wb,
HttpServletRequest request, HttpServletResponse response) throws Exception {
WritableSheet sheet = wb.createSheet("Spring", 0);
sheet.addCell(new Label(0, 0, "Spring-Excel test"));
List words = (List) model.get("wordList");
for (int i = 0; i < words.size(); i++) {
sheet.addCell(new Label(2+i, 0, (String) words.get(i)));
}
}
}
Note the differences between the APIs. We’ve found that the JExcelApi is somewhat more intuitive, and furthermore, JExcelApi has slightly better image-handling capabilities. There have been memory problems with large Excel files when using JExcelApi however.
注意API之间的不同。我们发现JExcelApi是更加直觉的,而且JExcelApi有轻量及的更好的图像处理能力。他们有内存问题对于大的Excel文件当使用了JExcelApi。
If you now amend the controller such that it returns xl as the name of the view ( return new ModelAndView("xl", map);) and run your application again, you should find that the Excel spreadsheet is created and downloaded automatically when you request the same page as before.
如果你现在修改控制因此他将返回xl作为视图名( return new ModelAndView("xl", map);)并且再次执行你的应用,你应当发现Excel的spreadsheet被创建并且自动下载当你请求相同的页面时。
Subclassing for PDF views
用于PDF视图的子类
The PDF version of the word list is even simpler. This time, the class extends org.springframework.web.servlet.view.document.AbstractPdfView and implements the buildPdfDocument() method as follows:
单词列表的PDF的版本是更加简单的。这一次,类继承了org.springframework.web.servlet.view.document.AbstractPdfView并且实现了buildPdfDocument()方法如下:
package pdf;
// imports omitted for brevity
public class PDFPage extends AbstractPdfView {
protected void buildPdfDocument(Map model, Document doc, PdfWriter writer,
HttpServletRequest req, HttpServletResponse resp) throws Exception {
List words = (List) model.get("wordList");
for (int i=0; i doc.add( new Paragraph((String) words.get(i))); } } } Once again, amend the controller to return the pdf view with return new ModelAndView("pdf", map);, and reload the URL in your application. This time a PDF document should appear listing each of the words in the model map. 再一次,为了控制返回pdf视图使用return new ModelAndView("pdf", map);,并且重新加载你应用中的URL。这一次一个PDF文档应当应用列表对于单词的每一个在model的map中。 23.11 JasperReports JasperReports ( http://jasperreports.sourceforge.net) is a powerful open-source reporting engine that supports the creation of report designs using an easily understood XML file format. JasperReports is capable of rendering reports in four different formats: CSV, Excel, HTML and PDF. JasperReports ( http://jasperreports.sourceforge.net)是一个有力的开源的引擎用于支持报告设计的创建使用一个简单的XML文件格式。JasperReports可以解析报告以四种不同的格式:CSV、Excel、HTML和PDF。 23.11.1 Dependencies 依赖 Your application will need to include the latest release of JasperReports, which at the time of writing was 0.6.1. JasperReports itself depends on the following projects: 你的应用将需要包括最新版本的JasperReports,这个版本在出版时应该是0.6.1,JasperReports本身依赖于下面的项目: BeanShell Commons BeanUtils Commons Collections Commons Digester Commons Logging iText POI JasperReports also requires a JAXP compliant XML parser. JasperReports也需要一个JAXP编译xml解析器。 23.11.2 Configuration 配置 To configure JasperReports views in your Spring container configuration you need to define a ViewResolver to map view names to the appropriate view class depending on which format you want your report rendered in. 配置JasperReports视图在你的spring容器配置中你需要定义一个ViewResolver对于map视图用于适当的视图类依赖于格式化你的视图解析他。 Configuring the ViewResolver 配置ViewResolver Typically, you will use the ResourceBundleViewResolver to map view names to view classes and files in a properties file. 通常,你需要使用ResourceBundleViewResolver作为map视图名对于视图类并且文件在属性文件中。 Here we’ve configured an instance of the ResourceBundleViewResolver class that will look for view mappings in the resource bundle with base name views. (The content of this file is described in the next section.) 这里我们配置了一个ResourceBundleViewResolver类的实例将查找视图匹配在资源绑定中对于基本命名视图。(这个文件的内容描述在后面的章节中) Configuring the Views 配置视图 The Spring Framework contains five different View implementations for JasperReports, four of which correspond to one of the four output formats supported by JasperReports, and one that allows for the format to be determined at runtime: spring框架包括五个视图实现对于JasperReports,他们中的四个相对于四种之一的格式通过JasperReports来支持,并且其中一个允许格式化定义在运行时: Table 23.2. JasperReports View classes JasperReports视图类 Class Name 类名 Render Format 解析格式 JasperReportsCsvView CSV JasperReportsHtmlView HTML JasperReportsPdfView PDF JasperReportsXlsView Microsoft Excel JasperReportsMultiFormatView The view is decided upon at runtime Mapping one of these classes to a view name and a report file is a matter of adding the appropriate entries in the resource bundle configured in the previous section as shown here: 匹配这些类中的一个对于视图名和一个报告文件是一个问题关于添加适当的实体在资源绑定中配置在之前章节展示过。 simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper Here you can see that the view with name simpleReport is mapped to the JasperReportsPdfView class, causing the output of this report to be rendered in PDF format. The url property of the view is set to the location of the underlying report file. 这里你可以看到使用simpleReport名字的视图被匹配到JasperReportsPdfView类,由于这个报告的输出对于解析以PDF的格式。这个视图的url属性将被设置为底层报告文件的路径。 About Report Files 关于报告文件 JasperReports has two distinct types of report file: the design file, which has a .jrxml extension, and the compiled report file, which has a .jasper extension. Typically, you use the JasperReports Ant task to compile your .jrxml design file into a .jasper file before deploying it into your application. With the Spring Framework you can map either of these files to your report file and the framework will take care of compiling the .jrxml file on the fly for you. You should note that after a .jrxml file is compiled by the Spring Framework, the compiled report is cached for the lifetime of the application. Thus, to make changes to the file you will need to restart your application. JasperReports有两个明显类型的报告文件:设计文件,以.jrxml为后缀并且是编译报告文件,以.jasper为后缀。通常,你使用JasperReports的Ant任务来编译你的.jrxml设计文件为.jasper文件在部署到你的应用之前。使用spring的框架你可以匹配这些文件中的一个对于你的报告文件并且框架将处理.jrxml文件。你应当注意到在.jrxml文件被spring框架处理之后,表一报告被缓存用于应用的生命周期。因此,保证改变文件你将需要重启你的应用。 Using JasperReportsMultiFormatView 使用JasperReportsMultiFormatView The JasperReportsMultiFormatView allows for the report format to be specified at runtime. The actual rendering of the report is delegated to one of the other JasperReports view classes - the JasperReportsMultiFormatView class simply adds a wrapper layer that allows for the exact implementation to be specified at runtime. JasperReportsMultiFormatView允许报告格式化为指定形式在运行时。实际解析报告是委托给其中一个JasperReports视图类————JasperReportsMultiFormatView类简单的添加了一个中间层允许正确的实现指定在运行时。 The JasperReportsMultiFormatView class introduces two concepts: the format key and the discriminator key. The JasperReportsMultiFormatView class uses the mapping key to look up the actual view implementation class, and it uses the format key to lookup up the mapping key. From a coding perspective you add an entry to your model with the format key as the key and the mapping key as the value, for example: JasperReportsMultiFormatView类引入了两个概念:格式化key和描述key。JasperReportsMultiFormatView类使用了匹配key来查找实际的视图实现类,并且他使用格式化key来查找匹配的key。来自一个编码视图你添加一个实体到你的模型使用了格式化key因此key和匹配key作为值,例如: public ModelAndView handleSimpleReportMulti(HttpServletRequest request, HttpServletResponse response) throws Exception { String uri = request.getRequestURI(); String format = uri.substring(uri.lastIndexOf(".") + 1); Map model = getModel(); model.put("format", format); return new ModelAndView("simpleReportMulti", model); } In this example, the mapping key is determined from the extension of the request URI and is added to the model under the default format key: format. If you wish to use a different format key then you can configure this using the formatKey property of the JasperReportsMultiFormatView class. 在这个例子中,匹配key是来自额外的请求URI并且是添加到model中在默认的格式化key。如果你希望使用一个不同的key,你可以配置他使用formatKey属性来自JasperReportsMultiFormatView类。 By default the following mapping key mappings are configured in JasperReportsMultiFormatView: 默认的下面的匹配key匹配被配置在JasperReportsMultiFormatView中: Table 23.3. JasperReportsMultiFormatView Default Mapping Key Mappings JasperReportsMultiFormatView默认视图匹配key Mapping Key View Class csv JasperReportsCsvView html JasperReportsHtmlView pdf JasperReportsPdfView xls JasperReportsXlsView So in the example above a request to URI /foo/myReport.pdf would be mapped to the JasperReportsPdfView class. You can override the mapping key to view class mappings using the formatMappings property of JasperReportsMultiFormatView. 因此上面的例子关于请求的URI /foo/myReport.pdf将匹配JasperReportsPdfView类。你可以覆盖匹配的key对于视图类匹配使用JasperReportsMultiFormatView中的formatMappings属性。 23.11.3 Populating the ModelAndView In order to render your report correctly in the format you have chosen, you must supply Spring with all of the data needed to populate your report. For JasperReports this means you must pass in all report parameters along with the report datasource. Report parameters are simple name/value pairs and can be added to the Map for your model as you would add any name/value pair. 为了正确解析你的报告以你选择的格式,你必须提供spring你所需要的所有的数据。对于JasperReports这意味着你必须传递所有的报告参数包括报告的数据源。报告参数是简单的键值对并且可以添加到模型的map中使得你可以添加任何键值对。 When adding the datasource to the model you have two approaches to choose from. The first approach is to add an instance of JRDataSource or a Collection type to the model Map under any arbitrary key. Spring will then locate this object in the model and treat it as the report datasource. For example, you may populate your model like so: 当添加数据源到你的模型你有两种方法来选择。第一种方式是添加一个JRDataSource实例或一个模型匹配的集合在任何key中。spring将定位模型中的object并且将他们作为报告数据源来处理。例如,你可以定义你的模型如下: private Map getModel() { Map model = new HashMap(); Collection beanData = getBeanData(); model.put("myBeanData", beanData); return model; } The second approach is to add the instance of JRDataSource or Collection under a specific key and then configure this key using the reportDataKey property of the view class. In both cases Spring will wrap instances of Collection in a JRBeanCollectionDataSource instance. For example: 第二种方式是添加JRDataSource的实例或指定key的集合和配置这个key使用视图类中的reportDataKey属性。这几种使得spring将包括集合实例到一个JRBeanCollectionDataSource实例中。例如: private Map getModel() { Map model = new HashMap(); Collection beanData = getBeanData(); Collection someData = getSomeData(); model.put("myBeanData", beanData); model.put("someData", someData); return model; } Here you can see that two Collection instances are being added to the model. To ensure that the correct one is used, we simply modify our view configuration as appropriate: 这是你可以看到的两种集合实例被添加到模型中。为了保证正确的使用,我们简单的修改我们的视图配置根据需要: simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper simpleReport.reportDataKey=myBeanData Be aware that when using the first approach, Spring will use the first instance of JRDataSource or Collection that it encounters. If you need to place multiple instances of JRDataSource or Collection into the model you need to use the second approach. 注意当你使用一种方式,spring将使用JRDataSource的实例或集合。如果你需要多个JRDataSource实例或集合到模型中你需要使用第二种方法。 23.11.4 Working with Sub-Reports 使用子报告 JasperReports provides support for embedded sub-reports within your master report files. There are a wide variety of mechanisms for including sub-reports in your report files. The easiest way is to hard code the report path and the SQL query for the sub report into your design files. The drawback of this approach is obvious: the values are hard-coded into your report files reducing reusability and making it harder to modify and update report designs. To overcome this you can configure sub-reports declaratively, and you can include additional data for these sub-reports directly from your controllers. JasperReports提供了支持对于内置的子报告在你的主报告文件中。这是一个通用的机制对于包含子报告到你的报告文件中。最简单的方式对于复杂的代码是报告路径和sql查询对于子报告到你设计的文件中。这种方式的缺点也是很明显的:值被硬编码到你的报告文件中减少了可重用性使得他更加难以被修改和更新你的报告设计。为了克服这个你可以明确配置子报告,并且你可以包括额外的数据对于这些子报告来自你的控制器。 Configuring Sub-Report Files 配置子报告文件 To control which sub-report files are included in a master report using Spring, your report file must be configured to accept sub-reports from an external source. To do this you declare a parameter in your report file like so: 为了控制哪些子报告文件被包含在主报告中通过使用spring,你的报告文件必须被配置来接收子报告来自外部的资源。为了这么做你需要在你的报告文件中定义一个参数如下: Then, you define your sub-report to use this sub-report parameter: 这样,你定义了你的子报告使用这个子报告参数: height="20" isRemoveLineWhenBlank="true" backcolor="#ffcc99"/> This defines a master report file that expects the sub-report to be passed in as an instance of net.sf.jasperreports.engine.JasperReports under the parameter ProductsSubReport. When configuring your Jasper view class, you can instruct Spring to load a report file and pass it into the JasperReports engine as a sub-report using the subReportUrls property: 这定义了一个主报告文件期望子报告被传递到net.sf.jasperreports.engine.JasperReports的实例在参数ProductsSubReport下。当配置你的Jasper视图类,你可以指导spring来加载一个报告文件并且传递他到JasperReports引擎作为一个子报告使用subReportUrls属性。 Here, the key of the Map corresponds to the name of the sub-report parameter in the report design file, and the entry is the URL of the report file. Spring will load this report file, compiling it if necessary, and pass it into the JasperReports engine under the given key. 这里map的key匹配子报告参数的名字在报告的设计文件中,并且整体是报告文件的URL。spring将加载这个报告文件,根据需要编译他并且将其传递给JasperReports引擎根据给定的key值。 Configuring Sub-Report Data Sources 配置子报告数据源 This step is entirely optional when using Spring to configure your sub-reports. If you wish, you can still configure the data source for your sub-reports using static queries. However, if you want Spring to convert data returned in your ModelAndView into instances of JRDataSource then you need to specify which of the parameters in your ModelAndView Spring should convert. To do this, configure the list of parameter names using the subReportDataKeys property of your chosen view class: 这一步是整体可选的当你使用spring来配置你的子报告时。如果你希望,你依然可以配置数据源为了你的子报告使用静态查询。然而,如果你希望spring来转换ModelAndView中的返回到JRDataSource的实例中,你需要指定spring应当转换的ModelAndView中的参数。为了实现这个目的,配置参数列表名使用subReportDataKeys属性为你选择的视图类: Here, the key you supply must correspond to both the key used in your ModelAndView and the key used in your report design file. 这里,你应用的key必须匹配你在ModelAndView中使用的key并且key使用在你的报告设计文件中。 23.11.5 Configuring Exporter Parameters 配置导出参数 If you have special requirements for exporter configuration — perhaps you want a specific page size for your PDF report — you can configure these exporter parameters declaratively in your Spring configuration file using the exporterParameters property of the view class. The exporterParameters property is typed as a Map. In your configuration the key of an entry should be the fully-qualified name of a static field that contains the exporter parameter definition, and the value of an entry should be the value you want to assign to the parameter. An example of this is shown below: 如果你有指定的需要对于导出配置————或许你希望指定页大小对于你的PDF报告————你可以直接配置这些导出参数在你的spring的配置文件中使用视图类的exporterParameters属性。exporterParameters属性是一个map类型。在你的配置中实体的key应当是静态域的全限定名包含导出参数定义并且实体的值应当是你希望指定的内容。下面是一个例子: