简单的建立一个后台项目
新建servlet:
内容如下:
package a; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了一个跨域请求"); response.setContentType("text/plain;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("success"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
web.xml
<servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>a.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>/s/t</url-pattern> </servlet-mapping>
前端代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <button onclick="goAjax()">ajax</button> </body> <script type="text/javascript" src="js/jquery-2.1.4.js" ></script> <script type="text/javascript"> function goAjax(){ $.ajax({ url:"http://192.168.0.102:8080/a/s/t", type:"get", success:function(data){ console.log(data); } }); } </script> </html>
运行前后台项目,出现异常情况
在查看ajax的发送情况
从这里可以看到结果是正确返回的;并且后台也是正常执行了。
因此得出结论:
跨域是浏览器在aja返回结果的时候进行了拦截,先执行,后判断,不是后台不允许跨域;
客户端建立一条img标签,地址是刚才的ajax地址
<img src="http://192.168.0.102:8080/a/s/t" />
查看请求
查看请求,依然是成功的。
结论:跨域只发生在xmlHttpRequest对象上,通俗点说就是发生在ajax上。
浏览器从我们的请求路径中解析出我们的ajax请求的主机信息,得知是跨域请求,就会给请求头添加一个origin头信息。
我们可以在返回的时候添加一个响应头,来通过浏览器对跨域拦截。
1.通过修改后台代码实现跨域
添加过滤器CrossFilter.java
package a; 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; public class CrossFilter implements Filter{ @Override public void destroy() {} @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain doChain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest) req; HttpServletResponse response=(HttpServletResponse)res; request.setCharacterEncoding("utf-8"); //response.setContentType("text/plain;charset=utf-8"); //response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8020");或者 response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "*");//GET POST //response.setHeader("Access-Control-Allow-Headers","content-type"); //跨域预检缓存 response.setHeader("Access-Control-Max-Age","3600"); doChain.doFilter(req,res); } @Override public void init(FilterConfig arg0) throws ServletException { } }
web.xml
<filter> <filter-name>CrossFilter</filter-name> <filter-class>a.CrossFilter</filter-class> </filter> <filter-mapping> <filter-name>CrossFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
现在已经可以实现跨域请求了。
简单请求:
1.get,head,post
2.请求header里面
1)无自定义头
2)Content-Type为以下几种:text/plain,multipart/form-data,application/x-www-form-urlencoded.
非简单请求
1.put,delete方法的ajax请求
2.发送json字符串格式的ajax请求
3.带自定义头的ajax请求
ajax发送非简单请求的时候,会出现请求不通的情况
$.ajax({ url:"http://192.168.0.102:8080/a/s/t", type:"post", contentType:"application/json", data:JSON.stringify({name:"gys"}), success:function(data){ console.log(data); } });
结合上面的提示我们给过滤器添加一条头部信息。
重新运行,跨域问题解决,查看请求的时候发现,一个ajax请求发送了两边。
第一条是一条预检请求,这个请求是在发生非简单请求时,检查跨域请求是否能被通过。
如果每次请求都这样预检一次,会非常耗费网络资源,影响我们的请求速度。
可以在过滤器端添加一个预检缓存。
现在只有第一次请求的时候会出现预检请求,后面的就没有了。
可是我现在想要恢复预检请求,把预检代码注释了,可是还没到预检请求的缓存时间,同样没有办法查看到预检请求。
可以勾选谷歌浏览器的Disable cache
晚上回来继续编写下面的内容
nginx的转发,实现跨域
nginx的配置反响代理,实现跨域。