Ajax访问Restful API跨域解决方案
最近开发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-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>
相关推荐
kentrl 2020-11-10
结束数据方法的参数,该如何定义?-- 集合为自定义实体类中的结合属性,有几个实体类,改变下标就行了。<input id="add" type="button" value="新增visitor&quo
ajaxyan 2020-11-09
zndy0 2020-11-03
学留痕 2020-09-20
Richardxx 2020-11-09
learningever 2020-09-19
chongxiaocheng 2020-08-16
ajaxhe 2020-08-16
lyqdanang 2020-08-16
curiousL 2020-08-03
TONIYH 2020-07-22
时光如瑾雨微凉 2020-07-19
83510998 2020-07-18
坚持着执着 2020-07-16
jiaguoquan00 2020-07-07
李永毅 2020-07-05
坚持着执着 2020-07-05