Java 谁在 Spring MVC 中设置响应内容类型(@ResponseBody)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3616359/
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-14 02:43:21  来源:igfitidea点击:

Who sets response content-type in Spring MVC (@ResponseBody)

javaweb-applicationsspring-mvccharacter-encoding

提问by Hurda

I'm having in my Annotation driven Spring MVC Java web application runned on jetty web server (currently in maven jetty plugin).

我在我的注解驱动 Spring MVC Java web 应用程序中运行在 jetty web 服务器上(目前在 maven jetty 插件中)。

I'm trying to do some AJAX support with one controller method returning just String help text. Resources are in UTF-8 encoding and so is the string, but my response from server comes with

我正在尝试使用一种仅返回字符串帮助文本的控制器方法来做一些 AJAX 支持。资源采用 UTF-8 编码,字符串也是如此,但我的服务器响应带有

content-encoding: text/plain;charset=ISO-8859-1 

even when my browser sends

即使我的浏览器发送

Accept-Charset  windows-1250,utf-8;q=0.7,*;q=0.7

I'm using somehow default configuration of spring

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

I have found a hint to add this bean to the configuration, but I think it's just not used, because it says it does not support the encoding and a default one is used instead.

我找到了将这个 bean 添加到配置中的提示,但我认为它没有被使用,因为它说它不支持编码,而是使用默认编码。

<bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
</bean>

My controller code is (note that this change of response type is not working for me):

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

@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;
}

采纳答案by axtavt

Simple declaration of the StringHttpMessageConverterbean is not enough, you need to inject it into AnnotationMethodHandlerAdapter:

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>

However, using this method you have to redefine all HttpMessageConverters, and also it doesn't work with <mvc:annotation-driven />.

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

So, perhaps the most convenient but ugly method is to intercept instantiation of the AnnotationMethodHandlerAdapterwith BeanPostProcessor:

因此,也许最方便但最丑陋的方法是拦截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;
    }
}

-

——

<bean class = "EncodingPostProcessor " />

回答by Theresia Sofia Snow

I'm using the CharacterEncodingFilter, configured in web.xml. Maybe that helps.

我正在使用在 web.xml 中配置的 CharacterEncodingFilter。也许这有帮助。

    <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

回答by digz6666

Just in case you can also set encoding by the following way:

以防万一,您还可以通过以下方式设置编码:

@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);
}

I think using StringHttpMessageConverter is better than this.

我认为使用 StringHttpMessageConverter 比这更好。

回答by redochka

Thanks digz6666, your solution works for me with a slight changes because I'm using json:

谢谢 digz6666,您的解决方案对我有用,因为我使用的是 json:

responseHeaders.add("Content-Type", "application/json; charset=utf-8");

The answer given by axtavt (whch you've recommended) wont work for me. Even if I've added the correct media type:

axtavt(您推荐的)给出的答案对我不起作用。即使我添加了正确的媒体类型:

if (conv instanceof StringHttpMessageConverter) {                   
                    ((StringHttpMessageConverter) conv).setSupportedMediaTypes(
                        Arrays.asList(
                                new MediaType("text", "html", Charset.forName("UTF-8")),
                                new MediaType("application", "json", Charset.forName("UTF-8")) ));
                }

回答by Marius

if none of the above worked for you try to make ajax requests on "POST" not "GET" , that worked for me nicely ... none of the above did. I also have the characterEncodingFilter.

如果以上都不适合您尝试在“POST”而不是“GET”上发出ajax请求,那对我来说很好用......以上都没有。我也有 characterEncodingFilter。

回答by Szilard Jakab

package com.your.package.spring.fix;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * @author Szilard_Jakab (JaKi)
 * Workaround for Spring 3 @ResponseBody issue - get incorrectly 
   encoded parameters     from the URL (in example @ JSON response)
 * Tested @ Spring 3.0.4
 */
public class RepairWrongUrlParamEncoding {
    private static String restoredParamToOriginal;

    /**
    * @param wrongUrlParam
    * @return Repaired url param (UTF-8 encoded)
    * @throws UnsupportedEncodingException
    */
    public static String repair(String wrongUrlParam) throws 
                                            UnsupportedEncodingException {
    /* First step: encode the incorrectly converted UTF-8 strings back to 
                  the original URL format
    */
    restoredParamToOriginal = URLEncoder.encode(wrongUrlParam, "ISO-8859-1");

    /* Second step: decode to UTF-8 again from the original one
    */
    return URLDecoder.decode(restoredParamToOriginal, "UTF-8");
    }
}

After I have tried lot of workaround for this issue.. I thought this out and it works fine.

在我为这个问题尝试了很多解决方法之后..我想到了这一点,它工作正常。

回答by Rossen Stoyanchev

Note that in Spring MVC 3.1 you can use the MVC namespace to configure message converters:

请注意,在 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>

Or code-based configuration:

或者基于代码的配置:

@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 ...
  }
}

回答by Reto-san

I set the content-type in the MarshallingView in the ContentNegotiatingViewResolverbean. It works easily, clean and smoothly:

我在ContentNegotiatingViewResolverbean的 MarshallingView 中设置了内容类型。它工作轻松、干净且顺畅:

<property name="defaultViews">
  <list>
    <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
      <constructor-arg>
        <bean class="org.springframework.oxm.xstream.XStreamMarshaller" />     
      </constructor-arg>
      <property name="contentType" value="application/xml;charset=UTF-8" />
    </bean>
  </list>
</property>

回答by dbyoung

I was fighting this issue recently and found a much better answer available in Spring 3.1:

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

@RequestMapping(value = "ajax/gethelp", produces = "text/plain")

So, as easy as JAX-RS just like all the comments indicated it could/should be.

因此,就像 JAX-RS 一样简单,就像所有评论都表明它可以/应该一样。

回答by Warrior

I found solution for Spring 3.1. with using @ResponseBody annotation. Here is example of controller using Json output:

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

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

}