FreeMarker
Apache FreeMarker (英語) は、HTML からメールなどへのあらゆる種類のテキスト出力を生成するためのテンプレートエンジンです。Spring Framework には、Spring MVC と FreeMarker テンプレートを使用するための組み込みの統合機能があります。
構成を表示
次の例は、FreeMarker をビューテクノロジーとして設定する方法を示しています。
Java
Kotlin
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
}
// Configure FreeMarker...
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("/WEB-INF/freemarker");
return configurer;
}
}
@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
}
// Configure FreeMarker...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("/WEB-INF/freemarker")
}
}
次の例は、XML で同じものを構成する方法を示しています。
<mvc:annotation-driven/>
<mvc:view-resolvers>
<mvc:freemarker/>
</mvc:view-resolvers>
<!-- Configure FreeMarker... -->
<mvc:freemarker-configurer>
<mvc:template-loader-path location="/WEB-INF/freemarker"/>
</mvc:freemarker-configurer>
または、次の例に示すように、すべてのプロパティを完全に制御するために FreeMarkerConfigurer
Bean を宣言することもできます。
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
</bean>
テンプレートは、前の例で示した FreeMarkerConfigurer
で指定されたディレクトリに保存する必要があります。上記の構成で、コントローラーが welcome
のビュー名を返す場合、リゾルバーは /WEB-INF/freemarker/welcome.ftl
テンプレートを探します。
FreeMarker の設定
FreeMarkerConfigurer
Bean で適切な Bean プロパティを設定することにより、FreeMarker の「設定」と "SharedVariables" を FreeMarker Configuration
オブジェクト(Spring によって管理される)に直接渡すことができます。freemarkerSettings
プロパティには java.util.Properties
オブジェクトが必要で、freemarkerVariables
プロパティには java.util.Map
が必要です。次の例は、FreeMarkerConfigurer
の使用方法を示しています。
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>
Configuration
オブジェクトに適用される設定と変数の詳細については、FreeMarker のドキュメントを参照してください。
フォーム処理
Spring は、特に <spring:bind/>
要素を含む JSP で使用するタグライブラリを提供します。この要素により、フォームは主にフォームバッキングオブジェクトの値を表示し、Web またはビジネス層の Validator
からの検証の失敗の結果を表示できます。Spring は、FreeMarker と同じ機能をサポートしていますが、フォーム入力要素自体を生成するための追加の便利なマクロがあります。
バインドマクロ
マクロの標準セットは、FreeMarker の spring-webmvc.jar
ファイル内で維持されるため、適切に構成されたアプリケーションで常に使用可能です。
Spring テンプレートライブラリで定義されているマクロの一部は内部(プライベート)と見なされますが、マクロ定義にはそのようなスコープは存在せず、呼び出し元のコードとユーザーテンプレートにすべてのマクロが表示されます。次のセクションでは、テンプレート内から直接呼び出す必要があるマクロのみに焦点を当てます。マクロコードを直接表示する場合、ファイルは spring.ftl
と呼ばれ、org.springframework.web.servlet.view.freemarker
パッケージに含まれています。
簡単なバインド
Spring MVC コントローラーのフォームビューとして機能する FreeMarker テンプレートに基づく HTML フォームでは、次の例のようなコードを使用して、フィールド値にバインドし、JSP の同等の方法と同様の方法で各入力フィールドのエラーメッセージを表示できます。次の例は、personForm
ビューを示しています。
<!-- FreeMarker macros have to be imported into a namespace.
We strongly recommend sticking to 'spring'. -->
<#import "/spring.ftl" as spring/>
<html>
...
<form action="" method="POST">
Name:
<@spring.bind "personForm.name"/>
<input type="text"
name="${spring.status.expression}"
value="${spring.status.value?html}"/><br />
<#list spring.status.errorMessages as error> <b>${error}</b> <br /> </#list>
<br />
...
<input type="submit" value="submit"/>
</form>
...
</html>
<@spring.bind>
には "path" 引数が必要です。この引数は、コマンドオブジェクトの名前(コントローラー構成で変更しない限り "command" です)の後にピリオドとコマンドオブジェクトのフィールド名が続きます。バインドしたい。command.address.street
などのネストされたフィールドを使用することもできます。bind
マクロは、web.xml
の ServletContext
パラメーター defaultHtmlEscape
で指定されたデフォルトの HTML エスケープ動作を想定しています。
<@spring.bindEscaped>
と呼ばれるマクロの代替形式は、ステータスエラーメッセージまたは値で HTML エスケープを使用するかどうかを明示的に指定する 2 番目の引数を取ります。必要に応じて、true
または false
に設定できます。追加のフォーム処理マクロにより、HTML エスケープの使用が簡単になります。これらのマクロは可能な限り使用する必要があります。それらについては次のセクションで説明します。
入力マクロ
FreeMarker 用の追加の便利なマクロは、バインディングとフォーム生成(検証エラー表示を含む)の両方を簡素化します。これらのマクロを使用してフォーム入力フィールドを生成する必要はありません。これらを単純な HTML と組み合わせたり、以前に強調した Spring バインドマクロへの直接呼び出しを組み合わせたりすることができます。
次の使用可能なマクロの表は、FreeMarker テンプレート(FTL)定義とそれぞれが取るパラメーターリストを示しています。
マクロ | FTL 定義 |
---|---|
|
<@spring.message code/> |
|
<@spring.messageText code, text/> |
|
<@spring.url relativeUrl/> |
|
<@spring.formInput path, attributes, fieldType/> |
|
<@spring.formHiddenInput path, attributes/> |
|
<@spring.formPasswordInput path, attributes/> |
|
<@spring.formTextarea path, attributes/> |
|
<@spring.formSingleSelect path, options, attributes/> |
|
<@spring.formMultiSelect path, options, attributes/> |
|
<@spring.formRadioButtons path, options separator, attributes/> |
|
<@spring.formCheckboxes path, options, separator, attributes/> |
|
<@spring.formCheckbox path, attributes/> |
|
<@spring.showErrors separator, classOrStyle/> |
In FreeMarker templates, formHiddenInput and formPasswordInput are not actually
required, as you can use the normal formInput macro, specifying hidden or password
as the value for the fieldType parameter.
|
The parameters to any of the above macros have consistent meanings:
-
path
: The name of the field to bind to (for example, "command.name") -
options
: AMap
of all the available values that can be selected from in the input field. The keys to the map represent the values that are 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. You can use anyMap
implementation, depending on required behavior. For strictly sorted maps, you can use aSortedMap
(such as aTreeMap
) with a suitableComparator
and, for arbitrary Maps that should return values in insertion order, use aLinkedHashMap
or aLinkedMap
fromcommons-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 (such as<br>
). -
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 atextarea
field, you may supply attributes (such as 'rows="5" cols="60"'), or you could pass style information such as 'style="border:1px solid silver"'. -
classOrStyle
: For theshowErrors
macro, the name of the CSS class that thespan
element that wraps each error uses. If no information is supplied (or the value is empty), the errors are wrapped in<b></b>
tags.
The following sections outline examples of the macros.
Input Fields
The formInput
macro takes the path
parameter (command.name
) and an additional attributes
parameter (which is empty in the upcoming example). 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 does not need to pass the
path parameter again — it operates on the field for which a binding was last created.
The showErrors
macro takes a separator parameter (the characters that are 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 can specify default
values for the attributes parameter. The following example shows how to use the formInput
and showErrors
macros:
<@spring.formInput "command.name"/>
<@spring.showErrors "<br>"/>
The next example shows the output 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.
The generated HTML resembles the following example:
Name:
<input type="text" name="name" value="">
<br>
<b>required</b>
<br>
<br>
The formTextarea
macro works the same way as the formInput
macro and accepts the same
parameter list. Commonly, the second parameter (attributes
) is used to pass style
information or rows
and cols
attributes for the textarea
.
Selection Fields
You can use four selection field macros to generate common UI value selection inputs in your HTML forms:
-
formSingleSelect
formMultiSelect
formRadioButtons
formCheckboxes
4 つのマクロはそれぞれ、フォームフィールドの値とその値に対応するラベルを含む Map
のオプションを受け入れます。値とラベルは同じにすることができます。
次の例は、FTL のラジオボタンです。フォームバックオブジェクトはこのフィールドにデフォルト値「ロンドン」を指定するため、検証は必要ありません。フォームがレンダリングされると、選択する都市のリスト全体が、モデル内の参照データとして "cityMap" という名前で提供されます。次のリストに例を示します。
...
Town:
<@spring.formRadioButtons "command.address.town", cityMap, ""/><br><br>
上記のリストは、cityMap
の各値に 1 つずつラジオボタンの行をレンダリングし、""
のセパレータを使用しています。追加の属性は提供されません(マクロの最後のパラメーターが欠落しています)。cityMap
は、マップ内の各キーと値のペアに同じ String
を使用します。マップのキーは、フォームが POST
リクエストパラメーターとして実際に送信するものです。マップ値は、ユーザーに表示されるラベルです。前の例では、3 つのよく知られた都市のリストと、フォームバッキングオブジェクトのデフォルト値を指定すると、HTML は次のようになります。
Town:
<input type="radio" name="address.town" value="London">London</input>
<input type="radio" name="address.town" value="Paris" checked="checked">Paris</input>
<input type="radio" name="address.town" value="New York">New York</input>
アプリケーションが(たとえば)内部コードで都市を処理することを期待している場合、次の例に示すように、適切なキーを使用してコードのマップを作成できます。
Java
Kotlin
protected Map<String, ?> referenceData(HttpServletRequest request) throws Exception {
Map<String, String> cityMap = new LinkedHashMap<>();
cityMap.put("LDN", "London");
cityMap.put("PRS", "Paris");
cityMap.put("NYC", "New York");
Map<String, Object> model = new HashMap<>();
model.put("cityMap", cityMap);
return model;
}
protected fun referenceData(request: HttpServletRequest): Map<String, *> {
val cityMap = linkedMapOf(
"LDN" to "London",
"PRS" to "Paris",
"NYC" to "New York"
)
return hashMapOf("cityMap" to cityMap)
}
コードは、ラジオの値が関連するコードである出力を生成しますが、ユーザーには、次のように、よりユーザーフレンドリーな都市名が表示されます。
Town:
<input type="radio" name="address.town" value="LDN">London</input>
<input type="radio" name="address.town" value="PRS" checked="checked">Paris</input>
<input type="radio" name="address.town" value="NYC">New York</input>
HTML エスケープ
前述のフォームマクロをデフォルトで使用すると、HTML 4.01 に準拠し、Spring のバインドサポートで使用される web.xml
ファイルで定義された HTML エスケープのデフォルト値を使用する HTML 要素が生成されます。要素を XHTML 準拠にするか、デフォルトの HTML エスケープ値をオーバーライドするには、テンプレート(またはテンプレートに表示されるモデル)で 2 つの変数を指定できます。テンプレートで指定することの利点は、後でテンプレート処理で異なる値に変更して、フォームの異なるフィールドに異なる動作を提供できることです。
タグの XHTML 準拠に切り替えるには、次の例に示すように、xhtmlCompliant
という名前のモデルまたはコンテキスト変数に true
の値を指定します。
<#-- for FreeMarker -->
<#assign xhtmlCompliant = true>
このディレクティブを処理した後、Spring マクロによって生成された要素はすべて XHTML 準拠になりました。
同様に、次の例に示すように、フィールドごとに HTML エスケープを指定できます。
<#-- until this point, default HTML escaping is used -->
<#assign htmlEscape = true>
<#-- 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 -->