【问题标题】:spring boot + thymeleaf cannot correctly encode UTF-8 characters form POSTspring boot + thymeleaf 无法正确编码 POST 中的 UTF-8 字符
【发布时间】: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 情况。

【问题讨论】:

    标签: spring spring-mvc encoding spring-boot thymeleaf


    【解决方案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 尽快发布。
    猜你喜欢
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    • 2014-08-31
    • 1970-01-01
    • 2017-01-02
    • 2019-08-01
    • 2017-04-27
    相关资源
    最近更新 更多