博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringMVC跨域乱码问题
阅读量:6673 次
发布时间:2019-06-25

本文共 3285 字,大约阅读时间需要 10 分钟。

hot3.png

2013-04-11 /  ,  ,   /  ,  ,  ,  ,   / 2,863 views

最近的工作重点转移至web开发,使用框架主要还是spring mvc, jackson, jQuery,但在开发中又遭遇了n年前的跨域问题,jsonp乱码问题,其实这些问题产生原因很简单,但实际上解决起来却需要了解各种机制运行内幕.

解决方案

  • 在web.xml中设置CharacterEncodingFilter,相信绝大多数乱码问题均可以解决,这其中的原理不用再讲解,毕竟这个filter的代码非常简单.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
    
<
!
--
Character
Encoding
filter
--
>
    
<
filter
>
        
<
filter
-
name
>
encodingFilter
<
/
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
>
encodingFilter
<
/
filter
-
name
>
        
<
url
-
pattern
>
/
*
<
/
url
-
pattern
>
        
<
dispatcher
>
REQUEST
<
/
dispatcher
>
        
<
dispatcher
>
FORWARD
<
/
dispatcher
>
    
<
/
filter
-
mapping
>
 

由于我使用的是spring mvc并且提供ajax访问,但在部署服务时出现了跨域问题,好在我使用的jQuery已经提供了解决跨域访问的方案,你只需要在原来的访问地址上加上?callback=?即可
当ajax请求发起时,jQuery会将callback赋值,而服务端也需要在业务处理完毕后将此参数做为方法名,而json串做为方法参数一起返回给jQuery,让其回调.
1
2
3
4
5
 
$
.
getJSON
(
host
+
"api/service/a.json?callback=?"
,
function
(
data
)
{
  
// TODO callback方法
}
 

这里JSON_FORMAT = “.json”,整个value等同于请求地址,method表示请求方式,由于jsonp只支持get方法,这里将设置成GET方法,最后将文档类型设定为json,而jsonMapper则是springside的一个工具类,这也算是jsonp最简单的封装方式了.

测试通过成功跨域调用,但很不幸出现了乱码.那么为什么在不跨域时对象成功返回,而跨域后却出现乱码呢?这还是需要对照两者的实现方式

1
2
3
4
5
6
7
8
9
 
// 跨域请求
@RequestMapping
(
value
=
"a"
+
JSON_FORMAT
,
method
=
RequestMethod
.
GET
,
        
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
@ResponseBody
public
String
doit
(
@RequestParam
(
@RequestParam
(
"callback"
)
String
callback
)
{
    
return
jsonMapper
.
toJsonP
(
callback
,
new
Object
(
)
)
;
}
 
1
2
3
4
5
6
7
8
9
 
// 非跨域请求
@RequestMapping
(
value
=
"a"
+
JSON_FORMAT
,
method
=
RequestMethod
.
GET
,
        
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
@ResponseBody
public
Object
doit
(
)
{
    
return
new
Object
(
)
;
}
 

在非跨域请求中,它会默认使用MappingJackson2HttpMessageConverter将对象转成json串,而它使用的编码格式是utf-8,所以这里不会出现乱码问题.

而当我们使用成jsonp后,由于返回对象是String对象,那么它将使用StringHttpMessageConverter进行转换,但这里的编码格式是ISO-8859-1,所以会出现乱码.
所以第一种最容易想到的方案就出来了,即按照ISO-8859-1的方式构造一个新的字符串

1
2
3
4
5
6
7
8
 
@RequestMapping
(
value
=
"a"
+
JSON_FORMAT
,
method
=
RequestMethod
.
GET
,
        
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
@ResponseBody
public
String
doit
(
@RequestParam
(
@RequestParam
(
"callback"
)
String
callback
)
{
    
return
new
String
(
jsonMapper
.
toJsonP
(
callback
,
new
Object
(
)
)
.
getBytes
(
"UTF-8"
)
,
Charset
.
forName
(
"ISO-8859-1"
)
)
;
}
 

虽然这种方式可以解决乱码,但明显创建了很多无用对象,并且每一次都要这样转换很麻烦,那么有没有更简单的方式呢,答案是肯定的

1
2
3
4
5
6
7
8
 
@RequestMapping
(
value
=
"a"
+
JSON_FORMAT
,
method
=
RequestMethod
.
GET
,
        
produces
=
MediaType
.
APPLICATION_JSON_VALUE
+
CHARSET
)
@ResponseBody
public
String
doit
(
@RequestParam
(
@RequestParam
(
"callback"
)
String
callback
)
{
    
return
jsonMapper
.
toJsonP
(
callback
,
new
Object
(
)
)
;
}
 

只需要在produces后指定编码格式即可,为了方便使用我将它定义成常量,方便后期使用

1
2
3
 
private
final
static
String
CHARSET
=
";charset=UTF-8"
;
 

这样就完美解决了乱码问题.

当然,网上还有不少自定义Converter的方法,这些方法可解决乱码问题,但不能解决跨域问题,因为它将整个字符串都加上了””,而jQuey不会认为其是方法只以为是普通字符串从而不能调用,针对不同场景还需要使用不同方式进行处理.

转载于:https://my.oschina.net/CasparLi/blog/339142

你可能感兴趣的文章
动态权限<三>华为小米特殊机制
查看>>
linux基本命令学习01
查看>>
Freebsd for ECS 系统盘扩容示例
查看>>
IPad分屏,当电脑第二显示屏
查看>>
kprobe原理解析
查看>>
String的线程安全
查看>>
云服务提供商告诉您云服务器对营销型网站的重要性
查看>>
前端通信:ajax设计方案(七)--- 增加请求错误监控、前端负载均衡以、请求宕机切换以及迭代问题修复...
查看>>
软硬件一体提高主链性能,「HPB芯链」想构建区块链版的云计算
查看>>
python中用string.maketrans和translate巧妙替换字符串
查看>>
全面深入认识C变量
查看>>
C语言嵌入式系统编程修炼之道——内存操作篇 原创21cnbao2005-10-19 22:06:00评论(0)...
查看>>
深思熟虑后做出的决定
查看>>
MYSQL中TIMESTAMP类型的默认值
查看>>
用C#动态创建Access数据库
查看>>
安全事件标准化
查看>>
分享B2B信息发布小技巧
查看>>
深入剖析微软ASP.NET Ajax中的数据绑定构架下篇之一
查看>>
选择最适合你的Linux学习方法
查看>>
JQuery ajax调用asp.net的webMethod
查看>>