Make @ResponseBody-annotated Spring (Boot) MVC con

2019-05-23 00:32发布

问题:

I'm building a Spring MVC service using Spring Boot and want to be able to return strings as plain text encoded in UTF-8. Following this description, I thought the only thing necessary should be to add the bean method

@Bean
public HttpMessageConverter<String> responseBodyConverter() {
    StringHttpMessageConverter converter = new StringHttpMessageConverter();
    converter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", Charset.forName("UTF-8"))));
    return converter;
}

But the root method in

@Controller
public class RootController {

    @RequestMapping(value="/"/*, produces="text/plain;charset=UTF-8"*/)
    @ResponseBody
    public String root() {
        return "æøå";
    }

}

responds the string æøå in ISO-8859-1 instead of UTF-8, unless I uncomment the produces part, in which case it actually returns UTF-8. The message converter doesn't seems to have any effect here.

Following this approach I confirm that the bean has actually been registered. Besides this bean, I also register an EmbeddedServletContainerFactory and CharacterEncodingFilter as described in another question, although I don't think that's relevant here.

Can someone explain what the registered HttpMessageConverter actually does, and how to make @ResponseBody-annotated controller methods return UTF-8 without having to provide produces every time?

Edit

As discussed in the comments, for the accepted answer to work, I had to upgrade the version of Spring Boot from 0.5.0.M6 to 0.5.0.BUILD-SNAPSHOT and, to prevent outputting a junk header, call converter.setWriteAcceptCharset(false) on the StringHttpMessageConverter.

回答1:

The default character set for the StringHttpMessageConverteris ISO-8859-1. That means when a client does not request a specific character set, then ISO-8859-1 will be returned.

If you want UTF-8to be the default character set then you pass it into the constructor:

converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));

Calling setSupportedMediaTypes() is then no longer necessary either as text/plain; charset=default character set is added automatically.