作者:Lily
在项目开发中,使用WFS数据服务做一些数据方面的操作的时候,经常会遇到跨域的问题,那么今天我就给大家介绍一下如何通过代理来解决WFS跨域的问题。
下面是我们在前端对WFS服务做操作的时候常遇到的问题:
XMLHttpRequest cannot load
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:xxxx' is therefore not allowed access.
很显然这是跨域的问题,那么我先简单的介绍一下什么是跨域,跨域就是因为JavaScript同源策略的限制,通俗的说就是一个站点中的资源去访问另外一个不同域名站点上的资源,比如说通过 style 标签加载外部样式表文件、通过 img 标签加载外部图片、通过 script 标签加载外部脚本文件、通过 Webfont 加载字体文件等等。同源策略如下:
遇到跨域问题一般都有多种解决方案,既然本文用代理解决,我也就说一下什么是代理。代理,通俗的讲就是一个传递媒介,它将客户端向服务器发送的请求进行传递和处理。一个完整的代理请求过程为:
1)客户端把向服务器发送的请求交给代理; 2) 代理接收并处理请求;3)代理将请求发送到服务器;4)服务器接收请求并将结果返回给代理;5)代理再将结果返回给客户端。
下面我以一个案例的形式帮助大家理解到底如何使用代理解决跨域问题:
首先,创建一个工程项目,该项目的目的是使用WFS服务做一个几何查询服务,并将查询结果在前端渲染显示,这里将这个项目命名为ky,新建一个html文件同样命名为ky,将所要实现的功能写进这个html里面,这时候在浏览器中访问这个html页面做查询操作,如下图,没有返回结果:
并且浏览器会报跨域的错误。例如本例的:
XMLHttpRequest cannot load
http://192.168.15.99:8090/iserver/services/data-world/wfs100. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.
那么如何解决呢,请看下面的操作步骤:
1、将工程文件夹(如本例ky)拷贝到iserver的webapps这个目录下。
2、将代理文件放在iserver webapps里的工程目录下,这个代理文件可以根据自己项目情况写一个,也可以在网上下载,下面是本例中用到的一个代理jsp文件(注:supermap iserver服务器中自带的有这个文件,文件位置为iserver解压包里的iClient\forJavaScript\examples目录下)。jsp的处理过程为:
1) 接收客户端请求传递的参数 2) 将参数重新组合 3) 通过java.net.URL构造构造新的HTTP请求 4) 读取请求返回的内容 5) 组合返回的内容再发回给客户端。
下面是实现的代码:
<%@page session="false"%>
<%@page import="java.net.*,java.io.*" %>
<%@ page pageEncoding="UTF-8" isELIgnored="false" %>
<%
try {
String reqUrl = request.getParameter("url");
URL url = new URL(reqUrl);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestProperty("content-type", "application/xml; charset=UTF-8");
con.setDoOutput(true);
con.setRequestMethod(request.getMethod());
//con.setCharacterEncoding("UTF-8");
int clength = request.getContentLength();
if(clength > 0) {
con.setDoInput(true);
byte[] idata = new byte[clength];
//String s = String.ValueOf(clength);
//System.out.println(clength);
BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
String line1 = null;
StringBuilder sb = new StringBuilder();
while((line1 = br.readLine())!=null){
sb.append(line1);
}
//request.getInputStream().read(idata, 0, clength);
//String test=String.valueOf(idata);
//System.out.println(sb);
//OutputStreamWriter out=new OutputStreamWriter(con.getOutputStream());
//out.write(new String(sb.toString().getBytes("ISO-8859-1")));
byte[] paradata = sb.toString().getBytes();
con.getOutputStream().write(paradata);
}
response.setContentType(con.getContentType());
BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream(),"UTF-8"));
String line;
StringBuilder sb1 = new StringBuilder();
while ((line = rd.readLine()) != null) {
out.println(line);
sb1.append(line);
}
rd.close();
} catch(Exception e) {
System.out.println(0);
System.out.println(e);
response.setStatus(500);
}
%>
3、 发送代理请求,按照这样的请求格式:SuperMap.ProxyHost= "项目地址/Proxy.jsp?url="
,注意url参数中特殊字符需要转码。将这段代码写入项目中能够访问到的位置
例如本例中我是将" SuperMap.ProxyHost= http://localhost:8090/ky/Proxy.jsp?url=”
这段代码放在init()
这个方法里面
4、 最后通过IP加端口号的形式访问发布后的项目就不会出现跨域的问题了,下图为查询成功所返回的结果:
以下链接是我对这个方法测试的一个例子,供大家参考,系统是发布在我本地的,WFS服务是在另外一台服务器上,在项目中代理请求的位置在ky.html的第123行:
http://download.csdn.net/detail/supermapsupport/9743816