谁在Spring MVC中设置响应内容types(@ResponseBody)
我在我的Annotation驱动的Spring MVC Java web应用程序上运行jetty web服务器(目前在maven jetty插件中)。
我想用一个控制器方法来做一些AJAX支持,只返回string帮助文本。 资源采用UTF-8编码,string也是如此,但是我的服务器响应自带
content-encoding: text/plain;charset=ISO-8859-1
即使当我的浏览器发送
Accept-Charset windows-1250,utf-8;q=0.7,*;q=0.7
我用某种方式默认configuration的spring
我已经find了将这个bean添加到configuration的提示,但是我认为它没有被使用,因为它说它不支持编码,而是使用默认的编码。
<bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/plain;charset=UTF-8" /> </bean>
我的控制器代码是(请注意,这种响应types的变化不适合我):
@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; }
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>
但是,使用这种方法你必须重新定义所有的HttpMessageConverter
,而且它不能和<mvc:annotation-driven />
。
所以,也许最方便但很难看的方法是用BeanPostProcessor
拦截AnnotationMethodHandlerAdapter
实例化:
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 " />
我find了Spring 3.1的解决scheme。 使用@ResponseBody注释。 以下是使用Json输出的控制器的示例:
@RequestMapping(value = "/getDealers", method = RequestMethod.GET, produces = "application/json; charset=utf-8") @ResponseBody public String sendMobileData() { }
请注意,在Spring MVC 3.1中,您可以使用MVC命名空间来configuration消息转换器:
<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:
@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 ... } }
以防万一您也可以通过以下方式设置编码:
@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); }
我认为使用StringHttpMessageConverter比这个更好。
您可以将Request =“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); }
看到这个博客更多的细节
我最近在和这个问题作斗争,发现在Spring 3.1中有更好的答案:
@RequestMapping(value = "ajax/gethelp", produces = "text/plain")
所以,像JAX-RS一样简单,就像所有的意见表示它可以/应该是。
我在ContentNegotiatingViewResolver bean的MarshallingView中设置了内容types。 它工作容易,清洁和平稳:
<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>
我正在使用在web.xml中configuration的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>
您可以使用产品来指示您从控制器发送的响应的types。 这个“生成”关键字在ajax请求中最有用,对我的项目非常有用
@RequestMapping(value = "/aURLMapping.htm", method = RequestMethod.GET, produces = "text/html; charset=utf-8") public @ResponseBody String getMobileData() { }
由于digz6666,你的解决scheme适用于我稍作修改,因为我使用的是json:
responseHeaders.add(“Content-Type”,“application / json; charset = utf-8”);
axtavt给出的答案(你推荐的)不会为我工作。 即使我已经添加了正确的媒体types:
if(conv instanceof StringHttpMessageConverter){ ((StringHttpMessageConverter)conv).setSupportedMediaTypes( Arrays.asList( 新的MediaType(“text”,“html”,Charset.forName(“UTF-8”)) new MediaType(“application”,“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 3.1.1中解决这个问题的简单方法是:在servlet-context.xml
添加以下configuration代码
<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>
不需要重写或执行任何操作。
根据链接 “如果没有指定字符编码,则Servlet规范要求使用ISO-8859-1的编码”。如果您使用的是Spring 3.1或更高版本,则使用下面的configuration将charset = UTF-8设置为应对机构
@RequestMapping(value =“你的映射url”,产生=“text / plain; charset = UTF-8”)
如果您决定通过以下configuration解决此问题:
<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>
你应该确认在所有* .xml文件中只应该有一个mvc:annotation-driven标签。 否则,configuration可能无效。
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:
<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>