谁在S​​pring MVC中设置响应内容类型(@ResponseBody)

Hur*_*rda 122 java web-applications spring-mvc character-encoding

我在我的Annotation驱动的Spring MVC Java Web应用程序中运行在jetty Web服务器上(目前在maven jetty插件中).

我试图用一个控制器方法做一些AJAX支持,只返回String帮助文本.资源采用UTF-8编码,字符串也是如此,但我的服务器响应是随附的

content-encoding: text/plain;charset=ISO-8859-1 
Run Code Online (Sandbox Code Playgroud)

即使我的浏览器发送

Accept-Charset  windows-1250,utf-8;q=0.7,*;q=0.7
Run Code Online (Sandbox Code Playgroud)

我正在以某种方式使用弹簧的默认配置

我发现了一个提示将这个bean添加到配置中,但我认为它只是没有使用,因为它说它不支持编码,而是使用默认编码.

<bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
</bean>
Run Code Online (Sandbox Code Playgroud)

我的控制器代码是(请注意,此响应类型的更改对我不起作用):

@RequestMapping(value = "ajax/gethelp")
public @ResponseBody String handleGetHelp(Locale loc, String code, HttpServletResponse response) {
    log.debug("Getting help for code: " + code);
    response.setContentType("text/plain;charset=UTF-8");
    String help = messageSource.getMessage(code, null, loc);
    log.debug("Help is: " + help);
    return help;
}
Run Code Online (Sandbox Code Playgroud)

小智 160

我找到了Spring 3.1的解决方案.使用@ResponseBody注释.以下是使用Json输出的控制器示例:

@RequestMapping(value = "/getDealers", method = RequestMethod.GET, 
produces = "application/json; charset=utf-8")
@ResponseBody
public String sendMobileData() {

}
Run Code Online (Sandbox Code Playgroud)

  • +1.这也解决了它,但只是在我切换到在applicationContext中使用`<mvc:annotation-driven />`之后.(而不是`<bean class ="[...] DefaultAnnotationHandlerMapping"/>`,无论如何都在Spring 3.2中弃用了......) (7认同)
  • @Hurda:显然你可以通过改变`produce`属性的值来指定你想要的任何内容类型. (2认同)
  • 对于UTF-8,请参阅`MediaType.APPLICATION_JSON_UTF8_VALUE`. (2认同)

axt*_*avt 60

简单声明StringHttpMessageConverterbean是不够的,你需要将它注入AnnotationMethodHandlerAdapter:

<bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <array>
            <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
            </bean>
        </array>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

但是,使用此方法您必须重新定义所有HttpMessageConverters,并且它也不起作用<mvc:annotation-driven />.

所以,也许最方便但最丑陋的方法是拦截AnnotationMethodHandlerAdapterwith的实例化BeanPostProcessor:

public class EncodingPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name)
            throws BeansException {
        if (bean instanceof AnnotationMethodHandlerAdapter) {
            HttpMessageConverter<?>[] convs = ((AnnotationMethodHandlerAdapter) bean).getMessageConverters();
            for (HttpMessageConverter<?> conv: convs) {
                if (conv instanceof StringHttpMessageConverter) {
                    ((StringHttpMessageConverter) conv).setSupportedMediaTypes(
                        Arrays.asList(new MediaType("text", "html", 
                            Charset.forName("UTF-8"))));
                }
            }
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String name)
            throws BeansException {
        return bean;
    }
}
Run Code Online (Sandbox Code Playgroud)

-

<bean class = "EncodingPostProcessor " />
Run Code Online (Sandbox Code Playgroud)

  • 这看起来像是一个肮脏的黑客.我不喜欢它但是要使用.Spring框架开发人员应该在这个案例上工作! (10认同)
  • 正如@ digz6666所说这是一个肮脏的黑客.Spring应该看看JAX-RS是如何做到的. (3认同)

Ros*_*hev 51

请注意,在Spring MVC 3.1中,您可以使用MVC命名空间来配置消息转换器:

<mvc:annotation-driven>
  <mvc:message-converters register-defaults="true">
    <bean class="org.springframework.http.converter.StringHttpMessageConverter">
      <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
    </bean>
  </mvc:message-converters>
</mvc:annotation-driven>
Run Code Online (Sandbox Code Playgroud)

或基于代码的配置:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

  private static final Charset UTF8 = Charset.forName("UTF-8");

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
    stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
    converters.add(stringConverter);

    // Add other converters ...
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 可以简化为 "文本/纯" 是默认无论如何:`<bean类= "org.springframework.http.converter.StringHttpMessageConverter"> <构造精氨酸值= "UTF-8"/> </豆>` (3认同)
  • @GiulioPiancastelli您可以通过将<property name ="writeAcceptCharset"value ="false"/>添加到bean来解决您的第一个问题 (3认同)

dig*_*666 44

以防您也可以通过以下方式设置编码:

@RequestMapping(value = "ajax/gethelp")
public ResponseEntity<String> handleGetHelp(Locale loc, String code, HttpServletResponse response) {
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.add("Content-Type", "text/html; charset=utf-8");

    log.debug("Getting help for code: " + code);
    String help = messageSource.getMessage(code, null, loc);
    log.debug("Help is: " + help);

    return new ResponseEntity<String>("returning: " + help, responseHeaders, HttpStatus.CREATED);
}
Run Code Online (Sandbox Code Playgroud)

我认为使用StringHttpMessageConverter比这更好.


Cha*_* Wu 19

你可以在RequestMapping中添加produce ="text/plain; charset = UTF-8"

@RequestMapping(value = "/rest/create/document", produces = "text/plain;charset=UTF-8")
@ResponseBody
public String create(Document document, HttpServletRespone respone) throws UnsupportedEncodingException {

    Document newDocument = DocumentService.create(Document);

    return jsonSerializer.serialize(newDocument);
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此博客

  • 这是一个错误的答案.根据spring docs:映射请求的可生成媒体类型,缩小主映射.格式是一系列媒体类型("text/plain","application/*"),只有在Accept与这些媒体类型之一匹配时才会映射请求.使用"!"运算符可以取消表达式,如"!text/plain",使用"text/plain"以外的Accept匹配所有请求. (3认同)
  • 那段代码不会编译; 你从void方法返回一些东西. (2认同)
  • 对不起坏的bug,现在已修好了 (2认同)

dby*_*ung 10

我最近在讨论这个问题,并在Spring 3.1中找到了一个更好的答案:

@RequestMapping(value = "ajax/gethelp", produces = "text/plain")
Run Code Online (Sandbox Code Playgroud)

因此,像JAX-RS一样简单就像所有评论所表明的那样.

  • @dbyoung这似乎不对,`produce`的javadoc说:"......只有在Content-Type与其中一种媒体类型匹配时才会映射请求." 这意味着`produce`的AFAIK与方法是否匹配请求有关,而不是响应应该具有哪种内容类型. (5认同)

小智 6

您可以使用生产来指示您从控制器发送的响应类型。这个“produces”关键字在ajax请求中最有用,对我的项目非常有帮助

@RequestMapping(value = "/aURLMapping.htm", method = RequestMethod.GET, produces = "text/html; charset=utf-8") 

public @ResponseBody String getMobileData() {

}
Run Code Online (Sandbox Code Playgroud)