Ajax及跨域请求

视频

1. JavaScript中的Ajax

1.1 功能

实现网页的动态展示。刷新网页中的部分页面内容,又不引起整个页面的刷新。

  • 完整代码:
	     let xmlHttpRequest = new XMLHttpRequest();
		 xmlHttpRequest.onreadystatechange = function () {
         	if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
             	var text = xmlHttpRequest.responseText;//服务器返回的字符串
             	console.log(text)
              //ToDo
          }
        }
        //GET请求发送数据:getText="/资源路径?key1=value&key2=value"
        xmlHttpRequest.open("GET",getText,true);
        xmlHttpRequest.send(); 

1.2 步骤详解(GET请求)

  1. 创建XMLHttpRequest对象
        let xmlHttpRequest = new XMLHttpRequest();
       
  1. 状态码发生改变onreadystatechange

xmlHttpRequest.readyState返回0-4,5个值,代表xmlHttpRequest 对象的5种不同状态:
0:xmlHttpRequest 对象的未初始化状态。这个值检测不到;
1: xmlHttpRequest对象使用open方法,创建了Http请求;
2: xmlHttpRequest对象使用send方法,处于发送数据状态;
3: 客户端已经返回数据,xmlHttpRequest对象正在接收数据的状态;
4:数据接收完毕

xmlHttpRequest.status 返回响应状态码,200表示响应成功

xmlHttpRequest.responseText返回Response响应的字符串。

 		xmlHttpRequest.onreadystatechange = function () {
          if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200){
              var text = xmlHttpRequest.responseText;//服务器返回的字符串
              //ToDo
          }
        }
  1. 初始请求数据
    XMLHttpRequest.open(method,URL,flag,name,password);
    参数:
    - method:请求方式GET | POST
    - URL:路径
    - flag: true异步请求;false同步请求。默认为true
    - name:服务器用户名
    - password: 服务器密码

    同步:在第4步发送请求之后,必须等待服务器将数据返回,在此期间不能执行其他任务。
    异步:在第4步发送请求之后,执行其他任务,无需等待数据返回。

        xmlHttpRequest.open("get",getText,true);
  1. 发送请求
        xmlHttpRequest.send(); 

1.3 通过POST请求发送表单

与GET请求有两个不同的地方

  1. 需要设置请求头:
    代码必须在open方法和send方法中间
	xmlHttpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8")
  1. 发送数据的位置
	xmlHttpRequest.send("key1=value&key2=value");

1.3.1 POST请求时发送到服务器的各种数据格式

  1. JSON数据格式application/json
xhr.setRequestHeader("Content-type","application/json; charset=utf-8");
  1. 提交 form 表单 application/x-www-form-urlencoded
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
  1. 通过form表单发送文件multipart/form-data
xhr.setRequestHeader("Content-type", "multipart/form-data; charset=utf-8");
  1. 发送数据为xml格式text/xml
xhr.setRequestHeader("Content-type", "text/xml; charset=utf-8");

1.4 返回的json格式如何处理

服务器返回的数据都是字符串格式,处理方法:

  1. eval方法
	var jsonObj = eval('('+jsonStr+')');//将json字符串jsonStr转换为jasn对象
	var value = jsonObj.key1;//返回json对象中键值为key1的值
  1. JSON.prse
	var jsonObj = JSON.parse(jsonStr);//将json字符串jsonStr转换为jasn对象

1.5 通过ajax发送请求和接收响应时乱码问题

  • Tomcat 10 没有任何乱码问题
  • Tomcat 9 及以下
  1. Get 请求:Response响应返回中文乱码
    解决办法,服务器端加入以下代码:
	response.setContentType("text/html;charset=UTF-8");
  1. POST请求:在请求和响应中文时都有乱码问题
    解决办法:
	request.setCharacterEncoding(UTF-8);//解决请求乱码
	response.setContentType("text/html;charset=UTF-8");//解决响应乱码

2. JQuery中的Ajax

详细的讲解
第一种:(参数最少的写法)

	$.ajax({
          url:"路径",
          data: {
                id: 1,
            },
          success:function (data) {
            $.each(data,function (i,n) {
                // each可以循环json格式的字符串,i为index,n为json的数据,取值:n.name
            })
          }
        })

