AJAX-个人版2.0

AJAX(Asynchronous Javascript And Xml)

传统请求及缺点

  • 传统的请求都有哪些?
    • 直接在浏览器地址栏上输入URL。
    • 点击超链接
    • 提交form表单
    • 使用JS代码发送请求
      • window.open(url)
      • document.location.href = url
      • window.location.href = url
  • 传统请求存在的问题
    • 页面全部刷新导致了用户的体验较差。
    • 传统的请求导致用户的体验有空白期。(用户的体验是不连贯的)
    • AJAX同步请求
回顾复习

老式的web创建工程方法就是创建项目然后添加web工件,然后添加lib依赖如:tomcat,servlet,等。

传统请求

对于传统请求操作:整体流程也就是创建静态页面,

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>演示传统请求,以及传统请求的缺点</title>
</head>
<body><!--直接在浏览器地址栏上输入URL--><!--超链接-->
<a href="/old/request">传统请求(超链接)</a><!--form表单提交-->
<form action="/old/request" method="get"><input type="submit" value="传统请求(form表单提交)">
</form><!--通过JS代码来发送请求-->
<input type="button" value="传统请求(通过JS代码发送请求)" onclick="sendRequest()"><script type="text/javascript">function sendRequest(){// 发送请求//window.location.href = ""document.location.href = "/old/request"}
</script></body>
</html>

然后到servlet层去调用

package com.bjpowernode.javaweb.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/request")
public class OldRequestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 响应信息到浏览器response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();// 向浏览器输出HTML代码,浏览器接收到HTML代码之后渲染页面,展现页面给用户。out.print("<h1>欢迎学习AJAX。。。。</h1>");}
}

AJAX概述

  • AJAX不能称为一种技术,它是多种技术的综合产物
  • AJAX可以让浏览器发送一种特殊的请求,这种请求可以是:异步的
  • 什么是异步,什么是同步?
    • 假设有t1和t2线程,t1和t2线程并发,就是异步。
    • 假设有t1和t2线程,t2在执行的时候,必须等待t1线程执行到某个位置之后t2才能执行,那么t2在等t1,显然他们是排队的,排队的就是同步。
    • AJAX是可以发送异步请求的。也就是说,在同一个浏览器页面当中,可以发送多个ajax请求,这些ajax请求之间不需要等待,是并发的。
  • AJAX代码属于WEB前端的JS代码。和后端的java没有关系,后端也可以是php语言(PHP(Hypertext Preprocessor)是一种广泛使用的开源脚本语言,主要用于Web开发),也可以是C语言。
  • AJAX 应用程序可能使用 XML 来传输数据,但将数据作为纯文本或 JSON 文本传输也同样常见。
  • AJAX可以更新网页的部分,而不需要重新加载整个页面。(页面局部刷新)
  • AJAX可以做到在同一个网页中同时启动多个请求,类似于在同一个网页中启动“多线程”,一个“线程”一个“请求”。

XMLHttpRequest对象

  • XMLHttpRequest对象是AJAX的核心对象,发送请求以及接收服务器数据的返回,全靠它了。

  • XMLHttpRequest对象,现代浏览器都是支持的,都内置了该对象。直接用即可。

  • 创建XMLHttpRequest对象

    • var xhr = new XMLHttpRequest();
      
  • XMLHttpRequest对象的方法

方法描述
abort()取消当前请求
getAllResponseHeaders()返回头部信息
getResponseHeader()返回特定的头部信息
open(method, url, async, user, psw)规定请求method:请求类型 GET 或 POSTurl:文件位置async:true(异步)或 false(同步)user:可选的用户名称psw:可选的密码
send()将请求发送到服务器,用于 GET 请求
send(string)将请求发送到服务器,用于 POST 请求
setRequestHeader()向要发送的报头添加标签/值对
  • XMLHttpRequest对象的属性

属性描述
onreadystatechange定义当 readyState 属性发生变化时被调用的函数
readyState保存 XMLHttpRequest 的状态。0:请求未初始化 1:服务器连接已建立 2:请求已收到 3:正在处理请求 4:请求已完成且响应已就绪
responseText以字符串返回响应数据
responseXML以 XML 数据返回响应数据
status返回请求的状态号200: "OK"403: "Forbidden"404: “Not Found”
statusText返回状态文本(比如 “OK” 或 “Not Found”)
回顾复习

前置条件,在html页面中

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>先能看懂下面这个代码,再学习AJAX。</title>
</head>
<body><script type="text/javascript">function sayHello(){alert("hello javascript")}
</script><!--需求:页面上有一个按钮,用户点击按钮之后,执行一段JS代码。-->
<input type="button" value="hello" onclick="sayHello()"><!--以上的实现方式,当然,大家都是没有问题的,但是通过JS代码给按钮绑定事件,这个你会吗?-->
<input type="button" value="hello2xxxxxxxxxxxxxxx" id="helloBtn"><script type="text/javascript">// 页面加载完毕之后,给id="helloBtn"的元素绑定鼠标单击事件// 这个function就是一个回调函数,这个回调函数什么时候执行?当load事件发生之后,这个回调函数才会执行。// 什么是load事件?load事件什么时候发生?注意:页面加载完毕之后,load事件发生。window.onload = function(){// 获取id="helloBtn"的对象var helloBtn = document.getElementById("helloBtn");// 给id="helloBtn"元素绑定click事件// 这个function也是一个回调函数,这个回调函数什么时候执行?// 当helloBtn被click的时候,被鼠标单击的时候,这个回调函数会执行。// 鼠标单击五次,这个回调函数就会被调用五次。helloBtn.onclick = function(){//alert("hello javascript2")//alert(this)// 这个回调函数中的this是谁呢?// this是发生事件的事件源对象。是按钮发生了鼠标单击,那么this代表的就是这个按钮对象。alert(this.value)}}
</script></body>
</html>

XMLHttpRequest对象的属性

前端准备

