学习Java的日子 Day66 Ajax

1.Ajax

1.1 简介

Ajax:(Asynchronous JavaScript And XML)指异步 JavaScript 及 XML

他不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的 Web 应用程序的技术,是基于JavaScript、XML、HTML、CSS新用法(前端技术)

Ajax指的是刷新(渲染)局部页面的技术

使用Ajax+JSON,前后端分离,大大提高了工作效率和用户体验

我们学习了AJAX 后,就可以使用AJAX和服务器进行通信,以达到使用 HTML+AJAX来替换JSP页面了。如下图,浏览器发送请求servlet,servlet 调用完业务逻辑层后将数据直接响应返回给浏览器页面,页面使用 HTML 来进行数据展示。

在这里插入图片描述

1.2 应用场景

  • 搜索
  • 地图
  • 校验
  • 获取数据

1.3 交互模型

在这里插入图片描述

传统的Web交互方式

发送请求,客户端会等待,发送好了,才会加载

同步发送请求:浏览器页面在发送请求给服务器,在服务器处理请求的过程中,浏览器页面不能做其他的操作(变成一个白板,一直刷新)。只能等到服务器响应结束后,浏览器页面才能继续做其他的操作

在这里插入图片描述

在这里插入图片描述

Ajax的交互方式

发送请求,浏览器一样可以使用

异步发送请求:浏览器页面发送请求给服务器,在服务器处理请求的过程中,浏览器页面还可以做其他的操作。

在这里插入图片描述

在这里插入图片描述

异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索词联想、用户名是否可用的校验,等等…

在这里插入图片描述

eg:在百度页面上,我们输入一些关键字后就会在下面联想出相关的内容,而联想出来的这部分数据肯定是存储在百度的服务器上,而我们并没有看出页面重新刷新,这就是 更新局部页面的效果。再如下图:

在这里插入图片描述

我们在用户名的输入框输入用户名,当输入框一旦失去焦点,如果用户名已经被占用就会在下方展示提示的信息;在这整个过程中也没有页面的刷新,只是在局部展示出了提示信息,这就是 更新局部页面的效果。

2.Ajax使用详解

2.1 XMLHttpRequest对象

该对象用于在前台与服务器交换数据。意味着可以在不重新加载整个网页的情况下,对网页的进行局部更新

所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)

前端发送XMLHttpRequest对象请求

//获取XMLHttpRequest对象
function getXMLHttpRequest() {
	var xmlHttp;
	if (window.XMLHttpRequest) {// 一般的浏览器
		xmlHttp = new XMLHttpRequest();
	}else if (window. ActiveXObject) {// IE6及以下浏览器
		xmlHttp = new ActiveXObject( "Microsoft.XMLHTTP");
	}
	return xmlHttp;
}

2.2 与服务器交换数据 open/send

如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send()

post请求需要设置请求头

函数描述示例
open(method,url,async);初始化请求参数(请求方式,请求地址,是否异步)xmlhttp.open(“GET”,“url”,true);
send();发送请求xmlhttp.send();
//发送异步的Post请求
function sendAjaxPost() {
	var xmlHttp = getXMLHttpRequest();
	//初始化请求参数
	xmlHttp.open("POST","MyServlet",true);
	//post需要设置请求头
    xmlHttp.setRequestHeader(
        "Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
	//发送请求,携带数据
	xmlHttp.send("username=abc&password=123");
} 

//发送异步的Get请求
function sendAjaxGet() {
	var xmlHttp = getXMLHttpRequest();
	//初始化请求参数
	xmlHttp.open("GET","MyServlet?username=abc&password=123",true);
	//发送请求,携带数据
	xmlHttp.send();
} 

2.3 onreadystatechange事件

请求被发送到服务器时,我们需要执行一些基于响应的任务

5种情况会触发:0 - 4 (面试题)4是最重要的,页面中的转圈圈是3

不是所有的浏览器都支持 0-4,但是所有的浏览器都支持4这个状态

函数描述
onreadystatechange每当 readyState 属性改变时,就会调用该函数。
属性描述
readyState存有 XMLHttpRequest 的状态。
从 0 到 4 发生变化:
0 - 请求未初始化服务器
1 - 连接已建立
2 - 请求已接收
3 - 请求处理中
4 - 请求已完成,且响应已就绪
status存有响应的状态。
200 - OK
404 - 未找到页面
//发送异步的Post请求
function sendAjaxPost() {
	
	var xmlHttp = getXMLHttpRequest();
	
	//每当readyState改变时,就会触发 onreadystatechange事件
	xmlHttp.onreadystatechange = function() {
		console.log(xmlHttp.readyState);//打印XMLHttpRequest的状态
		console.log(xmlHttp.status + "xx");//打印响应的状态
	}
	xmlHttp.open("POST","MyServlet",true);
    xmlHttp.setRequestHeader(
        "Content-Type","application/x-www-form-urlencoded;charset-UTF-8");
	xmlHttp.send("username=abc&password=123");
} 

完整代码如下:

<script>
    //1. 创建核心对象
    var xhttp;
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    
     //2. 获取响应
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            alert(this.responseText);
        }
    };
    
    //3. 发送请求
    xhttp.open("GET", "http://localhost:8080/ajax-demo/ajaxServlet");
    xhttp.send();


