1.什么是跨域?
简单理解就是JavaScript同源策略的限制,demo1.com域名下的js无法操作demo2.com或是demo3.com域名下的对象, 或者说是一个 Servlet 容器(tomcat)中项目调用另一个 servlet 容器(tomcat)中项目,称为跨域.
2.解决跨域请求可以使用jsonp或者httpclient
这里只介绍jsonp的用法.
httpclient使用思路:由demo1项目访问自己的控制器,自己的控制器访问自己的service,在自己的service中使用httpclient调用的demo2的控制器方法.
3.jsonp: 跨域ajax数据请求的解决方法
ajax不能进行跨域请求(如果 ajax 请求的控制器返回的就是字符串或json数据,不能访问),但是可以在一个项目直接访问另一个项目的 js 文件.
Web页面上调用另一个Web项目的js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如
4. 使用jsonp时服务器端返回的数据格式:
函数名(返回的数据); 例如:functionName({“id”:1,”name”:”张三”})
案例:
新建两个web项目demo1(http://localhost:8081/demo1’)
demo2(http://localhost:8082/demo2)
在demo1项目中一个页面编写代码请求的demo2中的控制器.
(客户端代码)即Demo1请求页面代码:
$(function(){
$("button").click(function(){
$.ajax({
url:'http://localhost:8082/demo2',
type:'post',
dataType:'jsonp',
jsonpCallback:'funtionName',
jsonp:'callback',
success:function(data){
alert(data+"success");
}
});
})
})
备注说明:
- dataType: 一定要设置jsonp
- jsonp: 传递给服务器的参数名. 省略时默认callback
- jsonpCallback: 参数名对应的值,表示最终回调的函数名. 可以省略.
比如上面代码传递参数就是http://localhost:8082/demo2? callback= funtionName
如果jsonCallback不配置,默认名就是 jquery:一堆数字 - 如果直接使用success:function()对jsonpCallback 值没有要求,可以不配置jsonpCallback.
- 如果单独编写了一个 function,必须要求 jsonpCallback 和function的名称相同.
(服务端代码)即Demo2控制器中代码:
@Controller
public class DemoController {
@RequestMapping("demo2")
@ResponseBody
public MappingJacksonValue demo(String callback){
Student stu = new Student();
stu.setId(1);
stu.setName("张三");
//把构造方法参数转换为json字符串并当作最终返回值函数的参数
MappingJacksonValue mjv = new MappingJacksonValue(stu);
//最终返回结果中函数名
mjv.setJsonpFunction(callback);
return mjv;
}
}
备注: 用spring对jackson 封装类MappingJacksonValue,要4.1以上的版本.
启动demo1和demo2项目
从demo1的请求页面点击按钮发送跨域请求: 在浏览器会返回: functionName({“id”:1,”name”:”张三”})
或者直接在浏览器输入http://localhost:8082/demo2? callback= funtionName