1.什么是跨域?
跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要!!!
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;
解决方案:
一.跨域问题:能够正常请求,但是没有办法获取到响应结果
b工程中直接在ajax访问a工程servlet
1 $(function(){ 2 $("#button").click(function () { 3 //获取到文本框的值 4 var username=$("#username").val(); 5 //发送Ajax请求www.a.com的A工程 6 $.ajax({ 7 url:"http://www.a.com:8080/projectA/AServlet?username="+username, 8 type:"GET", 9 success:function (result) { 10 alert(result); 11 }, 12 error:function () { 13 alert('系统错误~') 14 } 15 }); 16 }); 17 });
A工程中能正确接收值
但是success回调函数会报错提示
No 'Access-Control-Allow-Origin' header
解决方案一:设置请求头,在请求的资源中设置Access-Control-Allow-Origin请求头
//设置请求头
1 response.setHeader("Access-Control-Allow-Origin", "*");
正常回调
解决方案二:JSONP解决跨域问题
普通的跨域访问问题,浏览器会进行拦截,凡是src属性的都不会拦截
JSONP实现原理:动态加载<script>标签,利用src属性进行服务器资源的访问,但是只支持Get请求
1.在我们的Ajax请求当中,需要以JSONP方式请求(通过jquery手段,动态生成script)
jsonp:"代表的是前台传给后台,后台再传递给你 jsonpCallBack"
2.在AJAX请求当中需要将返回的数据格式指定为jsonp
dataType:"JSONP"
3.JSONP需要以Get请求发送
?username=zhangsan
4.后台需要做的事情:
1.正常接收数据
2.返回数据
前台传递过来的jsonp需要原路返回
String jsonp=request.getParameter("jsonpCallBack");
需要将返回的数据转换为JSON success
response.getWirter.write(jsonp+"("+返回的数据+")");
修改Ajax请求:
$(function(){ $("#button").click(function () { //获取到文本框的值 var username=$("#username").val(); //发送Ajax请求www.a.com的A工程 $.ajax({ url:"http://www.a.com:8080/projectA/AServlet?username="+username, type:"GET", jsonp:"jsonpCallBack", //回调函数 dataType:"JSONP", success:function (result) { alert(result); }, error:function () { alert('系统错误~') } }); }); });
更改后台请求,需要将JSONP原路返回
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.接受数据 String username=request.getParameter("username"); System.out.println("接收的数据:"+username); //接受Ajax传递的数据 String jsonpCallBack = request.getParameter("jsonpCallBack"); System.out.println("jsonpCallBack:"+jsonpCallBack); String success = JSON.toJSONString("success"); response.getWriter().write(jsonpCallBack+"("+success+")"); }
成功解决:
解决方案三:使用HTTPClient解决:就是不通过浏览器发送请求
B工程的页面发送的Ajax没有办法请求到A工程,因为浏览器会拦截,走后台,后台通过HTTPClient请求请求到A工程,获取到响应结果
1.B工程的bindex.jsp页面请求到B工程的Servlet
$(function(){ $("#button").click(function () { //获取到文本框的值 var username=$("#username").val(); //发送Ajax请求www.a.com的A工程 $.ajax({ url:"BServlet?username="+username, type:"GET", success:function (result) { alert(result); }, error:function () { alert('系统错误~') } }); }); });
2.B工程的BServlet去模拟HTTP请求到A工程
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //内部通过HTTPClient进行转发 //构建一个连接 CloseableHttpClient client = HttpClients.createDefault(); //构建请求 HttpGet get=new HttpGet("http://www.a.com:8080/projectA/AServlet?username="+request.getParameter("username")); //发送请求 CloseableHttpResponse httpResponse = client.execute(get); //获取返回结果 String result = EntityUtils.toString(httpResponse.getEntity()); //将A工程响应结果给页面 response.getWriter().write(result); }
3.A工程处理请求
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.接受数据 String username=request.getParameter("username"); System.out.println("接受的数据:"+username); //2.响应结果 response.getWriter().write("success"); }
成功解决: