加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Ajax访问Restful API跨域解决方案

发布时间:2020-12-16 01:52:53 所属栏目:百科 来源:网络整理
导读:最近开发API接口时,用Ajax调用远程服务上API的接口时,出现以下错误 : XMLHttpRequest cannot load http://192.168.1.101:8080/CDHAPI/bond/quote/minutely/1m/112188.SZ. No 'Access-Control-Allow-Origin' header is present on the requested resource.

最近开发API接口时,用Ajax调用远程服务上API的接口时,出现以下错误 :

XMLHttpRequest cannot load http://192.168.1.101:8080/CDHAPI/bond/quote/minutely/1m/112188.SZ. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
产生此种问题是由于Ajax跨域限制而引起的问题。Access-Control-Allow-Origin是HTML5中定义的一种服务器端返回Response header,用来解决资源(比如字体)的跨域权限问题。它定义了该资源允许被哪个域引用,或者被所有域引用。

根据这个思路,在服务端返回时在响应体的添加Header,设置Access-Control-Allow-Origin允许可访问的域。具体工作如下:

(1)写一个过滤器,在Reponse中Header中设置Access-Control-Allow-Origin:代码如下:

package com.sumscope.cdh.api.interceptor;

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;


public class CrossFilter implements Filter {
	private static final boolean debug = true;
	private FilterConfig filterConfig = null;
	
	public CrossFilter() {
		super();
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
        if (filterConfig != null) {
            if (debug) {                
                log("CrossFilter:Initializing filter");
            }
        }

	}
	
	 @Override
    public String toString() {
        if (filterConfig == null) {
            return ("CrossFilter()");
        }
        StringBuffer sb = new StringBuffer("CrossFilter(");
        sb.append(filterConfig);
        sb.append(")");
        return (sb.toString());
    }

	@Override
	public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException {
		if (debug) {
			log("CrossFilter:doFilter()");
        }

         if(response instanceof HttpServletResponse){
        	 HttpServletResponse alteredResponse = ((HttpServletResponse)response);
	        // I need to find a way to make sure this only gets called on 200-300 http responses
	        // TODO: see above comment
        	 addHeadersFor200Response(alteredResponse);
         }
         doBeforeProcessing(request,response);

         Throwable problem = null;
         try {
             chain.doFilter(request,response);
         } catch (Throwable t) {
             // If an exception is thrown somewhere down the filter chain,// we still want to execute our after processing,and then
             // rethrow the problem after that.
             problem = t;
             t.printStackTrace();
         }

         doAfterProcessing(request,response);

         // If there was a problem,we want to rethrow it if it is
         // a known type,otherwise log it.
         if (problem != null) {
             if (problem instanceof ServletException) {
                 throw (ServletException) problem;
             }
             if (problem instanceof IOException) {
                 throw (IOException) problem;
             }
             sendProcessingError(problem,response);
         }
       

	}

	@Override
	public void destroy() {

	}
	
	private void doBeforeProcessing(ServletRequest request,ServletResponse response)
            throws IOException,ServletException {
        if (debug) {
            log("CrossFilter:DoBeforeProcessing");
        }

    }    

    private void doAfterProcessing(ServletRequest request,ServletException {
        if (debug) {
        	log("CrossFilter:DoAfterProcessing");
        }
    }
    
    private void addHeadersFor200Response(HttpServletResponse response){
        //TODO: externalize the Allow-Origin
        response.addHeader("Access-Control-Allow-Origin","*");
        response.addHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,PUT,DELETE,HEAD");
        response.addHeader("Access-Control-Allow-Headers","X-PINGOTHER,Origin,X-Requested-With,Content-Type,Accept");
        response.addHeader("Access-Control-Max-Age","1728000");
    }
    
    private void sendProcessingError(Throwable t,ServletResponse response) {
        String stackTrace = getStackTrace(t);        

        if (stackTrace != null && !stackTrace.equals("")) {
            try {
                response.setContentType("text/html");
                PrintStream ps = new PrintStream(response.getOutputStream());
                PrintWriter pw = new PrintWriter(ps);                
                pw.print("<html>n<head>n<title>Error</title>n</head>n<body>n"); //NOI18N

                // PENDING! Localize this for next official release
                pw.print("<h1>The resource did not process correctly</h1>n<pre>n");                
                pw.print(stackTrace);                
                pw.print("</pre></body>n</html>"); //NOI18N
                pw.close();
                ps.close();
                response.getOutputStream().close();
            } catch (Exception ex) {
            }
        } else {
            try {
                PrintStream ps = new PrintStream(response.getOutputStream());
                t.printStackTrace(ps);
                ps.close();
                response.getOutputStream().close();
            } catch (Exception ex) {
            }
        }
    }
    
    public static String getStackTrace(Throwable t) {
        String stackTrace = null;
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            t.printStackTrace(pw);
            pw.close();
            sw.close();
            stackTrace = sw.getBuffer().toString();
        } catch (Exception ex) {
        }
        return stackTrace;
    }
    
