[Spring MVC] @ResponseBody返回结果乱码问题的解决

发现问题

在Controller类方法上加@ResponseBody,直接返回字符串,结果乱码。
如下所示:

MockHttpServletResponse:
              Status = 200
       Error message = null
             Headers = {Content-Type=[text/plain;charset=ISO-8859-1], Content-Length=[45]}
        Content type = text/plain;charset=ISO-8859-1
                Body = {
 "Msg":"???????????????nameEntTypeCode??"
}

用浏览器访问也是乱码。

分析问题

1、分析日志

日志级别设为DEBUG,查看日志,节选如下:
(1)
 <Method [handleRuleException] returned [{
 "Msg":"调用时规则时未传入必要参数:“nameEntTypeCode”。"
}]>
到这里还是对的。Handle调用完成,获得了返回值,接下来归View了。
(2)
ModelAndViewMethodReturnValueHandler@12eae9c] supports [class java.lang.String]>
web.method.annotation.ModelMethodProcessor@12c50a4] supports [class java.lang.String]>
web.servlet.mvc.method.annotation.ViewMethodReturnValueHandler@56a5b] supports [class java.lang.String]>
web.servlet.mvc.method.annotation.HttpEntityMethodProcessor@9463a0] supports [class java.lang.String]>
web.method.annotation.ModelAttributeMethodProcessor@1aad6f4] supports [class java.lang.String]>
web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor@1c45fa4] supports [class java.lang.String]>
快找到元凶了。
accept.PathExtensionContentNegotiationStrategy$JafMediaTypeFactory]
        Loading Java Activation Framework FileTypeMap from class path resource
                [org/springframework/mail/javamail/mime.types]    //默认支持的类型是从这里读取的

mvc.method.annotation.AbstractMessageConverterMethodProcessor<Written [{
"Msg":"调用时规则时未传入必要参数:“nameEntTypeCode”。"
}] as "text/plain;charset=ISO-8859-1" using [org.springframework.http.converter.StringHttpMessageConverter@1efa83c]>
找到元凶。他是怎样作案的呢?
我猜,大概是StringHttpMessageConverter注入了AbstractMessageConverterMethodProcessor。
“text/plain;charset=ISO-8859-1”是StringHttpMessageConverter的属性。

2、尝试解决

(1)AbstractMessageConverterMethodProcessor是抽象类,在StringHttpMessageConverter上想办法。
(2)
如果org.springframework.http.converter.StringHttpMessageConverter是单例,可以自己配置一下看看
<bean id="stringHttpMessageConverter"
  class="org.springframework.http.converter.StringHttpMessageConverter">
  <property name="supportedMediaTypes">
   <list>
    <value>text/plain;charset=UTF-8</value>
   </list>
  </property>
 </bean>
 在<xxx>-servlet.xml中配置无效。确认放在<mvc:annotation-driven>之前了。
 (3)注入的姿势不对,还是老实看看Spring源代码吧

3、寻找注入口

(1)
 RequestMappingHandlerAdapter构造函数中:
 public RequestMappingHandlerAdapter() {
       StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
       ...
      this.messageConverters.add(stringHttpMessageConverter);
 }
 直接这么new啊,太粗暴了。
 这只是默认行为,应该有覆盖办法的。
(2)
 跟代码,跟到
 private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
  List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();

  // Single-purpose return value types
  handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));

  // Annotation-based return value types
  handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
}
 
 然后找到:
  public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
          this.messageConverters = messageConverters;
 }

(3)

试试看:
 <mvc:annotation-driven>
     <mvc:message-converters>
         <bean class="org.springframework.http.converter.StringHttpMessageConverter">
          <property name="supportedMediaTypes">
     <list>
      <value>text/plain;charset=UTF-8</value>
     </list>
    </property>
         </bean>
     </mvc:message-converters>
 </mvc:annotation-driven>
 
这就是老版本的报错吧:
cvc-complex-type.2.1: 元素 'mvc:annotation-driven' 必须不含字符或元素信息项 [子级], 因为该类型的内容类型为空。
看mvc命名空间中xsd版本。
好吧,就是这里:
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

(4)

修正,好了:
MockHttpServletResponse:
              Status = 200
       Error message = null
             Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[79]}
        Content type = text/plain;charset=UTF-8
                Body = {
 "Msg":"调用时规则时未传入必要参数:“nameEntTypeCode”。"
}
       Forwarded URL = null
      Redirected URL = null
             Cookies = []

总结

1、遇到问题多看日志,多看代码。

2、Spring MVC注入口很多,太爽了,但应该谨慎使用,考虑影响范围。

3、HttpMessageConverter是神器,可以完成传入参数和返回值的转换,通过自定义Media Type可实现神奇效果,有机会好好研究下。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring中使用@ResponseBody注解返回结果时,可能会遇到中文码的问题解决这个问题可以通过配置消息转换器来指定字符编码为UTF-8。 在代码中,可以添加如下配置来解决中文问题: ```xml <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/html; charset=UTF-8"/> <property name="defaultCharset" value="UTF-8"/> </bean> </mvc:message-converters> ``` 这段配置会将返回的字符串转换成UTF-8编码的字符。 另外,还可以在Spring配置文件中启用注解驱动的Spring MVC功能,这样也可以解决中文码的问题: ```xml <mvc:annotation-driven> <!-- 解决ResponseBody返回码 --> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/html; charset=UTF-8"/> <property name="defaultCharset" value="UTF-8"/> </bean> </mvc:message-converters> </mvc:annotation-driven> ``` 这样配置后,@ResponseBody注解返回的结果就不会出现中文码的问题了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [spring+mybatis 通过@ResponseBody返回结果中文码的解决方法](https://download.csdn.net/download/weixin_38631225/12766950)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [解决@ResponseBody注解返回中文码](https://blog.csdn.net/hh680821/article/details/104730498)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值