Openlayers WFS 跨域问题解决思路

来源:互联网 发布:如何成为一个美工 编辑:程序博客网 时间:2024/04/27 17:30
文章转载出处:[Openlayers WFS跨域请求](http://blog.csdn.net/freeland1/article/details/41204485)

通常web项目于gis服务器不在同一域下,这就涉及到了wfs跨域问题。

1 c#代理

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Net;using System.IO;namespace WebApplication1{    /// <summary>    /// OpenlayerProxy 的摘要说明    /// </summary>    public class OpenlayerProxy : IHttpHandler    {        public void ProcessRequest(HttpContext context)        {            if (string.IsNullOrEmpty(context.Request["URL"])) return;            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(context.Request["URL"]);            request.UserAgent = context.Request.UserAgent;            request.ContentType = context.Request.ContentType;            request.Method = context.Request.HttpMethod;            byte[] trans = new byte[1024];            int offset = 0;            int offcnt = 0;            if (request.Method.ToUpper() == "POST")            {                Stream nstream = request.GetRequestStream();                while (offset < context.Request.ContentLength)                {                    offcnt = context.Request.InputStream.Read(trans, offset, 1024);                    if (offcnt > 0)                    {                        nstream.Write(trans, 0, offcnt);                        offset += offcnt;                    }                }                nstream.Close();            }            HttpWebResponse response = (HttpWebResponse)request.GetResponse();            //Encoding enc = Encoding.GetEncoding(65001);            context.Response.ContentType = response.ContentType;            StreamReader loResponseStream = new StreamReader(response.GetResponseStream());            string lcHtml = loResponseStream.ReadToEnd();            context.Response.Write(lcHtml);            response.Close();            loResponseStream.Close();        }        public bool IsReusable        {            get            {                return false;            }        }    }}

2 基于java的servlet

package com.nkstar.action;import javax.servlet.http.HttpServlet;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;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;/** * This is a transparent HTTP proxy written in Java that is similar to the proxy * in the OpenLayers examples, which is written in Python. These proxies are * used to circumvent browser restrictions on cross-domain requests with * Javascript. * </p> * <p> * To use the proxy you need to 1) configure the proxy servlet in your web.xml * and 2) use OpenLayers.setProxyHost to set the url-path to the proxy. If the * proxy is configured to listen to the url-pattern '/gwtOpenLayersProxy/*' then * the proxy host should be set to 'gwtOpenLayersProxy?targetURL='. * </p> * Initial code for this proxy is based upon <a href= * "http://trac.openlayers.org/changeset/8099/sandbox?format=diff&new=8099">the * following code</a><br /> * see also <a href= * "http://java.sun.com/docs/books/tutorial/networking/urls/readingWriting.html" * title="this networking tutorial">this networking tutorial</a> * <p> */@SuppressWarnings("serial")public class OpenLayersProxyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,        HttpServletResponse response) throws ServletException, IOException {    processRequest(request, response);}protected void doPost(HttpServletRequest request,        HttpServletResponse response) throws ServletException, IOException {    processRequest(request, response);}private void processRequest(HttpServletRequest request,        HttpServletResponse response) throws ServletException, IOException {    HttpURLConnection connection = null;    InputStream istream = null; // input to proxy    OutputStream ostream = null; // output from proxy    InputStream connectionIstream = null; // output for the target is    // input for the connection    OutputStream connectionOstream = null; // input for the target is    // output for the connection    String remoteHost = request.getRemoteHost(); // get host address of    // client - for checking    // allowedHosts    boolean allowedHost = isAllowedHost(remoteHost); // The allowedHosts    // are the hosts    // that are allowed    // to use the Open    // Proxy.    try {        // easy way to ignore case of param?        if (request.getParameter("targetURL") != null                &amp;&amp; request.getParameter("targetURL") != "" &amp;&amp; allowedHost) {            // HTTPUrlConnection looks at http.proxyHost and http.proxyPort            // system properties.            // Make sure these properties are set these if you are behind a            // proxy.            // step 1: initialize            String requestMethod = request.getMethod();            URL targetURL = new URL(request.getParameter("targetURL"));            connection = (HttpURLConnection) targetURL.openConnection();            connection.setRequestMethod(requestMethod);            transferHTTPRequestHeaders(connection, request);            // step 2: proxy requests            if (requestMethod.equals("GET")) {                // default for setDoInput is true                connectionIstream = connection.getInputStream();            }            ;            if (requestMethod.equals("POST")) {                transferHTTPRequestHeadersForPOST(connection, request);                int clength = request.getContentLength();// clength is                // for checking                // if there is a                // POST body. Is                // that                // sufficient?                if (clength &gt; 0) {                    istream = request.getInputStream();                    connection.setDoOutput(true);// for POST we need to                    // write to connection                    connection.setRequestProperty("Content-Length", Integer                            .toString(clength)); // only valid for POST                    // request                    connectionOstream = connection.getOutputStream();                    // copy the request body to remote outputStream                    copy(istream, connectionOstream);                }                connectionIstream = connection.getInputStream();            }            // step 3: return output            // can output be the same for GET/POST? or different return            // headers?            // servlet may return 3 things: status code, response headers,            // response body            // status code and headers have to be set before response body            response.setContentType(connection.getContentType());            ostream = response.getOutputStream();            copy(connectionIstream, ostream);        }        // if not targetURL send page that targetURL is required param    } catch (Exception e) {        response.setStatus(500); // what will user get? default page for        // response code        // WMS/WFS have specific responses to errors        // response.getWriter();//will writing custom result help        e.printStackTrace();    } finally {        if (istream != null) {            istream.close();        }        if (ostream != null) {            ostream.close();        }        if (connectionIstream != null) {            connectionIstream.close();        }        if (connectionOstream != null) {            connectionOstream.close();        }    }}private void copy(InputStream istream, OutputStream ostream)        throws Exception {    int bufferSize = 4 * 4 * 1024;// same buffer size as in Jetty utils    // (2*8192)    byte[] buffer = new byte[bufferSize];    int read;    while ((read = istream.read(buffer)) != -1) {        ostream.write(buffer, 0, read);    }}private void transferHTTPRequestHeaders(HttpURLConnection connection,        HttpServletRequest request) {    // TODO make sure all headers are copied to target, see for HTTP headers    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html    // Do request.getProperties to get request properties    if (request.getHeader("Accept") != null) {        connection                .setRequestProperty("Accept", request.getHeader("Accept"));    }    if (request.getHeader("Accept-Charset") != null) {        connection.setRequestProperty("Accept-Charset", request                .getHeader("Accept-Charset"));    }    if (request.getHeader("Accept-Encoding") != null) {        // TODO browsers accept gzipped, should proxy accept gzip and how to        // handle it?        // connection.setRequestProperty("Accept-Encoding",        // request.getHeader("Accept-Encoding"));    }    if (request.getHeader("Authorization") != null) {        connection.setRequestProperty("Authorization", request                .getHeader("Authorization"));    }    if (request.getHeader("Connection") != null) {        // TODO HTTP/1.1 proxies MUST parse the Connection header field        // before a message is forwarded and, for each connection-token in        // this field, remove any header field(s) from the message with the        // same name as the connection-token.        // connection.setRequestProperty("Connection",        // request.getHeader("Connection"));    }    // set de-facto standard proxy headers (x-forwarded-for, others?s)    if (request.getHeader("X-Forwarded-For") != null) {        connection.setRequestProperty("X-Forwarded-For", request                .getHeader("X-Forwarded-For"));// TODO append IP proxy    } else {        connection.setRequestProperty("X-Forwarded-For", request                .getRemoteAddr());// TODO append IP proxy    }}private void transferHTTPRequestHeadersForPOST(        HttpURLConnection connection, HttpServletRequest request) {    if (request.getHeader("Content-Type") != null) {        connection.setRequestProperty("Content-Type", request                .getContentType());    } else {        // throw exception?    }}private boolean isAllowedHost(String remoteHost) {    // TODO checking of host    return true;}

}

ashx,servlet这两种直接可以放在web项目当中部署,简单操作。

使用说明
OpenLayer2代理使用,只需在程序开头或init方法第一句写上proxyhost即可。
[javascript] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. OpenLayers.ProxyHost = ‘/OpenlayerProxy.ashx?URL=’;  
  2.   
  3.   var url = ‘http://localhost:8090/geoserver/wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&OUTPUTFORMAT=GML2&TYPENAME=pgrouting:Mypgrouting&viewparams=’ + viewparams;  
  4.         var request = OpenLayers.Request.POST({  
  5.             url: url,  
  6.             callback: onComplete  
  7.         });  
OpenLayer3 代理使用
[javascript] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. queryButton.addEventListener(‘click’function (event) {  
  2.        var viewparams = “ARRAY[[“ + locatearr.join(“],[“) + “]]”;  
  3.        viewparams = stringReg(viewparams);  
  4.        viewparams = ”destinationarr:” + viewparams;  
  5.        var url =‘http://localhost:8090/geoserver/wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&OUTPUTFORMAT=json&TYPENAME=pgrouting:Mypgrouting&viewparams=’ + viewparams;  
  6.        url = ’/OpenlayerProxy.ashx?URL=’ + encodeURIComponent(url);  
  7.        $.ajax({  
  8.            type: ”POST”,  
  9.            url: url,  
  10.            dataType:”text”,  
  11.            success: onComplete  
  12.        });  
  13.    });  

需要对url进行编码,否则代理进去丢失参数。

3 使用cros

3.1 下载地址:http://pan.baidu.com/s/1miDDwJu

3.2 下载后解压,得到的是org/mortbay/servlets/CrossOriginFilter.class文件,把此文件复制到安装目录下的WEB-INF/classes文件夹中,在我电脑上的路径为:GeoServer 2.7.0\webapps\geoserver\WEB-INF\classes\org\mortbay\servlets\CrossOriginFilter.class.

3.3 打开geoserver安装目录下的web.xml文件,我的电脑上路径为:GeoServer 2.7.0\webapps\geoserver\WEB-INF\web.xml

3.4 在filter集合末尾额外添加一个filter:
 <filter>
      <filter-name>cross-origin</filter-name>
      
      <filter-class>org.mortbay.servlets.CrossOriginFilter</filter-class>
      <init-param>
        <param-name>allowedOrigins</param-name>
        <param-value>*</param-value>
      </init-param>
      <init-param>
       <param-name>allowedMethods</param-name>
       <param-value>GET,POST</param-value>
      </init-param>
      <init-param>
       <param-name>allowedHeaders</param-name>
      <param-value>X-Requested-With,Content-Type,Accept,Origin</param-value>
      </init-param>
    </filter> 
3.5 在filter-mapping末尾额外添加一个filter-mapping
<filter-mapping>
        <filter-name>cross-origin</filter-name>
        <url-pattern>/*</url-pattern>    </filter-mapping>
3.6 重启GeoServer服务即可。
优点:post,get跨域请求即可。
–以上针对geoserver2.9以下版本,以独立安装方式,非war包形式安装。

–以下针对>=geoserver2.9版本设置如下:
1 从http://central.maven.org/maven2/org/eclipse/jetty/jetty-servlets/下载对应的jar,比如geoserver2.9依赖的jetty版本号是9.2.13.v20150730,那么就下载该版本的jar。
2 将下载好的 jetty-servlets-9.2.13.v20150730.jar 放到webapps/geoserver下的lib中。
3 配置下webapps/geoserver/web.xml。
<filter>
        <filter-name>cross-origin</filter-name>
        <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>cross-origin</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
4 重启geoserver即可。


4 使用jsonp

4.1  打开geoserver安装目录下的web.xml文件,我的电脑上路径为:GeoServer 2.7.0\webapps\geoserver\WEB-INF\web.xml
4.2 将jsonp注释取消

4.3 重启GeoServer。

4.4 使用示例
[javascript] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. function getFeature(options)  
  2. {  
  3.     $.ajax(Global360Val.gisserverhost+’geoserver/wfs’,{  
  4.         type: ’GET’,  
  5.         data: {  
  6.             service: ’WFS’,  
  7.             version: ’1.1.0’,  
  8.             request: ’GetFeature’,  
  9.             typename: options.typename,  
  10.             srsname: options.srid,  
  11.             outputFormat: ’text/javascript’,  
  12.             viewparams:options.viewparams,  
  13.             bbox:(options.extent===undefined)?undefined:options.extent.join(’,’) +  ‘,’+options.srid,//与filter只能用一个  
  14.             filter:options.filter  
  15.         },  
  16.         dataType: ’jsonp’,  
  17.         jsonpCallback:’callback:’+options.callback,  
  18.         jsonp:’format_options’  
  19.     });  
  20.   
  21. }  
[javascript] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1.  Source.deviceSource=new ol.source.Vector();  
  2.     getFeature({  
  3.         typename:’tb_place_management’,  
  4.         callback:’loadDevice’  
  5.     });  
  6. function loadDevice(res){  
  7.     var features=geojsonFormat.readFeatures(res);  
  8.     Source.deviceSource.addFeatures(features);  
  9. }  
优点:无需安装插件,取消注释即可。
缺点:jsonb只能get,对于参数过长的url的get会失败。不能post,所以提交xml,或者wfs_t都不行。
完毕!





1 0
原创粉丝点击