前提
- Spring Boot 1.3
- Parent POMとしてspring-boot-starter-parentを使用
- Thymeleaf 2.1.4
やりたいこと
Thymeleafで何個も似たようなことを書くのを止めたい
th:text
やth:href
に記述する内容が↓みたいに長くなってきた&大量に似たような記述をしなくちゃいけなくなってきたので、何とかしたい。
<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
)を実装。
@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を使って初期化するようにした)
@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として登録
@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できる。
ということで、問題だった箇所を↓のように書き換える。
<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に記載されているアプリケーションのバージョンを入れたかったので、
↓のように記述。
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