Qui définit le contenu de la réponse-type au printemps MVC (@Responsabilebody)

j'ai dans mon Annotation Le printemps MVC Java web application tournant sur le serveur web de jetty (actuellement dans le plugin de maven jetty).

j'essaye de faire du support AJAX avec une méthode de controller retournant juste du texte D'aide String. Les ressources sont codées en UTF-8, tout comme la chaîne de caractères, mais ma réponse du serveur est

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

même lorsque mon navigateur envoie

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

j'utilise en quelque sorte la valeur par défaut configuration du ressort

j'ai trouvé un indice pour ajouter ce bean à la configuration, mais je pense qu'il n'est pas utilisé, parce qu'il dit qu'il ne supporte pas l'encodage et un par défaut est utilisé à la place.

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

mon code de contrôleur est (notez que ce changement de type de réponse ne fonctionne pas pour moi):

@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;
}
114
demandé sur Henry 2010-09-01 12:49:15

16 réponses

la simple déclaration du haricot StringHttpMessageConverter n'est pas suffisante, vous devez l'injecter dans 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>

Cependant, en utilisant cette méthode, vous devez redéfinir tous les HttpMessageConverter s, et aussi il ne fonctionne pas avec <mvc:annotation-driven /> .

donc, peut-être la méthode la plus commode mais laide est d'intercepter l'instanciation du AnnotationMethodHandlerAdapter avec 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 " />
57
répondu axtavt 2011-03-01 18:06:12

j'ai trouvé la solution pour le printemps 3.1. avec l'utilisation d'une annotation @Responsibleebody. Voici un exemple de contrôleur utilisant la sortie Json:

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

}
145
répondu Warrior 2012-08-08 14:33:15

notez qu'au printemps MVC 3.1 Vous pouvez utiliser L'espace de noms MVC pour configurer les convertisseurs de messages:

<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>

ou configuration basée sur le code:

@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 ...
  }
}
48
répondu Rossen Stoyanchev 2012-10-08 16:48:27

juste au cas où vous pouvez aussi définir l'encodage de la manière suivante:

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

je pense qu'utiliser StringHttpMessageConverter est mieux que ça.

43
répondu digz6666 2011-03-14 00:58:43

vous pouvez ajouter produces = "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);
}

voir ce blog pour plus de détails

19
répondu Charlie Wu 2013-02-28 06:12:34

je luttais contre cette question récemment et j'ai trouvé une bien meilleure réponse disponible au printemps 3.1:

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

donc, aussi facile que JAX-RS comme tous les commentaires l'ont indiqué, il pourrait/devrait être.

10
répondu dbyoung 2012-07-21 06:21:42

j'ai défini le type de contenu dans la vue marshalling dans le ContentNegotiatingViewResolver bean. Il fonctionne facilement, propre et en douceur:

<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>
4
répondu Reto-san 2012-08-03 09:47:07

vous pouvez utiliser les produits pour indiquer le type de réponse que vous envoyez à partir du contrôleur. Ce mot-clé" produit "sera très utile dans la requête ajax et a été très utile dans mon projet

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

public @ResponseBody String getMobileData() {

}
4
répondu Balasubramanian Jayaraman 2013-05-27 10:34:57

j'utilise le fileur de caractères, configuré en web.XML. Peut-être cela peut vous aider.

    <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>
3
répondu Theresia Sofia Snow 2010-09-01 09:25:06

merci digz6666, votre solution fonctionne pour moi avec un léger changement parce que j'utilise json:

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

la réponse donnée par axtavt (ce que vous avez recommandé) ne fonctionnera pas pour moi. Même si j'ai ajouté le type de média correct:

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")) ));
                }
3
répondu redochka 2011-03-12 13:32:24

si aucun de ce qui précède a fonctionné pour vous essayer de faire des requêtes ajax sur "POST" pas "GET" , qui a fonctionné pour moi bien ... aucun de ces a fait. J'ai aussi le characterEncodingFilter.

2
répondu Marius 2011-04-06 12:13:29
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");
    }
}

après que j'ai essayé beaucoup de contournement pour cette question.. J'ai pensé à ça et ça marche très bien.

2
répondu Szilard Jakab 2011-07-22 22:05:46

le moyen simple de résoudre ce problème au printemps 3.1.1 est le suivant: Ajouter les codes de configuration suivants dans servlet-context.xml

    <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>

N'a pas besoin de remplacer ou de mettre en œuvre quoi que ce soit.

2
répondu AdaroMu 2013-10-11 06:42:35

selon le lien "si un codage de caractères n'est pas spécifié, la spécification de Servlet exige qu'un codage de ISO-8859-1 soit utilisé".Si vous utilisez spring 3.1 ou une version plus récente, utilisez la configuration fallowing pour régler charset=UTF-8 sur le corps de réponse.

@ RequestMapping (valeur = "your mapping url", produit = "text/plain;charset=UTF-8")

1
répondu Ramesh Papaganti 2015-08-04 06:04:34

si vous décidez de corriger ce problème par la configuration suivante:

<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>

vous devez confirmer que seul un mvc:annotation-driven balise dans tous vos *.fichier xml. sinon, la configuration peut ne pas être efficace.

1
répondu Lich 2017-03-16 01:56:41
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;
        }
    }
}

configuration de L'échantillon:

    <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>
0
répondu Igor Kostomin 2012-08-22 08:54:18