Spring MVC @ResponseBody响应中文乱码
问题:
在前端通过get请求服务端返回String类型的服务时,会出现中文乱码问题
原因:
由于spring默认对String类型的返回的编码采用的是 StringHttpMessageConverter
>>> spring mvc的一个bug,spring MVC有一系列HttpMessageConverter去处理用@ResponseBody注解的返回值,如返回list则使用MappingJacksonHttpMessageConverter,返回string,则使用StringHttpMessageConverter,这个convert使用的是字符集是iso-8859-1,而且是final的:
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
解决办法:
方案一:
对于需要返回字符串的方法添加注解,如下:只针对单个方法生效,不全局生效
- @RequestMapping(value = "/getUsers", produces = "application/json; charset=utf-8")
- public String getAllUser()throws JsonGenerationException, JsonMappingException, IOException{
- List < User > users = userService.getAll();
- ObjectMapper om = new ObjectMapper();
- System.out.println(om.writeValueAsString(users));
- DataGrid dg = new DataGrid();
- dg.setData(users);
- return om.writeValueAsString(dg);
- }
方案二:
在spring-servlet.xml中加入:
- <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>
方案三:
重写一个MessageConverter,然后注册到AnnotationMethodHandlerAdapter
- package com.h5.common.converter;
- import org.springframework.http.HttpInputMessage;
- import org.springframework.http.HttpOutputMessage;
- import org.springframework.http.MediaType;
- import org.springframework.http.converter.AbstractHttpMessageConverter;
- import org.springframework.util.StreamUtils;
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.nio.charset.Charset;
- import java.util.ArrayList;
- import java.util.List;
- public class EncodingAdapter extends AbstractHttpMessageConverter < String > {
- public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
- private final Charset defaultCharset;
- private final List < Charset > availableCharsets;
- private boolean writeAcceptCharset;
- public EncodingAdapter() {
- this(DEFAULT_CHARSET);
- }
- public EncodingAdapter(Charset defaultCharset) {
- super(new MediaType[]{
- new MediaType("text", "plain", defaultCharset),
- MediaType.ALL
- });
- this.writeAcceptCharset = true;
- this.defaultCharset = defaultCharset;
- this.availableCharsets = new ArrayList(Charset.availableCharsets().values());
- }
- public void setWriteAcceptCharset(boolean writeAcceptCharset) {
- this.writeAcceptCharset = writeAcceptCharset;
- }
- public boolean supports(Class < ? > clazz) {
- return String.class == clazz;
- }
- protected String readInternal(Class < ? extends String > clazz, HttpInputMessage inputMessage)throws IOException {
- Charset charset = this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
- return StreamUtils.copyToString(inputMessage.getBody(), charset);
- }
- protected Long getContentLength(String str, MediaType contentType) {
- Charset charset = this.getContentTypeCharset(contentType);
- try {
- return Long.valueOf((long)str.getBytes(charset.name()).length);
- } catch (UnsupportedEncodingException var5) {
- throw new IllegalStateException(var5);
- }
- }
- protected void writeInternal(String str, HttpOutputMessage outputMessage)throws IOException {
- if (this.writeAcceptCharset) {
- outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
- }
- Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
- StreamUtils.copy(str, charset, outputMessage.getBody());
- }
- protected List < Charset > getAcceptedCharsets() {
- return this.availableCharsets;
- }
- private Charset getContentTypeCharset(MediaType contentType) {
- return contentType != null && contentType.getCharSet() != null ? contentType.getCharSet() : this.defaultCharset;
- }
- }
//注册方法一:
- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
- <property name="messageConverters">
- <util:list>
- <bean class="com.ctrip.hotel.h5.common.converter.EncodingAdapter ">
- <constructor-arg index="0" value="UTF-8"/>
- </bean>
- </util:list>
- </property>
- </bean>
//注册方法二:
在webconfig.java中:
- @Override
- public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
- EncodingAdapter stringConverter = new EncodingAdapter();
- converters.add(0, stringConverter);
- }
方案四:
直接新建一个如下的类,放入代码即可。
- package com.h5.common.encode;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanPostProcessor;
- import org.springframework.http.MediaType;
- import org.springframework.http.converter.HttpMessageConverter;
- import org.springframework.http.converter.StringHttpMessageConverter;
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
- import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
- import java.nio.charset.Charset;
- import java.util.Arrays;
- import java.util.List;
- /**
- * Created by xingyuzhu on 2017/2/27.
- * 解决@ResponseBody返回的响应中中文乱码问题.
- */
- @Component
- public class EncodingPostProcessor implements BeanPostProcessor {
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName)
- throws BeansException{
- if (bean instanceof RequestMappingHandlerAdapter) {
- List < HttpMessageConverter < ? >> convs = ((RequestMappingHandlerAdapter)bean).getMessageConverters();
- for (HttpMessageConverter < ? > conv : convs) {
- if (conv instanceof StringHttpMessageConverter) {
- ((StringHttpMessageConverter)conv).setSupportedMediaTypes(
- Arrays.asList(new MediaType("text", "html",
- Charset.forName("UTF-8"))));
- }
- }
- }
- if (bean instanceof RequestResponseBodyMethodProcessor) {
- List < HttpMessageConverter < ? >> convs = ((RequestMappingHandlerAdapter)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;
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException{
- return bean;
- }
- }
方案五:
在我们的webconfig.java中,注册一个bean:该方法有缺陷RequestMappingHandlerAdapter中的其他messageconverter丢失,导致其他问题,比如返回的是一个jsp页面,就会挂掉
- @Bean
- public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
- RequestMappingHandlerAdapter reqMapHAdapter = new RequestMappingHandlerAdapter();
- ArrayList < HttpMessageConverter < ? >> msgConvs = new ArrayList < > ();
- StringHttpMessageConverter stringConverter = new
- StringHttpMessageConverter(Charset.forName("UTF-8"));
- stringConverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_PLAIN));
- msgConvs.add(stringConverter);
- reqMapHAdapter.setMessageConverters(msgConvs);
- return reqMapHAdapter;
- }
方案六:
在webconfig.java中:
- @Override
- public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
- StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
- converters.add(0, stringConverter);
- }
方案七:(篡改框架的编码,推荐使用)
在webconfig.java中,篡改一下StringHttpMessageConverter的编码方式
- @Override
- public void extendMessageConverters(List < HttpMessageConverter < ? >> converters) {
- HttpMessageConverter converter = Iterables.find(converters, new Predicate < HttpMessageConverter < ? >> () {
- @ Override
- public boolean apply( @ Nullable HttpMessageConverter < ? > input) {
- return input != null && input instanceof StringHttpMessageConverter;
- }
- }, null);
- if (converter == null) {
- StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
- stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "html", Charset.forName(UTF8))));
- converters.add(1, stringConverter); //默认的StringHttpMessageConverter在第二个位置
- return;
- }
- StringHttpMessageConverter stringHttpMessageConverter = (StringHttpMessageConverter)converter;
- stringHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "html", Charset.forName(UTF8))));
- }
Spring MVC @ResponseBody响应中文乱码的更多相关文章
- Spring下@ResponseBody响应中文内容乱码问题
引言: 在JQuery的Ajax请求中,收到的基于后台返回回来的结果出现乱码,在后台其内容正确,到了前台之后,确是乱码??????,该怎样解决呢? 1. 问题的提出 前端基于JQuery的Ajax进 ...
- 解决Spring MVC @ResponseBody返回中文字符串乱码问题
spring mvc使用的默认处理字符串编码为ISO-8859-1 解决方法: 第一种方法: 对于需要返回字符串的方法添加注解,如下: @RequestMapping(value="/use ...
- spring mvc get请求中文乱码问题
使用Spring MVC进行get请求时发现get请求带上中文参数,后台收到的是乱码,即使加了encoding filter也没用. 原因是,encoding filter 是针对post请求的,to ...
- Spring MVC @ResponseBody返回中文字符串乱码问题
朋友做小项目练手的时候遇到的,着实让他郁闷够呛..这个问题的确很恶心.. 项目中引用的json包,直接用@ResponseBody注解返回json字符串..有关这个的乱码问题网上很多,各种花样各种转码 ...
- 解决Spring MVC @ResponseBody出现问号乱码问题
原因是SpringMVC的@ResponseBody使用的默认处理字符串编码为ISO-8859-1,而我们前台或者客户端的编码一般是UTF-8或者GBK.现将解决方法分享如下! 第一种方法: 对于需要 ...
- spring mvc后台接收中文乱码
可从如下几方面着手 1.jsp页面编码 2.web.xml配置字符过滤器,该字符过滤器最好放在开头 3.tomcat下server.xml添加URIEncoding="UTF-8" ...
- spring mvc请求参数中文乱码解决方案
POST 请求 在web.xml中加上增加过滤器 <filter> <filter-name>encodingFilter</filter-name> <fi ...
- 1、spring mvc jsp页面中文乱码
jsp 页面头部 的page标签中加个 contentType="text/html;charset=utf-8"
- Springboot @ResponseBody返回中文乱码
最近我在把Spring 项目改造Springboot,遇到一个问题@ResponseBody返回中文乱码,因为response返回的content-type一直是application/json;ch ...
随机推荐
- Linux中一些约定俗成的文件扩展名
注:Linux中的所有内容均以文件的形式保存,但不依靠扩展名区分文件类型(根据权限区分),约定俗成的文件扩展名是为了方便管理员对文件进行区分 压缩包:“*.gz”.“*.bz2”.“*.tar.bz2 ...
- 企业级监控nagios实践
nagios 监控服务应用指南 小区:视频监控,保安 企业工作中为什么要部署监控系统 监控系统相当于哨兵的作用,监控几百台上千台服务器,监控系统非常重要. 监控系统都需要监控 1. 本地资源:负载up ...
- 【MVC】使用笔记
1,在ASP.NET MVC中,路由机制特别碉堡,直接对应于动作方法.没有必要给每一个动作方法添加视图,当视图返回View时,路由系统会自动寻找指定目录下的视图资源. public ViewResul ...
- python+RobotFramework
今天有人问我,她想在在robot里面用到数据库的一个值的随机数,但是不知道怎么实现,我用python写了一段代码链接数据库给表中所需的字段的值取随机数,代码如下: import random,pymy ...
- LibreOJ2302 - 「NOI2017」整数
Portal Description 有一个整数\(x=0\),对其进行\(n(n\leq10^6)\)次操作: 给出\(a(|a|\leq10^9),b(b\leq30n)\),将\(x\)加上\( ...
- VirtualBox - 虚拟机下主机与虚拟机、虚拟机与虚拟机之间通信配置
看了一下网上别人写的文章:http://www.it165.net/os/html/201401/7063.html 文章里面使用的是Debian,我这里配置的虚拟机系统一个是Ubuntu 14.10 ...
- csu 1600: Twenty-four point
传送门 1600: Twenty-four point Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 490 Solved: 78[Submit][S ...
- HDU 5360 【优先队列+贪心】
题意: 给定N个无序区间. 对合法区间的定义是: 在这个区间之前已经选出了至少l个合法区间,最多选出了r个合法区间.则该区间为合法区间. 输出最多能挑选出多少个合法区间,并输出合法区间的数量. 思路: ...
- 分享一下然让显卡满血复活的小技巧(GTX)
分享一下然让显卡满血复活的小技巧 笔者在玩大型游戏卡顿15fps下载如下操作 GTX950玩大型游戏都不会卡帧率稳定在30fps 下载GeForce Experience下载更新最新驱动 下载如下程序 ...
- oracle字段的所有类型
字段类型 中文说明 限制条件 其它说明 CHAR 固定长度字符串 最大长度2000 bytes VARCHAR2 可变长度的字符串 最大长度4000 ...