tutorial restcontroller responseentity responsebody requestbody mvc example java web-applications spring-mvc character-encoding

java - restcontroller - Quién establece el tipo de contenido de respuesta en Spring MVC(@ResponseBody)



spring rest return image (16)

Tengo en mi aplicación web Spring MVC Java accionada por Annotation ejecutada en el servidor web jetty (actualmente en maven jetty plugin).

Estoy tratando de hacer algo de compatibilidad con AJAX con un método de controlador que solo devuelve el texto de ayuda de Cadena. Los recursos están en codificación UTF-8 y también la cadena, pero mi respuesta del servidor viene con

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

incluso cuando mi navegador envía

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

Estoy usando de alguna manera la configuración predeterminada de la primavera

He encontrado una pista para agregar este bean a la configuración, pero creo que simplemente no se usa, porque dice que no es compatible con la codificación y en su lugar se usa una predeterminada.

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

Mi código de controlador es (tenga en cuenta que este cambio de tipo de respuesta no funciona para mí):

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


De acuerdo con el link "Si no se especifica una codificación de caracteres, la especificación del servlet requiere que se utilice una codificación de ISO-8859-1" .Si está utilizando el resorte 3.1 o posterior, use la siguiente configuración para configurar charset = UTF-8 en cuerpo de respuesta
@RequestMapping (value = "su url de mapeo", produce = "text / plain; charset = UTF-8")


Encontré una solución para Spring 3.1. con el uso de la anotación @ResponseBody. Aquí hay un ejemplo de controlador usando salida Json:

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


Establecí el tipo de contenido en MarshallingView en el bean ContentNegotiatingViewResolver . Funciona de manera fácil, limpia y sin problemas:

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


Estoy usando CharacterEncodingFilter, configurado en web.xml. Tal vez eso ayude.

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


Estuve luchando contra este problema recientemente y encontré una respuesta mucho mejor disponible en Spring 3.1:

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

Entonces, tan fácil como JAX-RS al igual que todos los comentarios indicaron que podría / debería ser.


Gracias digz6666, tu solución funciona para mí con ligeros cambios porque estoy usando json:

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

La respuesta dada por axtavt (que has recomendado) no funcionará para mí. Incluso si agregué el tipo de medio correcto:

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


La declaración simple del bean StringHttpMessageConverter no es suficiente, necesita StringHttpMessageConverter en 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>

Sin embargo, con este método debe redefinir todos los HttpMessageConverter y tampoco funciona con <mvc:annotation-driven /> .

Entonces, quizás el método más conveniente pero feo es interceptar la BeanPostProcessor de instancias de AnnotationMethodHandlerAdapter con 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 " />


La forma más simple de resolver este problema en Spring 3.1.1 es que: agregue los siguientes códigos de configuración en 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>

No es necesario anular o implementar nada.


Puede usar produce para indicar el tipo de respuesta que está enviando desde el controlador. Esta palabra clave "produce" será más útil en la solicitud de ajax y fue muy útil en mi proyecto

@RequestMapping(value = "/aURLMapping.htm", method = RequestMethod.GET, produces = "text/html; charset=utf-8") public @ResponseBody String getMobileData() { }


Solo en caso de que también pueda establecer la codificación de la siguiente manera:

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

Creo que usar StringHttpMessageConverter es mejor que esto.


Tenga en cuenta que en Spring MVC 3.1 puede usar el espacio de nombres MVC para configurar los convertidores de mensajes:

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

O configuración basada en código:

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


puede agregar produce = "text / plain; charset = UTF-8" a 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); }

mira este blog para más detalles


si decide solucionar este problema a través de la siguiente configuración:

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

debe confirmar que solo debe haber una etiqueta mvc: anotada en todo su archivo * .xml. de lo contrario, la configuración puede no ser efectiva.


si ninguno de los anteriores funcionó para usted, intente hacer que las peticiones ajax en "POST" no "GET", eso funcionó bien para mí ... ninguna de las anteriores sí lo hizo. También tengo el 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"); } }

Después de haber intentado solucionar este problema ... lo pensé y funciona bien.


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

Configuración de muestra:

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