JavaWeb第十九天

AJAX

概念

Asynchronous JavaScript And XML 异步JavaScript和XML
异步和同步
    在客户端和服务器相互通信的基础上
    同步
        客户端发送请求给服务器和服务器返回响应给客户端之间,也就是服务器处理请求做出响应的这段时间里,客户端只能等待服务器的响应,不能做其他事
    异步
        客户端发送请求给服务器之后,不需要等待服务器的响应,在服务器处理请求的时间段内,客户端可以做其他事
AJAX是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
    如 点击百度搜索结果页的输入框 会弹出关键词的关联条目 但网页其它部分的内容不变 这里只发送了一个对于关联条目的请求而不是对于整个网页的请求
    通过在后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新;传统网页如果需要更新内容,必须重新加载整个页面
可以提升用户体验

实现方式

原生JS实现方式
1、创建核心对象 W3School AJAX XHR创建对象
    var xmlhttp;
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
W3School AJAX XHR请求
2、建立连接 参数:请求参数GET/POST 请求的URL 异步或同步请求true异步
    GET 请求参数在URL后面拼接 send方法空参 POST 请求参数在send方法中定义 xmlhttp.send("username=tom");
    异步则点击按钮后可以同时在输入框中输入,同步则点击按钮后无法操作输入框,需要等待服务器响应后才能操作输入框
    xmlhttp.open("GET","ajaxServlet?username=tom",true);
3、发送请求
    xmlhttp.send();
4、接收并处理服务器的响应结果 获取响应结果 XHR响应
    需要在服务器响应成功之后再获取响应结果 XHR readyState
    当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange
    xmlhttp.onreadystatechange=function()
    {
        //判断xmlhttp对象的就绪状态是否为4(请求已完成,服务器已响应) 以及 响应状态码是否为200
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            //获取服务器的响应结果
            var responseText = xmlhttp.responseText;
            alert(responseText);
        }
    }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>原生js实现</title>
    <script>
        function fun() {
            //发送异步请求
            //1、创建核心对象 W3School AJAX XHR创建对象
            var xmlhttp;
            if (window.XMLHttpRequest)
            {// code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp=new XMLHttpRequest();
            }
            else
            {// code for IE6, IE5
                xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
            }
            //W3School AJAX XHR请求
            //2、建立连接 参数:请求参数GET/POST 请求的URL 异步或同步请求true异步
            //GET 请求参数在URL后面拼接 send方法空参 POST 请求参数在send方法中定义 xmlhttp.send("username=tom");
            //异步则点击按钮后可以同时在输入框中输入,同步则点击按钮后无法操作输入框,需要等待服务器响应后才能操作输入框
            xmlhttp.open("GET","ajaxServlet?username=tom",true);
            //3、发送请求
            xmlhttp.send();
            //4、接收并处理服务器的响应结果 获取响应结果 XHR响应
            //需要在服务器响应成功之后再获取响应结果 XHR readyState
            //当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange
            xmlhttp.onreadystatechange=function()
            {
                //判断xmlhttp对象的就绪状态是否为4(请求已完成,服务器已响应) 以及 响应状态码是否为200
                if (xmlhttp.readyState==4 && xmlhttp.status==200)
                {
                    //获取服务器的响应结果
                    var responseText = xmlhttp.responseText;
                    alert(responseText);
                }
            }
        }
    </script>
</head>
<body>
    <input type="button" value="发送异步请求" onclick="fun();">
    <input type="text">
</body>
</html>
JQuery实现方式
$.ajax() 通用方式
    语法
        $.ajax({键值对});
    常用的键
        url 请求路径
        type 请求方式
        data 请求参数
        success 响应成功后的回调函数
        error 响应失败后的回调函数
        dataType 接收的响应数据的格式,一般为JSON
$.get() 发送get请求
    语法
        $.get(url, [data], [callback], [type])
        参数
            url 请求路径
            data 请求参数
            callback 回调函数
            type 接收的响应数据的格式
$.post() 发送post请求
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JQuery实现方式</title>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <script>
        //$.ajax()方式
        function fun() {
            //发送异步请求
            $.ajax({
                url: "ajaxServlet1", //请求路径
                type: "POST", //请求方式
                //data: "username=jack&age=23", //请求参数 第一种方式
                data: {"username": "jack", "age": 23}, //请求参数 第二种方式
                success: function (data) {
                    //data用来接收服务器响应的数据
                    alert(data);
                }, //响应成功后的回调函数
                error: function () {
                    alert("出错啦...");
                }, //响应失败后的回调函数 如路径找不到
                dataType: "text"//接收的响应数据的格式 不指定会根据HTTP包 MIME信息判断
            });
        }
        //$.get()方式 会将请求参数拼接到请求路径后面
        function fun1() {
            $.get("ajaxServlet", {"username": "rose", "age": 23}, function (data) {
                alert(data);
            }, "text");
        }
        //$.post()方式 会将请求参数绑定在请求消息体中
        function fun2() {
            $.get("ajaxServlet", {"username": "lucy", "age": 23}, function (data) {
                alert(data);
            }, "text");
        }
    </script>