$.each(data,function (i,n)的参数:

  1. data为一维的数组或json对象时:i是key,n是value
  2. data为二位的数组或json对象是List集合时:i是下标,ndata[i]
参数名类型描述
urlString(默认: 当前页地址) 发送请求的地址。
typeString(默认: “GET”) 请求方式 (“POST” 或 “GET”), 默认为 “GET”。注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。
asyncBoolean(默认: true) 默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。
contentTypeString(默认: “application/x-www-form-urlencoded”) 发送信息至服务器时内容编码类型。默认值适合大多数应用场合。告诉服务器从浏览器提交过来的数据格式。
dataObject、String发送到服务器的数据。json格式
dataTypeString预期服务器返回的数据类型。json、string
errorFunction(默认: 自动判断 (xml 或 html)) 请求失败时将调用此方法。这个方法有三个参数:XMLHttpRequest 对象,错误信息,(可能)捕获的错误对象。
successFunction请求成功后回调函数。这个方法有两个参数:服务器返回数据,返回状态
beforeSendFunction请求发起前执行
completeFunction请求完成后执行,无论成功与否
  • 第二种
    $.get(“url”,{ data(key:value) },callback,“type”);
    $.post(“路径”,{ “数据名”:数据 },function(返回的数据){ 执行代码 },“数据格式”)

默认数据格式为json,可省略,get请求最简化写法:

	$.get("路径",function(返回的数据){ 执行代码 })
参数名称类型说明
urlString请求HTML页的URL地址
data(可选)Object发送到服务器的key/value数据会作为字符串附加到请求的URL中
callback(可选)Function请求成功时的回调函数,有两个参数:返回的数据,请求状态
type(可选)String服务器返回内容的格式:xml、html、script、json、text、default

3. 跨域请求

Ajax发送跨域请求时会被浏览器的同源策略(CORS)阻止,这是浏览器的安全策略。

总结:实现跨域请求必须服务器端配合,浏览器端无法单独实现跨域请求

示例
a站点:http://localhost:8080/a/
b站点:http://localhost:8081/b/
从a站点发送跨域请求到b站点,浏览器报错:

Access to XMLHttpRequest at 'http://localhost:8081/b/hello' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

什么是同源?
协议一致、域名一致、端口号一致。

3.1 在servlet端设置响应头,解决Ajax跨域访问

要访问的资源允许跨域访问。

//允许某个站点可以对本地资源跨域访问
response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
// 允许所有站点可以对本地资源跨域访问
response.setHeader("Access-Control-Allow-Origin","*");

3.2 jsonp,解决Ajax跨域访问

  1. jsonp不是Ajax请求,通过代码实现了类似Ajax局部刷新的效果。
  2. jsonp是利用了<script>标签的src属性。
  3. script加载时,会将src属性的值所指向的文件内容作为script代码执行,实现ajax的效果。
  4. 只能实现get请求。

3.2.1 简单示例

b中servlet返回的字符串,会在a的页面中当作script代码执行

a的web

<script type="text/javascript" src="http://localhost:8081/b/AjaxJsonp1"></script>

b的servlet

@WebServlet("/AjaxJsonp1")
public class AjaxJsonp1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().print("alert(\"Jsonp1!\")");
    }
}

3.2.2 复杂示例

执行过程

  1. 页面加载完毕后,点击button按钮
  2. body中增加script元素
  3. script元素加载时会加载自己的src属性,src属性指向b站点的ajaxjsonp2,并且通过get方法传递值fun=sayHello
  4. b 站点获取请求中的值sayHello,并返回了字符串sayHello({{"username":"jackson"}})
  5. 返回的字符串会被script元素当作script代码执行。
  6. 执行sayHello(data)方法

a站点中的页面

<html>
<head>
    <title>Title</title>
</head>
<body>
<script type="text/javascript">
    function sayHello(data){
        // 获取json字符串中的key对应的value,添加到div1中
        document.getElementById("div1").innerHTML = data.username
    }
</script>
<script type="text/javascript">
    window.onload = function () {
        document.getElementById("btn").onclick = () => {
            // 创建script元素
            const htmlScriptElement = document.createElement(`script`)
            // 设置script的type属性
            htmlScriptElement.type = "text/javascript"
            // 设置script的src属性,注意:通过get方法传入了参数fun=sayHello
            htmlScriptElement.src = "http://localhost:8081/b/ajaxjsonp2?fun=sayHello"
            // 将script元素添加到body中
            document.getElementsByTagName("body")[0].appendChild(htmlScriptElement)
        }

    }
</script>
<button id="btn">通过jsonp调用方法</button>
<div id="div1"></div>
</body>
</html>

b站点中的servlet

