3

I am evaluating spring boot with thymeleaf template engine. I am facing the problem of UTF8 character form posting problem.

For the simplest form.html post example :

<head>
  <title>test</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>

<body>

<form th:action="@{/test/doPost}" method="post">
  <input type="text" name="name" />
  <button type="submit">submit</button>
</form>

And in the controller :

@Controller
@RequestMapping("/test")
public class TestController {

  private Logger logger = LoggerFactory.getLogger(getClass());

  @RequestMapping(value = "/form", method = RequestMethod.GET)
  public String showForm() {
    return "test/form";
  }

  @RequestMapping(value = "/doPost", method = RequestMethod.POST)
  public String doPost(@RequestBody String body,
                       @RequestParam(value = "name", required = true) String name) {
    logger.info("body = {}", body);
    logger.info("name = {}", name);
    return "redirect:/test/form";
  }
}

Spring MVC (or thymeleaf) cannot correctly encode form with UTF-8 character in this example.

If I input ä , I'll see this log :

TestController - body = name=%C3%83%C2%A4
TestController - name = ä

ä should be encoded to %C3%A4 . the body should be name=%C3%A4 , but I don't know why it becomes %C3%83%C2%A4 and decoded to wrong characters.

I googled and found some solutions , such as adding an encoding filter :

  @Bean
  public Filter characterEncodingFilter() {
    CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
    characterEncodingFilter.setEncoding("UTF-8");
    characterEncodingFilter.setForceEncoding(true);
    return characterEncodingFilter;
  }

But not working.

Another solution is to thymeleafViewResolver.setCharacterEncoding("UTF-8"); by this way :

  @Bean
  public SpringResourceTemplateResolver templateResolver() {
    final SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
    templateResolver.setCacheable(false);
    templateResolver.setPrefix("classpath:/templates/");
    templateResolver.setSuffix(".html");
    templateResolver.setTemplateMode("HTML5");
    return templateResolver;
  }

  @Bean
  public SpringTemplateEngine springTemplateEngine() {
    SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
    springTemplateEngine.setTemplateResolver(templateResolver());

    return springTemplateEngine;
  }

  @Bean
  public ThymeleafViewResolver viewResolver() {
    ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
    thymeleafViewResolver.setTemplateEngine(springTemplateEngine());
    thymeleafViewResolver.setCharacterEncoding("UTF-8");
    return thymeleafViewResolver;
  }

But it doesn't work , either.

Moreover , ThymeleafViewResolver's characterEncoding is already set in the ThymeleafAutoConfiguration source code . There seems no need to re-define UTF-8 here.

It seems I have similar situation with this question : UTF-8 encoding with form post and Spring Controller . The accepted solution is

Moving CharacterEncodingFilter to the top and forcing the encoding to be set as UTF-8 solved the problem.

I tried this :

  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
    characterEncodingFilter.setEncoding("UTF-8");
    characterEncodingFilter.setForceEncoding(true);
    registrationBean.setFilter(characterEncodingFilter);
    registrationBean.setOrder(0);
    return registrationBean;
  }

But still not working.

I think UTF-8 form posting is very basic , but why it just cannot work here . Did I miss anything ?

environment :

<springboot.version>1.3.0.M5</springboot.version>
<spring.version>4.2.1.RELEASE</spring.version>

Thanks a lot.

A little off-topic : I've used many other frameworks , such as JSP/wicket/grails/play1/play2 , non of these have such annoying UTF-8 situation.

Community
  • 1
  • 1
smallufo
  • 11,516
  • 20
  • 73
  • 111

1 Answers1

3

This is a known issue, already fixed - the fix will be shipped with Spring Boot 1.3.0.RC1.

In the meantime, you can work around the problem by declaring the encoding filter manually:

@Autowired
private HttpEncodingProperties httpEncodingProperties;

@Bean
public OrderedCharacterEncodingFilter characterEncodingFilter() {
    OrderedCharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
    filter.setEncoding(this.httpEncodingProperties.getCharset().name());
    filter.setForceEncoding(this.httpEncodingProperties.isForce());
    filter.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filter;
}
Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
Brian Clozel
  • 56,583
  • 15
  • 167
  • 176