AJAX跨域详解今天在慕课上学习了AJAX跨域详解:https://www.imooc.com/learn/947搜集AJAX面试题的时候,其实我已经我遇到过AJAX跨域的问题。那个时候就知道为什么要跨域,跨域的解决方案是什么。今天随着课程的学习,加深了对AJAX跨域的理解,记录一下。为什么会出现跨域问题?上图也很清楚,因为浏览器本身对安全有限制(同源)。当我们发送XMLHttpRequest请求时,如果请求的域(主机域名、端口)不同,那么就会出现跨域问题(客户端无法获取到服务器返回的数据)。值得注意的是:跨域问题出现在XMLHttpRequest请求中,也就是说如果不是XMLHttpRequest请求,是不会出现跨域问题的。举个很简单的例子:写网页时,,URL解决跨域问题的思路是图片不在本地域。显然,跨域问题是受浏览器限制的,只有XMLHttpRequest才会出现。那么我们就可以利用这个思路来寻找解决方案:对于浏览器的问题,可以使用相关参数启动浏览器,这样可以解决跨域问题,但是通用性极低,了解一下就可以了。JSONP解决跨域JSONP是JSON使用的一种补充方法,不是官方协议。JSONP是一种解决跨域问题的协议。JSONP是现在很少用到的解决方案(比较复杂,需要修改后台代码),但是我们可以适当的理解一下。使用步骤在后台添加controller,继承AbstractJsonpResponseBodyAdvice类,完整代码如下:@ControllerAdvicepublicclassJsonpAdviceextendsAbstractJsonpResponseBodyAdvice{publicJsonpAdvice(){//TODO自动生成构造函数stubsuper("callback2");}}前端ajax请求://服务器返回的结果varresult;$.ajax({url:base+"/get1",dataType:"jsonp",jsonp:"callback2",//是否需要缓存,如果这里没有配置缓存,那么请求的url也会有一个参数缓存:true,成功:function(json){result=json;}});注意前端AJAX的jsonp:"callback2"一定要和我们的Controllersuper("callback2");匹配是一致的,否则就没有效果。JSONP的原理是动态创建脚本进行请求:JSONP的缺点:改服务端的代码,只支持GET方式(原理是动态创建脚本进行请求),发送的内容不支持anXMLHttpRequestrequest(XMLHttpRequestrequestshavemanyusefulFeatures)参考:https://www.cnblogs.com/blacksonny/p/5846411.htmlCORS解决跨域问题明白了,直接摘录:https://segmentfault.com/a/1190000012469713#articleHeader8。在Java中,我们写下面这个过滤器,就可以完全解决跨域的问题了:packagecom.imooc;importjava.io.IOException;importjavax.servlet.Filter;importjavax.servlet.FilterChain;importjavax.servlet.FilterConfig;导入javax.servlet.ServletException;导入javax.servlet.ServletRequest;导入javax.servlet.ServletResponse;导入javax.servlet.http.HttpServletRequest;导入javax.servlet.http.HttpServletResponse;导入org.apache.tomcat。util.buf.StringUtils;publicclassCrosFilterimplementsFilter{@Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{//TODO自动生成的方法存根}@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{//TODO自动生成的方法存根HttpServletResponseres=(HttpServletResponse)response;HttpServletRequestreq=(HttpServletRequest)请求;//带厨师即,origin必须是完全匹配,并且*Stringorigin=req.getHeader("Origin");如果(!org.springframework.util.StringUtils.isEmpty(origin)){res.addHeader("Access-Control-Allow-Origin",origin);}res.addHeader("Access-Control-Allow-Methods","*");//支持所有自定义标头和预检命令(非简单请求将具有预检命令)Stringheaders=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");//启用cookieres.addHeader("Access-Control-Allow-Credentials","true");链。doFilter(请求,响应);}@Overridepublicvoiddestroy(){//TODOAuto-generatedmethodstub}}上面说了非简单请求,那么什么是非简单请求,可以看下图:非简单请求Apreflight命令会下发(当然上面的Filter已经解决了preflightcommand的问题):Spring框架解决方案如果使用Spring框架,只需要一个注解就可以解决跨域问题:@CrossOriginHTTP服务器层在我们商业开发中,一般的请求流程是这样的:浏览器->HTTP服务器(Nginx、Apache)->应用服务器(Tomcat、Weblogic)上面写的Filter和Spring框架都在应用中解决了在服务端,我们也可以通过HTTP服务器(Nginx、Apache)来解决跨域问题!我用过Nginx,但是没用过Apache。下面简单记录下Nginx和Apache是??如何配置的:Nginx配置:Apache配置:Proxy解决跨域问题我们在上图中已经看到,解决跨域问题可以在“caller”中解决问题“调用者”解决了跨域问题。这是想法:让发送的请求代理成为域。例如: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
