spring boot + thymeleaf 无法正确编码 POST 中的 UTF-8 字符

Posted

技术标签:

【中文标题】spring boot + thymeleaf 无法正确编码 POST 中的 UTF-8 字符【英文标题】:spring boot + thymeleaf cannot correctly encode UTF-8 characters form POST 【发布时间】:2016-01-11 13:50:57 【问题描述】:

我正在使用 thymeleaf 模板引擎评估 spring boot。我正面临UTF8字符形式发布问题。

对于最简单的form.html 帖子示例:

<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>

在控制器中:

@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(或 thymeleaf)无法正确编码带有 UTF-8 字符的表单。

如果我输入 ä ,我会看到这个日志:

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

ä 应编码为 %C3%A4 。正文应该是 name=%C3%A4 ,但我不知道为什么它变成 %C3%83%C2%A4 并解码为错误的字符。

我google了一下,找到了一些解决方案,比如添加一个编码过滤器:

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

但不工作。

另一种解决方案是通过这种方式thymeleafViewResolver.setCharacterEncoding("UTF-8");

  @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;
  

但它也不起作用。

此外,ThymeleafViewResolver 的字符编码已经设置在 ThymeleafAutoConfiguration source code 中。这里似乎不需要重新定义UTF-8

似乎我对这个问题也有类似的情况:UTF-8 encoding with form post and Spring Controller。接受的解决方案是

将 CharacterEncodingFilter 移到顶部并强制编码 设置为 UTF-8 解决了这个问题。

我试过这个:

  @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;
  

但还是不行。

我认为 UTF-8 表单发布是非常基本的,但为什么它不能在这里工作。我错过了什么吗?

环境:

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

非常感谢。

有点跑题了:我用过很多其他框架,比如 JSP/wicket/grails/play1/play2,没有一个有这么烦人的 UTF-8 情况。

【问题讨论】:

【参考方案1】:

This is a known issue, already fixed - 该修复程序将随 Spring Boot 1.3.0.RC1 一起提供。

与此同时,您可以通过手动声明编码过滤器来解决此问题:

@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;

【讨论】:

谢谢。有用。希望 1.3.0.RC1 尽快发布。

以上是关于spring boot + thymeleaf 无法正确编码 POST 中的 UTF-8 字符的主要内容,如果未能解决你的问题,请参考以下文章

spring-boot-thymeleaf

Spring Boot中使用thymeleaf

spring boot整合Thymeleaf

Spring Boot2:使用Spring Boot结合Thymeleaf模板引擎使用总结

Spring Boot(十五):spring boot+jpa+thymeleaf增删改查示例

Spring Boot 学习笔记--整合Thymeleaf