やりたいこと
Thymeleafでリンクを生成する部分を拡張したい。
ThymeleafでURLを指定するときのこれ
<img th:src="@{/image/hoge.jpg}">
ホスト名がふくまれてないときに、CDNのホスト名をリンクに追加したい。
ex)
/image/hoge.jpg
->http://cdn.example.com/image/hoge.jpg
みたいにする
環境
- SpringBoot: 1.4.6.RELEASE
- Thymeleaf: 3.0.2.RELEASE
実装
org.thymeleaf.linkbuilder.AbstractLinkBuilder
を拡張したクラスを作成します。
リンクを生成する部分をbuildLink
メソッドに実装します。
CDNのホストを追加する必要がない場合は、デフォルトのURLを利用したいのでStandardLinkBuilder
を利用しています。
http://example.com/xxx
のように始まるリンクは、CDNのホストを追加しないようにしています。
if (UrlUtils.isAbsoluteUrl(link)) { ... }
のところ
@Component
public class CustomLinkBuilder extends AbstractLinkBuilder {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomLinkBuilder.class);
private final StandardLinkBuilder standardLinkBuilder = new StandardLinkBuilder();
private String cdnHost() {
return "http://localhost:8080";
}
private boolean isImageExtention(String path) {
return StringUtils.endsWith(path, ".jpg")
|| StringUtils.endsWith(path, ".jpeg")
|| StringUtils.endsWith(path, ".png")
|| StringUtils.endsWith(path, ".gif");
}
private boolean isImageLink(UriComponents components) {
final String path = components.getPath();
return StringUtils.startsWith(path, "/image/") && this.isImageExtention(path);
}
@Override
public String buildLink(final IExpressionContext context, final String base, final Map<String, Object> parameters) {
String link = this.standardLinkBuilder.buildLink(context, base, parameters);
LOGGER.debug("build link:{}", link);
if (UrlUtils.isAbsoluteUrl(link)) {
return link;
}
UriComponents components = UriComponentsBuilder.fromUriString(link).build();
if (this.isImageLink(components)) {
return this.cdnHost() + link;
}
return link;
}
}
TemplateEngineに、↑のクラスを設定します。
デフォルトのSpringTemplateEngine
に、CustomLinkBuilder
を設定したかったので、@Import(ThymeleafAutoConfiguration.class)
しています。
@Import
がないとSpringTemplateEngine
のBeanが生成されるタイミングより前に、@Bean SpringTemplateEngine customTemplateEngine() {}
が実行されるため、
@Autowired private SpringTemplateEngine templateEngine
がnullになるようです。
@Configuration
@Import(ThymeleafAutoConfiguration.class)
public class WebConfig {
@Autowired
private SpringTemplateEngine templateEngine;
@Autowired
private CustomLinkBuilder customLinkBuilder;
@Bean
public SpringTemplateEngine customTemplateEngine() {
this.templateEngine.setLinkBuilder(this.customLinkBuilder);
return this.templateEngine;
}
}
これで、<img th:src="@{/image/hoge/main.jpg}">
のようにtemplateに書くと、
<img src="http://localhost:8080/image/hoge/main.jpg">
と表示されます。
今回のソースはこちらになります。
参考になれば幸いです