</script>
</body>
</html>

注意:后端响应数据(向前端传数据):response.getWriter().write(“hello ajax~”);

3.实战案例

3.1 验证用户名

验证用户名的是否可以注册

注意:前后端每一次交互都要测试

register.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    ${msg}

    <h1>注册页面</h1>

    <form action="student?action=doRegister" method="post" enctype="multipart/form-data">

        账号:<input type="text" name="username" id="username"/><span id="usernameInfo"></span><br/>
        密码:<input type="password" name="password"/><br/>
        姓名:<input type="text" name="name"/><br/>
        年龄:<input type="text" name="age"/><br/>
        性别:
        <input type="radio" name="sex" value="man" checked="checked"/>男
        <input type="radio" name="sex" value="woman"/>女
        <br/>
        爱好:
        <input type="checkbox" name="hobbies" value="football"/>足球
        <input type="checkbox" name="hobbies" value="basketball"/>篮球
        <input type="checkbox" name="hobbies" value="shop"/>购物
        <br/>
        上传头像:<input type="file" name="photo"/><br/>

        <input type="submit" value="注册"/>
        <input type="button" value="返回" οnclick="goWelcome()"/>
    </form>

    <script type="text/javascript">
        function goWelcome(){
            window.location = "welcome.html";
        }

        
        //获取xmlHttp对象(先写这个)
    	function getXMLHttpRequest(){
        	let xmlHttp;
        	if(window.XMLHttpRequest){
           		 xmlHttp=new XMLHttpRequest();
       		 }else if (window.ActiveXObject){//兼容IE6及以下版本
           		 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
       		 }
       		 return xmlHttp;
   		 }

        let username=document.getElementById("username");//绑定事件
        let usernameInfo=document.getElementById("usernameInfo");//设置提示信息

        //绑定失去焦点的事件
        username.οnblur=function (){
            //获取当前对象的value属性值(输入的数据)
            let v=this.value;

            if (v.length!=0) {
                
                //获取Ajax发送请求对象
                let xmlHttp = getXMLHttpRequest();

                //绑定onreadystatechange事件
                xmlHttp.onreadystatechange = function (){
                    
                 	//console.log(xmlHttp.readystate);  1 2 3 4 
                    
                    //4表示服务器返回响应,200表示响应成功 
                    if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {

                        //获取响应数据 responseText(控制层传过来的数据)
                        let data = xmlHttp.responseText;

                        if (data == "1") {//状态码
                            usernameInfo.style.color = "green";
                            usernameInfo.innerText = "恭喜,账号可用";
                        } else if (data == "-1") {
                            usernameInfo.style.color = "red";
                            usernameInfo.innerText = "抱歉,账号已注册";
                        }
                    }
                }

                //设置参数(控制层方便使用)
                xmlHttp.open("POST", "student?action=isRegister");

                //设置请求头信息(POST请求必须要有)
                xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset-UTF-8");
                //发送请求(发给控制层中的isRegister这个功能中,request.getParamter获取)
                xmlHttp.send("username=" + v);

            }
        }

    </script>
</body>
</html>

控制层

StudentController

public void isRegister(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        //应该在service层中去操作
        String username = request.getParameter("username");
        boolean register = studentService.isRegister(username);
    
        String code;//状态码
    
        if(register){
            code="1";//未有此用户名
        }else {
            code="-1";//已有此用户名
        }
        //传给前端
        response.getWriter().write(code);
    }

运行结果:

在这里插入图片描述

3.2 省市级联效果

通过选择省从而关联出城市的数据

前端发送Ajax异步请求到服务器中获取对应的省市JSON数据,再在前端解析、适配到页面

  1. 添加数据库
  2. 导入数据库驱动包、Druid连接池
  3. 添加省、市实体类

数据库

在这里插入图片描述

