ajax跨域
一、ajax跨域问题存在的原因
跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)三者完全相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题,比如a标签、script标签、甚至form标签(可以直接跨域发送数据并接收数据)等;
二、 ajax跨域实现
解决跨域的三种方式
- jsonp
JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。
- 添加响应头, 允许跨域
addHeader(‘Access-Control-Allow-Origin:*’); //允许所有来源访问
addHeader(‘Access-Control-Allow-Method:POST,GET’); //允许访问的方式
- 通过代理
服务器A的test01.html页面想访问服务器B的后台action,返回“test”字符串,此时就出现跨域请求,浏览器控制台会出现报错提示,由于跨域是浏览器的同源策略造成的,对于服务器后台不存在该问题,可以在服务器A中添加一个代理action,在该action中完成对服务器B中action数据的请求,然后在返回到test01.html页面。
三、 ajax跨域demo
3.1 jsonp解决跨域请求
前端使用jQuery, 后台使用spring-mvc
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jsonp解决跨域请求</title>
<script type="text/javascript" src="http://libs.baidu.com/jquery/2.1.4/jquery.js"></script>
<script type="text/javascript">
function test(){
$.ajax({
url: 'http://localhost/ajax/test',
type: 'GET',
dataType: 'jsonp', // dataType设置为jsonp格式
success: function(data){
console.log(data)
alert(data)
}
})
}
</script>
</head>
<body>
<button id='test' onclick="test()" value="test">测试</button>
</body>
</html>
后台代码
@Controller()
@RequestMapping("/ajax")
public class AjaxController {
@RequestMapping(value = "/test", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String jsonpTest(@RequestParam(name="callback") String callback){
// 必须要为json格式, 否则前端会报错, 无法解析
String json = "{'name': 'hello'}";
// callback 与 json 用括号拼接
return callback + "("+ json +")";
}
}
测试结果:
3.2 添加响应头, 允许跨域
前端jQuery代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jsonp解决跨域请求</title>
<script type="text/javascript" src="http://libs.baidu.com/jquery/2.1.4/jquery.js"></script>
<script type="text/javascript">
function test3(){
$.ajax({
url: 'http://localhost/ajax/test3',
type: 'GET',
success: function(data){
console.log(data)
alert(data)
}
})
}
function test4(){
$.ajax({
url: 'http://localhost/ajax/test4',
type: 'GET',
success: function(data){
console.log(data)
alert(data)
}
})
}
</script>
</head>
<body>
<button id='test' onclick="test3()" value="test">测试3</button>
<button id='test' onclick="test4()" value="test">测试4</button>
</body>
</html>
添加响应头, 允许跨域, 这种方式不要求返回数据一定为json格式; spring-mvc中有两种实现方式:
- 方式一: 通过CrossOrigin注解
CrossOrigin(origins="", maxAge="")
origins表示跨域来源,*即任何来源; maxAge 缓存相应时间
@Controller()
@RequestMapping("/ajax")
public class AjaxController {
@CrossOrigin(origins = "*")
@RequestMapping(value = "/test3")
@ResponseBody
public String jsonTest3(){
return "hello";
}
}
测试3结果:
- 方式二: 通过在HttpServletResponse对象中设置响应头
Access-Control-Allow-Origin
@Controller()
@RequestMapping("/ajax")
public class AjaxController {
@RequestMapping(value = "/test4")
@ResponseBody
public String jsonTest4(HttpServletResponse response){
response.addHeader("Access-Control-Allow-Origin","*");
return "hello world";
}
}
测试4结果:
3.3 通过配置文件的方式允许跨域
在web.xml中配置
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
使用这个Filter即可让整个服务器全局允许跨域;