@WebServlet("/ajaxjsonp2")
public class AjaxJsonp2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // get传入参数,获取参数的值
        String fun = request.getParameter("fun");
        // 返回的值是字符串
        response.getWriter().print(fun + "({\"username\":\"jackson\"})");

    }
}

页面点击button后的代码:

<html>
<head>
    <title>Title</title>
</head>
<body>
<script type="text/javascript">
    function sayHello(data){
        // 获取json字符串中的key对应的value,添加到div1中
        document.getElementById("div1").innerHTML = data.username
    }
</script>
<script type="text/javascript">
    window.onload = function () {
        document.getElementById("btn").onclick = () => {
            // 创建script元素
            const htmlScriptElement = document.createElement(`script`)
            // 设置script的type属性
            htmlScriptElement.type = "text/javascript"
            // 设置script的src属性,注意:通过get方法传入了参数fun=sayHello
            htmlScriptElement.src = "http://localhost:8081/b/ajaxjsonp2?fun=sayHello"
            // 将script元素添加到body中
            document.getElementsByTagName("body")[0].appendChild(htmlScriptElement)
        }

    }
</script>
<button id="btn">通过jsonp调用方法</button>
<-- dia-->
<div id="div1">jackson</div>
<-- 点击button后会在body最后增加子元素 script,script元素在加载时会加载src的属性值-->
<script type="text/javascript" src="http://localhost:8081/b/ajaxjsonp2?fun=sayHello"></script>

</body>
</html>

3.3 jQuery封装的jsonp

  1. jQuery封装的jsonp看似与ajax一样,但它只是使用了ajax的外壳
  2. dataTape属性值:jsonp
  3. 在发送请求时浏览器中请求url:请求 URL: http://localhost:8081/b/ajaxjson3?callback=jQuery36007791340332230894_1656146765961&_=1656146765962,jquery自动生成键值对,键的名字默认为callback,键值对的默认值为随机字符串,并通过get方法传递给后台。后面的_=1656146765962为时间戳,防止浏览器读取缓存。
  4. servlet中需要获取该键值对的value,然后返回给浏览器。返回的数据:jQuery36007791340332230894_1656146765961({"username":"jackson"})
  5. 可以看出jquery实现jsonp和上面3.2.2中使用的方法是一样的,jquery把方法名和方法都进行了优化。

a站点网页

<html>
<head>
    <title>Title</title>
</head>
<body>
<script type="text/javascript" src="js/jquery-3.6.0.js"></script>
<script type="text/javascript">
    $(function () {
        $("#btn").click(function () {
            $.ajax({
                type: "GET",
                url: "http://localhost:8081/b/ajaxjson3",
                dataType: "jsonp",// 返回数据的格式
                success: function (data) {// data:返回的数据
                    $("#div1").html(data.username)
                }
            })
        })
    })
</script>
<button id="btn">jQuery实现jsonp</button>
<div id="div1"></div>
</body>
</html>

b站点servlet

@WebServlet("/ajaxjson3")
public class AjaxJsonp3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // jquery在get请求中添加键值对,key是callback,value为随机字符串
        String callback = request.getParameter("callback");
        response.getWriter().print(callback+"({\"username\":\"jackson\"})");
    }
}
  • a站点页面中ajax的另一种写法
  1. ajax发送请求时,请求 URL: 请求 URL: http://localhost:8081/b/ajaxjson4?fun=sayHello&_=1656148497823
  2. 不使用默认的参数名callback,指定为fun
  3. 不使用默认的回调函数success,指定回调函数为sayHello
<html>
<head>
    <title>Title</title>
</head>
<body>
<script type="text/javascript" src="js/jquery-3.6.0.js"></script>
<script type="text/javascript">
    function sayHello(data){
        $("#div1").html(data.username)
    }
    $(function () {
        $("#btn").click(function () {
            $.ajax({
                type: "GET",
                url: "http://localhost:8081/b/ajaxjson4",
                dataType: "jsonp",// 指定数据类型为jsonp
                jsonp:"fun", // 指定GET请求时参数的key为callback
                jsonpCallback:"sayHello" // 指定jsonp的回调函数为sayHello
            })
        })
    })
</script>
<button id="btn">jQuery实现jsonp</button>
<div id="div1"></div>
</body>
</html>

b站点中的servlet

@WebServlet("/ajaxjson4")
public class AjaxJsonp4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String funName = request.getParameter("fun");
        response.getWriter().print(funName+"({\"username\":\"jackson\"})");
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值