最近接触的项目,很多都是JS跨域提交请求数据的。所以自己私下翻了一些资料,整合了一个网上朋友的东西。自己做了一个简单的跨域提交的功能。
通常AJAX跨域提交,是被浏览器所禁止的。如果想通过跨域提交,可以使用JQUERY的JSONP,也可以用iframe,也可以使用代理。
我这里就使用代理方法去实现。原理就是:两个工程A和B,A中的JS提交请求到A中的代理类,代理类去请求B中的数据,并返回给代理类,代理类再返回给页面A。
首先是目标工程B,工程名:aaa的类:是个简单的Servlet
public class QueryInfoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String method = request.getParameter("method");
method = new String(method.getBytes("ISO-8859-1"),"UTF-8");
System.out.println("方法:" + method);
//可查询数据库,为了简单方便直接返回数据
String jsonStr = "[{\"方法名\":\""+method+"\",\"citys\":[{\"cityId\":\"010\", \"cityName\":\"北京\"},{\"cityId\":\"021\", \"cityName\":\"上海\"},{\"cityId\":\"022\", \"cityName\":\"天津\"},{\"cityId\":\"023\", \"cityName\":\"重庆\"}]}]";
response.setContentType("text/json;charset=UTF-8");
response.getWriter().write(jsonStr);
}
}
下面是工程A,工程名bbb的代理类:也是个简单的Servlet
public class ProxyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String param = request.getParameter("param");
URL connect = new URL("http://127.0.0.1:8080/aaa/queryInfo");
HttpURLConnection connection = (HttpURLConnection) connect.openConnection();
//设置提交方式
connection.setRequestMethod("POST");
//是否允许缓存
connection.setUseCaches(false);
//是否允许传递参数
connection.setDoOutput(true);
// 发送查询条件
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
// 参数实际上是普通的GET传参,method=城市查询&info=中国城市
String content = "method=" + URLEncoder.encode("城市查询", "UTF-8");
content += "&info=" + URLEncoder.encode("中国城市", "UTF-8");
out.writeBytes(content);
out.flush();
out.close();
StringBuffer data = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
data.append(line);
}
response.setContentType("text/json;charset=UTF-8");
response.getWriter().write(data.toString());
}
}
有了代理类,下面是JSP页面了:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%String path = request.getContextPath();%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" language="javascript" src="jquery.min.js"></script>
<script type="text/javascript">
function queryCity(){
$.ajax({
url:'/bbb/proxy', //提交请求到代理类,代理类去访问目标工程的数据
data:{
param : "ajaxtest"
},
async : true,
dataType : 'json',
error : function(){
alert('error');
},
success : function(data){
alert(data[0].citys[0].cityName);
}
});
}
</script>
</head>
<body>
<a href=javascript:queryCity()>查询城市</a><br/>
<div id="cityInfo"></div>
</body>
</html>
下面拓展上面的练习,引用跨域的JS来实现。
首先在aaa工程中写index.js,代码如下:
//声明Namespace
Namespace = new Object();
//根据传入的名字进行注册,以点号为分隔符,分别对其进行注册
Namespace.register = function(nsName){
var nsArr = nsName.split('.');
var strEval = "";
var strNS = "";
for (var i = 0; i < nsArr.length; i++){
if (i != 0){
strNS += ".";
}
strNS += nsArr[i];
//将要执行注册的名称,叠加成字符串
strEval += "if(typeof(" + strNS + ") == 'undefined' || !strNS){" + strNS + " = new Object();}"
}
//通过eval统一执行叠加的字符串
if(strEval != ""){
eval(strEval);
}
}
//注册命名空间
Namespace.register("xb.proxy");
Namespace.register("xb.cityInfo");
var proxyUrl = null;
var clientUrl = null;
xb.proxy = function(){
function registerProxy(proxyUrlValue, clientUrlValue){
proxyUrl = proxyUrlValue;
clientUrl = clientUrlValue;
}
return {
registerProxy : registerProxy
};
}();
xb.cityInfo = function() { //采用闭包的方式进行封装。
function queryCity(id, name, area, callProxyAjaxBack) {
if(proxyUrl == null || proxyUrl == ""){ //查询
$.ajax({
url:'/aaa/queryInfo',
data:{
id : id,
name : name,
area : area
},
async : true,
dataType : 'json',
error : function(){
alert('查询出错,远程JS请使用代理方式查询!');
},
success : function(data){
callProxyAjaxBack(data);
}
});
}else{ //走代理
var params = "";
params += "&id=" + id;
params += "&name=" + name;
params += "&area=" + area;
//var params = "&id=010&name="+encodeURIComponent("北京")+"&area="+encodeURIComponent("华北地区");
$.ajax({
url:proxyUrl,
data:{
targetUrl : clientUrl + '/aaa/queryInfo',
params : params
},
async : true,
dataType : 'json',
error : function(){
alert('远程JS代理查询出错!');
},
success : function(data){
callProxyAjaxBack(data);
}
});
}
}
return {
queryCity : queryCity
};
}();
aaa工程的servlet查询方法:
package com.zyujie.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class QueryInfoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
System.out.println("查询的城市是:" + name);
String jsonStr = "[{\"结果\":\""+name+"\",\"citys\":[{\"cityId\":\"010\", \"cityName\":\"北京\", \"population\" : \"2114.8万\", \"desc\":\"中华人民共和国的首都、直辖市和国家中心城市,也是中国的政治、文化、科教和国际交往中心,中国经济、金融的决策和管理中心,也是中华人民共和国中央人民政府和全国人民代表大会的办公所在地\"}]}]";
if(name.equals("北京")){
jsonStr = "[{\"结果\":\""+name+"\",\"citys\":[{\"cityId\":\"010\", \"cityName\":\"北京\", \"population\" : \"2114.8万\", \"desc\":\"中华人民共和国的首都、直辖市和国家中心城市,也是中国的政治、文化、科教和国际交往中心,中国经济、金融的决策和管理中心,也是中华人民共和国中央人民政府和全国人民代表大会的办公所在地\"}]}]";
}else if(name.equals("上海")){
jsonStr = "[{\"结果\":\""+name+"\",\"citys\":[{\"cityId\":\"021\", \"cityName\":\"上海\", \"population\" : \"2500万\", \"desc\":\"上海(Shanghai),简称“沪”,有“东方巴黎”的美称,中华人民共和国直辖市之一,中国国家中心城市,中国的经济、金融中心,繁荣的国际大都市,拥有中国大陆首个自贸区“中国(上海)自由贸易试验区\"}]}]";
}else if(name.equals("广州")){
jsonStr = "[{\"结果\":\""+name+"\",\"citys\":[{\"cityId\":\"020\", \"cityName\":\"广州\", \"population\" : \"1292.68万\", \"desc\":\"广州,简称穗,别称羊城、花城,广东省省会,位于广东省中南部,东江、西江、北江交汇处,珠江三角洲北缘,濒临中国南海\"}]}]";
}else if(name.equals("成都")){
jsonStr = "[{\"结果\":\""+name+"\",\"citys\":[{\"cityId\":\"028\", \"cityName\":\"成都\", \"population\" : \"1417万\", \"desc\":\"成都,四川省省会 ,成都位于中国华西地区东部,成都平原腹地,古为蜀国地,秦并巴、蜀为蜀郡并建城,汉因织锦业发达专设锦官管理,故有“锦官城”之称,五代蜀时遍种芙蓉,故别称“芙蓉城”,简称“蓉”。成都约在公元前5世纪中叶的古蜀国构筑城池,三国时期为蜀汉国都。巴蜀文化在这里留下了丰富的历史遗迹\"}]}]";
}else{
jsonStr = "[{\"结果\":\""+name+"\",\"citys\":[]}]";
}
//可查询数据库,为了简单方便直接返回数据
//String jsonStr = "[{\"方法名\":\""+method+"\",\"citys\":[{\"cityId\":\"010\", \"cityName\":\"北京\"},{\"cityId\":\"021\", \"cityName\":\"上海\"},{\"cityId\":\"022\", \"cityName\":\"天津\"},{\"cityId\":\"023\", \"cityName\":\"重庆\"}]}]";
response.setContentType("text/json;charset=UTF-8");
response.getWriter().write(jsonStr);
}
}
然后bbb工程代理类,一个servlet:
package com.my.servlet;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ProxyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String targetUrl = request.getParameter("targetUrl");
String params = request.getParameter("params");
URL connect = new URL(targetUrl);
HttpURLConnection connection = (HttpURLConnection) connect.openConnection();
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setDoOutput(true);
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
System.out.println(params);
out.writeBytes(params);
out.flush();
out.close();
StringBuffer data = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
data.append(line);
}
System.out.println(data.toString());
response.setContentType("text/json;charset=UTF-8");
response.getWriter().write(data.toString());
}
}
bbb工程的jsp,引用aaa工程中的index.js:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%String path = request.getContextPath();%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" language="javascript" src="jquery.min.js"></script>
<script type="text/javascript" language="javascript" src="http://127.0.0.1:7002/aaa/index.js"></script>
<script type="text/javascript" language="javascript">
function proxyFunc(){
var id = "010";
var name = "北京";
var area = "华北地区";
var str = prompt("输入要查询的城市信息","北京");
if(str){
name = str;
}
xb.proxy.registerProxy("/bbb/proxy", "http://127.0.0.1:7002");
xb.cityInfo.queryCity(id, encodeURIComponent(name), encodeURIComponent(area), function(data){
if(data[0].citys.length == 0){
document.getElementById("cityInfo").innerHTML = "<br/>查询的城市:" + name +" 无返回结果";
}else{
document.getElementById("cityInfo").innerHTML = "<br/>城市编号:" + data[0].citys[0].cityId + "<br/>城市名称:" + data[0].citys[0].cityName + "<br/>人口:" + data[0].citys[0].population + "<br/>" + data[0].citys[0].desc;
}
});
}
</script>
</head>
<body>
<a href=javascript:queryCity()>查询城市</a><br/>
<a href=javascript:proxyFunc()>代理查询城市</a><br/>
<div id="cityInfo"></div>
</body>
</html>
这样就完成引用外部js,代理实现js跨域提交的功能了。