AJAX跨域访问(不同域之间相互访问)

一、跨域:

  • 跨域是指从一个域名的网页去请求另一个域名的资源。比如从百度(https://baidu.com)页面去请求京东(https://www.jd.com)的资源。
  • 通过超链接或者form表单提交或者超链接的方式进行跨域是不存在问题的。但在一个域名的网页中的一段js代码发送ajax请求去访问另一个域名中的资源,由于同源策略的存在导致无法跨域访问,那么ajax就存在这种跨域问题。
  • 有一些情况下,我们是需要使用ajax进行跨域访问的。比如某公司的A页面(8080:a.bjpowernode.com)有可能需要获取B页面(8081:b.bjpowernode.com)。

二、同源策略:

  • 同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性同源就是协议(http)、域名(localhost)和端口(8080)都相同
  • Ajax无法跨域:http://localhost:8080/这个域名中的文件不能访问http://localhost:8081/这个域名中的内容。但是form表单和超链接可以。
  • 同源策略有什么用?如果你刚刚在网银输入账号密码,查看了自己还有1万块钱,紧接着访问一些非法的网站,这个网站可以访问刚刚的网银站点,并且获取账号密码,那后果可想而知。所以,从安全的角度来讲,同源策略是有利于保护网站信息的

三、解决Ajax跨域问题的方案:

方案一:设置响应头

在被访问的servlet中加入下述代码表示允许该域名访问我(该servlet)。

    response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); // 允许某个域名访问我
    response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有域名访问我

方案二:jsonp

  • jsonp:json with padding(带填充的json)
  • jsonp不是ajax请求,但是可以完成局部刷新的效果,并且可以解决跨域问题。
  • 注意:jsonp解决跨域的时候,只支持GET请求。不支持post请求。
  • 原理:script标签的src属性值可以是URL,作用是访问某个servlet,后端servlet响应该请求并返回一个字符串到标签中,浏览器接收到这个字符串后,会自动将字符串当做JS代码执行。
    如果后端响应的字符串是一段JS代码的字符串,那么就能实现JS的一系列操作,例如使用innerHTML方法动态生成标签的值、调用前端创建的函数等,类似ajax异步刷新。
  • 例子:用户点击按钮后从后端接收数据展示到前端。这里后端接收的数据是一个前端早已写好的函数。
    请添加图片描述
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jsonp跨域问题</title>
</head>
<body>
  <script type="text/javascript">
    function dosome(myjson){//这是我们自己写的函数,一会后端返回的JS代码是fun(json),然后调用我们这个函数给div标签内容赋值
      document.getElementById("mydiv").innerHTML = myjson.name;
    }
    window.onload =() => {//箭头函数
      document.getElementById("btn").onclick = () =>{//箭头函数,点击按钮创建一个<script>标签
        var myscript = document.createElement("script");//创建元素对象
        myscript.type = "text/javascript";//给对象设置type属性
        myscript.src = "http://localhost:8081/a/servlet01?fun=dosome";//给对象设置src属性,这里要加fun=dosome,这是get属性向后端传送数据的方法,目的是告诉后端我们自己写的函数名,方便后端使用我们前端自己写的函数
        document.getElementsByTagName("body")[0].appendChild(myscript);//将script标签添加到body中
      }
    }

  </script>
  <button id="btn">解决ajax跨域问题</button>
  <div id="mydiv"></div>
</body>
</html>
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
@WebServlet("/servlet01")
public class Servlets extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        //获取前端发送过来的函数名
        String fun = request.getParameter("fun");
        response.getWriter().print(fun+"({\"name\":\"zhangsan\"})");//返回的事一个JS代码:fun(json对象)
    }
}

请添加图片描述

方案三:jQuery封装jsonp

  • jQuery中的jsonp其实就是我们方案2的高度封装,底层原理完全相同。
  • 核心代码:
    //看似是ajax请求,实际上不是ajax请求。
     $.ajax({
         type : "GET",
         url : "跨域的url",//不需要传函数名了,函数名默认传的是&jsonp属性的值=jsonpCallback属性的值。
         dataType : "jsonp", // 指定数据类型,这里是重点!!区分ajax和jsonp的依据
         jsonp : "fun", // 指定参数名(不设置的时候,默认是:"callback")
         jsonpCallback : "sayHello" // 这里的函数就是我们自定义的函数
     							   // (不设置的时候,jQuery会自动生成一个随机的回调函数,
         						   //并且这个回调函数还会自动调用success的回调函数。所以如果不设置这个属性则必须设置success属性)
     })
    

方案四:代理机制(httpclient)

在这里插入图片描述

  • 我们知道1号服务器不能使用异步ajax直接访问二号服务器,所以我们可以1号服务器访问本服务器的servlet,然后本服务器的servlet去访问2号服务器的servlet。
  • 使用Java程序怎么去发送get/post请求呢?【GET和POST请求就是HTTP请求。】
    • 第一种方案:使用JDK内置的API(java.net.URL…),这些API是可以发送HTTP请求的。
    • 第二种方案:使用第三方的开源组件,比如:apache的httpclient组件。(httpclient组件是开源免费的,可以直接用)
  • 在java程序中,使用httpclient组件可以发送http请求。
    • 对于httpclient组件的代码,大家目前可以不进行深入的研究,可以从网上直接搜。然后粘贴过来,改一改,看看能不能完成发送get和post请求。
    • 使用httpclient组件,需要先将这个组件相关的jar包引入到项目当中。
      请添加图片描述
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>代理跨域问题</title>
</head>
<body>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
  $(function () {
    $("#btn").click(function () {
      $.ajax({
        type : "get",
        url : "/b/zhuan",
        async : true,
        dataType:"json",
        success : function(json) {
          $("#mydiv").html(json.name);
        }
      })
    })
  })
</script>
<button id="btn">解决ajax跨域问题</button>
<div id="mydiv"></div>
</body>
</html>


import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@WebServlet("/zhuan")
public class Zhongzhuan extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 使用java代码去发送HTTP get请求
        // 目标地址
        //String url = "https://www.baidu.com";
        String url = "http://localhost:8081/a/servlet02";
        HttpGet httpGet = new HttpGet(url);

        // 设置类型 "application/x-www-form-urlencoded" "application/json"
        httpGet.setHeader("Content-Type", "application/x-www-form-urlencoded");
        //System.out.println("调用URL: " + httpGet.getURI());

        // httpClient实例化
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 执行请求并获取返回
        HttpResponse response1 = httpClient.execute(httpGet);
        HttpEntity entity = response1.getEntity();
        //System.out.println("返回状态码:" + response.getStatusLine());

        // 显示结果
        BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
        String line = null;
        StringBuffer responseSB = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            responseSB.append(line);
        }
        response.getWriter().print(responseSB);
        //System.out.println("服务器响应的数据:" + responseSB);
        reader.close();

        httpClient.close();
    }
}

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
@WebServlet("/servlet02")
public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        response.getWriter().print("{\"name\":\"zhangsan\"}");//返回的事一个JS代码:fun(json对象)
    }
}

方案五:nginx反向代理

  • nginx反向代理中也是使用了这种代理机制来完成AJAX的跨域,实现起来非常简单,只要修改一个nginx的配置即可。具体细节老师没讲。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姓蔡小朋友

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值