ThymeleafでJavaScriptを生成する


概要

ひょんなことからThymeleafでJavaScriptを触ることがあったので備忘録です。

環境

OpenJDK 11.0.2
SpringBoot 2.3.4
Thymeleaf 3.0.11

TemplateEngine設定

AppConfig.java
@Configuration
public class AppConfig {

    @Bean
    public TemplateEngine scriptTemplateEngine() {
        final TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setDialect(new SpringStandardDialect());
        templateEngine.setTemplateResolver(scriptTemplateResolver());

        return templateEngine;
    }

    private ITemplateResolver scriptTemplateResolver() {

        final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("/templates/scripts/");
        templateResolver.setSuffix(".js");
        templateResolver.setTemplateMode(TemplateMode.JAVASCRIPT);
        templateResolver.setCharacterEncoding("utf-8");
        templateResolver.setCacheable(false);
        templateResolver.setCheckExistence(true);

        return templateResolver;
    }
}

テンプレートファイル作成

resources/templates/scripts/sample.js
'use strict';

(() => {

    const rawData = [# th:text="${rawData}" /];
    const jsonData = [# th:text="${jsonData}" /]; 

    console.log(rawData);
    console.log(jsonData);

})();

2つの変数を渡す形にします。

コントローラ設定

SampleController.java
@Controller
@RequiredArgsConstructor
public class SampleController {

    private final TemplateEngine scriptTemplateEngine;
    private final ObjectMapper objectMapper;

    @GetMapping(value = "/app.js", produces = "text/javascript")
    @ResponseBody
    public String sample() throws JsonProcessingException {

        String path = "sample";

        Map<String, Object> map = new HashMap<>();
        map.put("id", 1);
        map.put("name", "Takeshi");
        List<Map<String, Object>> list = new ArrayList<>();
        list.add(map);

        Context ctx = new Context();
        ctx.setVariable("rawData", list);
        ctx.setVariable("jsonData", objectMapper.writeValueAsString(list));

        return scriptTemplateEngine.process(path, ctx);
    }
}

sample()の方でデータを作成し、先ほどの変数名と同じ名前でそれぞれデータそのものとJSON文字列に変換したデータをprocessメソッドに渡し返却します。
注意したいのがthymeleaf-spring5の依存性を追加すると、自動でViewを返却するためのBeanがtemplateEngineという名前で作成されます。
設定ファイルで作成したBeanを使用する場合はその際に使用したBean名でDIする必要があります。

結果

アプリを起動し/app.jsにアクセスしてみます。

無事作成できました。
動的にJS作成する機会はそうそうないとは思いますが参考まで。

Thymeleafのアップデートは2年ほどないみたいですね。
開発止まったのですかね。