ajax异步访问及跨域处理
文章目录
- 1 认识同步和异步
- 1.1 什么是同步交互
- 1.2 什么是异步交互
- 2 AJAX介绍
- 3 案例开发之验证用户名
- 4 JSON格式
- 4.1 响应普通文本数据
- 4.2 JSON的介绍和应用
- 4.3 JSON 与 JS 对象的关系
- 4.4 JSON 和 JS 对象互转
- 4.5 GSON工具类的使用
- 5 AJAX结合jQuery实现
- 5.1 jQuery.ajax()的简单使用
- 5.1.1 基本语法
- 5.1.2 JSON格式处理
- 5.2 jQuery.ajax()属性介绍
- 5.3 jQuery实现ajax的其他写法
- 5.3.1 $.load()
- 5.3.2 $.get()
- 5.3.3 $.getJSON()
- 5.3.4 $.post()
- 5.3.5 测试代码
- 5.4 jsonp跨域处理
- 5.4.1 什么是跨域?
- 5.4.2 实现的原理是什么?
- 5.4.3 通过getJson方实现跨域请求
- 展:通过后台代码也可以实现跨域,一般在过滤器中添加如下代码,那么前端在请求时就不用考虑跨域问题了
1 认识同步和异步
1.1 什么是同步交互
首先用户向HTTP服务器提交一个处理请求。接着服务器端接收到请求后,按照预先编写好的程序中的业务逻辑进行处理,比如和数据库服务器进行数据信息交换。最后,服务器对请求进行响应,将结果返回给客户端,返回一个HTML在浏览器中显示,通常会有CSS样式丰富页面的显示效果。
优点
可以保留浏览器后退按钮的正常功能。在动态更新页面的情况下,用户可以回到前一个页面状态,浏览器能记下历史记录中的静态页面,用户通常都希望单击后退按钮时,就能够取消他们的前一次操作,同步交互可以实现这个需求.
缺点
1同步交互的不足之处,会给用户一种不连贯的体验,当服务器处理请求时,用户只能等待状态,页面中的显示内容只能是空白。
2因为已经跳转到新的页面,原本在页面上的信息无法保存,好多信息需要重新填写
1.2 什么是异步交互
指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。在部分情况下,我们的项目开发中都会优先选择不需要等待的异步交互方式。将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。这就是异步。异步不用等所有操作等做完,就响应用户请求。即先响应用户请求,然后慢慢去写数据库,用户体验较好
优点
1前端用户操作和后台服务器运算可以同时进行,可以充分利用用户操作的间隔时间完成运算
2页面没有跳转,响应回来的数据直接就在原页面上,页面原有信息得以保留
缺点
可能破坏浏览器后退按钮的正常行为。在动态更新页面的情况下,用户无法回到前一个页面状态,这是因为浏览器仅能记录的始终是当前一个的静态页面。用户通常都希望单击后退按钮,就能够取消他们的前一次操作,但是在AJAX这样异步的程序,却无法这样做。
2 AJAX介绍
AJAX 即
“Asynchronous Javascript And XML”(异步 JavaScript和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
AJAX关键技术
使用CSS构建用户界面样式,负责页面排版和美工
使用DOM进行动态显示和交互,对页面进行局部修改
使用XMLHttpRequest异步获取数据
使用JavaScript将所有的元素绑定在一起
AJAX的最大的特点: 异步访问,局部刷新
3 案例开发之验证用户名
AJAX之验证用户名是否被占用
JS表单验证只能校验格式是否正确,但是无法验证用户名是否已经存在,这个就需要后台程序接受到数据后通过查询才能够完成的,那么这里就非常适用于使用异步方式校验,保证用于数据提交后,业务完成的成功率.提升用于体验感
页面代码
$Title%sSourceCode%lt;/title> var xhr ; function checkUname(){ // 获取输入框中的内容 var unameDOM=document.getElementById("unameI"); var unameText =unameDOM.value; var unameInfoDom =document.getElementById("unameInfo"); if(null == unameText || unameText == ''){ unameInfoDom.innerText="用户名不能为空"; return; } unameInfoDom.innerText=""; // 发送异步请求 // 获取一个 XMLHttpRequest对象 ,对象可以帮助我们发送异步请求 xhr =new XMLHttpRequest(); // 使用xhr对象设置打开链接,设置请求方式和参数xhr.open("请求方式","请求的URL",是否使用异步方式); xhr.open("GET","unameCheckServlet.do?uname="+unameText,true); // 设置回调函数 xhr.onreadystatechange=showReturnInfo; // 正式发送请求 xhr.send(null); } function showReturnInfo(){ if(xhr.readyState==4 && xhr.status==200){ var returnInfo =xhr.responseText; var unameInfoDom =document.getElementById("unameInfo"); unameInfoDom.innerText=returnInfo; } } 用户名:
密码:servlet代码
异步后台
package com.msr.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("/unameCheckServlet.do") public class UnameCheckServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String uname = req.getParameter("uname"); String info=""; if("msb".equals(uname)){ info="用户名已经占用"; }else{ info="用户名可用"; } // 向浏览器响应数据 resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().print(info); } }
同步后台
说明:这里只是做对比,在后台增加了阻塞时间,直观感受同步异步区别
@WebServlet("/myServlet1.do") public class MyServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } // 接收参数 String uname = req.getParameter("uname"); String pwd = req.getParameter("pwd"); // 作出响应 resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().print("登录成功"); } }
AJAX异步提交请求的步骤为
1 获取XMLHTTPRequest对象xhr=new XMLHttpRequest();
2打开链接xhr.open(“GET”,“loginServlet?uname=”+uname,true);
3设置回调函数xhr.onreadystatechange=showRnturnInfo;
4提交数据 xhr.send(data)
目前存在的问题
原生js提交AJAX异步请求代码比较繁琐,处理复杂数据比较麻烦,后续可以使用jQuery解决
4 JSON格式
4.1 响应普通文本数据
如果服务器给我们响应的数据非常简答,那么使用字符串就好了,不需要我们做复杂的处理,后台编码也简单.
页面代码
AJAX数据响应格式 var xhr; function getData(){ xhr =new XMLHttpRequest(); xhr.open("GET","testDataServlet",true) xhr.onreadystatechange=showData xhr.send(null) } function showData(){ if(xhr.readyState==4&&xhr.status==200) { var text =xhr.responseText; console.info(text) } } 触发
后台代码
@WebServlet("/testDataServlet") public class TestDataServlet extends HttpServlet { @Override public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.getWriter().print("普通文本数据"); } }
总结:
如果响应的数据是一个对象或者对象集合,数据处理起来会非常麻烦,可以使用JSON格式处理
4.2 JSON的介绍和应用
JSON(JavaScriptObject Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。它有如下优点
1轻量级,在这里用它不是为了厉害的功能代码,而是为了实现数据转换
2 Json 格式既能考虑到前端对象的特点 同时也能兼顾后台对象信息的特点
3 Json 格式可以被前端直接识别并解析成对象
4 jQuery形式实现AJAX默认前后端传递数据的格式就是JSON
Title /* * JSON格式创建对象 * {"属性名":"属性值","属性名":属性值 ... ... } * */ var person ={"name":"zhangsan","age":10} alert(person.name) alert(person.age) var persons =[{"name":"zhangsan","age":10},{"name":"lisi","age":10},{"name":"wangwu","age":10}]; for (var i = 0; i var person =persons[i]; console.log(person.name) console.log(person.age) } var personStr='{"name":"zhangsan","age":10}';// 是一个字符串 // 可以直接把上面这种格式的字符串直接转换成对象 var p =JSON.parse(personStr); console.log(p.name) console.log(p.age) a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的 var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
h34.4 JSON 和 JS 对象互转/h3 p要实现从JSON字符串转换为JS对象,使用 JSON.parse() 方法:/p blockquote pvar obj = JSON.parse(‘{“a”: “Hello”, “b”: “World”}’); //结果是 {a: ‘Hello’, b: ‘World’}/p /blockquote p要实现从JS对象转换为JSON字符串,使用 JSON.stringify() 方法:/p blockquote pvar json = JSON.stringify({a: ‘Hello’, b: ‘World’}); //结果是 ‘{“a”: “Hello”, “b”: “World”}’/p /blockquote p问题:/ppJSON格式字符串,拼接比较麻烦,可以修改toString方法但是就破坏了toString原有的格式,而且一旦字段如果太多修改工作量大,后面可以使用JSON工具类转换/p h34.5 GSON工具类的使用/h3 pgson工具类中已经给我们封装好了json格式和java对象之间转换的API,我们直接使用即可,再也不用手动去转换项目中/p p添加gson-2.2.4.jar(暂不上传)/ppimg src="https://img-blog.csdnimg.cn/direct/d67628bff50a47ba8209324803bb8a06.png" //pp页面代码/p pre class="brush:python;toolbar:false"%@ page contentType="text/html;charset=UTF-8" language="java" % html head title$Title%sSourceCode%lt;/title> var xhr ; function testData(){ xhr =new XMLHttpRequest(); xhr.open("GET","testServlet.do",true); xhr.onreadystatechange=showReturnInfo; xhr.send(null); } function showReturnInfo(){ if(xhr.readyState==4 && xhr.status==200){ var info =xhr.responseText; var users=JSON.parse(info) for (var i = 0; i var user =users[i]; console.log(user.uname) console.log(user.age) console.log(user.gender) console.log(user.birthday) } } } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { User user1 =new User("晓明1",10,"男",new Date()); User user2 =new User("晓明2",10,"男",new Date()); User user3 =new User("晓明3",10,"男",new Date()); User user4 =new User("晓明4",10,"男",new Date()); User user5 =new User("晓明5",10,"男",new Date()); ArrayList // 获取输入框中的内容 if(null == $("#unameI").val() || '' == $("#unameI").val()){ $("#unameInfo").text("用户名不能为空"); return; } $("#unameInfo").text(""); // 通过jQuery.ajax() 发送异步请求 $.ajax( { type:"GET",// 请求的方式 GET POST url:"unameCheckServlet.do?", // 请求的后台服务的路径 data:"uname="+$("#unameI").val(),// 提交的参数 success:function(info){ // 响应成功执行的函数 $("#unameInfo").text(info) } } ) } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String uname = req.getParameter("uname"); String info=""; if("msr".equals(uname)){ info="用户名已经占用"; }else{ info="用户名可用"; } // 向浏览器响应数据 resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().print(info); } } // 向后台发送一个ajax异步请求 // 接收响应的数据 $.ajax( { type:"GET", url:"servlet1.do", data:{"username":"zhangsan","password":"123456"},// key=value&key=value {"属性名":"属性值"} dataType:"json",//以什么格式接收后端响应给我们的信息 success:function(list){ $.each(list,function(i,e){ console.log(e) }) } } ) } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); Student stu1=new Student("小黑","男",10,new Date()); Student stu2=new Student("小白","男",10,new Date()); Student stu3=new Student("小黄","男",10,new Date()); Student stu4=new Student("小花","男",10,new Date()); ArrayList $.ajax({ url:"servlet1", /*post get 部分浏览器可使用put delete*/ type:"get", /*请求超时的时间设置*/ timeout:2000, /*是否发送异步请求,默认值为true,如需同步请求,改为false*/ async:true, /*是否从浏览器的缓存中加载信息,默认为true,false则不读取浏览器缓存*/ cache:true, /*向服务器发送的数据,可以是key/value格式,也可以是对象格式 * get方式下,会将信息附加在url后,如果数据不是字符串,会转换成字符串格式 * */ data:{username:"bjmsb",password:"bjmsb"}, /* * 默认值为true 默认情况下,发送的数据将被转换为对象以配合 * content-type:application/x-www-form-urlencoded * 如果发送信息不希望被转换,设置为false即可 * */ proccessData:true, /*发送到服务器的数据为String类型时,默认值为 * application/x-www-form-urlencoded * 该值适合大多数应用场景 * */ contentType:"application/x-www-form-urlencoded", /* * 预期服务器返回值类型, * 如果不指定 jQuery根据http响应mime信息返回xml或者text * 并作为返回值传递,可选类型如下 * xml 返回xml数据(基本淘汰) * html:返回纯文本HTML信息 * script:返回JS脚本, * json:返回json数据 * jsonp:jsonp格式 * text:返回纯文本,也是默认格式 * */ dataType:"json", /* * 指定跨域回调函数名 * */ //jsonp:"fun1", /*只有当请求参数为dataType为jsonp或者script,并且是get方式请求时 * 才能强制修改字符集,通常在跨域编码不同时使用 * */ // scriptCharset:"utf-8", beforeSend:function(XMLHttpRequest){ /* * 请求发送前可以通过该方法修改XMLHttpRequest对象函数 * 如听见请求头 * 如果该方法返回false,则会取消ajax请求 * */ }, success:function(data,textStatus){ /* *一般请求成功后会调用的函数,有两个可选参数 * data,数据 根据dataType的配置处理之后的数据 可能是xml text json 等 * testStatus ,描述响应状态的字符串 * */ }, error:function(XMLHttpRequest,textStatus,errorThrown){ /* * 请求失败时调用的函数,可选参数有 * XMLHttpRequest对象 * 错误信息 * 捕获的异常对象 * */ }, complete:function(XMLHttpRequest,textStatus){ /* * 无论请求是否成功都睡调用的回调函数 * 可选参数有 * XMLHttpRequest对象 * textStatus 描述成功请求的类型的字符串 * */ }, dataFilter:function(data,type){ /* * 数据过滤方法 * 给Ajax返回的原始数据进行预处理的函数。 * 提供data和type两个参数。 * data是Ajax返回的原始数据, * type是调用jQuery.ajax时提供的dataType参数。 * 函数返回的值将由jQuery进一步处理 * */ } }) } //$("#d1").load("servlet2.do","username=aaa&password=bbb",function(){alert("响应结束")}) $("#d1").load("loadPage.html #a") } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); resp.setContentType("text/html;charset=UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.getWriter().print("