register.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    ${msg}

    <h1>注册页面</h1>

    <form action="student?action=doRegister" method="post" enctype="multipart/form-data">

        账号:<input type="text" name="username" id="username"/><span id="usernameInfo"></span><br/>
        密码:<input type="password" name="password"/><br/>
        姓名:<input type="text" name="name"/><br/>
        年龄:<input type="text" name="age"/><br/>
        性别:
        <input type="radio" name="sex" value="man" checked="checked"/>男
        <input type="radio" name="sex" value="woman"/>女
        <br/>
        爱好:
        <input type="checkbox" name="hobbies" value="football"/>足球
        <input type="checkbox" name="hobbies" value="basketball"/>篮球
        <input type="checkbox" name="hobbies" value="shop"/>购物
        <br/>
        上传头像:<input type="file" name="photo"/><br/>

        籍贯:
        <select id="province" name="province">
            <option value="xxx">-- 请选择 --</option>
        </select>省
        <select id="city" name="province">
            <option value="xxx">-- 请选择 --</option>
        </select>市
        <br>

        <input type="submit" value="注册"/>
        <input type="button" value="返回" οnclick="goWelcome()"/>
    </form>

    <script type="text/javascript">
        function goWelcome(){
            window.location = "welcome.html";
        }

        //要写ajax异步请求,必须先写一个对象
  	 	 function getXMLHttpRequest(){
       		 let xmlHttp;
       	 	if(window.XMLHttpRequest){
           		 xmlHttp=new XMLHttpRequest();
       	 	}else if (window.ActiveXObject){//兼容IE6及以下版本
           		 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        		}
       		 return xmlHttp;
  		  }
        
        
        let province=document.getElementById("province");
        let city=document.getElementById("city");

        //获取省列表的函数
        function showProvince(){
            let xmlHttp=getXMLHttpRequest();

            //绑定onreadystatechange事件
            xmlHttp.onreadystatechange = function (){
                //4表示服务器返回响应,200表示响应成功
                if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {

                    //获取响应数据
                    let data = xmlHttp.responseText;

                    //解析json数据
                    let provinceArr=eval(data);

                    for (let i = 0; i <provinceArr.length; i++) {
                        let code=provinceArr[i].code;
                        let name=provinceArr[i].name;

                        let option=document.createElement("option");//创建子节点
                        option.value=code;
                        option.innerText=name

                        province.appendChild(option);//把子节点放入省里
                    }
                }
            }

            //设置参数
            xmlHttp.open("GET","province?action=getProvinces");

            //发送请求
            xmlHttp.send();
        }

        //一开始就调用获取省列表的函数
        showProvince();

        //给省份绑定改变事件
        province.οnchange=function(){
            let v=this.value;
            if (v=="xxx"){
                city.innerHTML="<option value='xxx'>-- 请选择 --</option>";

            }else {//发送ajax异步提交
                let xmlHttp=getXMLHttpRequest();

                //绑定onreadystatechange事件
                xmlHttp.onreadystatechange = function (){
                    //4表示服务器返回响应,200表示响应成功
                    if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {

                        //先清空城市列表
                        city.innerText="";

                        //获取响应数据
                        let data=xmlHttp.responseText;
                        //解析json数据
                        let cityArr=eval(data);

                        for (let i = 0; i <cityArr.length; i++) {
                            let code=cityArr[i].code;
                            let name=cityArr[i].name;

                            let option=document.createElement("option");
                            option.value=code;
                            option.innerText=name;

                            city.appendChild(option);
                        }
                    }
                }

                //设置参数
                xmlHttp.open("GET","province?action=getCities&code="+v);
                //发送请求
                xmlHttp.send();

            }
        }

    </script>
</body>
</html>

实体类:省份 Province

package com.qf.pojo;

public class Province {

    private String code;
    private String name;
	//省略
}

实体类:城市 City

public class City {

    private String code;
    private String name;
	//省略
}

ProvinceMapper

public interface ProvinceMapper {

    public List<Province> getProvince();

    public List<City> getCities(String parentCode);
}

ProvinceMapperImpl

数据的增删改查

public class ProvinceMapperImpl implements ProvinceMapper {
    @Override
    public List<Province> getProvince() {
        try {
            List<Province> provinces = DBUtils.commonQueryList(Province.class, "select * from provinces where parent_code=?", "01");
            return provinces;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<City> getCities(String parentCode) {
        try {
            List<City> cities = DBUtils.commonQueryList(City.class, "select * from provinces where parent_code=?", parentCode);

            return cities;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }
}

ProvinceService

public interface ProvinceService {

    //全部都是ajax传输,来回都使用JSON格式返回(String类型)
    public String getProvinces();

    //全部都是ajax传输,来回都使用JSON格式返回
    public String getCities(HttpServletRequest request);

}

ProvinceServiceImpl

业务逻辑

package com.qf.service.impl;

public class ProvinceServiceImpl implements ProvinceService {
    //建依赖(多态)
    private ProvinceMapper provinceMapper=new ProvinceMapperImpl();
    @Override
    public String getProvinces() {
        List<Province> province = provinceMapper.getProvince();
        String jsonStr = JSON.toJSONString(province);
        return jsonStr;
    }

    @Override
    public String getCities(HttpServletRequest request) {
        //获取省份的code
        String code = request.getParameter("code");
        List<City> cities = provinceMapper.getCities(code);
        String jsonStr = JSON.toJSONString(cities);
        return jsonStr;
    }
}

ProvinceController

页面跳转,给前端传数据

@WebServlet("/province")
public class ProvinceController extends BaseServlet {

   private ProvinceService provinceService=new ProvinceServiceImpl();
   public void getProvinces(HttpServletRequest request, HttpServletResponse response) throws IOException {
       String provinces = provinceService.getProvinces();
       //传回给客户端数据
       response.getWriter().write(provinces);
   }

    public void getCities(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String cities = provinceService.getCities(request);
        response.getWriter().write(cities);
    }
}

运行结果:

在这里插入图片描述

总结

1.使用Ajax+JSON,前后端分离,大大提高了工作效率和用户体验

2.Ajax
1.概念
2.Ajax与传统型的交互有何区别

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A 北枝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值