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

Java 谁在Spring MVC中设置响应内容类型(@ResponseBody),java,web-applications,spring-mvc,character-encoding,Java,Web Applications,Spring Mvc,Character Encoding,我正在JettyWeb服务器上运行注释驱动的SpringMVCJavaWeb应用程序(目前在maven jetty插件中) 我正在尝试使用一个只返回字符串帮助文本的控制器方法来支持AJAX。资源采用UTF-8编码,字符串也是如此,但我的服务器响应附带了UTF-8编码 content-encoding: text/plain;charset=ISO-8859-1 即使我的浏览器发送 Accept-Charset windows-1250,utf-8;q=0.7,*;q=0.7 我正在使用s

我正在JettyWeb服务器上运行注释驱动的SpringMVCJavaWeb应用程序(目前在maven jetty插件中)

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

content-encoding: text/plain;charset=ISO-8859-1 
即使我的浏览器发送

Accept-Charset  windows-1250,utf-8;q=0.7,*;q=0.7
我正在使用spring的默认配置

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

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

我正在使用在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>

字符编码滤波器
org.springframework.web.filter.CharacterEncodingFilter
编码
UTF-8
强制编码
真的

StringHttpMessageConverter
bean的简单声明是不够的,您需要将其注入
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>
-


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

@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);
}
@RequestMapping(value=“ajax/gethelp”)
public ResponseEntity handleGetHelp(区域设置loc、字符串代码、HttpServletResponse){
HttpHeaders responseHeaders=新的HttpHeaders();
add(“内容类型”,“text/html;charset=utf-8”);
调试(“获取代码帮助:“+code”);
字符串help=messageSource.getMessage(代码,null,loc);
调试(“帮助是:“+Help”);
返回新的ResponseEntity(“返回:+help,responseHeaders,HttpStatus.CREATED”);
}

我认为使用StringHttpMessageConverter比这更好。

谢谢digz6666,您的解决方案对我来说只需稍作改动,因为我使用的是json:

responseHeaders.add("Content-Type", "application/json; charset=utf-8"); add(“内容类型”,“应用程序/json;字符集=utf-8”); 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")) )); } 如果(StringHttpMessageConverter的conv实例){ ((StringHttpMessageConverter)conv).设置支持的媒体类型( Arrays.asList( 新媒体类型(“文本”、“html”、字符集.forName(“UTF-8”), 新的媒体类型(“应用程序”、“json”、Charset.forName(“UTF-8”); }
如果上面这些都不适用于您尝试在“POST”而不是“GET”上发出ajax请求,那么这对我来说非常有用。。。以上这些都没有。我还有characterEncodingFilter

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

在我尝试了很多解决这个问题的方法之后。。我想出来了,效果很好。

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

或基于代码的配置:

@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 ...
  }
}
<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>
@配置
@EnableWebMvc
公共类WebConfig扩展了WebMVCConfigureAdapter{
私有静态最终字符集UTF8=Charset.forName(“UTF-8”);
@凌驾

public void configureMessageConverters(List我在bean的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>

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

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

因此,JAX-RS就像所有评论指出的那样简单。

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

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

}
您可以将products=“text/plain;charset=UTF-8”添加到RequestMapping

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

公共最终类可配置StringHttpMessageConverter扩展AbstractHttpMessageConverter{
私有字符集defaultCharset;
公共字符集getDefaultCharset(){
返回默认字符集;
}
可获得的私人最终清单;
私有布尔writeAcceptCharset=true;
公共可配置StringHttpMessageConverter(){
super(新的MediaType(“text”、“plain”、StringHttpMessageConverter.DEFAULT\u字符集)、MediaType.ALL);
defaultCharset=StringHttpMessageConverter.DEFAULT\u字符集;
this.availableCharsets=newarraylist(Charset.availableCharsets().values());
}
公共可配置StringHttpMessageConverter(字符串字符集名称){
super(新的MediaType(“text”、“plain”、Charset.forName(charsetName))、MediaType.ALL);
defaultCharset=Charset.forName(charsetName);
this.availableCharsets=newarraylist(Charset.availableCharsets().values());
}
/**
*指示是否应将{@code Accept Charset}写入任何传出请求。
*默认值为{@code true}。
*/
public void setWriteAcceptCharset(布尔writeAcceptCharset){
this.writeAcceptCharset=writeAcceptCharset;
}
@凌驾
公共布尔支持(类clazz){
返回字符串.class.equals(clazz);
}
@凌驾
受保护的字符串readInternal(类clazz,HttpInputMessage inputMessage)引发IOException{
Charset Charset=getContentTypeCharset(inputMessage.getHeaders().getContentType());
返回FileCopyUtils.copyToString(新的InputStreamReader(inputMessage.getBody(),charset));
}
@凌驾
受保护的长getContentLength(字符串s,MediaType contentType){
Charset Charset=getContentTypeCharset(contentType);
试一试{
返回(长)s.getBytes(charset.name()).length;
}
捕获(不支持DencodingException ex){
//不应该发生
抛出新的内部错误(例如getMessage());
}
}
@凌驾
受保护的void writeInternal(字符串s,HttpOutputMessage outputMessage)引发IOException{
if(writeAcceptCharset){
outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());
}
Charset Charset=getContentTypeCharset(outputMessage)。
@RequestMapping(value = "/getDealers", method = RequestMethod.GET, 
produces = "application/json; charset=utf-8")
@ResponseBody
public String sendMobileData() {

}
@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);
}
public final class ConfigurableStringHttpMessageConverter extends AbstractHttpMessageConverter<String> {