</head>
<body>
    <input type="button" value="发送异步请求" onclick="fun2();">
    <input type="text">
</body>
</html>

JSON

概念

JavaScript Object Notation JavaScript对象表示法 用于封装数据
var p = {"name": "张三", "age": 23, "gender": "男", "address": {"province": "福建", "city": "福鼎"}};
多用于存储和交换文本信息的语法,进行数据的传输,比xml更小、更快、更易于解析

语法

基本规则
数据在键值对中
    键可以用引号,也可以不用引号
    值可以是数字(整数或浮点数)/字符串(双引号中)/逻辑值(true/false)/数组[]/对象{}/null
数据由逗号分隔
花括号保存对象 {}
方括号保存数组 [] var persons = {
                    "persons": [
                        {"name": "张三", "age": 23, "gender": "男"},
                        {"name": "李四", "age": 24, "gender": "女"},
                        {"name": "王五", "age": 25, "gender": "女"}
                    ]
                }
[]和{}可以互相嵌套
获取数据
json对象.键名
json对象["键名"]
数组对象[索引]
遍历获取基本格式json对象的键值对
    for(var key in person) {
        alert(key + ":" + person[key]);
    }
遍历获取json对象数组的中json对象的键值对
    for (var i = 0; i < persons2.length; i++) {
        var person = persons2[i];
        for (var key in person) {
            alert(key + ":" + person[key]);
        }
    }
json数据和Java对象的转换
客户端和服务器通信使用json作为数据载体
使用json解析器 如Jsonlib Gson fastjson jackson(SpringMVC内置解析器)
json -> java
    1、导入jackson的jar包
    创建domain/Person类以及对应的对象
    创建test/JacksonTest类进行单元测试
    2、创建jackson核心对象ObjectMapper
    3、调用ObjectMapper的方法进行转换
        readValue(json字符串数据, class类型);
java -> json
    步骤
        1、导入jackson的jar包
        创建domain/Person类以及对应的对象
        创建test/JacksonTest类进行单元测试
        2、创建jackson核心对象ObjectMapper
        3、调用ObjectMapper的方法进行转换
            writeValue(参数1, obj);
                参数1
                    File 将obj对象转换为json字符串,并保存到指定的文件中
                    Writer 将obj对象转换为json字符串,并将json数据填充到指定的字符输出流中
                    OutputStream 将obj对象转换为json字符串,并将json数据填充到指定的字节输出流中
            writeValueAsString(obj);将对象转为json字符串
    注解
        @JsonIgnore 被忽略的属性不会被转为json字符串
        @JsonFormat 属性值格式化
    复杂的Java对象的转换
        List对象转为数组
        Map对象转为Json对象
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>json数据语法</title>
    <script>
        //基本格式
        var person = {"name": "张三", "age": 23, "gender" :true};
        //alert(person.name);
        //alert(person["name"]);
        //{}嵌套[]
        var persons1 = {
            "persons": [
                {"name": "张三", "age": 23, "gender": "男"},
                {"name": "李四", "age": 24, "gender": "女"},
                {"name": "王五", "age": 25, "gender": "女"}
            ]
        };
        //alert(persons1.persons[2].name);
        //[]嵌套{}
        var persons2 = [
            {"name": "张三", "age": 23, "gender": "男"},
            {"name": "李四", "age": 24, "gender": "女"},
            {"name": "王五", "age": 25, "gender": "女"}
        ];
        //alert(persons2[1].name);

        //获取person对象中所有的键和值
        // for (var key in person) {
        //     alert(key + person[key]);//key默认是字符串,不需要再加引号
        // }
        //获取persons2对象中所有的键和值
        for (var i = 0; i < persons2.length; i++) {
            var person = persons2[i];
            for (var key in person) {
                alert(key + ":" + person[key]);
            }
        }
    </script>
</head>
<body>

</body>
</html>
Jackson测试类
package test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import domain.Person;
import org.junit.Test;

import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

