Javascript关于Ajax使用的具体步骤及案例
简介
- Ajax是XMLHttpRequest对象和Javascript、XML、CSS、DOM等多种技术的组合
- Ajax应用使得通过javascript实现在不刷新页面的情况下,对数据进行进行更新,有利于降低网络流量,改善用户体验
- JQuery封装的ajax是基于原生javascript的ajax语法的,所以掌握原生的ajax请求还是很重要的
- 学习ajax碰到不少问题,也投入了很多时间,为了避免走弯路,于是在经过很多测试验证之后进行了相关语法总结
- 以下案例展示了用原生javascript通过Ajax发送请求、jquery中封装的ajax发送请求,后台读取图片返回到HTML页面显示的案例
内容摘要
-
Ajax常通过XMLHttpRequest创建实例
-
创建与服务器的请求
2.1 指定GET请求方式
2.2 指定POST请求方式 -
指定XMLHttpRequest返回结果的处理函数
3.1 通过onreadystatechange属性指定状态改变时所触发的处理函数
3.2 通过onload属性指定事件处理函数 -
指定XMLHttpRequest发生错误的处理函数
-
跨域请求的设置
-
发送请求
-
Ajax请求核心源码
7.1 原生Javascript请求
7.2 Jquery中ajax请求方式 -
完整源码
8.1 前端源码
8.2 后端源码 -
实现效果
Ajax使用具体步骤
1. Ajax常通过XMLHttpRequest创建实例
var req = new XMLHttpRequest();
考虑不同版本的浏览器兼容性,可将其封装在一个函数中
function createAjaxObject() {
var req = null;
//非IE浏览器
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
//IE浏览器
} else if (window.ActiveXObject) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!req) {
alert("无法创建XMLHttpRequest对象");
}
return req;
}
2.创建与服务器的请求
请求方式分两种:一种是POST,另一种是GET
2.1指定GET请求方式
- GET方式传递的参数,要放在url之后
- 若包含中文,一定要使用encodeURI(url)对请求参数进行转义,否则会报如下错误:
GET http://localhost:8080/JqueryTest/ReadImgServlet?msg=ajax%E5%8F%91%E9%80%81%E7%9A%84%E5%8F%82%E6%95%B0&filePath=C:\Users\Lenovo\Pictures\be90611b453f3e476533412964e49dee.jpg 400 - 指定url参数,最好指定一个时间戳追加到url参数之后,避免浏览器缓存而得不到最新结果
var filePath = var filePath = "C:\\Users\\Lenovo\\Pictures\\be90611b453f3e476533412964e49dee.jpg";
//指定时间戳
filePath +="&nocache="+new Date().getTime();
var url = "http://localhost:8080/JqueryTest/ReadImgServlet?msg=ajax发送的参数&filePath="+filePath;
url = encodeURI(url);
//第三个参数 true表示异步,false同步
req.open("GET", url, true);
2.2 指定POST请求方式
- 使用post方式,通常会把请求参数放在send方法中,但也可以把请求参数放在url后面
- 发送post请求,需要使用setRequestHeader设置请求头,且要放在send语句之前
- 若后端编码是utf-8,则请求头里面还必须加上编码,否则后端获取的参数会出现乱码
var url = "http://localhost:8080/JqueryTest/ReadImgServlet";
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
//req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
3. 指定XMLHttpRequest返回结果的处理函数
3.1 通过onreadystatechange属性指定状态改变时所触发的处理函数
-
若处理函数外部独立的一个函数,比如:function callBack(){},只需
req.onreadystatechange = callBack; -
若需要给外部处理函数传递参数,比如:function callBack(param){},只需
req.onreadystatechange = function(){ callBack(req.responseText); }; -
有关属性状态码
属性readyState用于获取请求的状态码:
0:请求未初始化
1:正在加载
2:已加载
3:交互中
4:请求完成属性status用于返回服务器的http状态码:
200:表示成功
202:表示请求被接受,但尚未成功
400:错误的请求
404:文件未找到
500:内部服务器错误属性response:返回服务器的响应,后端返回的string,这里获得的也是字符串
属性responseText:返回为字符串
属性responseXML:返回为xml对象,该对象可解析为dom对象
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var img = document.getElementById("readimg");
img.src = req.responseText;
}
};
3.2 通过onload属性指定事件处理函数
onload属性具有与onreadystatechange相近的功能:
1.onload属性与onreadystatechange属性保留一个就可以,两个同时都存在则两个都会被调用
2.onload指定的事件处理函数,当状态码返回4时就会被调用
3.onreadystatechange具体全面,onload则简洁方便
req.onload = function() {
alert("info:" + req.response);
};
4. 指定XMLHttpRequest发生错误的处理函数
通过onerror属性指定,该处理函数是可选,一般最好指定否则发生错误很难排查
req.onerror = function() { alert("请求错误!"); };
5. 跨域请求的设置
若两个页面拥有的协议(protocol)、端口(port)或主机(host),任何一个的不同,就被当作是跨域
实现跨域请求要注意以下两点:
- 设置withCredentials值为true,且必须放在send方法之前
req.withCredentials = true;
//默认为false,设置跨域请求是否提供凭据信息(cookie、HTTP认证及客户端SSL证明等)
//可理解为当前请求为跨域类型时是否在请求中协带cookie
withCredentials不设置为true的影响:
- 当试图把首次传递的参数保存:request.getSession().setAttribute(“msg”, msg);
- 然后第二次请求request.getSession().getAttribute(“msg”),获取msg的值为null,这表明在跨域访问时,服务器不会保留session中的值
- 在后端设置跨域请求,通常可直接创建一个过滤器允许跨域访问,并将其添加到web.xml中
配置文件:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>UploadDownloadFile</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>com.filter.MyCorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
过滤器:com.filter.MyCorsFilter
package com.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet Filter implementation class MyCorsFilter
*/
public class MyCorsFilter implements Filter {
/**
* Default constructor.
*/
public MyCorsFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
/* 允许跨域的主机地址 */
HttpServletResponse response = (HttpServletResponse)servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
// response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
response.setHeader("Access-Control-Allow-Headers","*");
response.setHeader("Access-Control-Allow-Method","*");
// 允许所有的域名跨域访问
// response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
// pass the request along the filter chain
chain.doFilter(servletRequest, servletResponse);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
6. 发送请求
当发送post请求:
//open方法是POST方式
req.send("msg=ajax发送的参数&filePath=" + filePath);
-
要记得在发送之前先设置设置setRequestHeader,如果不设置会出现后端获取不到参数的情况
String msg = request.getParameter(“msg”); //此时msg为null
需要注意的是,不设置setRequestHeader此时改为在url后添加请求参数在后端却能够获取
2. 参数一般在send方法中添加,该方式传递参数无需使用encodeURI方法转义
发送Get请求:
//open方法是GET方式
req.send(null);
- 使用req.send(null)或req.send()
,不要在send中传递参数,这样获后端取不到参数 - get方式要直接在url上添加传递的参数
7. Ajax请求核心源码
7.1 原生Javascript请求
- Get请求方式
// Get请求方式
function readimg() {
var filePath = "C:\\Users\\Lenovo\\Pictures\\be90611b453f3e476533412964e49dee.jpg";
filePath +="&nocache="+new Date().getTime();
var url = "http://localhost:8080/JqueryTest/ReadImgServlet?msg=ajax发送的参数&filePath="+filePath;
// 参数需要转义
url = encodeURI(url);
// 创建XMLHttpRequest
var req = new XMLHttpRequest();
// 创建与服务器的连接
req.open("GET", url, true);
// 返回结果的处理函数
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var img = document.getElementById("readimg");
img.src = req.responseText;
}
};
// 发生错误的处理函数
req.onerror = function(){alert("请求错误");};
// 设置跨域请求提供凭据信息
req.withCredentials = true;
req.send();
}
- POST请求方式
// post请求方式
function readImgPost(){
// 图片文件的路径
var filePath = "C:\\Users\\Lenovo\\Pictures\\be90611b453f3e476533412964e49dee.jpg";
var url = "http://localhost:8080/JqueryTest/ReadImgServlet";
// 创建XMLHttpRequest
var req = new XMLHttpRequest();
// 发送POST请求
req.open("POST", url, true);
// 设置请求头
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
// 返回结果的处理函数
req.onload = function() {
var img = document.getElementById("readimg");
img.src = req.response;
};
// 发生错误的处理函数
req.onerror = function(){alert("请求错误");};
req.withCredentials = true;
var param = "msg=ajax发送的参数&filePath="+filePath;
req.send(param);
}
7.2 Jquery中ajax请求方式
function jqueryAjax(){
var filePath = "C:\\Users\\Lenovo\\Pictures\\be90611b453f3e476533412964e49dee.jpg";
var param = "msg=ajax发送的参数&filePath="+filePath;
var urls = "http://localhost:8080/JqueryTest/ReadImgServlet";
// 若是get请求,含有中文字符,必须对参数转义,否则报错
param = encodeURI(param);
$.ajax({
url: urls,
// type:"post",
type: "get",
data:param,
// dataType: "json",
dataType:"text",
xhrFields: {
withCredentials: true
},
error:function(e){alert("请求错误");},
crossDomain: true,
success: function(data) {
var img = document.getElementById("readimg");
//直接返回字符串
img.src = data;
}
});
}
8. 完整实现
8.1 前端源码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
<script>
// Get请求方式
function readimg() {
var filePath = "C:\\Users\\Lenovo\\Pictures\\be90611b453f3e476533412964e49dee.jpg";
filePath +="&nocache="+new Date().getTime();
var url = "http://localhost:8080/JqueryTest/ReadImgServlet?msg=ajax发送的参数&filePath="+filePath;
// 参数需要转义
url = encodeURI(url);
// 创建XMLHttpRequest
var req = new XMLHttpRequest();
// 创建与服务器的连接
req.open("GET", url, true);
// 返回结果的处理函数
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var img = document.getElementById("readimg");
img.src = req.responseText;
}
};
// 发生错误的处理函数
req.onerror = function(){alert("请求错误");};
// 设置跨域请求提供凭据信息
req.withCredentials = true;
req.send();
}
// post请求方式
function readImgPost(){
// 图片文件的路径
var filePath = "C:\\Users\\Lenovo\\Pictures\\be90611b453f3e476533412964e49dee.jpg";
var url = "http://localhost:8080/JqueryTest/ReadImgServlet";
// 创建XMLHttpRequest
var req = new XMLHttpRequest();
// 发送POST请求
req.open("POST", url, true);
// 设置请求头
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
// 返回结果的处理函数
req.onload = function() {
var img = document.getElementById("readimg");
img.src = req.response;
};
// 发生错误的处理函数
req.onerror = function(){alert("请求错误");};
req.withCredentials = true;
var param = "msg=ajax发送的参数&filePath="+filePath;
req.send(param);
}
//Jquery请求方式
function jqueryAjax(){
var filePath = "C:\\Users\\Lenovo\\Pictures\\be90611b453f3e476533412964e49dee.jpg";
var param = "msg=ajax发送的参数&filePath="+filePath;
var urls = "http://localhost:8080/JqueryTest/ReadImgServlet";
// get请求必须对参数转义
param = encodeURI(param);
$.ajax({
url: urls,
type: "get",
data:param,
// dataType: "json",
dataType:"text",
xhrFields: {
withCredentials: true
},
error:function(e){alert("请求错误");},
crossDomain: true,
success: function(data) {
var img = document.getElementById("readimg");
img.src = data;
}
});
}
window.onload = function(){
// 页面加载后调用函数显示图片
// GET方式请求
// readimg();
// POST方式请求
readImgPost();
}
</script>
</head>
<body>
<img src="" id="readimg" alt="待加载">
</body>
</html>
8.2 后端源码(过滤器配置参考上面)
package servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
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 javax.servlet.http.HttpSession;
import sun.misc.BASE64Encoder;
/**
* Servlet implementation class ReadImgServlet
*/
@WebServlet("/ReadImgServlet")
public class ReadImgServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ReadImgServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// 待读取的图片的完整路径
// String filePath = "C:\\Users\\Lenovo\\Pictures\\06dd54ddf31d6e3eda1427bee4575ae8.jpg";
String filePath = request.getParameter("filePath");
System.out.println("request参数中的图片路径:"+filePath);
String info = ImageToBase64(filePath);
// System.out.println("图片信息:"+info);
String msg = null;
// request先设置编码,否则之后乱码
request.setCharacterEncoding("utf-8");
HttpSession session = request.getSession();
// 获取session中msg
msg = (String) session.getAttribute("msg");
System.out.println("session保存的msg:"+msg);
// 获取request中msg
msg = request.getParameter("msg");
// 将msg保存到session
request.getSession().setAttribute("msg", msg);
System.out.println("request传递的msg:"+msg);
// response.getWriter()需要放在最后面,否则会出现如下错误
// java.lang.IllegalStateException: Cannot create a session after the response has been committed
response.getWriter().print(info);
}
public static String ImageToBase64(String imageFile) {
int pos = imageFile.lastIndexOf(".")+1;
String fileType = imageFile.substring(pos);
InputStream in = null;
byte[] data = null;
// 读取图片字节数组
try {
in = new FileInputStream(imageFile);
// in.available()计算字节大小
data = new byte[in.available()];
// InputStream把数据读取到字节数组中
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
if (data != null) {
// 返回Base64编码过的字节数组字符串
String res = "data:image/"+fileType+";Base64,"+encoder.encode(data);
return "data:image/jpeg;base64," + encoder.encode(data);
}
return null;
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
9. 实现效果
本文地址:https://blog.csdn.net/qq_43521551/article/details/107161479
下一篇: 完整的访问统计程序(三 应用篇)