    private Charset defaultCharset;

    public Charset getDefaultCharset() {
        return defaultCharset;
    }

    private final List<Charset> availableCharsets;

    private boolean writeAcceptCharset = true;

    public ConfigurableStringHttpMessageConverter() {
        super(new MediaType("text", "plain", StringHttpMessageConverter.DEFAULT_CHARSET), MediaType.ALL);
        defaultCharset = StringHttpMessageConverter.DEFAULT_CHARSET;
        this.availableCharsets = new ArrayList<Charset>(Charset.availableCharsets().values());
    }

    public ConfigurableStringHttpMessageConverter(String charsetName) {
        super(new MediaType("text", "plain", Charset.forName(charsetName)), MediaType.ALL);
        defaultCharset = Charset.forName(charsetName);
        this.availableCharsets = new ArrayList<Charset>(Charset.availableCharsets().values());
    }

    /**
     * Indicates whether the {@code Accept-Charset} should be written to any outgoing request.
     * <p>Default is {@code true}.
     */
    public void setWriteAcceptCharset(boolean writeAcceptCharset) {
        this.writeAcceptCharset = writeAcceptCharset;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return String.class.equals(clazz);
    }

    @Override
    protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
        Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType());
        return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
    }

    @Override
    protected Long getContentLength(String s, MediaType contentType) {
        Charset charset = getContentTypeCharset(contentType);
        try {
            return (long) s.getBytes(charset.name()).length;
        }
        catch (UnsupportedEncodingException ex) {
            // should not occur
            throw new InternalError(ex.getMessage());
        }
    }

    @Override
    protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException {
        if (writeAcceptCharset) {
            outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());
        }
        Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType());
        FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset));
    }

    /**
     * Return the list of supported {@link Charset}.
     *
     * <p>By default, returns {@link Charset#availableCharsets()}. Can be overridden in subclasses.
     *
     * @return the list of accepted charsets
     */
    protected List<Charset> getAcceptedCharsets() {
        return this.availableCharsets;
    }

    private Charset getContentTypeCharset(MediaType contentType) {
        if (contentType != null && contentType.getCharSet() != null) {
            return contentType.getCharSet();
        }
        else {
            return defaultCharset;
        }
    }
}
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <util:list>
                <bean class="ru.dz.mvk.util.ConfigurableStringHttpMessageConverter">
                    <constructor-arg index="0" value="UTF-8"/>
                </bean>
            </util:list>
        </property>
    </bean>
@RequestMapping(value = "/aURLMapping.htm", method = RequestMethod.GET, produces = "text/html; charset=utf-8") 

public @ResponseBody String getMobileData() {

}
    <annotation-driven>
    <message-converters register-defaults="true">
    <beans:bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <beans:property name="supportedMediaTypes">    
    <beans:value>text/plain;charset=UTF-8</beans:value>
    </beans:property>
    </beans:bean>
    </message-converters>
    </annotation-driven>
<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>