AJAX跨域完全讲解
AJAX跨域完全讲解今天在慕课网上学习了AJAX跨域完全讲解:https://www.imooc.com/learn/947 我在收集AJAX面试题的时候其实就已经有过AJAX跨域的问题的了,当时候知道了为什么会存在跨域,以及跨域解决的方案有哪些,今天随着课程的学习,又加深了AJAX跨域的理解,以此记录下来。 为什么会发生产生跨域问题?上面的图也很清晰了,因为浏览器为了安全(同源),本身就限制了。
值得注意的是:跨域的问题是发生在XMLHttpRequest请求的,也就是说,不是XMLHttpRequest请求是不会有跨域问题的
解决跨域问题的思路明显地,跨域的问题是由于浏览器限制的,是XMLHttpRequest才会发生的,那么我们可以以这个思路去找找解决思路:
对于浏览器的问题,可以使用相关的参数进行启动浏览器,是可以解决跨域的问题,但是通用性是极低的,了解即可。 JSONP解决跨域JSONP是JSON使用的一种补充方式,不是官方的协议。JSONP是一种解决跨域问题的一种协议 JSONP这种解决方案其实现在已经很少用了(复杂一点,需要修改后台代码),但我们可以适当了解一下。 使用步骤在后端增加一个控制器,继承AbstractJsonpResponseBodyAdvice类,完整代码如下: @ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() { // TODO Auto-generated constructor stub super("callback2"); } } 前端ajax请求: // 服务器返回的结果 var result; $.ajax({ url: base +"/get1",dataType: "jsonp",jsonp: "callback2",//是否需要缓存,如果这里没有配置缓存,那么请求的URL还会有一个参数 cache:true,success: function(json){ result = json; } }); 注意的是,前端AJAX的 JSONP原理是动态创建script来进行请求的:
JSONP的弊端:
参考资料:
CORS解决跨域问题CORS解决跨域问题(也就是我们服务端被调用方解决跨域的思路) 对于CORS是怎么理解的,我就直接摘抄一下:http://www.52php.cn/article/p-pkpxwxvf-brm.html的了。
在Java中,我们写下面这个过滤器,就可以完全解决跨域的问题了: package com.imooc; import java.io.IOException; 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.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.tomcat.util.buf.StringUtils; public class CrosFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException { // TODO Auto-generated method stub HttpServletResponse res = (HttpServletResponse) response; HttpServletRequest req = (HttpServletRequest) request; //带cookie的时候,origin必须是全匹配,不能使用* String origin = req.getHeader("Origin"); if (!org.springframework.util.StringUtils.isEmpty(origin)) { res.addHeader("Access-Control-Allow-Origin",origin); } res.addHeader("Access-Control-Allow-Methods","*"); // 支持所有自定义头和预检命令(非简单请求会有预检命令) String headers = req.getHeader("Access-Control-Request-Headers"); if (!org.springframework.util.StringUtils.isEmpty(headers)) { res.addHeader("Access-Control-Allow-Headers",headers); } res.addHeader("Access-Control-Max-Age","3600"); // enable cookie res.addHeader("Access-Control-Allow-Credentials","true"); chain.doFilter(request,response); } @Override public void destroy() { // TODO Auto-generated method stub } } 上面提到了非简单请求,那什么是非简单请求呢,可以看下面的图:
非简单请求会发出一个预检命令的(当然了,我们上面的Filter已经解决预检命令的问题了):
Spring框架解决如果使用的是Spring框架的话,那就只需要一个注解就能够解决跨域的问题了: HTTP服务器层我们在的商用开发中,一般请求的过程是这样的:浏览器->HTTP服务器(Nginx,Apache)->应用服务器(Tomcat,Weblogic) 上面编写的Filter、Spring框架都是在应用服务器上解决的,我们也是可以通过HTTP服务器(Nginx,Apache)来进行解决跨域问题的!
Nginx我用过,Apache我倒是还没用过,下面就简单记录了Nginx和Apache是如何配置的: Nginx配置: Apache配置:
代理解决跨域问题在之前的图我们已经看到了,解决跨域的问题可以在“调用方”中来进行解决。 “调用方”解决跨域的问题是这个思路的:让发送出去的请求代理成是本域的 举个例子: www.zhongfucheng.top是调用方 www.zhongfucheng.site是被调用方 它俩是不同域的,但我们可以在nginx或Apache上进行配置代理:将被调用方www.zhongfucheng.site映射成别的路径 比如,像下面的图,将8080端口的映射成了ajaxServer,当调用方访问ajaxServer路径时,这样的方法在外部看起来就不像是跨域了,像是访问本地(8081端口),但实际访问别的域(8080端口)
总结令我感到最简单的是通过Spring的注解就可以解决跨域的问题了,JSONP的方式已经是很少用的了,因为存在一定的弊端,但了解一下也无妨,毕竟可能面试的时候会问到。当没有用任何框架的时候,写Filter也不麻烦,也只是配置了一下HTTP头信息而已。如果使用Nginx、Apache时,也可以用代理或者配置HTTP头信息都可以解决。看完之后,有没有觉得跨域问题就迎刃而解了。 如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,想要获取更多的Java资源的同学,可以 关注微信公众号:Java3y (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |