LoginSignup
6
8

More than 5 years have passed since last update.

Thymeleaf Springのpropertyを利用したUtility Objectを作る

Posted at

前提

  • Spring Boot 1.3
    • Parent POMとしてspring-boot-starter-parentを使用
  • Thymeleaf 2.1.4

やりたいこと

Thymeleafで何個も似たようなことを書くのを止めたい

th:textth:hrefに記述する内容が↓みたいに長くなってきた&大量に似たような記述をしなくちゃいけなくなってきたので、何とかしたい。

problem.html
<link rel="stylesheet" type="text/css" th:href="@{${@environment.getProperty('testapp.static-file.path')}/css/style.css?ver=${@environment.getProperty('testapp.version')}}"/>
<link rel="stylesheet" type="text/css" th:href="@{${@environment.getProperty('testapp.static-file.path')}/css/layout.css?ver=${@environment.getProperty('testapp.version')}}"/>
<link rel="stylesheet" type="text/css" th:href="@{${@environment.getProperty('testapp.static-file.path')}/css/debug.css?ver=${@environment.getProperty('testapp.version')}}"/>

具体的には、「propertyから値を読み込んで、それをもとにURLを生成処理を行うfunction」を作って、記述をスッキリさせたい。

アプローチ

Utility Objectを作る

カスタム Utility Object を追加する ー Thymeleaf | Developers.IOを読みながら自分なりにやってみる。

カスタム Utility Objectの実装と登録

まずは、実際にURL生成を行うためのクラス(PathBuilder)を実装。

PathBuilder.java
@Component public class PathBuilder {

    @Value("${testapp.static-file.path}")
    private String staticFilePath;

    @Value("${testapp.version}")
    private String projectVersion;

    public String build(String path) {
        return staticFilePath + path + "?ver=" + projectVersion;
    }
}

次に、Dialectクラス(TestAppDialect)を作って、PathBuilderを登録
(ここでは、PathBuilderを格納したMapを使って初期化するようにした)

TestAppDialect.java
@Component
public class TestAppDialect extends AbstractDialect implements IExpressionEnhancingDialect {

    private Map<String, Object> expressionObjects;

    public TestAppDialect(Map<String, Object> expressionObjects) {
        super();
        this.expressionObjects = expressionObjects;
    }

    @Override
    public Map<String, Object> getAdditionalExpressionObjects(
        IProcessingContext iProcessingContext) {
        return expressionObjects;
    }

    @Override
    public String getPrefix() {
        return null;
    }
}

つづけて、TestAppDialectをBeanとして登録

WebMvcConfig.java
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
  //...

    @Bean
    TestAppDialect testAppDialect() {
        return new TestAppDialect(ImmutableMap.of("pathBuilder", pathBuilder()));
    }

    @Bean
    PathBuilder pathBuilder() {
        return new PathBuilder();
    }

  //...
}

html上でUtility Objectを使用する

カスタムUtility Objectは、${#object.method}という形式でcallできる。
ということで、問題だった箇所を↓のように書き換える。

solved.html
<link rel="stylesheet" type="text/css" th:href="@{${#pathBuilder.build('/css/style.css')}}"/>
<link rel="stylesheet" type="text/css" th:href="@{${#pathBuilder.build('/css/layout.css')}}"/>
<link rel="stylesheet" type="text/css" th:href="@{${#pathBuilder.build('/css/debug.css')}}"/>

おまけ: pomに記述したversion情報をpropertyとして使う

testapp.version
には、pom.xmlに記載されているアプリケーションのバージョンを入れたかったので、
↓のように記述。

application.properties
testapp.version=@pom.version@

spring-boot-starter-parentを使う場合、
maven-resources-pluginの設定は自動でなされるんだけど、
delimiterが${..}じゃなくて@..@になってるのでそこだけ注意。
c.f Spring Boot Reference Guilde - 45.7.1 Automatically expand info properties at build time

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8