来源:forYounker的专栏 - CSDNBlog
转自:http://blog.csdn.net/forYounker/archive/2007/08/28/1761817.aspx
Ajax从诞生那天起,xmlHttprequest对象不能跨域请求的问题就一直存在。跨域请求,简单来说,本地的HTML文件只能够访问本地的XML数据源,而不能够访问到其他服务器上的XML数据源文件。xmlHttprequest对象这种特性,是基于网络的安全策略。这些我在这里不详细展开。xmlHttprequest的这种安全策略,在提供安全性的同时,也引进一些限制,如,读取异域的RSS。
解决Ajax跨域问题,目前大概有4种方案。下面我重点讲述目前流行的解决方案---用服务器代理(中间过渡)的解决方案。中间过渡,就是在Ajax与不同域的服务器进行通讯的中间加一层过渡,这一层过渡可以是PHP、JSP、ASP、Servlet等任何具备网络通讯功能的语言,由中间层向不同域的服务器进行读取数据的操作。
下面我用Servlet为服务器代理,用Step by Step的方式,以一个读取异域RSS的例子,讲述这种解决方案。
<!--[if !supportLists]-->1、 <!--[endif]-->首先在MyEclipse中,建立一个web project。然后,新建一个html文件,取名为ReadRSS.html.
此html文件的作用包括:
(1)、向本地服务器发送请求,通过本地服务器中的Servlet,向远程服务器拿rss文件。代码为:XML_Http_Request.open("GET",url,true); //true---异步; false---同步。注意,这里的url为:var url="proxyServlet?RSS_URL="+url; 这里的proxyServlet是本地服务器上的文件。
(2)、显示rss文件。processRequest函数将rss文件打印出来。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
代码如下:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ReadRSS</title>
<script language="javascript">
var XML_Http_Request = false;
function createXMLHttpRequest(){
XML_Http_Request = false;
if(window.XMLHttpRequest){ //for Mozilla
XML_Http_Request = new XMLHttpRequest();
if(XML_Http_Request.overrideMimeType){
XML_Http_Request.overrideMimeType("text/xml");
}
}
else if(window.ActiveXObject){ //for IE
try{
XML_Http_Request = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
XML_Http_Request = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){}
}
}
}
function send_Request(url){
/*The function send_request has some other parameters.
function send_request(url,Parameter1,Parameter2,...,Parametern){
*/
var url="proxyServlet?RSS_URL="+url;
createXMLHttpRequest();
if(!XML_Http_Request){
window.alert("Cannot create XMLHttpRequest instance!");
return false;
}
XML_Http_Request.onreadystatechange = processRequest;
/*The function processRequest has some parameters.
XML_Http_Request.onreadystatechange = function(){
processRequest(Parameter1,Parameter2,...,Parametern);
};
*/
XML_Http_Request.open("GET",url,true); //true---异步; false---同步
XML_Http_Request.send(null);
}
function processRequest(){
/*The function processRequest has some parameters.
function processRequest(Parameter1,Parameter2,...,Parametern){
*/
if(XML_Http_Request.readyState == 4) {
if(XML_Http_Request.status == 200) {
/*******************************************************************************/
//statements
var results = XML_Http_Request.responseXML;
var title = null;
var item = null;
var link = null;
var description = null;
var ccc = results.getElementsByTagName("channel");
var headtitle = ccc[0].getElementsByTagName("title")[0].firstChild.nodeValue;
var headlink = ccc[0].getElementsByTagName("link")[0].firstChild.nodeValue;
var cell = document.createElement("div");
cell.innerHTML = "<h1><a href="+headlink+" target=_blank>"+headtitle+"</a></h1><br>";
document.getElementById("result").appendChild(cell);
var items = results.getElementsByTagName("item");
for(var i = 0; i < items.length; i++) {
item = items[i];
link=item.getElementsByTagName("link")[0].firstChild.nodeValue;
title = item.getElementsByTagName("title")[0].firstChild.nodeValue;
var cell = document.createElement("div");
cell.innerHTML = "<li><a href="+link+" target=_blank>"+title+"</a></li><br>";
document.getElementById("result").appendChild(cell);
}
/*******************************************************************************/
}
}
}
</script>
</head>
<body onLoad="javascript:send_Request('http://localhost:7001/AjaxProxy/rss2.xml'); ">
<div id="result">
</div>
</body>
</html>
<!--[if !supportLists]-->2、 <!--[endif]-->新建一个servlet,命名为ProxyServlet.java。修改web.xml文件,<url-pattern>ProxyServlet</url-pattern>,以匹配html向本地服务器请求的地址。这样,将html与servlet连接起来,让servlet来获取异域rss的xml文件。ProxyServlet.java主要功能是将异域rss的xml文件response出来。
代码如下:
package action;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ProxyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private int READ_BUFFER_SIZE = 1024;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String urlString = request.getParameter("RSS_URL");
writeResponse(response, urlString);
}
private void writeResponse(HttpServletResponse response, String urlString) throws ServletException{
try {
URL url = new URL(urlString);
URLConnection urlConnection = url.openConnection();
response.setContentType(urlConnection.getContentType());
InputStream ins = urlConnection.getInputStream();
OutputStream outs = response.getOutputStream();
byte[] buffer = new byte[READ_BUFFER_SIZE];
int bytesRead = 0;
while ((bytesRead = ins.read(buffer, 0, READ_BUFFER_SIZE)) != -1) {
outs.write(buffer, 0, bytesRead);
}
System.out.println(outs);
outs.flush();
outs.close();
ins.close();
} catch (Exception e) {
try {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
} catch (IOException ioe) {
throw new ServletException(ioe);
}
}
}
}