`
Josh_Persistence
  • 浏览: 1650117 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

(二)Java 中文乱码学习 与Spring @ResponseBody中的乱码 - Spring @ResponseBody中的乱码

阅读更多

        第二篇、Spring @ResponseBody中的乱码

 

一、在开始本篇之前,可以参照上一篇关于Java中的乱码的基本知识:

http://josh-persistence.iteye.com/blog/2084971

 

二、如果在Spring的@Responsbody返回的内容中,发现乱码,需要从以下几方面来解决。

 

1. 确保在web.xml中配置Spring的Character Encoding Filter:

 

 

<!-- Servlet Encoding Start -->
    <filter>
        <filter-name>Set Character Encoding</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>
    <filter-mapping>
        <filter-name>Set Character Encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- Servlet Encoding End -->

 

 

2. 如果在@ResponseBody注释的方法下的返回值类型是String,则在结果返回给用户之前,如果在Spring的配置文件中配置了<mvc:annotation-driven />,则Spring默认会去调用一个叫StringHttpMessageConverter

的类进行内容的输出。为什么会出现乱码呢?

  解决方法1:       查看StringHttpMessageConverter的源码,发下StringHttpMessageConverter类中的默认编码是ISO-8859-1编码,改编码是西欧字符集编码,显然不会支持中文。(PS:感觉这是Spring的bug,明显应该用UTF-8嘛,我已经在Spring官网上中报了这个bug)

 

public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");

private final Charset defaultCharset;

private final List<Charset> availableCharsets;

 

 

而且从上面的代码中可以看出,与字符相关的3个变量都是final的,意味着我们不能通过set或者构造器的注入去动态的更改上面3个值。

 

进一步分析源码可以看出,StringHttpMessageConverter继承与AbstractHttpMessageConverter<String>,分析该抽象类得,相关的操作字符编码的方法可以重写,于是我们可以自定义一个类继承StringHttpMessageConverter,然后重写相关的方法,代码如下:

 

/**
 * 
 */
package com.chuanliu.platform.activity.basic.converter;



import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.StreamUtils;

/**
 * 用于处理中文乱码问题: Spring bug -
 * 
 * In StringHttpMessageConverter, the default char set is ISO-8859-1(西欧字符集)
 * 
 * @author Josh Wang(Sheng)
 *
 * @email  josh_wang23@hotmail.com
 */
public class UTF8StringHttpMessageConverter extends StringHttpMessageConverter {

        private static final MediaType UTF8 = new MediaType("text", "plain", 
           Charset.forName("UTF-8"));

	private boolean writeAcceptCharset = true;
	
	@Override
	protected void writeInternal(String s, HttpOutputMessage outputMessage)
			throws IOException {
		if (this.writeAcceptCharset)
			outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());
		
		Charset charset = UTF8.getCharSet();
		
		StreamUtils.copy(s, charset, outputMessage.getBody());
		
	}

	@Override
	protected List<Charset> getAcceptedCharsets() {
		return Arrays.asList(UTF8.getCharSet());
	}

	@Override
	protected MediaType getDefaultContentType(String t) throws IOException {
		return UTF8;
	}

	public boolean isWriteAcceptCharset() {
		return writeAcceptCharset;
	}

	public void setWriteAcceptCharset(boolean writeAcceptCharset) {
		this.writeAcceptCharset = writeAcceptCharset;
	}
	
	
}

 

 

定义好上面的类后,只需要将该类注册到Spring的annotaion 处理序列中即可,于是当@ResponseBody中返回的类型是String类型时,Spring将会调用上面自定义类中复写的方法,从而返回UTF-8的编码:

 

 

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
    <bean class="com.chuanliu.platform.activity.basic.converter.UTF8StringHttpMessageConverter"/>
  </mvc:message-converters>
</mvc:annotation-driven>  

 

 

解决方法2:最简单的方法:

在@Responsebody标注的方法上加上:produces="application/json;charset=utf-8"

如:

@RequestMapping(value="/circle/{cid}", produces="application/json;charset=utf-8")
@ResponseBody

 

 

解决方法3:指定返回值为对象不要返回String

既然上面分析了其原因是上面的StringHttpMessageConverter类中使用了ISO-8859-1编码,那么如果业务逻辑允许,我们完全可以不要返回一个字符串(String),完全可以返回一个对象,这样Spring默认会去调用一个叫MappingJackson2HttpMessageConverter的类,该类不仅会将你返回的对象转换成JSON返回,而且该类中使用的是我们想要的UTF-8字符集,相关代码为:

 

 

public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

 

 

这种方法其实也是种很好的方法,因为更多的时候我们希望我们返回的对象直接转换成一个json字符串返回。如果你想判断Spring中最终有没有调用:MappingJackson2HttpMessageConverter或者是StringHttpMessageConverter或者是自定义的UTF8StringHttpMessageConverter的方法,你可以在这两个类的源码的writeInternal()等方法中设置断点。如果没有按期望的去调用MappingJackson2HttpMessageConverter中的writeInternal()等方法,则可能你需要配置让Spring对默认返回的视图按Json来处理,在我的应用中,我只只需要在如下的内容协商器中设置json viewer即可:

 

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    
	    <!-- 设置为true以忽略对Accept Header的支持 -->
	    <property name="ignoreAcceptHeader" value="true" />
	   	
	   	<!-- 在没有扩展名时即: "/user/1" 时的默认展现形式 -->
	    <property name="defaultContentType" value="text/html" />
    
   		<!-- 扩展名至mimeType的映射,即 /user.json => application/json -->
	    <property name="mediaTypes">
	        <map>
	            <entry key="html" value="text/html"/>    
	            <entry key="json" value="application/json" />
	            <entry key="xml" value="application/xml" />
	        </map>
	    </property>
    
    	<!-- 用于开启 /userinfo/123?format=json 的支持,false为关闭之,其实.json的方式更简洁 -->
    	<property name="favorParameter" value="false" />
    
    	<property name="viewResolvers">
	        <list>
	            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
	                <bean
	                    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	                    <property name="prefix" value="/WEB-INF/jsp/"></property>
	                    <property name="suffix" value=".jsp"></property>
	                </bean>
	        </list>
    	</property>

		<property name="defaultViews">
	        <list>
				<!-- for application/json -->
	            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
	        </list>
    	</property>
	</bean> 
 
	

    <!-- Default view resolver will be used if the upper resolve unavailable(the default format is html) -->
    <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="3">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="contentType" value="text/html"/>        
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- json view -->
<!--     <bean id="defaultJsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/> -->
    

 

 

0
0
分享到:
评论

相关推荐

    springMVC3使用@ResponseBody向浏览器返回 json,注意区分jar包前缀

    --处理 @ResponseBody 中文乱码问题 --&gt; &lt;bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"&gt; &lt;property name="messageConverters"&gt; &lt;list&gt; &lt;!-- Support...

    spring+mybatis 通过@ResponseBody返回结果中文乱码的解决方法

    spring+mybatis 通过@ResponseBody返回结果中文乱码的解决方法 在使用 Spring+Mybatis 框架时,经常会遇到一个问题,就是通过 @ResponseBody 返回结果时,中文字符会出现乱码的问题。这是因为在 Spring MVC 中,...

    SpringMVC中解决@ResponseBody注解返回中文乱码问题

    本文将详细介绍如何解决SpringMVC中`@ResponseBody`注解返回中文乱码的问题。 首先,我们可以尝试使用`@RequestMapping`注解的`produces`属性来指定响应内容的MIME类型和字符集。例如: ```java @RequestMapping...

    Spring MVC中默认的ResponseBody为String的乱码问题.pdf

    在Spring MVC框架中,开发者经常遇到ResponseBody返回的字符串出现乱码的问题,特别是当字符串中包含中文字符时。这是因为Spring MVC默认使用了StringHttpMessageConverter来处理Response Body中的字符串,而这个...

    json 中文乱码解决方案

    本文将详细介绍如何解决JSON中的中文乱码问题,并提供几种简单实用的方法来帮助开发者避免这类问题的发生。 #### 一、问题背景与原因分析 在Web开发中,前后端之间传递的数据格式往往采用JSON(JavaScript Object ...

    SSM框架整合(解决中文乱码,二级缓存,JSON,事务)

    这个项目包针对的是在实际开发中可能会遇到的一些常见问题,如中文乱码、二级缓存、JSON处理以及事务管理。以下是这些知识点的详细解释: 1. **Spring**:作为核心容器,Spring提供依赖注入(DI)和面向切面编程(AOP)...

    jackon 2.9.1

    总结来说,Jackson 2.9.1是一个用于处理JSON的Java库,常与Spring MVC结合使用,通过`@ResponseBody`注解实现将Java对象直接转换为JSON并返回给客户端。在实际应用中,需要注意依赖包的正确引入,以及处理字符集以...

    SpringMVC解决乱码

    然而,在使用SpringMVC时,可能会遇到乱码问题,例如在使用@ResponseBody注解时返回的数据出现乱码。在本文中,我们将讨论解决SpringMVC乱码问题的两种方法。 方法一:配置AnnotationMethodHandlerAdapter 在...

    flex上传下载 并解决中文乱码

    在本主题中,我们将深入探讨如何使用Flex进行文件上传和下载,并解决过程中可能出现的中文乱码问题。 一、Flex文件上传 1. Flex组件:Flex中可以使用`FileReference`组件来实现文件上传。用户通过选择文件后,`...

    spring mvc 自學筆記

    在 Spring MVC 中处理中文乱码通常有两种方法: - **设置字符编码过滤器**:通过配置一个全局的字符编码过滤器来解决所有请求的乱码问题。 ```java @WebFilter(urlPatterns = "/*") public class ...

    用ajax传递json到前台中文出现问号乱码问题的解决办法

    后来发现,因为在controller中返回json用了@ResponseBody,而spring源码中@ResponseBody 的实现类发现其默认的编码是 iso-8859-1,而项目用的编码为utf-8,所以传中文会出现乱码。 这里我使用了注解来解决: @...

    Spring MVC面试题(2022最新版)

    如何解决POST请求中文乱码问题,GET的又如何处理呢? - 对于POST请求,可以在web.xml中配置字符编码过滤器,确保所有请求都使用统一的字符编码: ```xml &lt;filter-name&gt;characterEncodingFilter&lt;/filter-name&gt; ...

    Java Web项目中Spring框架处理JSON格式数据的方法

    在Java Web项目中,Spring框架通过Spring MVC提供了一种灵活的方式来处理JSON格式的数据。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有易于人阅读和编写,易于机器解析和生成等特点。由于其...

    Spring MVC面试宝典1.pdf

    ##### 3.4 如何解决POST请求中文乱码问题,GET的又如何处理呢? - **POST请求**:在web.xml中配置过滤器CharacterEncodingFilter来设置字符编码。 - **GET请求**:同样可以通过配置过滤器解决,也可以通过修改Tomcat...

    基于java反射机制的山寨版WEB2

    在"基于Java反射机制的山寨版WEB2"项目中,开发者利用这一特性创建了一个简易的Web应用程序,实现了文件上传下载、处理中文乱码、NEW和SPRING模式的支持以及JSON数据交互等功能。 1. **文件上传下载与中文乱码处理*...

    base64,java与JavaScript实现

    ### 关于Base64编码及Java与JavaScript的实现 #### Base64简介 Base64是一种将二进制数据转换为ASCII字符串表示形式的方法。它主要用于处理非文本数据的存储和传输,例如图像、视频等多媒体文件。由于互联网传输...

    Java面试框架高频问题2019

    **问题八:如何解决POST请求中文乱码问题,GET的又如何处理呢?** - POST请求可以通过配置过滤器解决。 - GET请求需要在客户端编码为UTF-8。 **问题九:SpringMVC的异常处理?** - 使用`@ControllerAdvice`和`@...

    Spring MVC注解开发总结

    在Spring MVC框架中,注解开发使得我们能够更简洁、高效地编写Web应用程序。下面将对标题和描述中提到的知识点进行详细总结。 一、Spring MVC注解开发的基本实现步骤 1. **创建Web工程**:首先需要创建一个Java ...

    springmvc-restful

    在IT行业中,Spring MVC是一个广泛使用的Java Web框架,它提供了构建高效、灵活和模块化的Web应用程序的能力。在处理RESTful API时,Spring MVC扮演着核心角色。本篇将深入探讨"springmvc-restful"主题,特别是关于...

    SpringMVC+Mybatis JAVA配置 非XML

    1,搭建SpringMVC 2,加载properties配置文件 3,集成mybatis ...7,解决@ResponseBody return String的中文乱码问题 8,配置静态资源映射ResourceHandlers 9,配置ViewControllers 10,配置filter 11,配置拦截器

Global site tag (gtag.js) - Google Analytics