Openlayers WFS 跨域问题解决思路

    xiaoxiao2021-03-25  56

    文章转载出处:[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 && request.getParameter("targetURL") != "" && 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 > 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 ? OpenLayers.ProxyHost = ‘/OpenlayerProxy.ashx?URL=’;      var url = ‘http://localhost:8090/geoserver/wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&OUTPUTFORMAT=GML2&TYPENAME=pgrouting:Mypgrouting&viewparams=’ + viewparams;          var request = OpenLayers.Request.POST({              url: url,              callback: onComplete          });   OpenLayer3 代理使用 [javascript] view plain copy print ? queryButton.addEventListener(‘click’function (event) {         var viewparams = “ARRAY[[“ + locatearr.join(“],[“) + “]]”;         viewparams = stringReg(viewparams);         viewparams = ”destinationarr:” + viewparams;         var url =‘http://localhost:8090/geoserver/wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&OUTPUTFORMAT=json&TYPENAME=pgrouting:Mypgrouting&viewparams=’ + viewparams;         url = ’/OpenlayerProxy.ashx?URL=’ + encodeURIComponent(url);         $.ajax({             type: ”POST”,             url: url,             dataType:”text”,             success: onComplete         });     });   需要对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 ? function getFeature(options)  {      $.ajax(Global360Val.gisserverhost+’geoserver/wfs’,{          type: ’GET’,          data: {              service: ’WFS’,              version: ’1.1.0’,              request: ’GetFeature’,              typename: options.typename,              srsname: options.srid,              outputFormat: ’text/javascript’,              viewparams:options.viewparams,              bbox:(options.extent===undefined)?undefined:options.extent.join(’,’) +  ‘,’+options.srid,//与filter只能用一个              filter:options.filter          },          dataType: ’jsonp’,          jsonpCallback:’callback:’+options.callback,          jsonp:’format_options’      });    }   [javascript] view plain copy print ?  Source.deviceSource=new ol.source.Vector();      getFeature({          typename:’tb_place_management’,          callback:’loadDevice’      });  function loadDevice(res){      var features=geojsonFormat.readFeatures(res);      Source.deviceSource.addFeatures(features);  }   优点:无需安装插件,取消注释即可。 缺点:jsonb只能get,对于参数过长的url的get会失败。不能post,所以提交xml,或者wfs_t都不行。 完毕!

    转载请注明原文地址: https://ju.6miu.com/read-34422.html

    最新回复(0)