    public void log(String msg) {
        filterConfig.getServletContext().log(msg);        
    }


}

在Web.xml配置域名访问过滤器
 <filter>   
    <filter-name>crossFilter</filter-name>
   <filter-class>com.sumscope.cdh.api.interceptor.CrossFilter</filter-class>
 </filter>
<filter-mapping>
   <filter-name>crossFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
ajax调用:
<html>
<meta charset="utf-8">
<script src="jquery.min.js"></script>
<script src="d3.min.js"></script>
<script src="techan.min.js"></script>

<style>

    body {
        font: 10px sans-serif;
    }

    .axis path,.axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
    }

    text.symbol {
        fill: #BBBBBB;
    }

    path {
        fill: none;
        stroke-width: 1;
    }

    path.candle {
        stroke: #000000;
    }

    path.candle.body {
        stroke-width: 0;
    }

    path.candle.up {
        fill: #00AA00;
        stroke: #00AA00;
    }

    path.candle.down {
        fill: #FF0000;
        stroke: #FF0000;
    }

    .close.annotation.up path {
        fill: #00AA00;
    }

    path.volume {
        fill: #DDDDDD;
    }

    .indicator-plot path.line {
        fill: none;
        stroke-width: 1;
    }

    .ma-0 path.line {
        stroke: #1f77b4;
    }

    .ma-1 path.line {
        stroke: #aec7e8;
    }

    .ma-2 path.line {
        stroke: #ff7f0e;
    }

    button {
        position: absolute;
        right: 110px;
        top: 25px;
    }

    path.macd {
        stroke: #0000AA;
    }

    path.signal {
        stroke: #FF9999;
    }

    path.zero {
        stroke: #BBBBBB;
        stroke-dasharray: 0;
        stroke-opacity: 0.5;
    }

    path.difference {
        fill: #BBBBBB;
        opacity: 0.5;
    }

    path.rsi {
        stroke: #000000;
    }

    path.overbought,path.oversold {
        stroke: #FF9999;
        stroke-dasharray: 5,5;
    }

    path.middle,path.zero {
        stroke: #BBBBBB;
        stroke-dasharray: 5,5;
    }

    .analysis path,.analysis circle {
        stroke: blue;
        stroke-width: 0.8;
    }

    .trendline circle {
        stroke-width: 0;
        display: none;
    }

    .mouSEOver .trendline path {
        stroke-width: 1.2;
    }

    .mouSEOver .trendline circle {
        stroke-width: 1;
        display: inline;
    }

    .dragging .trendline path,.dragging .trendline circle {
        stroke: darkblue;
    }

    .interaction path,.interaction circle {
        pointer-events: all;
    }

    .interaction .body {
        cursor: move;
    }

    .trendlines .interaction .start,.trendlines .interaction .end {
        cursor: nwse-resize;
    }

    .supstance path {
        stroke-dasharray: 2,2;
    }

    .supstances .interaction path {
        pointer-events: all;
        cursor: ns-resize;
    }

    .mouSEOver .supstance path {
        stroke-width: 1.5;
    }

    .dragging .supstance path {
        stroke: darkblue;
    }

    .crosshair {
        cursor: crosshair;
    }

    .crosshair path.wire {
        stroke: #DDDDDD;
        stroke-dasharray: 1,1;
    }

    .crosshair .axisannotation path {
        fill: #DDDDDD;
    }

</style>
<body>
<div id="formQuote">
    <input type="text" name="symbol" placeholder="Enter Symbol">
    <input type="button" name="btnQuote" value="Get Quote" />
    <select name="symbolList">
        <option value=""></option>
        <option value="110031.SH">110031.SH</option>
        <option value="112188.SZ">112188.SZ</option>
    </select>
