最近开发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, ServletResponse response)
throws IOException, ServletException {
if (debug) {
log("CrossFilter:DoAfterProcessing");
}
}
private void addHeadersFor200Response(HttpServletResponse response){
//TODO: externalize the Allow-Origin
response.addHeader("Access-Control-Al