Spring Boot 2.5.0 - REST 控制器,MockMvc 不是 UTF-8

Posted

技术标签:

【中文标题】Spring Boot 2.5.0 - REST 控制器,MockMvc 不是 UTF-8【英文标题】:Spring Boot 2.5.0 - REST controller, MockMvc not UTF-8 【发布时间】:2021-08-13 17:52:20 【问题描述】:

在我的 REST 控制器中,我使用 @PostMapping@GetMapping等,没有任何其他规范。

因此默认值必须是JSON,例如@GetMapping。也没有指定字符编码,我假设它必须是UTF-8,我在文档中找不到默认字符编码。

但是在我的测试中我使用MockMvc。 当我发出POST 请求时,它看起来像这样:

public static MvcResult performPost(MockMvc mockMvc, String endpoint, String payload, ResultMatcher status) throws Exception 
    MvcResult mvcResult = mockMvc.perform(
        post(endpoint)
            .content(payload)
            .contentType(MediaType.APPLICATION_JSON_VALUE))
        .andDo(print())
        .andExpect(status)
        .andReturn();

    return mvcResult;

问题:.andDo(print()) 部分似乎没有使用 UTF-8。如何解决这个问题?在我的 NetBeans IDE 的控制台中,某些字符(例如德语 'ü')未正确打印。它看起来像(见正文):

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"application/json", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = application/json
             Body = "Tür"
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

问题: 当我的方法返回MvcResult时,我可以这样做:

MockHttpServletResponse response = mvcResult.getResponse(); 
ObjectMapper objectMapper = new ObjectMapper();
    
String contentAsString = response.getContentAsString(StandardCharsets.UTF_8);

我发现,我必须使用StandardCharset.UTF_8 来获取正确的字符,例如'ü'

但是为什么MockHttpServletResponse responsecharacterEncoding ISO-8859-1ISO-8859-1来自哪里,这一套在哪里?可以改成UTF-8吗?

当我改为尝试时:

String contentAsString = response.getContentAsString(StandardCharsets.ISO_8859_1);

我没有得到德语 'ü',字符串值是 "Tür"。虽然在ISO_8859_1 中根据https://en.wikipedia.org/wiki/ISO/IEC_8859-1 字符'ü' 在代码页布局表中。

【问题讨论】:

【参考方案1】:

是的,这绝对是尴尬

班级:repository\org\springframework\spring-test\5.3.7\spring-test-5.3.7.jar!\org\springframework\test\web\servlet\result\MockMvcResultHandlers.class

方法:

public static ResultHandler print() 
    return print(System.out);

方法:

public static ResultHandler print(OutputStream stream) 
    return new PrintWriterPrintingResultHandler(new PrintWriter(stream, true));

构造函数:

public PrintWriter(OutputStream out, boolean autoFlush) 
    this(out, autoFlush, Charset.defaultCharset());

据我了解,罪魁祸首是 Charset.defaultCharset(),应该是 UTF-8

【讨论】:

以上是关于Spring Boot 2.5.0 - REST 控制器,MockMvc 不是 UTF-8的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2.5.0、Spring Cloud 2020.0.2 和 Hibernate 5.4.31 - H2 数据库多行插入失败

rest-spring-boot-starter

列出所有已部署的 REST 端点(spring-boot、tomcat)

初入spring boot(八 )Spring Data REST

Spring Boot测试中使用REST Assured(转)

Spring Boot 2.5.0 重新设计的spring.sql.init 配置有啥用?