1. 概要

このチュートリアルでは、Handlebars。javaライブラリを調べて、テンプレートを簡単に管理できるようにします。

2. Mavenの依存関係

ハンドルバーの依存関係を追加することから始めましょう:

<dependency>
    <groupId>com.github.jknack</groupId>
    <artifactId>handlebars</artifactId>
    <version>4.1.2</version>
</dependency>

3. シンプルなテンプレート

ハンドルバーテンプレートは、任意の種類のテキストファイルにすることができます。 {{name}}や{{#eachpeople}}などのタグで構成されています。

次に、 Mapや他のObject。などのコンテキストオブジェクトを渡して、これらのタグに入力します。

3.1. thisを使用する

単一の文字列値をテンプレートに渡すために、任意のオブジェクトをコンテキストとして使用できます。 {{も使用する必要がありますこれ}}t テンプレートのag。

次に、Handlebarsはコンテキストオブジェクトで toString メソッドを呼び出し、タグを次の結果に置き換えます。

@Test
public void whenThereIsNoTemplateFile_ThenCompilesInline() throws IOException {
    Handlebars handlebars = new Handlebars();
    Template template = handlebars.compileInline("Hi {{this}}!");
    
    String templateString = template.apply("Baeldung");
    
    assertThat(templateString).isEqualTo("Hi Baeldung!");
}

上記の例では、最初に Handlebarsのインスタンス、APIエントリポイントを作成します。

次に、そのインスタンスにテンプレートを提供します。 ここでは、テンプレートをインラインで渡しますが、すぐにいくつかのより強力な方法が表示されます。

最後に、コンパイルされたテンプレートにコンテキストを与えます。 {{this}} は、 toString、を呼び出すことになります。そのため、「HiBaeldung!」が表示されます。

3.2. Mapをコンテキストオブジェクトとして渡す

コンテキストにStringを送信する方法を見たところで、Mapを試してみましょう。

@Test
public void whenParameterMapIsSupplied_thenDisplays() throws IOException {
    Handlebars handlebars = new Handlebars();
    Template template = handlebars.compileInline("Hi {{name}}!");
    Map<String, String> parameterMap = new HashMap<>();
    parameterMap.put("name", "Baeldung");
    
    String templateString = template.apply(parameterMap);
    
    assertThat(templateString).isEqualTo("Hi Baeldung!");
}

前の例と同様に、テンプレートをコンパイルしてからコンテキストオブジェクトを渡しますが、今回はMapとして渡します。

また、{{this}}の代わりに{{name}}を使用していることに注意してください。 これは、マップにキー、名前が含まれている必要があることを意味します

3.3. カスタムオブジェクトをコンテキストオブジェクトとして渡す

テンプレートにカスタムオブジェクトを渡すこともできます。

public class Person {
    private String name;
    private boolean busy;
    private Address address = new Address();
    private List<Person> friends = new ArrayList<>();
 
    public static class Address {
        private String street;       
    }
}

Person クラスを使用すると、前の例と同じ結果が得られます。

@Test
public void whenParameterObjectIsSupplied_ThenDisplays() throws IOException {
    Handlebars handlebars = new Handlebars();
    Template template = handlebars.compileInline("Hi {{name}}!");
    Person person = new Person();
    person.setName("Baeldung");
    
    String templateString = template.apply(person);
    
    assertThat(templateString).isEqualTo("Hi Baeldung!");
}

{{名前}} テンプレートで私たちにドリルダウンしますオブジェクトとの値を取得します名前分野

4. テンプレートローダー

これまで、コード内で定義されたテンプレートを使用してきました。 ただし、これが唯一のオプションではありません。 テキストファイルからテンプレートを読み取ることもできます。

Handlebars.javaは、クラスパス、ファイルシステム、またはサーブレットコンテキストからテンプレートを読み取るための特別なサポートを提供します。 デフォルトでは、Handlebarsはクラスパスをスキャンして、指定されたテンプレートをロードします:

@Test
public void whenNoLoaderIsGiven_ThenSearchesClasspath() throws IOException {
    Handlebars handlebars = new Handlebars();
    Template template = handlebars.compile("greeting");
    Person person = getPerson("Baeldung");
    
    String templateString = template.apply(person);
    
    assertThat(templateString).isEqualTo("Hi Baeldung!");
}

つまり、compileInlineではなくcompileを呼び出したため、これはハンドルバーがクラスパスで/greeting.hbsを探すためのヒントです。

ただし、ClassPathTemplateLoaderを使用してこれらのプロパティを構成することもできます。

@Test
public void whenClasspathTemplateLoaderIsGiven_ThenSearchesClasspathWithPrefixSuffix() throws IOException {
    TemplateLoader loader = new ClassPathTemplateLoader("/handlebars", ".html");
    Handlebars handlebars = new Handlebars(loader);
    Template template = handlebars.compile("greeting");
    // ... same as before
}

この場合、クラスパスで/handlebars/greeting.htmlを探すようにHandlebarsに指示しています。

最後に、複数のTemplateLoaderインスタンスをチェーンできます。

@Test
public void whenMultipleLoadersAreGiven_ThenSearchesSequentially() throws IOException {
    TemplateLoader firstLoader = new ClassPathTemplateLoader("/handlebars", ".html");
    TemplateLoader secondLoader = new ClassPathTemplateLoader("/templates", ".html");
    Handlebars handlebars = new Handlebars().with(firstLoader, secondLoader);
    // ... same as before
}

つまり、ここには2つのローダーがあります。つまり、ハンドルバーは2つのディレクトリでgreetingテンプレートを検索します。

5. ビルトインヘルパー

組み込みのヘルパーは、テンプレートを作成するときに追加の機能を提供します。

5.1. withヘルパー

withヘルパーは現在のコンテキストを変更します

{{#with address}}
<h4>I live in {{street}}</h4>
{{/with}}

サンプルテンプレートでは、 {{#with address}} タグがセクションを開始し、 {{/with}}タグがセクションを終了します

基本的に、現在のコンテキストオブジェクト(たとえばperson)をドリルダウンし、withセクションのローカルコンテキストとしてアドレスを設定します。その後、このセクションのすべてのフィールド参照は、 person.address

したがって、{{street}}タグはperson.address.streetの値を保持します。

@Test
public void whenUsedWith_ThenContextChanges() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    Template template = handlebars.compile("with");
    Person person = getPerson("Baeldung");
    person.getAddress().setStreet("World");
    
    String templateString = template.apply(person);
    
    assertThat(templateString).contains("<h4>I live in World</h4>");
}

テンプレートをコンパイルし、Personインスタンスをコンテキストオブジェクトとして割り当てています。 PersonクラスにはAddressフィールドがあることに注意してください。 これは、withヘルパーに提供しているフィールドです。

コンテキストオブジェクトに1つのレベルを追加しましたが、コンテキストオブジェクトにネストされたレベルが複数ある場合は、さらに深く掘り下げることはまったく問題ありません。

5.2. ヘルパー

各ヘルパーはコレクションを繰り返し処理します

{{#each friends}}
<span>{{name}} is my friend.</span>
{{/each}}

{{#eachfriends}}タグと{//each}} タグを使用して反復セクションを開始および終了した結果、ハンドルバーはfriendsを反復処理します。 ]コンテキストオブジェクトのフィールド。

@Test
public void whenUsedEach_ThenIterates() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    Template template = handlebars.compile("each");
    Person person = getPerson("Baeldung");
    Person friend1 = getPerson("Java");
    Person friend2 = getPerson("Spring");
    person.getFriends().add(friend1);
    person.getFriends().add(friend2);
    
    String templateString = template.apply(person);
    
    assertThat(templateString)
      .contains("<span>Java is my friend.</span>", "<span>Spring is my friend.</span>");
}

この例では、2つのPersonインスタンスをコンテキストオブジェクトのfriendsフィールドに割り当てています。 したがって、Handlebarsは最終出力でHTML部分を2回繰り返します。

5.3. ifヘルパー

最後に、ifヘルパーが条件付きレンダリングを提供します

{{#if busy}}
<h4>{{name}} is busy.</h4>
{{else}}
<h4>{{name}} is not busy.</h4>
{{/if}}

テンプレートでは、busyフィールドに応じてさまざまなメッセージを提供しています。

@Test
public void whenUsedIf_ThenPutsCondition() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    Template template = handlebars.compile("if");
    Person person = getPerson("Baeldung");
    person.setBusy(true);
    
    String templateString = template.apply(person);
    
    assertThat(templateString).contains("<h4>Baeldung is busy.</h4>");
}

テンプレートをコンパイルした後、コンテキストオブジェクトを設定します。 ビジーフィールドが真であるため、最終出力は

Baeldungがビジーです。

になります。

6. カスタムテンプレートヘルパー

独自のカスタムヘルパーを作成することもできます。

6.1. ヘルパー

Helper インターフェイスを使用すると、テンプレートヘルパーを作成できます。

最初のステップとして、Helperの実装を提供する必要があります。

new Helper<Person>() {
    @Override
    public Object apply(Person context, Options options) throws IOException {
        String busyString = context.isBusy() ? "busy" : "available";
        return context.getName() + " - " + busyString;
    }
}

ご覧のとおり、 Helper インターフェースには、contextおよびオプションオブジェクトを受け入れるメソッドが1つだけあります。 ここでは、Personnameフィールドとbusyフィールドを出力します。

ヘルパーを作成したら、カスタムヘルパーをハンドルバーに登録する必要があります

@Test
public void whenHelperIsCreated_ThenCanRegister() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    handlebars.registerHelper("isBusy", new Helper<Person>() {
        @Override
        public Object apply(Person context, Options options) throws IOException {
            String busyString = context.isBusy() ? "busy" : "available";
            return context.getName() + " - " + busyString;
        }
    });
    
    // implementation details
}

この例では、 Handlebars.registerHelper()メソッドを使用して、isBusyという名前でヘルパーを登録しています。

最後のステップとして、ヘルパーの名前を使用してテンプレートにタグを定義する必要があります

{{#isBusy this}}{{/isBusy}}

各ヘルパーには開始タグと終了タグがあることに注意してください。

6.2. ヘルパーメソッド

ヘルパーインターフェイスを使用する場合、作成できるヘルパーは1つだけです対照的に、ヘルパーソースクラスを使用すると、複数のテンプレートヘルパーを定義できます。

さらに、特定のインターフェースを実装する必要はありません。 クラスにヘルパーメソッドを記述し、HandleBarsがリフレクションを使用してヘルパー定義を抽出します。

public class HelperSource {

    public String isBusy(Person context) {
        String busyString = context.isBusy() ? "busy" : "available";
        return context.getName() + " - " + busyString;
    }

    // Other helper methods
}

ヘルパーソースには複数のヘルパー実装を含めることができるため、登録は単一のヘルパー登録とは異なります。

@Test
public void whenHelperSourceIsCreated_ThenCanRegister() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    handlebars.registerHelpers(new HelperSource());
    
    // Implementation details
}

Handlebars.registerHelpers()メソッドを使用してヘルパーを登録しています。 また、ヘルパーメソッドの名前はヘルパータグの名前になります。

7. テンプレートの再利用

ハンドルバーライブラリは、既存のテンプレートを再利用するためのいくつかの方法を提供します。

7.1. テンプレートの包含

テンプレートを含めることは、テンプレートを再利用するためのアプローチの1つです。 テンプレートの構成に有利です

<h4>Hi {{name}}!</h4>

これは、 header テンプレート–header.html。のコンテンツです。

別のテンプレートで使用するには、headerテンプレートを参照する必要があります。

{{>header}}
<p>This is the page {{name}}</p>

ページtemplate – page.html – には、{{>header}}を使用したheaderテンプレートが含まれています。

Handlebars.javaがテンプレートを処理するとき、最終出力にはheaderの内容も含まれます。

@Test
public void whenOtherTemplateIsReferenced_ThenCanReuse() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    Template template = handlebars.compile("page");
    Person person = new Person();
    person.setName("Baeldung");
    
    String templateString = template.apply(person);
    
    assertThat(templateString)
      .contains("<h4>Hi Baeldung!</h4>", "<p>This is the page Baeldung</p>");
}

7.2. テンプレートの継承

コンポジションの代わりに、Handlebarsはテンプレート継承を提供します。

{{#block}}および{{#partial}} タグを使用して、継承関係を実現できます。

<html>
<body>
{{#block "intro"}}
  This is the intro
{{/block}}
{{#block "message"}}
{{/block}}
</body>
</html>

そうすることで、メッセージベーステンプレートには、イントロメッセージの2つのブロックがあります。

継承を適用するには、 {{#partial}} を使用して、他のテンプレートでこれらのブロックをオーバーライドする必要があります。

{{#partial "message" }}
  Hi there!
{{/partial}}
{{> messagebase}}

これはsimplemessageテンプレートです。 messagebase テンプレートが含まれており、messageブロックもオーバーライドされていることに注意してください。

8. 概要

このチュートリアルでは、テンプレートを作成および管理するためのハンドルバーjavaについて説明しました。

基本的なタグの使用法から始めて、ハンドルバーテンプレートをロードするためのさまざまなオプションを確認しました。

また、多くの機能を提供するテンプレートヘルパーについても調査しました。 最後に、テンプレートを再利用するさまざまな方法を検討しました。

最後に、GitHubですべての例のソースコードを確認してください。