Search code examples
javaspringspring-bootmodel-view-controllerthymeleaf

Is this possible to inject html code in utf-8 encoding to html page using thymeleaf and spring


Recently I've decided to try to learn Thymeleaf with Spring MVC. And currently I'm storing html body fragments such as img, iframe etc. The problem has appeared after injecting this html fragments into one general html page using thymeleaf tags with UTF-8 encoding and cyrillic symbols. To be more precisely, these html fragments come in Model attribute from Spring controller. Is it possible to inject just the fragment into the one general html page such as below:

<html xmlns:th="https://www.thymeleaf.org">
<head></head>
<body>
[(${contents})] <!-- contents is that fragment I want to inject -->
</body>
</html>

Controller's request method is shown below:

    @GetMapping("/getArticle/{id}")
public String getArticle(@PathVariable Long id, Model model) throws IOException {
    Article article = articleService.getById(id);
    String contents = new String(Files.readAllBytes(Paths.get(article.getText())));
    model.addAttribute("contents", contents);
    return "news//article";
}

Content insert fragment example:

<h1>Кириллица</h1>
<br/><iframe style='width: 30%; height: 35%;' src='link'></iframe><br/>
Классный видос, да?

The result of combining 2 previous lists gives me this

As I've previously mentioned, I've faced the trouble I have some curve symbols instead of russian ones. Also, I should note that, in case of normal page loading without injection, all the russian symbols are shown correctly. There's my ViewResolver and TemplateResolver from Spring configuration:

@Bean
public SpringResourceTemplateResolver templateResolver() {
    SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
    templateResolver.setApplicationContext(applicationContext);
    templateResolver.setPrefix("/WEB-INF/views/");
    templateResolver.setSuffix(".html");
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setTemplateMode(TemplateMode.HTML);
    templateResolver.setCacheable(true);
    return templateResolver;
}

@Bean
public ThymeleafViewResolver viewResolver() {
    ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
    thymeleafViewResolver.setCharacterEncoding("UTF-8");
    thymeleafViewResolver.setContentType("text/html; charset=UTF-8");
    return thymeleafViewResolver;
}

So, the question is next: is this possible to directly inject html code which is received from the controller as an attribute using thymeleaf tags with correct UTF-8 encoding without curve symbols?


Solution

  • You can do this, but you would at least need to change this line:

    String contents = new String(Files.readAllBytes(Paths.get(article.getText())));
    

    to this:

    String contents = Files.readString(Paths.get(article.getText()), StandardCharsets.UTF_8);
    

    This uses the readString() method with a java.nio.charset.StandardCharsets.UTF_8 character set. Otherwise, your bytes from readAllBytes() are being written to a string in what could be some other (non-UTF-8) encoding - probably depending on the default character set picked up by the JVM when it started.

    However, for learning Thymeleaf, I would recommend looking into Thymeleaf fragments (if you have not already done so), since these are designed for this purpose.

    This will then lead you into template layouts, which have a lot of flexibility.