欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Javascript关于Ajax使用的具体步骤及案例

程序员文章站 2022-05-02 19:02:36
...

简介

  • Ajax是XMLHttpRequest对象和Javascript、XML、CSS、DOM等多种技术的组合
  • Ajax应用使得通过javascript实现在不刷新页面的情况下,对数据进行进行更新,有利于降低网络流量,改善用户体验
  • JQuery封装的ajax是基于原生javascript的ajax语法的,所以掌握原生的ajax请求还是很重要的
  • 学习ajax碰到不少问题,也投入了很多时间,为了避免走弯路,于是在经过很多测试验证之后进行了相关语法总结
  • 以下案例展示了用原生javascript通过Ajax发送请求、jquery中封装的ajax发送请求,后台读取图片返回到HTML页面显示的案例

内容摘要

  1. Ajax常通过XMLHttpRequest创建实例

  2. 创建与服务器的请求
    2.1 指定GET请求方式
    2.2 指定POST请求方式

  3. 指定XMLHttpRequest返回结果的处理函数
    3.1 通过onreadystatechange属性指定状态改变时所触发的处理函数
    3.2 通过onload属性指定事件处理函数

  4. 指定XMLHttpRequest发生错误的处理函数

  5. 跨域请求的设置

  6. 发送请求

  7. Ajax请求核心源码
    7.1 原生Javascript请求
    7.2 Jquery中ajax请求方式

  8. 完整源码
    8.1 前端源码
    8.2 后端源码

  9. 实现效果

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请求方式

  1. GET方式传递的参数,要放在url之后
  2. 若包含中文,一定要使用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
  3. 指定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请求方式

  1. 使用post方式,通常会把请求参数放在send方法中,但也可以把请求参数放在url后面
  2. 发送post请求,需要使用setRequestHeader设置请求头,且要放在send语句之前
  3. 若后端编码是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属性指定状态改变时所触发的处理函数

  1. 若处理函数外部独立的一个函数,比如:function callBack(){},只需
    req.onreadystatechange = callBack;

  2. 若需要给外部处理函数传递参数,比如:function callBack(param){},只需
    req.onreadystatechange = function(){ callBack(req.responseText); };

  3. 有关属性状态码
    属性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),任何一个的不同,就被当作是跨域

实现跨域请求要注意以下两点:

  1. 设置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中的值
  1. 在后端设置跨域请求,通常可直接创建一个过滤器允许跨域访问,并将其添加到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);
  1. 要记得在发送之前先设置设置setRequestHeader,如果不设置会出现后端获取不到参数的情况

    String msg = request.getParameter(“msg”); //此时msg为null

    需要注意的是,不设置setRequestHeader此时改为在url后添加请求参数在后端却能够获取

​ 2. 参数一般在send方法中添加,该方式传递参数无需使用encodeURI方法转义

发送Get请求:

//open方法是GET方式
req.send(null);
  1. 使用req.send(null)或req.send()
    ,不要在send中传递参数,这样获后端取不到参数
  2. 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. 实现效果

Javascript关于Ajax使用的具体步骤及案例

相关标签: JavaScript jquery