ajax1.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>ajax get请求</title>
</head>
<body><script type="text/javascript">window.onload = function(){document.getElementById("helloBtn").onclick = function (){// 发送ajax get请求//console.log("发送ajax get请求")// 1.第一步:创建AJAX核心对象XMLHttpRequestvar xhr = new XMLHttpRequest();// 2.第二步:注册回调函数// 这是一个回调函数,这个函数在XMLHttpRequest对象的readyState状态值发生改变的时候被调用。xhr.onreadystatechange = function (){// 这里的回调函数会被调用多次。// 0 -> 1 被调用一次// 1 -> 2 被调用一次// 2 -> 3 被调用一次// 3 -> 4 被调用一次//console.log(xhr.readyState)// 当XMLHttpRequest对象的readyState的状态是4的时候,表示响应结束了。/*if (xhr.readyState == 4) {}*/if (this.readyState == 4) {// 响应结束了。//console.log("响应结束了")// 响应结束之后,一般会有一个HTTP的状态码。// HTTP状态码常见的包括:200表示成功了,404表示资源找不到,500表示服务器内部错误。// HTTP状态码是HTTP协议的一部分,HTTP协议中规定的。服务器响应之后都会有一个状态码。// 获取HTTP状态码//console.log("HTTP响应状态码:" + this.status)if (this.status == 404) {alert("对不起,您访问的资源不存在,请检查请求路径")} else if(this.status == 500){alert("对不起,服务器发生了严重的内部错误,请联系管理员")} else if(this.status == 200){//alert("响应成功,完美")// 200表示完全响应完毕,成功结束了。// 通过XMLHttpRequest对象获取响应的信息。// 通过XMLHttpRequest对象的responseText属性来获取响应的信息。//alert(this.responseText)// 把响应信息放到div图层当中,渲染document.getElementById("mydiv").innerHTML = this.responseText}}}// 3.第三步:开启通道(open只是浏览器和服务器建立连接,通道打开,并不会发送请求)// XMLHttpRequest对象的open方法// open(method, url, async, user, psw)// method: 请求的方式,可以是GET,也可以是POST,也可以是其它请求方式。// url:请求的路径// async: 只能是true或者false,true表示此ajax请求是一个异步请求,false表示此ajax请求是一个同步请求。(大部分请求都是true,要求异步。极少数情况需要同步,以后再说。)// user:用户名 pwd: 密码,用户名和密码是进行身份认证的,说明要想访问这个服务器上的资源,可能需要提供一些口令才能访问。需不需要用户名和密码,主要看服务器的态度。xhr.open("GET", "/ajax/ajaxrequest1", true)// 4.第四步:发送请求xhr.send()}}
</script><!--给一个按钮,用户点击这个按钮的时候发送ajax请求-->
<input type="button" value="hello ajax" id="helloBtn"><!--给一个div图层,ajax接收了响应的数据之后,在div中进行渲染。-->
<div id="mydiv"></div></body>
</html>

servlet层

AjaxRequest1Servlet

package com.bjpowernode.ajax.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/ajaxrequest1")
public class AjaxRequest1Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {/*String s = null;s.toString();*/// Servlet向浏览器响应一段数据PrintWriter out = response.getWriter();// out对象向浏览器输出信息// 服务器的代码实际上和以前的代码还是完全一样的。// 只不过这个out在响应的时候,浏览器客户端的XMLHttpRequest对象会接收到这个响应的信息。out.print("<font color='red'>welcome to study ajax!!!!</font>");}
}

AJAX GET请求

  • 发送AJAX get请求,前端代码:

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>发送ajax get请求</title>
    </head>
    <body>
    <script type="text/javascript">window.onload = function () {document.getElementById("btn").onclick = function () {//1. 创建AJAX核心对象var xhr = new XMLHttpRequest();//2. 注册回调函数xhr.onreadystatechange = function(){if (this.readyState == 4) {if (this.status == 200) {// 通过XMLHttpRequest对象的responseText属性可以获取到服务器响应回来的内容。// 并且不管服务器响应回来的是什么,都以普通文本的形势获取。(服务器可能响应回来:普通文本、XML、JSON、HTML...)// innerHTML属性是javascript中的语法,和ajax的XMLHttpRequest对象无关。// innerHTML可以设置元素内部的HTML代码。(innerHTML可以将后面的内容当做一段HTML代码解释并执行)//document.getElementById("myspan").innerHTML = this.responseTextdocument.getElementById("mydiv").innerHTML = this.responseText// innerText也不是AJAX中的,是javascript中的元素属性,和XMLHttpRequest无关。// innerText也是设置元素中的内容,但是即使后面是一段HTML代码,也是将其看做一个普通字符串设置进去。//document.getElementById("myspan").innerText = this.responseText}else{alert(this.status)}}}//3. 开启通道xhr.open("GET", "/ajax/ajaxrequest2", true)//4. 发送请求xhr.send()}}
    </script>
    <button id="btn">发送ajax get请求</button>
    <span id="myspan"></span>
    <div id="mydiv"></div>
    </body>
    </html>
    
  • 发送AJAX get请求,后端代码:

    package com.bjpowernode.ajax.servlet;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;
    import java.io.PrintWriter;/*** @program: 代码* @ClassName: AjaxRequest2Servlet* @version: 1.0* @description:* @author: bjpowernode* @create: 2022-05-13 10:46**/@WebServlet("/ajaxrequest2")
    public class AjaxRequest2Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应的内容类型以及字符集response.setContentType("text/html;charset=UTF-8");// 获取响应流PrintWriter out = response.getWriter();// 响应out.print("<font color='red'>用户名已存在!!!</font>");}
    }
  • AJAX get请求如何提交数据呢?

    • get请求提交数据是在“请求行”上提交,格式是:url?name=value&name=value&name=value…
    • 其实这个get请求提交数据的格式是HTTP协议中规定的,遵循协议即可。
回顾复习

ajax2.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>发送ajax get请求</title>
</head>
<body>
<script type="text/javascript">window.onload = function () {document.getElementById("btn").onclick = function () {//1. 创建AJAX核心对象var xhr = new XMLHttpRequest();//2. 注册回调函数xhr.onreadystatechange = function(){if (this.readyState == 4) {if (this.status == 200) {// 通过XMLHttpRequest对象的responseText属性可以获取到服务器响应回来的内容。// 并且不管服务器响应回来的是什么,都以普通文本的形势获取。(服务器可能响应回来:普通文本、XML、JSON、HTML...)// innerHTML属性是javascript中的语法,和ajax的XMLHttpRequest对象无关。// innerHTML可以设置元素内部的HTML代码。(innerHTML可以将后面的内容当做一段HTML代码解释并执行)//document.getElementById("myspan").innerHTML = this.responseTextdocument.getElementById("mydiv").innerHTML = this.responseText// innerText也不是AJAX中的,是javascript中的元素属性,和XMLHttpRequest无关。// innerText也是设置元素中的内容,但是即使后面是一段HTML代码,也是将其看做一个普通字符串设置进去。//document.getElementById("myspan").innerText = this.responseText}else{alert(this.status)}}}//3. 开启通道// 获取到用户填写的usercode和usernamevar usercode = document.getElementById("usercode").valuevar username = document.getElementById("username").value// 搞一个时间戳//alert(new Date().getTime())//xhr.open("GET", "/ajax/ajaxrequest2?t="+new Date().getTime()+"&usercode="+usercode+"&username="+username, true)xhr.open("GET", "/ajax/ajaxrequest2?t="+Math.random()+"&usercode="+usercode+"&username="+username, true)//4. 发送请求xhr.send()}}
</script>
usercode<input type="text" id="usercode"><br>
username<input type="text" id="username"><br>
<button id="btn">发送ajax get请求</button>
<span id="myspan"></span>
<div id="mydiv"></div>
</body>
</html>

AjaxRequest2Servlet

package com.bjpowernode.ajax.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @program: 代码* @ClassName: AjaxRequest2Servlet* @version: 1.0* @description:* @author: bjpowernode* @create: 2022-05-13 10:46**/@WebServlet("/ajaxrequest2")
public class AjaxRequest2Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应的内容类型以及字符集response.setContentType("text/html;charset=UTF-8");// 获取响应流PrintWriter out = response.getWriter();// 响应//out.print("<font color='red'>用户名已存在!!!</font>");// 获取ajax get请求提交的数据String usercode = request.getParameter("usercode");String username = request.getParameter("username");out.print("usercode=" + usercode + ", username=" + username);}
}

ajax3.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>发送ajax get请求</title>
</head>
<body>
<script type="text/javascript">//1. 创建AJAX核心对象var xhr = new XMLHttpRequest();  //设置成全局的window.onload = function () {document.getElementById("btn").onclick = function () {//2. 注册回调函数xhr.onreadystatechange = callback  //将函数名作为变量赋值//3. 开启通道xhr.open("GET", "/ajax/ajaxrequest2", true)//4. 发送请求xhr.send()}}function callback(){if(xhr.readyState == 4){if (xhr.status == 200) {document.getElementById("mydiv").innerHTML = xhr.responseText}else{alert(xhr.status)}}}
</script>
<button id="btn">发送ajax get请求</button>
<span id="myspan"></span>
<div id="mydiv"></div>
</body>
</html>

AjaxRequest3Servlet

package com.bjpowernode.ajax.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @program: 代码* @ClassName: AjaxRequest3Servlet* @version: 1.0* @description: 发送AJAX POST请求* @author: bjpowernode* @create: 2022-05-13 15:39**/
@WebServlet("/ajaxrequest3")
public class AjaxRequest3Servlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();//out.print("<font color='red'>用户名已存在!!!</font>");// 获取提交数据String username = request.getParameter("username");String password = request.getParameter("password");out.print("用户名是:" + username + ",密码是:" + password);}
}

AJAX get请求如何提交数据呢

前端

 //3. 开启通道// 获取到用户填写的usercode和usernamevar usercode = document.getElementById("usercode").valuevar username = document.getElementById("username").value.....
usercode<input type="text" id="usercode"><br>
username<input type="text" id="username"><br>

后端

 // 获取ajax get请求提交的数据String usercode = request.getParameter("usercode");String username = request.getParameter("username");

AJAX GET请求的缓存问题

  • 对于低版本的IE浏览器来说,AJAX的get请求可能会走缓存。存在缓存问题。对于现代的浏览器来说,大部分浏览器都已经不存在AJAX get缓存问题了。
  • 什么是AJAX GET请求缓存问题呢?
    • 在HTTP协议中是这样规定get请求的:get请求会被缓存起来。
    • 发送AJAX GET请求时,在同一个浏览器上,前后发送的AJAX请求路径一样的话,对于低版本的IE来说,第二次的AJAX GET请求会走缓存,不走服务器。
  • POST请求在HTTP协议中规定的是:POST请求不会被浏览器缓存。
  • GET请求缓存的优缺点:
    • 优点:直接从浏览器缓存中获取资源,不需要从服务器上重新加载资源,速度较快,用户体验好。
    • 缺点:无法实时获取最新的服务器资源。
  • 浏览器什么时候会走缓存?
    • 第一:是一个GET请求
    • 第二:请求路径已经被浏览器缓存过了。第二次发送请求的时候,这个路径没有变化,会走浏览器缓存。
  • 如果是低版本的IE浏览器,怎么解决AJAX GET请求的缓存问题呢?
    • 可以在请求路径url后面添加一个时间戳,这个时间戳是随时变化的。所以每一次发送的请求路径都是不一样的,这样就不会走浏览器的缓存问题了。
    • 可以采用时间戳:“url?t=” + new Date().getTime()
    • 或者可以通过随机数:“url?t=” + Math.random()
    • 也可以随机数+时间戳…
回顾复习

AJAX GET请求的缓存问题

前端

 // 搞一个时间戳//alert(new Date().getTime()) //xhr.open("GET", "/ajax/ajaxrequest2?t="+new Date().getTime()+"&usercode="+usercode+"&username="+username, true)xhr.open("GET", "/ajax/ajaxrequest2?t="+Math.random()+"&usercode="+usercode+"&username="+username, true)

AJAX POST请求

  • AJAX POST请求和GET请求的代码区别在哪里?就是前端代码有区别。后端代码没有区别。

    // 4. 发送AJAX POST请求
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") // 设置请求头的内容类型。模拟form表单提交数据。
    // 获取表单中的数据
    var username = document.getElementById("username").value;
    var password = document.getElementById("password").value;
    // send函数中的参数就是发送的数据,这个数据在“请求体”当中发送。
    xhr.send("username="+username+"&password="+password)
    

  • 实现一个案例:使用AJAX POST请求实现用户注册的时候,用户名是否可用。(验证用户名是否可以注册)实现步骤如下:

    • 在前端,用户输入用户名之后,失去焦点事件blur发生,然后发送AJAX POST请求,提交用户名
    • 在后端,接收到用户名,连接数据库,根据用户名去表中搜索
    • 如果用户名已存在
      • 后端响应消息:对不起,用户名已存在(在前端页面以红色字体展示)
    • 如果用户名不存在
      • 后端响应消息:用户名可以使用(在前端页面以绿色字体展示)
  • 实现一个案例:用户点击按钮之后,发送AJAX请求,显示学生列表。

    • 在后端java程序中拼接HTML代码,然后将HTML代码直接响应到浏览器客户端。这种方式不好,不应该在java代码中编写HTML代码,能否在java程序中直接向前端响应数据?可以,可以在后端拼接JSON格式的字符串,或者XML格式的字符串,将这个字符串发送给前端,前端解析即可。
回顾复习

AJAX POST请求

前端ajax4.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>发送ajax post请求</title>
</head>
<body><script type="text/javascript">window.onload = function () {document.getElementById("mybtn").onclick = function () {// 发送AJAX POST请求// 1. 创建AJAX核心对象var xhr = new XMLHttpRequest();// 2. 注册回调函数xhr.onreadystatechange = function (){if (this.readyState == 4) {if (this.status == 200) {document.getElementById("mydiv").innerHTML = this.responseText}else{alert(this.status)}}}// 3. 开启通道xhr.open("POST", "/ajax/ajaxrequest3", true)// 4. 发送请求// 怎么模拟AJAX提交form表单呢?设置请求头的内容类型(这行代码非常关键,是模拟form表单提交的关键代码。)// 设置请求头的内容类型时,必须在open之后。xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")// 放到send()这个函数的小括号当中的数据,会自动在请求体当中提交数据。// 使用JS代码获取用户填写的用户名和密码var username = document.getElementById("username").value;var password = document.getElementById("password").value;//xhr.send("注意格式:放在这里的数据就是在请求体当中提交的,格式不能随便来,还是需要遵循HTTP的协议:name=value&name=value&name=value")xhr.send("username="+username+"&password="+password)}}
</script>用户名<input type="text" id="username"><br>
密码<input type="password" id="password"><br><button id="mybtn">发送AJAX POST请求</button><div id="mydiv"></div></body>
</html>

后端

package com.bjpowernode.ajax.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @program: 代码* @ClassName: AjaxRequest3Servlet* @version: 1.0* @description: 发送AJAX POST请求* @author: bjpowernode* @create: 2022-05-13 15:39**/
@WebServlet("/ajaxrequest3")
public class AjaxRequest3Servlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();//out.print("<font color='red'>用户名已存在!!!</font>");// 获取提交数据String username = request.getParameter("username");String password = request.getParameter("password");out.print("用户名是:" + username + ",密码是:" + password);}
}

实现一个案例

前端ajax5.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>AJAX POST请求验证用户名是否可用</title>
</head>
<body><script type="text/javascript">window.onload = function(){document.getElementById("username").onfocus = function (){document.getElementById("tipMsg").innerHTML = ""}document.getElementById("username").onblur = function (){//console.log("正在发送AJAX POST请求验证用户名")// 发送AJAX POST请求// 1.var xhr = new XMLHttpRequest()// 2.xhr.onreadystatechange = function () {if (this.readyState == 4) {if (this.status == 200) {document.getElementById("tipMsg").innerHTML = this.responseText}else{alert(this.status)}}}// 3.xhr.open("POST", "/ajax/ajaxrequest4", true)// 4.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")// 获取表单数据var username = document.getElementById("username").valuexhr.send("uname=" + username)}}
</script>用户名:<input type="text" id="username"><span id="tipMsg"></span></body>
</html>

后端

package com.bjpowernode.ajax.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;/*** @program: 代码* @ClassName: AjaxRequest4Servlet* @version: 1.0* @description: 验证用户名是否可用* @author: bjpowernode* @create: 2022-05-14 10:19**/
@WebServlet("/ajaxrequest4")
public class AjaxRequest4Servlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获取用户名String uname = request.getParameter("uname");// 打布尔标记(一种编程模型)boolean flag = false; // 默认是用户名不存在。// 连接数据库验证用户名是否存在Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {// 1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC", "root", "root");// 3.获取预编译的数据库操作对象String sql = "select id,name from t_user where name = ?";ps = conn.prepareStatement(sql);ps.setString(1, uname);// 4.执行SQL语句rs = ps.executeQuery();// 5.处理结果集if (rs.next()) {// 用户名已存在。flag = true;}} catch (Exception e) {e.printStackTrace();} finally {// 6.释放资源if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if (ps != null) {try {ps.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}// 响应结果到浏览器response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();if (flag) {// 用户名已存在,不可用out.print("<font color='red'>对不起,用户名已存在</font>");}else{// 用户名不存在,可以使用out.print("<font color='green'>用户名可以使用</font>");}}
}

基于JSON的数据交换

  • 在WEB前端中,如何将一个json格式的字符串转换成json对象

    var jsonStr = "{\"username\" : \"zhangsan\", \"password\" : \"1233344\"}"
    var jsonObj = JSON.parse(jsonStr)
    console.log(jsonObj.username)
    console.log(jsonObj.password)
    
  • 在后端拼接JSON格式的字符串,响应给前端的浏览器

    json.append("[");
    while (rs.next()) {// 获取每个学生的信息String name = rs.getString("name");String age = rs.getString("age");String addr = rs.getString("addr");// 拼接json格式的字符串// {"name":"   王五    ","age":    20      ,"addr":"      北京大兴区     "},json.append("{\"name\":\"");json.append(name);json.append("\",\"age\":");json.append(age);json.append(",\"addr\":\"");json.append(addr);json.append("\"},");
    }
    jsonStr = json.substring(0, json.length() - 1) + "]";
    
  • 拼接JSON格式的字符串太痛苦,可以使用阿里巴巴的fastjson组件,它可以将java对象转换成json格式的字符串

    List<Student> studentList = new ArrayList<>();
    while (rs.next()) {// 取出数据String name = rs.getString("name");int age = rs.getInt("age");String addr = rs.getString("addr");// 将以上数据封装成Student对象Student s = new Student(name, age, addr);// 将Student对象放到List集合studentList.add(s);
    }
    // 将List集合转换成json字符串
    jsonStr = JSON.toJSONString(studentList);
    

    注意:使用fastjson需要引入fastjson-1.2.2.jar

回顾复习

json知识回顾

json格式

jsontest1.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>json test</title>
</head>
<body><script type="text/javascript">/*在javascript语言中怎么创建一个json对象呢?语法是什么?var jsonobj = {"属性名1" : 属性值,"属性名2" : 属性值,"属性名3" : 属性值,"属性名4" : 属性值,"属性名5" : 属性值}注意:属性值的数据类型,那就随意了。可能是数字,可能是布尔类型,可能是字符串,可能是数组.....*//*var user = {"usercode" : 111,"username" : "zhangsan","sex" : true,"age" : 20,"aihaos" : ["抽烟", "喝酒", "烫头"],"addr" : address}// 另一个json对象var address = {"city" : "北京","street" : "北京大兴区","zipcode" : "123456"}*/var user = {"usercode" : 111,"username" : "zhangsan","sex" : true,"age" : 20,"aihaos" : ["抽烟", "喝酒", "烫头"],"addr" : {"city" : "北京","street" : "北京大兴区","zipcode" : "123456"}}// 访问json对象的属性// 第一种方式console.log(user.usercode)console.log(user.username)console.log(user.sex ? "男" : "女")console.log(user.age)for (var i = 0; i < user.aihaos.length; i++) {console.log(user.aihaos[i])}// 访问这个用户是哪个街道的?console.log(user.addr.street)// 第二种方式console.log(user["usercode"])console.log(user["username"])console.log(user["sex"] ? "男的" : "女的")console.log(user["age"])</script></body>
</html>

将一个json格式的字符串转换成json对象

jsontest2.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>json test2</title>
</head>
<body>
<!--从后端java程序中响应回来的是json格式的字符串,那么你怎么把json格式的字符串转换成json对象呢?-->
<script type="text/javascript">// 这是一个json对象var user = {"username" : "zhangsan","password" : "123456"}// 是json对象,才能这样访问。alert(user.username + "," + user.password)// 从服务器端返回来的不是一个json对象,是一个json格式的字符串var fromJavaServerJsonStr = "{\"usercode\" : 111, \"age\" : 20}"// 有两种方式:// 第一种方式:使用eval函数。(这个以前在javascript语言中讲过,这里就不再说了。)// 第二种方式:调用javascript语言中的内置对象JSON的一个方法parse。var jsonobj = JSON.parse(fromJavaServerJsonStr)alert(jsonobj.usercode + "," + jsonobj.age)</script>
</body>
</html>

前端ajax6.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>发送AJAX请求,显示学生列表</title>
</head>
<body><script type="text/javascript">window.onload = function () {document.getElementById("btn").onclick = function () {// 1.创建核心对象var xhr = new XMLHttpRequest();// 2.注册回调函数xhr.onreadystatechange = function () {if (this.readyState == 4) {if (this.status == 200) {//document.getElementById("stutbody").innerHTML = this.responseText// 将json格式的字符串转换成json对象var stuList = JSON.parse(this.responseText) // 是一个数组,并且数组中有多个学生数据var html = ""for (var i = 0; i < stuList.length; i++) {var stu = stuList[i]html += "<tr>"html += "<td>"+(i+1)+"</td>"html += "<td>"+stu.name+"</td>"html += "<td>"+stu.age+"</td>"html += "<td>"+stu.addr+"</td>"html += "</tr>"}document.getElementById("stutbody").innerHTML = html} else {alert(this.status)}}}// 3.开启通道xhr.open("GET", "/ajax/ajaxrequest5?t=" + new Date().getTime(), true)// 4.发送请求xhr.send()}}
</script><input type="button" value="显示学员列表" id="btn"><table width="50%" border="1px"><thead><tr><th>序号</th><th>姓名</th><th>年龄</th><th>住址</th></tr></thead><tbody id="stutbody"><!--<tr><td>1</td><td>张三</td><td>20</td><td>北京大兴区</td></tr><tr><td>2</td><td>李四</td><td>22</td><td>北京海淀区</td></tr>--></tbody>
</table></body>
</html>

后端

package com.bjpowernode.ajax.servlet;import com.alibaba.fastjson.JSON;
import com.bjpowernode.ajax.beans.Student;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;/*** @program: 代码* @ClassName: AjaxRequest5Servlet* @version: 1.0* @description: 发送AJAX请求动态展示学员列表* @author: bjpowernode* @create: 2022-05-14 12:08**/
@WebServlet("/ajaxrequest5")
public class AjaxRequest5Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 连接数据库,查询学员信息,拼接HTML代码,响应HTML代码到浏览器(这里就不再连接数据库了,写死了。)response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();/*// 连接数据库,拼接HTML代码StringBuilder html = new StringBuilder();// 目前存在的缺点:在后端的java代码中又开始拼接HTML代码了。显然这是在后端java中写前端的HTML代码。不好维护。// 能不能直接将数据返回,给WEB前端数据就行了。让WEB前端能够拿到数据就行,然后页面展示的功能交给WEB前端来处理。// 我们后端的java代码能不能只返回数据????可以。(返回数据可以采用JSON的格式,也可以采用XML的格式)html.append("<tr>");html.append("<td>1</td>");html.append("<td>王五</td>");html.append("<td>20</td>");html.append("<td>北京大兴区</td>");html.append("</tr>");html.append("<tr>");html.append("<td>2</td>");html.append("<td>李四</td>");html.append("<td>22</td>");html.append("<td>北京海淀区</td>");html.append("</tr>");out.print(html);*/// 将以上程序拼接HTML,换成拼接JSON格式的字符串。//String jsonStr = "[{\"name\":\"王五\",\"age\":20,\"addr\":\"北京大兴区\"}, {\"name\":\"李四\",\"age\":22,\"addr\":\"北京海淀区\"}]";// 准备StringBuilder对象,拼接JSONStringBuilder json = new StringBuilder();String jsonStr = "";// 连接数据库,查询所有的学生,拼接json字符串Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {// 1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC", "root", "root");// 3.获取预编译的数据库操作对象String sql = "select name, age, addr from t_student";ps = conn.prepareStatement(sql);// 4.执行SQL语句rs = ps.executeQuery();// 5.处理结果集/*json.append("[");while (rs.next()) {// 获取每个学生的信息String name = rs.getString("name");String age = rs.getString("age");String addr = rs.getString("addr");// 拼接json格式的字符串// {"name":"   王五    ","age":    20      ,"addr":"      北京大兴区     "},json.append("{\"name\":\"");json.append(name);json.append("\",\"age\":");json.append(age);json.append(",\"addr\":\"");json.append(addr);json.append("\"},");}jsonStr = json.substring(0, json.length() - 1) + "]";*/List<Student> studentList = new ArrayList<>();while (rs.next()) {// 取出数据String name = rs.getString("name");int age = rs.getInt("age");String addr = rs.getString("addr");// 将以上数据封装成Student对象Student s = new Student(name, age, addr);// 将Student对象放到List集合studentList.add(s);}// 将List集合转换成json字符串jsonStr = JSON.toJSONString(studentList);} catch (Exception e) {e.printStackTrace();} finally {// 6.释放资源if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if (ps != null) {try {ps.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}// 响应JSON格式的字符串给前端。out.print(jsonStr);}
}

阿里巴巴的fastjson组件

用例展示

fastjson包下的

User.java

package com.bjpowernode.fastjson;/*** @program: 代码* @ClassName: User* @version: 1.0* @description: 用户类* @author: bjpowernode* @create: 2022-05-14 18:13**/
public class User {private String id;private String username;private int age;public User() {}public User(String id, String username, int age) {this.id = id;this.username = username;this.age = age;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

用例测试

package com.bjpowernode.fastjson;import com.alibaba.fastjson.JSON;import java.util.ArrayList;
import java.util.List;/*** @program: 代码* @ClassName: FastjsonTest* @version: 1.0* @description: 测试阿里巴巴的fastjson的使用* @author: bjpowernode* @create: 2022-05-14 18:13**/
public class FastjsonTest {public static void main(String[] args) {// 创建一个User类型的对象User user = new User("111", "zhangsan", 20);// 将以上的User对象转换成json格式的字符串// 使用阿里巴巴的fastjson组件中的JSON类即可。// fastjson中又一个类,叫做:JSON。全部大写。// JSON类中的方法都是静态的方法,直接调用即可。String jsonStr = JSON.toJSONString(user);System.out.println(jsonStr);// 尝试List集合是否可以转换成数组List<User> userList = new ArrayList<>();User user1 = new User("120", "lisi", 30);User user2 = new User("130", "jackson", 33);userList.add(user1);userList.add(user2);String jsonStr2 = JSON.toJSONString(userList);System.out.println(jsonStr2);}
}

转到Ajax包下进行升级改造

创建实体类Student.java

package com.bjpowernode.ajax.beans;/*** @program: 代码* @ClassName: Student* @version: 1.0* @description: 学生类* @author: bjpowernode* @create: 2022-05-14 18:19**/
public class Student {private String name;private int age;private String addr;public Student() {}public Student(String name, int age, String addr) {this.name = name;this.age = age;this.addr = addr;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getAddr() {return addr;}public void setAddr(String addr) {this.addr = addr;}
}

到servlet去实现

package com.bjpowernode.ajax.servlet;import com.alibaba.fastjson.JSON;
import com.bjpowernode.ajax.beans.Student;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;/*** @program: 代码* @ClassName: AjaxRequest5Servlet* @version: 1.0* @description: 发送AJAX请求动态展示学员列表* @author: bjpowernode* @create: 2022-05-14 12:08**/
@WebServlet("/ajaxrequest5")
public class AjaxRequest5Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 连接数据库,查询学员信息,拼接HTML代码,响应HTML代码到浏览器(这里就不再连接数据库了,写死了。)response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();/*// 连接数据库,拼接HTML代码StringBuilder html = new StringBuilder();// 目前存在的缺点:在后端的java代码中又开始拼接HTML代码了。显然这是在后端java中写前端的HTML代码。不好维护。// 能不能直接将数据返回,给WEB前端数据就行了。让WEB前端能够拿到数据就行,然后页面展示的功能交给WEB前端来处理。// 我们后端的java代码能不能只返回数据????可以。(返回数据可以采用JSON的格式,也可以采用XML的格式)html.append("<tr>");html.append("<td>1</td>");html.append("<td>王五</td>");html.append("<td>20</td>");html.append("<td>北京大兴区</td>");html.append("</tr>");html.append("<tr>");html.append("<td>2</td>");html.append("<td>李四</td>");html.append("<td>22</td>");html.append("<td>北京海淀区</td>");html.append("</tr>");out.print(html);*/// 将以上程序拼接HTML,换成拼接JSON格式的字符串。//String jsonStr = "[{\"name\":\"王五\",\"age\":20,\"addr\":\"北京大兴区\"}, {\"name\":\"李四\",\"age\":22,\"addr\":\"北京海淀区\"}]";// 准备StringBuilder对象,拼接JSONStringBuilder json = new StringBuilder();String jsonStr = "";// 连接数据库,查询所有的学生,拼接json字符串Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {// 1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC", "root", "root");// 3.获取预编译的数据库操作对象String sql = "select name, age, addr from t_student";ps = conn.prepareStatement(sql);// 4.执行SQL语句rs = ps.executeQuery();// 5.处理结果集/*json.append("[");while (rs.next()) {// 获取每个学生的信息String name = rs.getString("name");String age = rs.getString("age");String addr = rs.getString("addr");// 拼接json格式的字符串// {"name":"   王五    ","age":    20      ,"addr":"      北京大兴区     "},json.append("{\"name\":\"");json.append(name);json.append("\",\"age\":");json.append(age);json.append(",\"addr\":\"");json.append(addr);json.append("\"},");}jsonStr = json.substring(0, json.length() - 1) + "]";*/List<Student> studentList = new ArrayList<>();while (rs.next()) {// 取出数据String name = rs.getString("name");int age = rs.getInt("age");String addr = rs.getString("addr");// 将以上数据封装成Student对象Student s = new Student(name, age, addr);// 将Student对象放到List集合studentList.add(s);}// 将List集合转换成json字符串jsonStr = JSON.toJSONString(studentList);} catch (Exception e) {e.printStackTrace();} finally {// 6.释放资源if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if (ps != null) {try {ps.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}// 响应JSON格式的字符串给前端。out.print(jsonStr);}
}

基于XML的数据交换

  • 注意:如果服务器端响应XML的话,响应的内容类型需要写成:

    response.setContentType("text/xml;charset=UTF-8");
    
  • xml和JSON都是常用的数据交换格式

    • XML体积大,解析麻烦。较少用。
    • JSON体积小,解析简单,较常用。
  • 基于XML的数据交换,前端代码

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>使用XML完成数据交换</title>
    </head>
    <body>
    <script type="text/javascript">window.onload = function(){document.getElementById("btn").onclick = function(){// 1.创建XMLHTTPRequest对象var xhr = new XMLHttpRequest();// 2.注册回调函数xhr.onreadystatechange = function () {if (this.readyState == 4) {if (this.status == 200) {// 服务器端响应了一个XML字符串,这里怎么接收呢?// 使用XMLHTTPRequest对象的responseXML属性,接收返回之后,可以自动封装成document对象(文档对象)var xmlDoc = this.responseXML//console.log(xmlDoc)// 获取所有的<student>元素,返回了多个对象,应该是数组。var students = xmlDoc.getElementsByTagName("student")//console.log(students[0].nodeName)var html = "";for (var i = 0; i < students.length; i++) {var student = students[i]// 获取<student>元素下的所有子元素html += "<tr>"html += "<td>"+(i+1)+"</td>"var nameOrAge = student.childNodesfor (var j = 0; j < nameOrAge.length; j++) {var node = nameOrAge[j]if (node.nodeName == "name") {//console.log("name = " + node.textContent)html += "<td>"+node.textContent+"</td>"}if (node.nodeName == "age") {//console.log("age = " + node.textContent)html += "<td>"+node.textContent+"</td>"}}html += "</tr>"}document.getElementById("stutbody").innerHTML = html}else{alert(this.status)}}}// 3.开启通道xhr.open("GET", "/ajax/ajaxrequest6?t=" + new Date().getTime(), true)// 4.发送请求xhr.send()}}
    </script>
    <button id="btn">显示学生列表</button>
    <table width="500px" border="1px"><thead><tr><th>序号</th><th>姓名</th><th>年龄</th></tr></thead><tbody id="stutbody"><!--<tr><td>1</td><td>zhangsan</td><td>20</td></tr><tr><td>2</td><td>lisi</td><td>22</td></tr>--></tbody>
    </table>
    </body>
    </html>
    
  • 基于XML的数据交换,后端java程序:

    package com.bjpowernode.ajax.servlet;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;
    import java.io.PrintWriter;/*** @program: 代码* @ClassName: AjaxRequest6Servlet* @version: 1.0* @description: 服务器端返回XML字符串* @author: bjpowernode* @create: 2022-05-15 11:48**/
    @WebServlet("/ajaxrequest6")
    public class AjaxRequest6Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 注意:响应的内容类型是XML。response.setContentType("text/xml;charset=UTF-8");PrintWriter out = response.getWriter();/*<students><student><name>zhangsan</name><age>20</age></student><student><name>lisi</name><age>22</age></student></students>*/StringBuilder xml = new StringBuilder();xml.append("<students>");xml.append("<student>");xml.append("<name>zhangsan</name>");xml.append("<age>20</age>");xml.append("</student>");xml.append("<student>");xml.append("<name>lisi</name>");xml.append("<age>22</age>");xml.append("</student>");xml.append("</students>");out.print(xml);}
    }

回顾复习

前端ajax7.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>使用XML完成数据交换</title>
</head>
<body>
<script type="text/javascript">window.onload = function(){document.getElementById("btn").onclick = function(){// 1.创建XMLHTTPRequest对象var xhr = new XMLHttpRequest();// 2.注册回调函数xhr.onreadystatechange = function () {if (this.readyState == 4) {if (this.status == 200) {// 服务器端响应了一个XML字符串,这里怎么接收呢?// 使用XMLHTTPRequest对象的responseXML属性,接收返回之后,可以自动封装成document对象(文档对象)var xmlDoc = this.responseXML//console.log(xmlDoc)// 获取所有的<student>元素,返回了多个对象,应该是数组。var students = xmlDoc.getElementsByTagName("student")//console.log(students[0].nodeName)var html = "";for (var i = 0; i < students.length; i++) {var student = students[i]// 获取<student>元素下的所有子元素html += "<tr>"html += "<td>"+(i+1)+"</td>"var nameOrAge = student.childNodesfor (var j = 0; j < nameOrAge.length; j++) {var node = nameOrAge[j]if (node.nodeName == "name") {//console.log("name = " + node.textContent)html += "<td>"+node.textContent+"</td>"}if (node.nodeName == "age") {//console.log("age = " + node.textContent)html += "<td>"+node.textContent+"</td>"}}html += "</tr>"}document.getElementById("stutbody").innerHTML = html}else{alert(this.status)}}}// 3.开启通道xhr.open("GET", "/ajax/ajaxrequest6?t=" + new Date().getTime(), true)// 4.发送请求xhr.send()}}
</script>
<button id="btn">显示学生列表</button>
<table width="500px" border="1px"><thead><tr><th>序号</th><th>姓名</th><th>年龄</th></tr></thead><tbody id="stutbody"><!--<tr><td>1</td><td>zhangsan</td><td>20</td></tr><tr><td>2</td><td>lisi</td><td>22</td></tr>--></tbody>
</table>
</body>
</html>

后端

package com.bjpowernode.ajax.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @program: 代码* @ClassName: AjaxRequest6Servlet* @version: 1.0* @description: 服务器端返回XML字符串* @author: bjpowernode* @create: 2022-05-15 11:48**/
@WebServlet("/ajaxrequest6")
public class AjaxRequest6Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 注意:响应的内容类型是XML。response.setContentType("text/xml;charset=UTF-8");PrintWriter out = response.getWriter();/*<students><student><name>zhangsan</name><age>20</age></student><student><name>lisi</name><age>22</age></student></students>*/StringBuilder xml = new StringBuilder();xml.append("<students>");xml.append("<student>");xml.append("<name>zhangsan</name>");xml.append("<age>20</age>");xml.append("</student>");xml.append("<student>");xml.append("<name>lisi</name>");xml.append("<age>22</age>");xml.append("</student>");xml.append("</students>");out.print(xml);}
}

AJAX乱码问题

  • 测试内容:

    • 发送ajax get请求
      • 发送数据到服务器,服务器获取的数据是否乱码?
      • 服务器响应给前端的中文,会不会乱码?
    • 发送ajax post请求
      • 发送数据到服务器,服务器获取的数据是否乱码?
      • 服务器响应给前端的中文,会不会乱码?
  • 包括还要测试tomcat服务器的版本:

    • tomcat10和tomcat9都要进行测试。
  • 测试结果:

    • 对于tomcat10来说,关于字符集,我们程序员不需要干涉,不会出现乱码。

    • 对于tomcat9来说呢?

      • 响应中文的时候,会出现乱码,怎么解决?

        response.setContentType("text/html;charset=UTF-8");
        
      • 发送ajax post请求的时候,发送给服务器的数据,服务器接收之后乱码,怎么解决?

        request.setCharacterEncoding("UTF-8");
        
回顾复习

总体来说,解决乱码问题中请求时乱码 只有post 要设置 响应乱码都需要设置

针对tomcat9以及之前的

测试用例:ajax-enconding包下的测试

前端ajax8.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>测试AJAX乱码问题</title>
</head>
<body><script type="text/javascript">window.onload = function(){// ajax getdocument.getElementById("btn1").onclick = function(){var xhr = new XMLHttpRequest();xhr.onreadystatechange = function (){if (this.readyState == 4) {if (this.status == 200) {document.getElementById("mydiv").innerHTML = this.responseText}}}var username = document.getElementById("username").valuexhr.open("GET", "/ajax-encoding/ajaxrequest7?username="+username+"&t=" + new Date().getTime(), true)xhr.send()}// ajax postdocument.getElementById("btn2").onclick = function(){var xhr = new XMLHttpRequest();xhr.onreadystatechange = function (){if (this.readyState == 4) {if (this.status == 200) {document.getElementById("mydiv").innerHTML = this.responseText}}}xhr.open("POST", "/ajax-encoding/ajaxrequest7", true)xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")var username = document.getElementById("username").valuexhr.send("username=" + username)}}
</script><input type="text" id="username">
<button id="btn1">发送ajax get请求,测试乱码问题</button>
<button id="btn2">发送ajax post请求,测试乱码问题</button><div id="mydiv"></div></body>
</html>

后端

package com.bjpowernode.ajax.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** @program: 代码* @ClassName: AjaxRequest7Servlet* @version: 1.0* @description: 测试ajax乱码问题* @author: bjpowernode* @create: 2022-05-15 12:25**/
@WebServlet("/ajaxrequest7")
public class AjaxRequest7Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 接收的中文会不会乱码String username = request.getParameter("username");System.out.println(username);// 响应中文会有乱码吗?response.setContentType("text/html;charset=UTF-8"); // tomcat9以及之前的版本,这行代码是必须要加的。PrintWriter out = response.getWriter();out.print(username);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 接收的中文会不会乱码request.setCharacterEncoding("UTF-8");String username = request.getParameter("username");System.out.println(username);// 响应中文会有乱码吗?response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();out.print(username);}
}

AJAX的异步与同步

  • 什么是异步?什么是同步?

    • ajax请求1和ajax请求2,同时并发,谁也不用等谁,这就是异步。(a不等b,b也不等a)
    • 如果ajax请求1在发送的时候需要等待ajax请求2结束之后才能发送,那么这就是同步。(a等待b,或者b等待a,只要发生等待,就是同步。)
  • 异步和同步在代码上如何实现?

    // 假设这个是ajax请求1
    // 如果第三个参数是false:这个就表示“ajax请求1”不支持异步,也就是说ajax请求1发送之后,会影响其他ajax请求的发送,只有当我这个请求结束之后,你们其他的ajax请求才能发送。
    // false表示,不支持异步。我这个请求发了之后,你们其他的请求都要靠边站。都等着。你们别动呢,等我结束了你们再说。
    xhr1.open("请求方式", "URL", false)
    xhr1.send()// 假设这个是ajax请求2
    // 如果第三个参数是true:这个就表示“ajax请求2”支持异步请求,也就是说ajax请求2发送之后,不影响其他ajax请求的发送。
    xhr2.open("请求方式", "URL", true) 
    xhr2.send()
    
  • 什么情况下用同步?(大部分情况下我们都是使用ajax异步方式,同步很少用。)

    • 举一个例子

      • 用户注册
        • 用户名需要发送ajax请求进行校验
        • 邮箱地址也需要发送ajax请求校验
        • 其他的也可能需要发送ajax请求。。。
        • 并且最终注册按钮的时候,也是发送ajax请求进行注册。
        • 那么显然,注册的Ajax请求和校验的ajax请求不能异步,必须等待所有的校验ajax请求结束之后,注册的ajax请求才能发。

回顾复习

前端:ajax9.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>演示ajax同步和异步</title>
</head>
<body><script type="text/javascript">window.onload = function(){document.getElementById("btn1").onclick = function (){var xhr = new XMLHttpRequest();xhr.onreadystatechange = function (){if (this.readyState == 4) {if (this.status == 200) {document.getElementById("div1").innerHTML = this.responseText}else{alert(this.status)}}}//xhr.open("GET", "/ajax/ajaxrequest8?t=" + new Date().getTime(), true)// 我不支持异步了,我这个请求只要发,你们都得靠边站。都得等着我结束你们才能发请求。xhr.open("GET", "/ajax/ajaxrequest8?t=" + new Date().getTime(), false)xhr.send()}document.getElementById("btn2").onclick = function (){var xhr = new XMLHttpRequest();xhr.onreadystatechange = function (){if (this.readyState == 4) {if (this.status == 200) {document.getElementById("div2").innerHTML = this.responseText}else{alert(this.status)}}}xhr.open("GET", "/ajax/ajaxrequest9?t=" + new Date().getTime(), true)xhr.send()}}
</script><button id="btn1">ajax请求1</button><div id="div1"></div><button id="btn2">ajax请求2</button><div id="div2"></div></body>
</html>

后端AjaxRequest8Servlet

package com.bjpowernode.ajax.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @program: 代码* @ClassName: AjaxRequest8Servlet* @version: 1.0* @description: 测试ajax同步和异步* @author: bjpowernode* @create: 2022-05-15 13:06**/
@WebServlet("/ajaxrequest8")
public class AjaxRequest8Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try {Thread.sleep(10 * 1000);} catch (InterruptedException e) {e.printStackTrace();}response.setContentType("text/html;charset=UTF-8");response.getWriter().print("ajax请求1");}
}

AjaxRequest9Servlet

package com.bjpowernode.ajax.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @program: 代码* @ClassName: AjaxRequest8Servlet* @version: 1.0* @description: 测试ajax同步和异步* @author: bjpowernode* @create: 2022-05-15 13:06**/
@WebServlet("/ajaxrequest9")
public class AjaxRequest9Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");response.getWriter().print("ajax请求2");}
}

AJAX代码封装

  • AJAX请求相关的代码都是类似的,有很多重复的代码,这些重复的代码能不能不写,能不能封装一个工具类。要发送ajax请求的话,就直接调用这个工具类中的相关函数即可。

  • 接下来,手动封装一个工具类,这个工具类我们可以把它看做是一个JS的库。我们把这个JS库起一个名字,叫做jQuery。(我这里封装的jQuery只是一个前端的库,和后端的java没有关系,只是为了方便web前端代码的编写,提高WEB前端的开发效率)

  • 手动开发jQuery,源代码

    function jQuery(selector){if (typeof selector == "string") {if (selector.charAt(0) == "#") {domObj = document.getElementById(selector.substring(1))return new jQuery()}}if (typeof selector == "function") {window.onload = selector}this.html = function(htmlStr){domObj.innerHTML = htmlStr}this.click = function(fun){domObj.onclick = fun}this.focus = function (fun){domObj.onfocus = fun}this.blur = function(fun) {domObj.onblur = fun}this.change = function (fun){domObj.onchange = fun}this.val = function(v){if (v == undefined) {return domObj.value}else{domObj.value = v}}// 静态的方法,发送ajax请求/*** 分析:使用ajax函数发送ajax请求的时候,需要程序员给我们传过来什么?*      请求的方式(type):GET/POST*      请求的URL(url):url*      请求时提交的数据(data):data*      请求时发送异步请求还是同步请求(async):true表示异步,false表示同步。*/jQuery.ajax = function(jsonArgs){// 1.var xhr = new XMLHttpRequest();// 2.xhr.onreadystatechange = function(){if (this.readyState == 4) {if (this.status == 200) {// 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。var jsonObj = JSON.parse(this.responseText)// 调用函数jsonArgs.success(jsonObj)}}}if (jsonArgs.type.toUpperCase() == "POST") {// 3.xhr.open("POST", jsonArgs.url, jsonArgs.async)// 4.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")xhr.send(jsonArgs.data)}if (jsonArgs.type.toUpperCase() == "GET") {xhr.open("GET", jsonArgs.url + "?" + jsonArgs.data, jsonArgs.async)xhr.send()}}
    }
    $ = jQuery// 这里有个细节,执行这个目的是为了让静态方法ajax生效。
    new jQuery()
  • 使用以上库,怎么用?

    <script type="text/javascript" src="/ajax/js/jQuery-1.0.0.js"></script>
    <script type="text/javascript">$(function(){$("#btn1").click(function(){$.ajax({type : "POST",url : "/ajax/ajaxrequest11",data : "username=" + $("#username").val(),async : true,success : function(json){$("#div1").html(json.uname)}})})})
    </script>
    
回顾复习

js的编写以及封装到jQury

js知识部分复习js-review.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>回顾javascript中的类的定义,对象的创建。属性的访问,方法的访问。</title>
</head>
<body><script type="text/javascript">// 在JS当中怎么定义一个类。function User(a, b){// 属性this.usercode = a;this.username = b;// 方法(实例方法,通过对象调用的。)this.doSome = function(){console.log(this.username + " doSome....")}// 静态方法(直接用类名调用)User.doOther = function(){console.log("user doOther....")}}/*User = function(usercode, username){// 属性this.usercode = usercode;this.username = username;// 方法(实例方法,通过对象调用的。)this.doSome = function(){console.log(username + " doSome....")}// 静态方法(直接用类名调用)User.doOther = function(){console.log("user doOther....")}}*/// 创建对象,访问对象的属性,访问对象的方法,访问静态方法// User(); 直接这样调用,你只是把它当做一个普通的函数去执行,不会创建对象,在堆中没有这个对象。// new User(); 这样调用的话,其实就是调用该类的构造方法,创建对象,并且在堆中分配空间。var user = new User("111", "zhangsan");// 访问属性alert(user.usercode + "," + user.username)// 调用方法(实例方法)user.doSome()// 调用静态方法User.doOther()// 后期如果想给某个类型扩展方法,还可以使用prototype属性User.prototype.扩展的 = function(){console.log("打印。。。。。")}user.扩展的()</script></body>
</html>

前端代码一点点的封装ajax10.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>手动封装JS库jQuery</title>
</head>
<body><script type="text/javascript">/*封装一个函数,通过这个函数可以获取到html页面中的节点,这个函数我给他起一个名字,叫做:jQuery*//*要封装的代码是:根据id来获取元素。document.getElementById("btn")*//*设计思路来自于CSS的语法。 #id 可以获取到这个元素 */function jQuery(selector){ // selector可能是#id,也可以能是其他的选择器,例如类选择器:.class// 根据id获取元素if (typeof selector == "string") {if (selector.charAt(0) == "#") {// selector是一个id选择器//var domObj = document.getElementById(selector.substring(1))// 升级成全局变量domObj = document.getElementById(selector.substring(1))// 返回的dom对象//return domObj// 返回的jQuery对象return new jQuery()}}// 页面加载完毕之后,注册回调函数。if (typeof selector == "function") {window.onload = selector}// 定义一个html()函数,代替:domObj.innerHTML = ""this.html = function(htmlStr){domObj.innerHTML = htmlStr}// 定义一个click()函数,代替:domObj.onclick = function(){}this.click = function(fun){domObj.onclick = fun}this.focus = function (fun){domObj.onfocus = fun}this.blur = function(fun) {domObj.onblur = fun}this.change = function (fun){domObj.onchange = fun}// ....this.val = function(v){if (v == undefined) {return domObj.value}else{domObj.value = v}}}$ = jQuery  //$ 就是变量名  字母 数字 下划线// --------------------------------------------------------------------------------------------------------------/*window.onload = function () {// document.getElementById("btn").onclick = function(){//     document.getElementById("div1").innerHTML = "<font color='red'>用户名不可用!!!!</font>"// }// jQuery("#btn").onclick = function(){//     jQuery("#div1").innerHTML = "<font color='red'>用户名不可用~~~~</font>"// }$("#btn").onclick = function(){$("#div1").innerHTML = "<font color='red'>~~~~用户名不可用~~~~</font>"}}*/// $(function(){}) 作用是什么?// 只要你写上以上的代码,就表示在页面加载完毕之后,执行里面的回调函数。/*$(function () {$("#btn").onclick = function(){$("#div1").innerHTML = "<font color='red'>%%%%%%%%用户名不可用~~~~</font>"}})*/$(function () {$("#btn").click(function(){$("#div1").html("<font color='red'>%%%%%%%%用户名不可用%%%%%%%%%</font>")// 获取到文本框中的用户名/*var username = document.getElementById("username").valuealert(username)*/var username = $("#username").val()alert(username)// 修改文本框的value//document.getElementById("username").value = "呵呵"$("#username").val("呵呵了!!!")})})</script>用户名:<input type="text" id="username"><button id="btn">显示信息</button><div id="div1"></div></body>
</html>

将自己写好的js工具包自己封装到一个包里,js包下的jQuery-1.0.0.js

function jQuery(selector){if (typeof selector == "string") {if (selector.charAt(0) == "#") {domObj = document.getElementById(selector.substring(1))return new jQuery()}}if (typeof selector == "function") {window.onload = selector}this.html = function(htmlStr){domObj.innerHTML = htmlStr}this.click = function(fun){domObj.onclick = fun}this.focus = function (fun){domObj.onfocus = fun}this.blur = function(fun) {domObj.onblur = fun}this.change = function (fun){domObj.onchange = fun}this.val = function(v){if (v == undefined) {return domObj.value}else{domObj.value = v}}// 静态的方法,发送ajax请求/*** 分析:使用ajax函数发送ajax请求的时候,需要程序员给我们传过来什么?*      请求的方式(type):GET/POST*      请求的URL(url):url*      请求时提交的数据(data):data*      请求时发送异步请求还是同步请求(async):true表示异步,false表示同步。*/jQuery.ajax = function(jsonArgs){// 1.var xhr = new XMLHttpRequest();// 2.xhr.onreadystatechange = function(){if (this.readyState == 4) {if (this.status == 200) {// 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。var jsonObj = JSON.parse(this.responseText)// 调用函数jsonArgs.success(jsonObj)}}}if (jsonArgs.type.toUpperCase() == "POST") {// 3.xhr.open("POST", jsonArgs.url, jsonArgs.async)// 4.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")xhr.send(jsonArgs.data)}if (jsonArgs.type.toUpperCase() == "GET") {xhr.open("GET", jsonArgs.url + "?" + jsonArgs.data, jsonArgs.async)xhr.send()}}
}
$ = jQuery// 这里有个细节,执行这个目的是为了让静态方法ajax生效。
new jQuery()

jQury就是js代码的封装

封装后的应用测试jQueryTest.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>测试我们自己编写jQuery库(jQuery本质上就是JS的库)</title>
</head>
<body><!--使用jQuery库的第一件事,是把jQuery库引进来-->
<script type="text/javascript" src="js/jQuery-1.0.0.js"></script><script type="text/javascript">$(function(){$("#btn").click(function(){//alert("hello")// 获取文本框内容alert($("#usercode").val())// 修改文本框的value$("#usercode").val("张三")// 设置div内容$("#mydiv").html("我们自己封装的jQuery不是也挺好吗!!!")})})
</script><button id="btn">hello</button><br>
用户代码:<input type="text" id="usercode"><br>
<div id="mydiv"></div>
</body>
</html>

AJAX代码封装

前端调用ajax11.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>将AJAX代码进行封装,封装到jQuery库当中</title>
</head>
<body><script type="text/javascript" src="/ajax/js/jQuery-1.0.0.js"></script><script type="text/javascript">window.onload = function(){document.getElementById("btn").onclick = function (){/*// 1.var xhr = new XMLHttpRequest();// 2.xhr.onreadystatechange = function(){if (this.readyState == 4) {if (this.status == 200) {// 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。var jsonObj = JSON.parse(this.responseText)// 返回的json格式的数据:{"uname" : "zhangsan"}document.getElementById("mydiv").innerHTML = jsonObj.uname}}}// 3.xhr.open("POST", "/ajax/ajaxrequest10", true)// 4.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")var username = document.getElementById("username").valuexhr.send("username=" + username)*/// 调用jQuery的工具类中的ajax方法来发送ajax请求var username = document.getElementById("username").value$.ajax({type : "POST",url : "/ajax/ajaxrequest10",data : "username=" + username,async : true,// 程序响应回来之后,对于客户端来说要拿到响应的数据,然后解析这个数据,展示到页面上。success : function(json){document.getElementById("mydiv").innerHTML = json.uname}})}}
</script>
<button id="btn">发送ajax请求</button><br>
用户名:<input type="text" id="username"><br>
<div id="mydiv"></div>
</body>
</html>

封装好的jQury,jQuery-1.0.0.js

function jQuery(selector){if (typeof selector == "string") {if (selector.charAt(0) == "#") {domObj = document.getElementById(selector.substring(1))return new jQuery()}}if (typeof selector == "function") {window.onload = selector}this.html = function(htmlStr){domObj.innerHTML = htmlStr}this.click = function(fun){domObj.onclick = fun}this.focus = function (fun){domObj.onfocus = fun}this.blur = function(fun) {domObj.onblur = fun}this.change = function (fun){domObj.onchange = fun}this.val = function(v){if (v == undefined) {return domObj.value}else{domObj.value = v}}// 静态的方法,发送ajax请求/*** 分析:使用ajax函数发送ajax请求的时候,需要程序员给我们传过来什么?*      请求的方式(type):GET/POST*      请求的URL(url):url*      请求时提交的数据(data):data*      请求时发送异步请求还是同步请求(async):true表示异步,false表示同步。*/jQuery.ajax = function(jsonArgs){// 1.var xhr = new XMLHttpRequest();// 2.xhr.onreadystatechange = function(){if (this.readyState == 4) {if (this.status == 200) {// 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。var jsonObj = JSON.parse(this.responseText)// 调用函数jsonArgs.success(jsonObj)}}}if (jsonArgs.type.toUpperCase() == "POST") {// 3.xhr.open("POST", jsonArgs.url, jsonArgs.async)// 4.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")xhr.send(jsonArgs.data)}if (jsonArgs.type.toUpperCase() == "GET") {xhr.open("GET", jsonArgs.url + "?" + jsonArgs.data, jsonArgs.async)xhr.send()}}
}
$ = jQuery// 这里有个细节,执行这个目的是为了让静态方法ajax生效。
new jQuery()

后端AjaxRequest10Servet.java

package com.bjpowernode.ajax.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @program: 代码* @ClassName: AjaxRequest10Servet* @version: 1.0* @description: 将AJAX请求封装到jQuery当中* @author: bjpowernode* @create: 2022-05-15 19:10**/
@WebServlet("/ajaxrequest10")
public class AjaxRequest10Servet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");String username = request.getParameter("username");//{"uname" : "zhangsan"}response.getWriter().print("{\"uname\" : \""+username+"\"}");}
}

测试自己写的库

前端:ajax12.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>测试我们自己手动开发的jQuery库</title>
</head>
<body><!--引入自己写的jQuery库-->
<script type="text/javascript" src="/ajax/js/jQuery-1.0.0.js"></script><script type="text/javascript">$(function(){$("#btn1").click(function(){// 发送ajax请求$.ajax({//type : "GET",type : "POST",url : "/ajax/ajaxrequest11",data : "username=" + $("#username").val(),async : true,success : function(json){$("#div1").html(json.uname)}})})})
</script><button id="btn1">发送ajax请求</button><br>
用户名:<input type="text" id="username"><br>
<div id="div1"></div></body>
</html>

调用的库:jQuery-1.0.0.js

function jQuery(selector){if (typeof selector == "string") {if (selector.charAt(0) == "#") {domObj = document.getElementById(selector.substring(1))return new jQuery()}}if (typeof selector == "function") {window.onload = selector}this.html = function(htmlStr){domObj.innerHTML = htmlStr}this.click = function(fun){domObj.onclick = fun}this.focus = function (fun){domObj.onfocus = fun}this.blur = function(fun) {domObj.onblur = fun}this.change = function (fun){domObj.onchange = fun}this.val = function(v){if (v == undefined) {return domObj.value}else{domObj.value = v}}// 静态的方法,发送ajax请求/*** 分析:使用ajax函数发送ajax请求的时候,需要程序员给我们传过来什么?*      请求的方式(type):GET/POST*      请求的URL(url):url*      请求时提交的数据(data):data*      请求时发送异步请求还是同步请求(async):true表示异步,false表示同步。*/jQuery.ajax = function(jsonArgs){// 1.var xhr = new XMLHttpRequest();// 2.xhr.onreadystatechange = function(){if (this.readyState == 4) {if (this.status == 200) {// 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。var jsonObj = JSON.parse(this.responseText)// 调用函数jsonArgs.success(jsonObj)}}}if (jsonArgs.type.toUpperCase() == "POST") {// 3.xhr.open("POST", jsonArgs.url, jsonArgs.async)// 4.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")xhr.send(jsonArgs.data)}if (jsonArgs.type.toUpperCase() == "GET") {xhr.open("GET", jsonArgs.url + "?" + jsonArgs.data, jsonArgs.async)xhr.send()}}
}
$ = jQuery// 这里有个细节,执行这个目的是为了让静态方法ajax生效。
new jQuery()

后端:AjaxRequest11Servlet

package com.bjpowernode.ajax.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Locale;/*** @program: 代码* @ClassName: AjaxRequest11Servlet* @version: 1.0* @description: 测试自己写的jQuery库* @author: bjpowernode* @create: 2022-05-15 19:38**/
@WebServlet("/ajaxrequest11")
public class AjaxRequest11Servlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");response.setContentType("text/html;charset=UTF-8");// {"uname":"zhangsan"}response.getWriter().print("{\"uname\":\""+username.toUpperCase()+"\"}");}protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");response.setContentType("text/html;charset=UTF-8");// {"uname":"zhangsan"}response.getWriter().print("{\"uname\":\""+username.toLowerCase()+"\"}");}}

AJAX实现省市联动

  • 什么是省市联动?

    • 在网页上,选择对应的省份之后,动态的关联出该省份对应的市。选择对应的市之后,动态的关联出该市对应的区。(首先要清楚需求)
  • 进行数据库表的设计

    • t_area (区域表)
      id(PK-自增)	  code		name		pcode
      ---------------------------------------------
      1				001		 河北省		null
      2				002		 河南省		null
      3				003		 石家庄	    001
      4				004		 邯郸			 001
      5				005		 郑州			 002
      6				006		 洛阳			 002
      7				007		 丛台区	    004  将全国所有的省、市、区、县等信息都存储到一张表当中。
      采用的存储方式实际上是code pcode形势。
      
  • 建表t_area,模拟好数据。

  • 首先实现第一个功能:

    • 页面加载完毕之后,先把省份全部展现出来。

数据库设计,实体类的创建Area.java

package com.bjpowernode.ajax.beans;/*** @program: 代码* @ClassName: Area* @version: 1.0* @description: 区域* @author: bjpowernode* @create: 2022-05-15 22:02**/
public class Area {private String code;private String name;public Area() {}public Area(String code, String name) {this.code = code;this.name = name;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

前端ajax13.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>省市联动</title>
</head>
<body><!--引入我们自己编写的jQuery库-->
<script type="text/javascript" src="/ajax/js/jQuery-1.0.0.js"></script><script type="text/javascript">$(function(){// 发送ajax请求,获取所有的省份。省份的pcode是null$.ajax({type : "get",url : "/ajax/listArea",data : "t=" + new Date().getTime(),async : true,success : function(jsonArr){// [{"code":"001", "name":"河北省"},{"code":"002", "name":"河南省"}]// 以上格式的json是我们自己设计出来的,希望服务器能够给我们返回这样一个json格式的字符串。var html = "<option value=''>--请选择省份--</option>";for (var i = 0; i < jsonArr.length; i++) {var area = jsonArr[i]html += "<option value='"+area.code+"'>"+area.name+"</option>"}$("#province").html(html)}})// 只要change发生,就发送ajax请求$("#province").change(function(){//alert("发送ajax请求")//alert(this)//alert(this.value)// 发送ajax请求$.ajax({type : "get",url : "/ajax/listArea",data : "t=" + new Date().getTime() + "&pcode=" + this.value,async : true,success : function(jsonArr){// [{"code":"006", "name":"XXX"},{"code":"008", "name":"YYYY"}]var html = "<option value=''>--请选择市--</option>";for (var i = 0; i < jsonArr.length; i++) {var area = jsonArr[i]html += "<option value='"+area.code+"'>"+area.name+"</option>"}$("#city").html(html)}})})})
</script><select id="province"><!--<option value="">&#45;&#45;请选择省份&#45;&#45;</option><option value="001">河北省</option><option value="002">河南省</option>-->
</select><select id="city"></select></body>
</html>

后端ListAreaServlet.java

package com.bjpowernode.ajax.servlet;import com.alibaba.fastjson.JSON;
import com.bjpowernode.ajax.beans.Area;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;/*** @program: 代码* @ClassName: ListAreaServlet* @version: 1.0* @description: 动态获取对应的区域* @author: bjpowernode* @create: 2022-05-15 21:57**/
@WebServlet("/listArea")
public class ListAreaServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String pcode = request.getParameter("pcode");// 连接数据库,获取所有的对应区域。最终响应一个JSON格式的字符串给WEB前端。Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;List<Area> areaList = new ArrayList<>();try {// 注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 获取连接String url = "jdbc:mysql://localhost:3306/bjpowernode?useUnicode=true&characterEncoding=UTF-8";String user = "root";String password = "root";conn = DriverManager.getConnection(url, user, password);// 获取预编译数据库操作对象String sql = "";if(pcode == null){sql = "select code,name from t_area where pcode is null";ps = conn.prepareStatement(sql);}else{sql = "select code,name from t_area where pcode = ?";ps = conn.prepareStatement(sql);ps.setString(1, pcode);}// 执行SQLrs = ps.executeQuery();// 处理结果集while (rs.next()) {String code = rs.getString("code");String name = rs.getString("name");Area a = new Area(code, name);areaList.add(a);}} catch (Exception e) {e.printStackTrace();} finally {// 释放资源if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if (ps != null) {try {ps.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}response.setContentType("text/html;charset=UTF-8");// 使用fastjson将java对象转换成json字符串。String json = JSON.toJSONString(areaList);// 响应JSON。response.getWriter().print(json);}
}

AJAX跨域问题

跨域的理解

跨域

  • 跨域是指从一个域名的网页去请求另一个域名的资源。比如从百度(https://baidu.com)页面去请求京东(https://www.jd.com)的资源。
  • 通过超链接或者form表单提交或者window.location.href的方式进行跨域是不存在问题的(大家可以编写程序测试一下)。但在一个域名的网页中的一段js代码发送ajax请求去访问另一个域名中的资源,由于同源策略的存在导致无法跨域访问,那么ajax就存在这种跨域问题。
  • 同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,同源就是协议、域名和端口都相同。
  • 同源策略有什么用?如果你刚刚在网银输入账号密码,查看了自己还有1万块钱,紧接着访问一些不规矩的网站,这个网站可以访问刚刚的网银站点,并且获取账号密码,那后果可想而知。所以,从安全的角度来讲,同源策略是有利于保护网站信息的。
  • 有一些情况下,我们是需要使用ajax进行跨域访问的。比如某公司的A页面(a.bjpowernode.com)有可能需要获取B页面(b.bjpowernode.com)。

同源还是不同源

  • 区分同源和不同源的三要素

    • 协议
    • 域名
    • 端口
  • 协议一致,域名一致,端口号一致,三个要素都一致,才是同源,其它一律都是不同源

URL1URL2是否同源描述
http://localhost:8080/a/index.htmlhttp://localhost:8080/a/first同源协议 域名 端口一致
http://localhost:8080/a/index.htmlhttp://localhost:8080/b/first同源协议 域名 端口一致
http://www.myweb.com:8080/a.jshttps://www.myweb.com:8080/b.js不同源协议不同
http://www.myweb.com:8080/a.jshttp://www.myweb.com:8081/b.js不同源端口不同
http://www.myweb.com/a.jshttp://www.myweb2.com/b.js不同源域名不同
http://www.myweb.com/a.jshttp://crm.myweb.com/b.js不同源子域名不同

复现AJAX跨域问题

AJAX跨域解决方案

跨域解决方案之代理机制

方案1:设置响应头
  • 核心原理:跨域访问的资源允许你跨域访问。

  • 实现:

    • response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); // 允许某个
      response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有
      
方案2:jsonp
  • jsonp:json with padding(带填充的json【学完之后再理解这个什么意思!!!】)
  • jsonp不是一个真正的ajax请求。只不过可以完成ajax的局部刷新效果。可以说jsonp是一种类ajax请求的机制。
  • jsonp不是ajax请求,但是可以完成局部刷新的效果,并且可以解决跨域问题。
  • 注意:jsonp解决跨域的时候,只支持GET请求。不支持post请求。
方案3:jQuery封装的jsonp
  • 牛人们写的jQuery库,已经对jsonp进行了封装。大家可以直接拿来用。

  • 用之前需要引入jQuery库的js文件。(这里的jQuery库咱们就不再封装了,咱们直接用jQuery写好的jsonp方式。)

  • jQuery中的jsonp其实就是我们方案2的高度封装,底层原理完全相同。

  • 核心代码

    • $.ajax({type : "GET",url : "跨域的url",dataType : "jsonp", // 指定数据类型jsonp : "fun", // 指定参数名(不设置的时候,默认是:"callback")jsonpCallback : "sayHello" // 指定回调函数的名字// (不设置的时候,jQuery会自动生成一个随机的回调函数,//并且这个回调函数还会自动调用success的回调函数。)
      })
      
方案4:代理机制(httpclient)

跨域解决方案之代理机制

  • 使用Java程序怎么去发送get/post请求呢?【GET和POST请求就是HTTP请求。】
    • 第一种方案:使用JDK内置的API(java.net.URL…),这些API是可以发送HTTP请求的。
    • 第二种方案:使用第三方的开源组件,比如:apache的httpclient组件。(httpclient组件是开源免费的,可以直接用)
  • 在java程序中,使用httpclient组件可以发送http请求。
    • 对于httpclient组件的代码,大家目前可以不进行深入的研究,可以从网上直接搜。然后粘贴过来,改一改,看看能不能完成发送get和post请求。
    • 使用httpclient组件,需要先将这个组件相关的jar包引入到项目当中。
方案5:nginx反向代理
  • nginx反向代理中也是使用了这种代理机制来完成AJAX的跨域,实现起来非常简单,只要修改一个nginx的配置即可。以后大家学习nginx之后再说吧。!!!!
回顾复习

A B 两个模块的结构

A站点去访问 B 站点,常规

A

A站点的index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>a应用的index页面</title>
</head>
<body>
<!--通过超链接的方式可以跨域吗?可以-->
<a href="http://localhost:8081/b/index.html">b的index页面(跨域访问)</a><!--form表单发送请求可以跨域吗?可以-->
<form action="http://localhost:8081/b/user/reg" method="post">用户名:<input type="text" name="username"><br>密码:<input type="password" name="password"><br><input type="submit" value="注册">
</form><br><br><br><!--通过js代码中的window.location.href/document.location.href可以跨域吗?可以-->
<button onclick="window.location.href='http://localhost:8081/b/index.html'">b的index页面(跨域访问)1</button>
<button onclick="document.location.href='http://localhost:8081/b/index.html'">b的index页面(跨域访问)2</button><!--使用script标签可以加载js文件,这个可以跨域吗?可以-->
<script type="text/javascript" src="http://localhost:8081/b/my.js"></script><br><!--加载其他站点的图片,可以跨域吗?可以-->
<img src="http://localhost:8081/b/bd_logo.png" /></body>
</html>

B

B站点下的web资源,自己看源码,较简单,且没啥东西

B站点的Servlet,UserRegServlet

package com.bjpowernode.b.web.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/user/reg")
public class UserRegServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获取用户名和密码String username = request.getParameter("username");String password = request.getParameter("password");// 响应到前端response.getWriter().print(username + ":" + password);}
}

A站点去访问 B 站点,Ajax

A 站点前端ajax1.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>测试:ajax跨域访问会不会有问题???</title>
</head>
<body>
<script type="text/javascript">/*window.onload = function(){document.getElementById("btn").onclick = function(){}}*//** 默认情况下:发送ajax跨域请求的时候会出现以下错误:* 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.* 出现这个错误的根本原因是:跨域的时候,不允许共享同一个XMLHttpRequest对象。因为共享同一个XMLHttpRequest对象是不安全的。* 重点提示:CORS策略阻止(这个ajax跨域请求被:同源策略阻止。)* 什么是同源策略?????*      同源策略是浏览器的一种安全策略。* 什么是同源?什么是不同源?*      协议一致、域名一致、端口号一致。才是同源。*      只要上面的任一元素不一致,就是不同源。*      同源:XMLHttpRequest对象可以共享。*      不同源:XMLHttpRequest对象不可以共享。*/// 使用ES6新特性:箭头函数window.onload = () => {document.getElementById("btn").onclick = () => {// 发送ajax的跨域请求// 1. 创建核心对象// let是一个关键字,可以定义变量。// ES6的新特性:let和const关键字都可以定义变量。// 注意:在JS中声明变量,可以使用:var let const。他们之间有什么区别?自己研究。let xmlHttpRequest = new XMLHttpRequest();// 2. 注册回调函数xmlHttpRequest.onreadystatechange = () => {if (xmlHttpRequest.readyState == 4) {if (xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {document.getElementById("mydiv").innerHTML = xmlHttpRequest.responseText}}}// 3. 开启通道xmlHttpRequest.open("GET", "http://localhost:8081/b/hello", true)// 4. 发送请求xmlHttpRequest.send()}}</script>
<button id="btn">发送ajax跨域请求</button>
<div id="mydiv"></div>
</body>
</html>

B站点的后端HelloServlet

package com.bjpowernode.b.web.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/hello")
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应头,允许ajax跨域请求//response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");response.setHeader("Access-Control-Allow-Origin", "*");// 响应//response.getWriter().print("hello ajax!!!");response.getWriter().print("{\"username\":\"zhangsan\"}");}
}

jspon传输

A前端ajax2.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>jsonp实现跨域</title>
</head>
<body><script type="text/javascript">/*** 这是我自定义的函数*/function sayHello(data){//alert("hello world!")alert("hello," + data.name)}function sum(){alert("求和。。。")}
</script><!--超链接也可以跨域呀?为什么不用呢?因为超链接点击之后会跳转页面,无法做到页面局部刷新效果。-->
<!--script标签是可以跨域的。src属性可以是xxx.js文件,那这个路径可以是一个servlet路径吗?可以-->
<script type="text/javascript" src="http://localhost:8081/b/jsonp1?fun=sum"></script></body>
</html>

B后端JSONPServlet1.java

package com.bjpowernode.b.web.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/jsonp1")
public class JSONPServlet1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 在后台输出//System.out.println("jsonp方式完成跨域访问");// 向前端响应一段js代码呢?PrintWriter out = response.getWriter();//out.print("alert(123)"); // 这是响应一段js代码,只不过这个alert函数是JS内置的函数,可以直接用。// 注意:不要误以为是后端java代码调用了sayHello()函数,实际上后端只负责响应一个字符串回去。// 真正的调用者,还是浏览器,浏览器接收到这个字符串之后,会自动将这个字符串当做一段js代码解释执行。//out.print("sayHello()"); // 这也是响应一段JS代码。只不过这个sayHello函数是程序员自定义的。//响应一段js代码,然后传一个json数据给前端//out.print("sayHello({\"name\" : \"jackson\"})");// 动态获取函数名String fun = request.getParameter("fun");//out.print(fun + "({\"name\" : \"jackson\"})");out.print(fun + "()");}
}

待填充的jspon

A站点前端ajax3.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>jsonp跨域</title>
</head>
<body><!--<script type="text/javascript" src="http://localhost:8081/b/jsonp2?fun=sayHello"></script>--><script type="text/javascript">// 自定义的函数function sayHello(data){ // data是一个json:{"username" : "lucy"}document.getElementById("mydiv").innerHTML = data.username}window.onload = () => {document.getElementById("btn").onclick = () => {// 加载script元素// 创建script元素对象const htmlScriptElement = document.createElement("script");// 设置script的type属性htmlScriptElement.type = "text/javascript"// 设置script的src属性htmlScriptElement.src = "http://localhost:8081/b/jsonp2?fun=sayHello"// 将script对象添加到body标签中(这一步就是加载script)document.getElementsByTagName("body")[0].appendChild(htmlScriptElement)}}
</script><button id="btn">jsonp解决跨域问题,达到ajax局部刷新的效果</button><div id="mydiv"></div></body>
</html>

B 后端JSONPServlet2.java

package com.bjpowernode.b.web.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/jsonp2")
public class JSONPServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获取函数名String fun = request.getParameter("fun");// 响应一段js代码response.getWriter().print(fun + "({\"username\" : \"lucy\"})");}
}

jQuery封装的jsonp

A 站点

js包下 jquery-3.6.0.min.js

前端实现ajax4.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>jQuery的jsonp封装解决ajax跨域问题</title>
</head>
<body><!--引入jQuery库:这个jQuery库是官网的,不是咱们手写封装的山寨版。-->
<script type="text/javascript" src="/a/js/jquery-3.6.0.min.js"></script><script type="text/javascript">// 这个函数不需要你写,jQuery可以自动帮助你生成//function jQuery3600508253314856699_1655528968612(json){ // 系统自动生成的这个函数默认情况,会自动调用success的回调函数。 }// 自定义的函数function sayHello(data){$("#mydiv").html("欢迎你:" + data.username)}$(function(){$("#btn").click(function(){// 发送所谓的ajax请求(其实本质上并不是一个ajax请求。只是披着ajax的皮。乔装打扮的ajax。)$.ajax({type : "GET", // jsonp请求只支持get请求。// 虽然这里的url是这样写的,但实际上发送的请求是:/b/jsonp3?callback=jQuery3600508253314856699_1655528968612&_=1655528968613// callback=jQuery3600508253314856699_1655528968612// callback就是我们之前的fun// jQuery3600508253314856699_1655528968612就是我们之前的sayHello,而这个名字是jQuery自动为我们生成的。url : "http://localhost:8081/b/jsonp3",dataType : "jsonp", // 指定数据类型是jsonp形式。【最关键的是它】jsonp : "fun", // 不采用默认的参数名callback,用这个属性来指定具体的参数名。jsonpCallback : "sayHello" // 不采用默认的回调函数,用这个属性来指定具体的回调函数。/*success : function(data){ // data变量用来接收服务器端的响应(data是一个json:{"username":"lisi"})$("#mydiv").html("欢迎你:" + data.username)}*/})})})
</script><button id="btn">jQuery库封装的jsonp</button><div id="mydiv"></div></body>
</html>

B

后端JSONPServlet3.java

package com.bjpowernode.b.web.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/jsonp3")
public class JSONPServlet3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获取函数名//String callback = request.getParameter("callback");String callback = request.getParameter("fun");// 响应一段js代码,调用函数response.getWriter().print(callback + "({\"username\":\"lisi\"})");}
}

代理机制(httpclient)

通过java来实现浏览器的操纵

导入相应的依赖

编写对应的java类,记得访问自己的模块要将其放到tomcat上部署一下

HttpClientSendGet.java

package com.bjpowernode.httpclient;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.InputStreamReader;public class HttpClientSendGet {public static void main(String[] args) throws Exception {// 使用java代码去发送HTTP get请求// 目标地址//String url = "https://www.baidu.com";String url = "http://localhost:8081/b/hello";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 response = httpClient.execute(httpGet);HttpEntity entity = response.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);}System.out.println("服务器响应的数据:" + responseSB);reader.close();httpClient.close();}
}

来实现A和B模块两个互通

同上将jar包依赖分别加到两个模块

B模块

B后端:TargetServlet.java

package com.bjpowernode.b.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/target")
public class TargetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 响应一个json字符串。response.getWriter().print("{\"username\":\"jackson\"}");}
}

A模块

A后端ProxyServlet

package com.bjpowernode.javaweb.servlet;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;@WebServlet("/proxy")
public class ProxyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 通过httpclient组件,发送HTTP GET请求,访问 TargetServletHttpGet httpGet = new HttpGet("http://localhost:8081/b/target");httpGet.setHeader("Content-Type", "application/x-www-form-urlencoded");CloseableHttpClient httpClient = HttpClients.createDefault();HttpResponse resp = httpClient.execute(httpGet);HttpEntity entity = resp.getEntity();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);}reader.close();httpClient.close();// b站点响应回来的数据response.getWriter().print(responseSB);}
}

A前端

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>使用代理机制完成ajax跨域访问</title>
</head>
<body>
<script type="text/javascript">// ES6当中的有一个新语法:箭头函数。window.onload = () => {document.getElementById("btn").onclick = () => {// 发送ajax请求// 1.创建核心对象const xmlHttpRequest = new XMLHttpRequest(); // const可以声明变量。(可以自己研究一下:var let const声明变量时有什么区别)// 2.注册回调函数xmlHttpRequest.onreadystatechange = () => {if (xmlHttpRequest.readyState == 4) {// 这里也可以使用区间的方式,因为状态码是200~299都是正常响应结束。if (xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {document.getElementById("mydiv").innerHTML = xmlHttpRequest.responseText}}}// 3.开启通道xmlHttpRequest.open("GET", "/a/proxy", true)// 4.发送请求xmlHttpRequest.send()}}
</script>
<button id="btn">使用代理机制解决ajax跨域访问</button>
<div id="mydiv"></div>
</body>
</html>

AJAX实现搜索联想 自动补全

  • 什么是搜索联想?自动补全?
    • 百度是一个很典型的代表。在百度的搜索框中输入相关信息的时候,会有搜索联想以及自动补全。
    • 搜索联想和自动补全:实际上是为了方便用户的使用。让用户的体验更好。
    • 搜索联想:当用户输入一些单词之后,自动联想出用户要搜索的信息,给一个提示。
    • 自动补全:当联想出一些内容之后,用户点击某个联想的单词,然后将这个单词自动补全到搜索框当中。
    • 搜索联想和自动补全功能,因为是页面局部刷新效果,所以需要使用ajax请求来完成。
  • 搜索联想,自动补全功能的核心实现原理?
    • 当键盘事件发生之后,比如:keyup:键弹起事件。
    • 发送ajax请求,请求中提交用户输入的搜索内容,例如:北京(发送ajax请求,携带“北京”两个字)
    • 后端接收到ajax请求,接收到“北京”两个字,执行select语句进行模糊查询。返回查询结果。
    • 将查询结果封装成json格式的字符串,将json格式的字符串响应到前端。
    • 前端接收到json格式的字符串之后,解析这个json字符串,动态展示页面。

回顾复习

数据库

drop table if exists t_ajax;
create table t_ajax(id int primary key auto_increment,content varchar(255)
);
insert into t_ajax(content) values('javascript');
insert into t_ajax(content) values('javaweb');
insert into t_ajax(content) values('java');
insert into t_ajax(content) values('java123');
insert into t_ajax(content) values('mysql');
insert into t_ajax(content) values('myweb');
insert into t_ajax(content) values('myapp');
insert into t_ajax(content) values('jdk');
commit;
select * from t_ajax;

前端autocomplete.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>ajax实现搜索联想和自动补全功能</title><style>.userInput {width: 300px;height: 25px;font-size: 20px;padding-left: 5px;}.showDataDiv {width: 310px;border: 1px solid lightgray;background-color: antiquewhite;display: none;}.showDataDiv p {padding-left: 5px;margin-top: 2px;margin-bottom: 2px;}.showDataDiv p:hover{cursor: pointer;border: 1px blue solid;background-color: aliceblue;}</style>
</head>
<body><script type="text/javascript">/*不使用jQuery,也不使用我们自己写的jQuery库。使用原生的ajax实现搜索联想和自动补全。*/window.onload = () => {document.getElementById("keywords").onkeyup = function(){if (this.value == "") {document.getElementById("datadiv").style.display = "none"}else{// 发送ajax请求// 1. 创建AJAX核心对象const xmlHttpRequest = new XMLHttpRequest();// 2. 注册回调函数xmlHttpRequest.onreadystatechange = () => {if (xmlHttpRequest.readyState == 4) {if (xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {// [{"content":"javascript"},{"content":"javaweb"},{"content":"java..."}]const json = JSON.parse(xmlHttpRequest.responseText);// 遍历数组let html = ""for (let i = 0; i < json.length; i++) {html += "<p οnclick='setInput(\""+json[i].content+"\")'>"+json[i].content+"</p>"}document.getElementById("datadiv").innerHTML = html// 显示出来document.getElementById("datadiv").style.display = "block"}}}// 3. 开启通道xmlHttpRequest.open("GET", "/ajax-autocomplete/query?_="+new Date().getTime()+"&keywords=" + this.value, true)// 4. 发送请求xmlHttpRequest.send()}}}function setInput(content){document.getElementById("keywords").value = contentdocument.getElementById("datadiv").style.display = "none"}
</script><input type="text" class="userInput" id="keywords"><div id="datadiv" class="showDataDiv"><!--<p>北京疫情最新情况</p><p>北京天气</p><p>北京时间</p><p>北京人</p>-->
</div>
</body>
</html>

后端:

package com.bjpowernode.javaweb.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;@WebServlet("/query")
public class QueryServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获取用户输入的关键字String keywords = request.getParameter("keywords");// jdbc代码连接数据库,根据关键字查询数据库,返回数据,拼接json格式的字符串Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;StringBuilder sb = new StringBuilder();sb.append("[");try {// 注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 获取连接String url = "jdbc:mysql://localhost:3306/bjpowernode?useUnicode=true&characterEncoding=UTF-8";String user = "root";String password = "root";conn = DriverManager.getConnection(url, user, password);String sql = "select content from t_ajax where content like ?"; // 模糊查询的时候,条件不建议使用%开始,因为会让字段上的索引失效,查询效率降低。ps = conn.prepareStatement(sql);ps.setString(1, keywords + "%");rs = ps.executeQuery();// [{"content":"javascript"},{"content":"javaweb"},{"content":"java..."}]while (rs.next()) {String content = rs.getString("content");sb.append("{\"content\":\""+content+"\"},");}}catch(Exception e){e.printStackTrace();} finally {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}if (ps != null) {try {ps.close();} catch (SQLException e) {e.printStackTrace();}}if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}}response.setContentType("text/html;charset=UTF-8");response.getWriter().print(sb.subSequence(0, sb.length() - 1) + "]");}
}

完事

附录:HTTP状态信息

1xx: 信息

消息:描述:
100 Continue服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。
101 Switching Protocols服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。

2xx: 成功

消息:描述:
200 OK请求成功(其后是对GET和POST请求的应答文档。)
201 Created请求被创建完成,同时新的资源被创建。
202 Accepted供处理的请求已被接受,但是处理未完成。
203 Non-authoritative Information文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝。
204 No Content没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。
206 Partial Content客户发送了一个带有Range头的GET请求,服务器完成了它。

3xx: 重定向

消息:描述:
300 Multiple Choices多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。
301 Moved Permanently所请求的页面已经转移至新的url。
302 Found所请求的页面已经临时转移至新的url。
303 See Other所请求的页面可在别的url下被找到。
304 Not Modified未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy客户请求的文档应该通过Location头所指明的代理服务器提取。
306 Unused此代码被用于前一版本。目前已不再使用,但是代码依然被保留。
307 Temporary Redirect被请求的页面已经临时移至新的url。

4xx: 客户端错误

消息:描述:
400 Bad Request服务器未能理解请求。
401 Unauthorized被请求的页面需要用户名和密码。
402 Payment Required此代码尚无法使用。
403 Forbidden对被请求页面的访问被禁止。
404 Not Found服务器无法找到被请求的页面。
405 Method Not Allowed请求中指定的方法不被允许。
406 Not Acceptable服务器生成的响应无法被客户端所接受。
407 Proxy Authentication Required用户必须首先使用代理服务器进行验证,这样请求才会被处理。
408 Request Timeout请求超出了服务器的等待时间。
409 Conflict由于冲突,请求无法被完成。
410 Gone被请求的页面不可用。
411 Length Required“Content-Length” 未被定义。如果无此内容,服务器不会接受请求。
412 Precondition Failed请求中的前提条件被服务器评估为失败。
413 Request Entity Too Large由于所请求的实体的太大,服务器不会接受请求。
414 Request-url Too Long由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。
415 Unsupported Media Type由于媒介类型不被支持,服务器不会接受请求。
416服务器不能满足客户在请求中指定的Range头。
417 Expectation Failed

5xx: 服务器错误

消息:描述:
500 Internal Server Error请求未完成。服务器遇到不可预知的情况。
501 Not Implemented请求未完成。服务器不支持所请求的功能。
502 Bad Gateway请求未完成。服务器从上游服务器收到一个无效的响应。
503 Service Unavailable请求未完成。服务器临时过载或当机。
504 Gateway Timeout网关超时。
505 HTTP Version Not Supported服务器不支持请求中指明的HTTP协议版本。
ter().print(sb.subSequence(0, sb.length() - 1) + “]”);
}

}


完事## 附录:HTTP状态信息### 1xx: 信息| 消息:                   | 描述:                                                        |
| :---------------------- | :----------------------------------------------------------- |
| 100 Continue            | 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。 |
| 101 Switching Protocols | 服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。   |### 2xx: 成功| 消息:                             | 描述:                                                        |
| :-------------------------------- | :----------------------------------------------------------- |
| 200 OK                            | 请求成功(其后是对GET和POST请求的应答文档。)                |
| 201 Created                       | 请求被创建完成,同时新的资源被创建。                         |
| 202 Accepted                      | 供处理的请求已被接受,但是处理未完成。                       |
| 203 Non-authoritative Information | 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝。 |
| 204 No Content                    | 没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。 |
| 205 Reset Content                 | 没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。 |
| 206 Partial Content               | 客户发送了一个带有Range头的GET请求,服务器完成了它。         |### 3xx: 重定向| 消息:                  | 描述:                                                        |
| :--------------------- | :----------------------------------------------------------- |
| 300 Multiple Choices   | 多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。 |
| 301 Moved Permanently  | 所请求的页面已经转移至新的url。                              |
| 302 Found              | 所请求的页面已经临时转移至新的url。                          |
| 303 See Other          | 所请求的页面可在别的url下被找到。                            |
| 304 Not Modified       | 未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。 |
| 305 Use Proxy          | 客户请求的文档应该通过Location头所指明的代理服务器提取。     |
| 306 *Unused*           | 此代码被用于前一版本。目前已不再使用,但是代码依然被保留。   |
| 307 Temporary Redirect | 被请求的页面已经临时移至新的url。                            |### 4xx: 客户端错误| 消息:                             | 描述:                                                        |
| :-------------------------------- | :----------------------------------------------------------- |
| 400 Bad Request                   | 服务器未能理解请求。                                         |
| 401 Unauthorized                  | 被请求的页面需要用户名和密码。                               |
| 402 Payment Required              | 此代码尚无法使用。                                           |
| 403 Forbidden                     | 对被请求页面的访问被禁止。                                   |
| 404 Not Found                     | 服务器无法找到被请求的页面。                                 |
| 405 Method Not Allowed            | 请求中指定的方法不被允许。                                   |
| 406 Not Acceptable                | 服务器生成的响应无法被客户端所接受。                         |
| 407 Proxy Authentication Required | 用户必须首先使用代理服务器进行验证,这样请求才会被处理。     |
| 408 Request Timeout               | 请求超出了服务器的等待时间。                                 |
| 409 Conflict                      | 由于冲突,请求无法被完成。                                   |
| 410 Gone                          | 被请求的页面不可用。                                         |
| 411 Length Required               | "Content-Length" 未被定义。如果无此内容,服务器不会接受请求。 |
| 412 Precondition Failed           | 请求中的前提条件被服务器评估为失败。                         |
| 413 Request Entity Too Large      | 由于所请求的实体的太大,服务器不会接受请求。                 |
| 414 Request-url Too Long          | 由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。 |
| 415 Unsupported Media Type        | 由于媒介类型不被支持,服务器不会接受请求。                   |
| 416                               | 服务器不能满足客户在请求中指定的Range头。                    |
| 417 Expectation Failed            |                                                              |### 5xx: 服务器错误| 消息:                          | 描述:                                              |
| :----------------------------- | :------------------------------------------------- |
| 500 Internal Server Error      | 请求未完成。服务器遇到不可预知的情况。             |
| 501 Not Implemented            | 请求未完成。服务器不支持所请求的功能。             |
| 502 Bad Gateway                | 请求未完成。服务器从上游服务器收到一个无效的响应。 |
| 503 Service Unavailable        | 请求未完成。服务器临时过载或当机。                 |
| 504 Gateway Timeout            | 网关超时。                                         |
| 505 HTTP Version Not Supported | 服务器不支持请求中指明的HTTP协议版本。             |

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/373750.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一键换衣,这个AI可以让你实现穿衣自由

基于图像的虚拟穿衣是一种流行且前景广阔的图像合成技术&#xff0c;能够显著改善消费者的购物体验&#xff0c;并降低服装商家的广告成本。顾名思义&#xff0c;虚拟穿衣任务旨在生成目标人穿着给定服装的图像。 OOTDiffusion简述 图1 虚拟换衣 基于图像的虚拟穿衣目前面临两…

系统分析师-基础知识

基础知识 一、计算机组成与结构1、计算机系统基础知识1.1 计算机硬件组成1.2 中央处理单元&#xff08;CPU&#xff09;1.3 数据表示1.3.1 R进制转十进制&#xff1a;1.3.2 十进制转R进制&#xff1a; 1.4 校验码&#xff08;3种校验码&#xff09;1.4.1 基本知识1.4.2 奇偶校验…

2024-07抖音/快手/小红书/视频号/美团无人直播技术:最新不封号无人直播的操作方法详细介绍

2024年最新研究出来的无人直播技术&#xff0c;目前不封号&#xff0c;用途大大的&#xff0c;可带货&#xff0c;可引流&#xff0c;可获客。 手机自动直播源码通常涉及到实时流媒体技术和应用开发&#xff0c;它涉及以下几个关键部分&#xff1a; 摄像头接入&#xff1a;使用…

vue3 学习笔记01 -- 搭建项目及基础配置

vue3 学习笔记01 – 搭建项目及基础配置 确保你已经安装了Node.js&#xff08;建议使用最新的LTS版本&#xff09; 搭建项目 初始化项目 如果选择npm创建项目再执行 npm create vitelatest my-vue3-app --template vue-ts使用yarn&#xff0c;如果电脑没有安装yarn cnpm i ya…

(一)、python程序--模拟电脑鼠走迷宫

一、绪论 1、简介 电脑鼠走迷宫是一种比赛&#xff0c;制作实物电脑鼠小车在迷宫找目标点&#xff0c;用时最短者获胜。考验参赛选手软硬件结合的能力。 2、走迷宫模拟软件中已实现功能 1、点击迷宫墙壁可编辑迷宫&#xff0c;并且可保存和加载迷宫形状文件&#xff1b; 2、…

无线麦克风哪个牌子的好,麦克风哪个品牌音质最好,热门款式推荐

​在当今这个数字化迅速发展的时代&#xff0c;无线领夹麦克风已经成为自媒体创作者、直播主播以及专业录音师不可或缺的工具。它们以其小巧便携、易于操作和出色的录音质量&#xff0c;极大地提升了音频录制的效率和质量。无论是户外探险的Vlog拍摄&#xff0c;还是室内直播的…

基于Android平台开发,天气预报APP

1.项目功能思维导图 2. 项目涉及到的技术点 数据来源&#xff1a;和风天气API使用okhttp网络请求框架获取api数据使用gson库解析json数据使用RecyclerViewadapter实现未来7天列表展示和天气指数使用PopupMenu 实现弹出选项框使用动画定时器实现欢迎页倒计时和logo动画使用Text…

解决IDEA每次新建项目都需要重新配置maven的问题

每次打开IDEA都要重新配置maven&#xff0c;这是因为在DEA中分为项目设置和全局设置&#xff0c;这个时候我们就需要去到全局中设置maven了。我用的是IntelliJ IDEA 2023.3.4 (Ultimate Edition)&#xff0c;以此为例。 第一步&#xff1a;打开一个空的IDEA&#xff0c;选择左…

传知代码-多行人姿态检测系统

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 概述 本项目创新在于采用多级网络串联工作来进行目标的行为分析&#xff0c;并使用在视频监控领域&#xff0c;可部署在任何有需要的人员流动密集场所(如医院&#xff0c;机场&#xff0c;养老院等)或者用于空巢…

springboot三层架构详细讲解

目录 springBoot三层架构0.简介1.各层架构1.1 Controller层1.2 Service层1.3 ServiceImpl1.4 Mapper1.5 Entity1.6 Mapper.xml 2.各层之间的联系2.1 Controller 与 Service2.2 Service 与 ServiceImpl2.3 Service 与 Mapper2.4 Mapper 与 Mapper.xml2.5 Service 与 Entity2.6 C…

Java语言程序设计——篇三(1)

选择结构 概述选择单分支if语句例题讲解 双分支if-else语句例题讲解 条件运算符多分支的if-else语句例题讲解 嵌套的if语句例题讲解 switch语句结构例题讲解代码演示运行结果 概述 Java中的控制结构&#xff0c;包括&#xff1a; 1、选择结构( if、if-else、switch ) 2、循环结…

最佳 iPhone 解锁软件工具,可免费下载用于电脑操作的

业内专业人士表示&#xff0c;如果您拥有 iPhone&#xff0c;您一定知道忘记锁屏密码会多么令人沮丧。由于 Apple 的安全功能强大&#xff0c;几乎不可能在没有密码或 Apple ID 的情况下访问锁定的 iPhone。 “当我忘记密码时&#xff0c;如何在没有密码的情况下解锁iPhone&am…

Docker 部署 ShardingSphere-Proxy 数据库中间件

文章目录 Github官网文档ShardingSphere-Proxymysql-connector-java 驱动下载conf 配置global.yamldatabase-sharding.yamldockerdocker-compose.yml Apache ShardingSphere 是一款分布式的数据库生态系统&#xff0c; 可以将任意数据库转换为分布式数据库&#xff0c;并通过数…

Python 轻松生成多种条形码、二维码 (Code 128、EAN-13、QR code等)

条形码和二维码是现代信息交换和数据存储的重要工具&#xff0c;它们将信息以图形的形式编码&#xff0c;便于机器识别和数据处理&#xff0c;被广泛应用于物流、零售、医疗、教育等各领域。 本文将介绍如何使用Python快速生成各种常见的条形码如Code 128、EAN-13&#xff0c;…

20240711 每日AI必读资讯

&#x1f3a8;Runway Gen-3 Alpha 详细使用教程以及提示词指南大全 - 7月9日&#xff0c;著名生成式AI平台Runway在官网公布了&#xff0c;最新发布的文生视频模型Gen-3 Alpha的文本提示教程。 - 从技术层面来说&#xff0c;输入的文本提示会被转换成“向量”&#xff0c;这些…

滑动变阻器在实际应用中需要注意哪些安全事项?

滑动变阻器在实际应用中&#xff0c;为了确保其正常运作及保护电路安全&#xff0c;需要注意以下安全事项&#xff1a; 一、了解并遵守规格参数 最大电阻值和允许通过的最大电流值&#xff1a;使用前&#xff0c;必须清楚滑动变阻器的最大电阻值和允许通过的最大电流值&#x…

基于SAM的零样本相似性评价方法

文章目录 介绍方法SAM编码器相似性指标代码复现介绍 图像转换具有广泛的应用,如风格转换和模态转换,通常是生成具有高度真实和忠实的图像。这些问题仍然很困难,特别是在保存语义结构很重要的时候。传统的图像级相似性度量的用途有限,因为图像的语义是高级的,并且不受对原…

什么样的开放式耳机好用舒服?南卡、倍思、Oladance高人气质量绝佳产品力荐!

​开放式耳机在如今社会中已经迅速成为大家购买耳机的新趋势&#xff0c;深受喜欢听歌和热爱运动的人群欢迎。当大家谈到佩戴的稳固性时&#xff0c;开放式耳机都会收到一致好评。对于热爱运动的人士而言&#xff0c;高品质的开放式耳机无疑是理想之选。特别是在近年来的一些骑…

jitsi 使用JWT验证用户身份

前言 Jitsi Meet是一个很棒的会议系统,但是默认他运行所有人创建会议,这样在某种程度上,我们会觉得他不安全,下面我们就来介绍下使用JWT来验证用户身份 方案 卸载旧的lua依赖性sudo apt-get purge lua5.1 liblua5.1-0 liblua5.1-dev luarocks添加ubuntu的依赖源,有则不需…

内容协商源码解析与自定义 MessageConverter

目录 内容协商 1、引入xml依赖 2、postman分别测试返回json和xml 3、开启浏览器参数方式内容协商功能 4、内容协商原理 5、自定义 MessageConverter 综上 内容协商 根据客户端接收能力不同&#xff0c;返回不同媒体类型的数据。 若客户端无法解析服务端返回的内容&#…