public class JacksonTest {
    //Java对象转为json字符串
    @Test
    public void test1() throws IOException {
        //创建Person对象
        Person p = new Person();
        p.setName("张三");
        p.setAge(23);
        p.setGender("男");
        //创建jackson核心对象ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(p);
        System.out.println(json);//{"name":"张三","age":23,"gender":"男"}
        //将转换得到的json数据写入文件
        //mapper.writeValue(new File("1.txt"), p);
        //将转换得到的json数据填充到一个字符输出流中
        mapper.writeValue(new FileWriter("b.txt"), p);
    }

    //注解
    @Test
    public void test2() throws JsonProcessingException {
        //创建Person对象
        Person p = new Person();
        p.setName("张三");
        p.setAge(23);
        p.setGender("男");
        p.setBirthday(new Date());
        //创建jackson核心对象ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(p);
        System.out.println(json);//{"name":"张三","age":23,"gender":"男","birthday":1611236549046}
        //忽略属性birthday后 {"name":"张三","age":23,"gender":"男"}
        //格式化属性birthday后 {"name":"张三","age":23,"gender":"男","birthday":"2021-01-21"}
    }

    //复杂Java对象转换为json list集合
    @Test
    public void test3() throws JsonProcessingException {
        //创建Person对象
        Person p1 = new Person();
        p1.setName("张三");
        p1.setAge(23);
        p1.setGender("男");
        p1.setBirthday(new Date());
        Person p2 = new Person();
        p2.setName("李四");
        p2.setAge(24);
        p2.setGender("女");
        p2.setBirthday(new Date());
        Person p3 = new Person();
        p3.setName("王五");
        p3.setAge(25);
        p3.setGender("女");
        p3.setBirthday(new Date());
        List<Person> persons = new ArrayList<Person>();
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        //创建jackson核心对象ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(persons);
        System.out.println(json);//[{"name":"张三","age":23,"gender":"男","birthday":"2021-01-21"},{"name":"李四","age":24,"gender":"女","birthday":"2021-01-21"},{"name":"王五","age":25,"gender":"女","birthday":"2021-01-21"}]
    }

    //复杂Java对象转换为json map集合
    @Test
    public void test4() throws JsonProcessingException {
        //创建Map对象
        Map<String, Object> persons = new HashMap<String, Object>();
        persons.put("name", "张三");
        persons.put("age", 23);
        persons.put("gender", "男");
        persons.put("birthday", new Date());
        //创建jackson核心对象ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(persons);
        System.out.println(json);//{"birthday":1611237342973,"gender":"男","name":"张三","age":23}
    }

    //json字符串转Java对象
    @Test
    public void test5() throws IOException {
        String json = "{\"name\":\"张三\",\"age\":23,\"gender\":\"男\"}";
        //创建jackson核心对象ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        Person person = mapper.readValue(json, Person.class);
        System.out.println(person);//Person{name='张三', age=23, gender='男'}
    }
}

案例

校验注册的用户名是否已经存在
分析
    当文本输入框失去焦点,发送ajax请求去数据库查询该用户名是否存在
    存在则提示信息:此用户名太受欢迎,请更换一个
    不存在则提示信息:此用户名可用
步骤
    创建注册页面
        创建注册表单
        当文本输入框失去焦点
            获取用户名输入框的值
            发送请求查询数据库中是否存在该用户名
                请求url:findUserServlet
        创建findUserServlet
            获取请求参数username
            创建存储响应数据的Map对象map
            调用service层的方法查询数据库中是否存在一样的用户名
                存在
                    map.put("userExist", true);
                    map.put("msg", "此用户名太受欢迎,请更换一个");
                不存在
                    map.put("userExist", false);
                    map.put("msg", "此用户名可用");
            将map转换为json字符串,并填充到response.getWriter()中
                mapper.writeValue(response.getWriter(), map);
注意
    ajax发送请求时需要指定接收的数据类型为json,否则数据会被当作text处理
        将$.get()最后一个参数指定为json
        或
        设置MIME类型的响应头response.setContentType("application/json;charset=utf-8");
            tomcat/conf/web.xml注明了json对应的格式为application/json
druid.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day17
username=root
password=root
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <script>
        $(function () {
            //给username输入框绑定一个blur离焦事件
            $("#username").blur(function () {
                //获取文本输入框的值
                var username = $(this).val();
                //发送ajax请求
                //期望服务器返回的数据格式为{"userExist": true, "msg": "此用户名太受欢迎,请更换一个"}
                //                     {"userExist": false, "msg": "此用户名可用"}
                $.get("findUserServlet", {username: username}, function (data) {
                    var s_username = $("#s_username");
                    //判断userExist的值是否为true
                    if (data.userExist) {
                        s_username.css("color", "red");
                        s_username.html(data.msg);
                    } else {
                        s_username.css("color", "green");
                        s_username.html(data.msg);
                    }
                }, "json");
            });
        });
    </script>