</div>
</body>
<script>
    var api_root = "http://<span style="font-family: Arial,Helvetica,sans-serif;">192.168.1.101</span>:8080/CDHAPI/bond";
    
    var formQuote = $("#formQuote");
    $.extend(formQuote,{
        in_symbol: formQuote.find("input[name=symbol]"),symbol_list: formQuote.find("select[name=symbolList]"),selectSymbol: function() {
            symbol = this.symbol_list.children("option:checked").val();
            this.in_symbol.val(symbol);
        },submit: function() {
            symbol = $.trim(this.in_symbol.val()); 
            if (!symbol.length) {
                alert("Please input a Symbol!");
                return false;
            }
            var url = api_root + "/quote/minutely/1m/" + symbol;
            console.log(url);
            this.showQuoteChart(url);
        },showQuoteChart: function(url) {
            var self = this;
            //d3.csv("data.csv",function(error,data) {
            d3.json(url,data) {
            //d3.json("quote.json",data) {
                var accessor = candlestick.accessor(),indicatorPreRoll = 0;  // Don't show where indicators don't have data
console.log(data);
                data = data.map(function(d) {
                    return {
                        /*
                        date: parseDate(d.Date),open: +d.Open,high: +d.High,low: +d.Low,close: +d.Close,volume: +d.Volume
                        */
                        date: new Date(d.durationTime),open: +d.openCleanPrice,high: +d.highCleanPrice,low: +d.lowCleanPrice,close: +d.closeCleanPrice,volume: +d.volume
                        
                    };
                }).sort(function(a,b) { return d3.ascending(accessor.d(a),accessor.d(b)); });

                x.domain(techan.scale.plot.time(data).domain());
                y.domain(techan.scale.plot.ohlc(data.slice(indicatorPreRoll)).domain());
                yPercent.domain(techan.scale.plot.percent(y,accessor(data[indicatorPreRoll])).domain());
                yVolume.domain(techan.scale.plot.volume(data).domain());

                svg.select("g.candlestick").datum(data).call(candlestick);
                svg.select("g.close.annotation").datum([data[data.length-1]]).call(closeAnnotation);
                svg.select("g.volume").datum(data).call(volume);
                svg.select("g.sma.ma-0").datum(techan.indicator.sma().period(10)(data)).call(sma0);
                svg.select("g.sma.ma-1").datum(techan.indicator.sma().period(20)(data)).call(sma1);
                svg.select("g.ema.ma-2").datum(techan.indicator.ema().period(50)(data)).call(ema2);

                svg.select("g.crosshair.ohlc").call(ohlcCrosshair).call(zoom);

                var zoomable = x.zoomable();
                zoomable.domain([indicatorPreRoll,data.length]); // Zoom in a little to hide indicator preroll

                self.drawChart();

                // Associate the zoom with the scale after a domain has been applied
                zoom.x(zoomable).y(y);
                zoomPercent.y(yPercent);
            });
        },resetChart: function() {
            zoom.scale(1);
            zoom.translate([0,0]);
            this.drawChart();
        },drawChart: function() {
            zoomPercent.translate(zoom.translate());
            zoomPercent.scale(zoom.scale());

            svg.select("g.x.axis").call(xAxis);
            svg.select("g.ohlc .axis").call(yAxis);
            svg.select("g.volume.axis").call(volumeAxis);
            svg.select("g.percent.axis").call(percentAxis);

            // We know the data does not change,a simple refresh that does not perform data joins will suffice.
            svg.select("g.candlestick").call(candlestick.refresh);
            svg.select("g.close.annotation").call(closeAnnotation.refresh);
            svg.select("g.volume").call(volume.refresh);
            svg.select("g .sma.ma-0").call(sma0.refresh);
            svg.select("g .sma.ma-1").call(sma1.refresh);
            svg.select("g .ema.ma-2").call(ema2.refresh);
            svg.select("g.crosshair.ohlc").call(ohlcCrosshair.refresh);
        },initialize: function() {
            var self = this;
            this.find("input[name=btnQuote]").click(function(event) { self.submit(); });
            this.symbol_list.on("change",function(event) { self.selectSymbol(); });
        },});
    formQuote.initialize();
    
