4
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Spring Boot + ThymeleafでSpringTemplateEngineをカスタマイズする

やりたいこと

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">と表示されます。


今回のソースはこちらになります。
参考になれば幸いです:sweat_smile:

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What are the problem?