</head>
<body>
    <form>
        <input type="text" name="username" id="username" placeholder="请输入用户名">
        <span id="s_username"></span>
        <br>
        <input type="password" name="password" id="password" placeholder="请输入密码"><br>
        <input type="submit" value="注册">
    </form>
</body>
</html>
domain
domain/Administrator
package domain;

public class Administrator {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Administrator{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

domain/Person
package domain;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.util.Date;

public class Person {
    private String name;
    private int age;
    private String gender;
    //@JsonIgnore //忽略该属性
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date birthday;

    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 getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

util
util/JDBCUtils
package util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * JDBC工具类 使用Durid连接池
 */
public class JDBCUtils {

    private static DataSource ds ;

    static {

        try {
            //1.加载配置文件
            Properties pro = new Properties();
            //使用ClassLoader加载配置文件,获取字节输入流
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            pro.load(is);

            //2.初始化连接池对象
            ds = DruidDataSourceFactory.createDataSource(pro);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接池对象
     */
    public static DataSource getDataSource(){
        return ds;
    }


    /**
     * 获取连接Connection对象
     */
    public static Connection getConnection() throws SQLException {
        return  ds.getConnection();
    }
}

servlet
servlet/AjaxServlet
package servlet;

import java.io.IOException;

@javax.servlet.annotation.WebServlet("/ajaxServlet")
public class AjaxServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        //获取请求参数
        String username = request.getParameter("username");
//        try {
//            Thread.sleep(3000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        System.out.println(username);
        //响应
        response.getWriter().write("hello," + username);
    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        this.doPost(request, response);
    }
}

servlet/findUserServlet
package servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import domain.Administrator;
import service.UserService;
import service.impl.UserServiceImpl;

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.HashMap;
import java.util.Map;

@WebServlet("/findUserServlet")
public class findUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //response.setContentType("text/html;charset=utf-8");
        response.setContentType("application/json;charset=utf-8");
        //获取用户名
        String username = request.getParameter("username");
        //期望服务器返回的数据格式为{"userExist": true, "msg": "此用户名太受欢迎,请更换一个"}
        //                      {"userExist": false, "msg": "此用户名可用"}
        //创建Map对象存储响应的数据
        Map<String, Object> map = new HashMap<String, Object>();
        //调用service层判断用户名是否存在 这里简化
//        if ("tom".equals(username)) {
//            //存在
//            map.put("userExist", true);
//            map.put("msg", "此用户名太受欢迎,请更换一个");
//        } else {
//            map.put("userExist", false);
//            map.put("msg", "此用户名可用");
//        }
        //调用service层判断用户名是否存在
        UserService service = new UserServiceImpl();
        Administrator administrator = service.findUserByUserName(username);
        System.out.println(administrator);
        //判断根据用户名获取的管理员是否为空
        if (administrator == null) {
            System.out.println("为空");
            map.put("userExist", false);
            map.put("msg", "此用户名可用");
        } else {
            System.out.println("不为空");
            map.put("userExist", true);
            map.put("msg", "此用户名太受欢迎,请更换一个");
        }
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(response.getWriter(), map);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

service
service/UserService
package service;

import domain.Administrator;

public interface UserService {
    Administrator findUserByUserName(String username);
}

service/impl/UserServiceImpl
package service.impl;

import dao.UserDao;
import dao.impl.UserDaoImpl;
import domain.Administrator;
import service.UserService;

public class UserServiceImpl implements UserService {
    private UserDao dao = new UserDaoImpl();
    @Override
    public Administrator findUserByUserName(String username) {
        return dao.findUserByUserName(username);
    }
}

dao
dao/UserDao
package dao;

import domain.Administrator;

public interface UserDao {
    Administrator findUserByUserName(String username);
}

dao/impl/UserDaoImpl
package dao.impl;

import dao.UserDao;
import domain.Administrator;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import util.JDBCUtils;

public class UserDaoImpl implements UserDao {
    //1、创建JDBCTemplate对象
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    @Override
    public Administrator findUserByUserName(String username) {
        //使用JDBC操作数据库
        //定义sql
        String sql = "select * from administrator where username = ?";
        //执行sql
        Administrator administrator;
        try {
            administrator = template.queryForObject(sql, new BeanPropertyRowMapper<Administrator>(Administrator.class), username);
        } catch (Exception e) {
            administrator = null;
        }
        return administrator;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值