/* Techanjs */
    var dim = {
        width: 960,height: 360,margin: { top: 20,right: 50,bottom: 30,left: 50 },ohlc: { height: 305 },};
    dim.plot = {
        width: dim.width - dim.margin.left - dim.margin.right,height: dim.height - dim.margin.top - dim.margin.bottom
    };

    var parseDate = d3.time.format("%d-%b-%y").parse;

    var zoom = d3.behavior.zoom()
            .on("zoom",formQuote.drawChart);

    var zoomPercent = d3.behavior.zoom();

    var x = techan.scale.financetime()
            .range([0,dim.plot.width]);

    var y = d3.scale.linear()
            .range([dim.ohlc.height,0]);

    var yPercent = y.copy();   // Same as y at this stage,will get a different domain later

    var yVolume = d3.scale.linear()
            .range([y(0),y(0.2)]);

    var candlestick = techan.plot.candlestick()
            .xScale(x)
            .yScale(y);

    var sma0 = techan.plot.sma()
            .xScale(x)
            .yScale(y);

    var sma1 = techan.plot.sma()
            .xScale(x)
            .yScale(y);

    var ema2 = techan.plot.ema()
            .xScale(x)
            .yScale(y);

    var volume = techan.plot.volume()
            .accessor(candlestick.accessor())   // Set the accessor to a ohlc accessor so we get highlighted bars
            .xScale(x)
            .yScale(yVolume);

    var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");

    var timeAnnotation = techan.plot.axisannotation()
            .axis(xAxis)
            .format(d3.time.format('%Y-%m-%d'))
            .width(65)
            .translate([0,dim.plot.height]);

    var yAxis = d3.svg.axis()
            .scale(y)
            .orient("right");

    var ohlcAnnotation = techan.plot.axisannotation()
            .axis(yAxis)
            .format(d3.format(',.2fs'))
            .translate([x(1),0]);

    var closeAnnotation = techan.plot.axisannotation()
            .axis(yAxis)
            .accessor(candlestick.accessor())
            .format(d3.format(',0]);

    var percentAxis = d3.svg.axis()
            .scale(yPercent)
            .orient("left")
            .tickFormat(d3.format('+.1%'));

    var percentAnnotation = techan.plot.axisannotation()
            .axis(percentAxis);

    var volumeAxis = d3.svg.axis()
            .scale(yVolume)
            .orient("right")
            .ticks(3)
            .tickFormat(d3.format(",.3s"));

    var volumeAnnotation = techan.plot.axisannotation()
            .axis(volumeAxis)
            .width(35);

    var ohlcCrosshair = techan.plot.crosshair()
            .xScale(timeAnnotation.axis().scale())
            .yScale(ohlcAnnotation.axis().scale())
            .xAnnotation(timeAnnotation)
            .yAnnotation([ohlcAnnotation,percentAnnotation,volumeAnnotation])
            .verticalWireRange([0,dim.plot.height]);

    var svg = d3.select("body").append("svg")
            .attr("width",dim.width)
            .attr("height",dim.height);

    var defs = svg.append("defs");

    defs.append("clipPath")
            .attr("id","ohlcClip")
        .append("rect")
            .attr("x",0)
            .attr("y",0)
            .attr("width",dim.plot.width)
            .attr("height",dim.ohlc.height);

    svg = svg.append("g")
            .attr("transform","translate(" + dim.margin.left + "," + dim.margin.top + ")");

    svg.append('text')
            .attr("class","symbol")
            .attr("x",20)
            .text("Facebook,Inc. (FB)");

    svg.append("g")
            .attr("class","x axis")
            .attr("transform","translate(0," + dim.plot.height + ")");

    var ohlcSelection = svg.append("g")
            .attr("class","ohlc")
            .attr("transform",0)");

    ohlcSelection.append("g")
            .attr("class","axis")
            .attr("transform","translate(" + x(1) + ",0)")
        .append("text")
            .attr("transform","rotate(-90)")
            .attr("y",-12)
            .attr("dy",".71em")
            .style("text-anchor","end")
            .text("Price ($)");

    ohlcSelection.append("g")
            .attr("class","close annotation up");

    ohlcSelection.append("g")
            .attr("class","volume")
            .attr("clip-path","url(#ohlcClip)");

    ohlcSelection.append("g")
            .attr("class","candlestick")
            .attr("clip-path","indicator sma ma-0")
            .attr("clip-path","indicator sma ma-1")
            .attr("clip-path","indicator ema ma-2")
            .attr("clip-path","percent axis");

    ohlcSelection.append("g")
            .attr("class","volume axis");

    // Add trendlines and other interactions last to be above zoom pane
    svg.append('g')
            .attr("class","crosshair ohlc");

    svg.append('g')
            .attr("class","crosshair macd");

    svg.append('g')
            .attr("class","crosshair rsi");

</script>
</html>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读