Java 如何在 json 格式的 restTemplate 中将 MediaType 设置为 UTF-8

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18236975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:37:54  来源:igfitidea点击:

How to set MediaType to UTF-8 in restTemplate with json format

javaresttomcatspring-mvc

提问by Ericton

I have one problem that I can't convert the data in json format to UTF-8 when the server response. I have set MediaTypein spring configuration xml, but it seems not work. And here is my server side code to response:

我有一个问题,当服务器响应时,我无法将 json 格式的数据转换为 UTF-8。我MediaType在 spring 配置 xml 中设置了,但似乎不起作用。这是我要响应的服务器端代码:

    @RequestMapping(value = "/post",  method = RequestMethod.POST)
    public @ResponseBody String postData(@RequestBody ObjectNode request){
        // do something with request
        return response;
    }

When server response, data in json format will contain value as unicode. And in client side configuration:

当服务器响应时,json 格式的数据将包含 unicode 的值。在客户端配置中:

    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
      <property name="messageConverters">
        <list>
            <bean id="formConverter" class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean id="stringConverter" class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingHymansonHttpMessageConverter" >
                <property name="supportedMediaTypes">
                      <list>
                        <bean class="org.springframework.http.MediaType">
                           <constructor-arg value="application" />
                           <constructor-arg value="json" />
                           <constructor-arg value="#{T(java.nio.charset.Charset).forName('UTF-8')}"/>
                         </bean>
                      </list>
                </property>
            </bean>
        </list>
      </property>
    </bean>

And here is my client side code to request for data, and I use postForObject method:

这是我请求数据的客户端代码,我使用 postForObject 方法:

    @Autowired
    private RestTemplate restTemplate;

    public ObjectNode postObjectNode(ObjectNode request){
          ObjectNode node = restTemplate.postForObject("http://localhost:8080/server/post", request, ObjectNode.class);
          return node;
}

And as a result, data that contain the unicode will convert to ????. Is it cause by server or cause by restTemplate client. please help me. Thanks in advance...

因此,包含 unicode 的数据将转换为????. 是由服务器引起的还是由restTemplate 客户端引起的。请帮我。提前致谢...

回答by Larry.Z

If the handler method return Stringtype for @ResponseBody, default Message Converter is StringHttpMessageConverter, you can config the converter like this

如果处理程序方法返回String类型为@ResponseBody,则默认消息转换器为StringHttpMessageConverter,您可以像这样配置转换器

    <mvc:annotation-driven >
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/plain;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

回答by vicont

Obviously it's a dirty hack, but Spring forced me to do it :) It works fine in our project. We're calling a method that changes StringHttpMessageConverter.DEFAULT_CHARSET reflectively after context initialization.

显然这是一个肮脏的黑客,但 Spring 强迫我这样做:) 它在我们的项目中运行良好。我们正在调用一个在上下文初始化后反射性地更改 StringHttpMessageConverter.DEFAULT_CHARSET 的方法。

Create a class somewhere in your package:

在包中的某处创建一个类:

public class CharsetPostProcessor implements InitializingBean, ApplicationContextAware {

    private ApplicationContext applicationContext;

    static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

        field.set(null, newValue);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        Field charsetField = applicationContext.getBean("stringHttpMessageConverter").getClass().getField("DEFAULT_CHARSET");
        Charset charset = Charset.forName("UTF-8");
        setFinalStatic(charsetField, charset);
    }
}

And add following into your Spring context definition:

并将以下内容添加到您的 Spring 上下文定义中:

<bean class="your.package.CharsetPostProcessor" />
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter" />

回答by Grigory Kislin

In may case browser request Header "Acept" was: text/html,application/xhtml+xml,application/xml;q=0.9/;q=0.8.

在可能的情况下,浏览器请求标题“Acept”是:text/html,application/xhtml+xml,application/xml;q=0.9/;q=0.8。

So additional supportedMediaTypes solve problem:

所以额外的 supportedMediaTypes 解决了问题:

<mvc:annotation-driven >
  <mvc:message-converters>
    <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/plain;charset=UTF-8</value>
                <value>text/html;charset=UTF-8</value>
            </list>
        </property>
    </bean>
  </mvc:message-converters>
</mvc:annotation-driven>

Note, that "text/*;charset=UTF-8" doesn't work.

请注意,“text/*;charset=UTF-8”不起作用。