最近项目中要使用跨域调用,所以开始研究,虽然简单,中间却也出现不少问题。至于jsonp和跨域的介绍,网上到处都是,此处就不再赘述,有需要的自行查找吧,本文就在直接进入应用了。
ps:跨域需使用两个不同的服务,可以w3c的在线测试作为请求端,自己的服务作为服务端,w3c的在线测试工具,可以通过任意一个“亲自试一试”进入哦。
一. 前台代码
本文前台有两种写法,但是大同小异,不过是远程要不要写js的问题,仅供参考。
1. 不调用远程js
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
function demo(name){
$.ajax({
url : "http://..地址.../Demo/jsonpServlet.do",
data : {
"name" : name
},
dataType : "jsonp",
//jsonp: "callback",
//jsonpCallback: "callbackFun",
success : function(data) {
alert(data.msg);
},
error : function(XMLHttpRequest,error,exp) {
alert("XMLHttpRequest:"+XMLHttpRequest.status+"\nerr:"+error+"\n exp:"+exp);
} //error用于提示错误信息,可不用
});
}
</script>
</head>
<body>
<input type="button" value="click" οnclick="demo('aaa');"/>
</body>
</html>
关于jsonp和jsonpCallback两个参数,在ajax发送请求时,会被发送给服务器,如果不写,jquery会自动生成,jsonp默认为callback,而
jsonpCallback随机生成,如不明白,可再参考本文后台代码部分,以下是w3c原文:
jsonp
在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在 "callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。
为 jsonp 请求指定一个回调函数名。这个值将用来取代 jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>index</title>
<script type="text/javascript" src="js/jquery-1.9.1.js"></script>
<script src="http://--远程地址--/Demo/js/remote.js"></script>
</head>
<body>
<script>
function getData(data){
alert(data);
}
function test(){
demo("admin",getData);
}
</script>
<input type="button" value="click" οnclick="test();"/>
</body>
</html>
function demo(name,callbackFun){
$.ajax({
url : "http://--地址--/Demo/jsonpServlet.do",
data : {
"name" : name
},
dataType : "jsonp",
success : function(data) {
callbackFun(data);
},
error : function(XMLHttpRequest,error,exp) {
alert("XMLHttpRequest:"+XMLHttpRequest.status+"\nerr:"+error+"\n exp:"+exp);
}
});
}
这种方法相对前一种,不过是多传递了函数,这样写的好处是调用端只需要使用数据就可以了,不需要知道服务提供数据的url($.ajax的url部分),服务端可以随意改动服务。
二、服务端后台代码
一个非常简单的servlet
package com.demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JsonpServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json;charset=UTF-8");
String callback = req.getParameter("callback"); //引号中的callback就是上面提到的jsonp默认的参数传递名,通过它可取的回调函数, //即jsonpCallback部分,
String name = req.getParameter("name");
System.out.println("name = "+name+"\tcallback = "+callback);
String msg = null;
if (name.equals("admin")) {
msg = "it is right!";
}else {
msg = "Sorry,it is wrong!";
}
msg = "{'msg':'"+msg+"'}"; //组装json数据
resp.getWriter().write(callback.concat("(").concat(msg).concat(")")); //组装输出格式
resp.getWriter().flush();
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
1. callback.concat("(").concat(msg).concat(")")是组装返回数据的格式,注意一定要组装为这种 “ 回调函数(json数据)”的格式,若只输出json数据,而没有外面的回调函数,会得到parseerror的错误和xxx was not called的异常
2. json中不要有引号等符号,这同样会造成上面的错误。本人就犯了此错误,浪费了大量时间o(╯□╰)o.......