AJAX

417

JSON

概述:
• JSON(JavaScript Object Notation):JS 对象标记。
• 是一种轻量级的数据交换格式。
• 易于阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

JSON语法(客户端)

JSON对象与JSON字符串

      //  JSON对象
      var person = { name: "lz", age: 20, sex: "男" };
      console.log(person.name);
      console.log(person.age);
      console.log(person.sex);
      var arr = [1, 2, 3, 4];
      //   JSON字符串
      var str = '{ "name": "lz", "age": 20, "sex": "男" }';
      var str2 = "[1, 2, 3, 4]";

浏览器两者转换:

      //   字符串->JSON对象
      var p1 = JSON.parse(str);
      alert(p1.name);
      //    JSON对象->字符串
      var strjson = JSON.stringify(p1);
      alert(strjson);

JSON 值:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或false)
  • 数组(在中括号中)
  • 对象(在大括号中)
  • null

JSON解析(服务端)

为什么需要解析?

  • 浏览器和服务器之间交互采用JSON格式,但传输的是JSON字符串。
  • 需要转成Java对象或JS对象,这种转换过程称为JSON解析。

[wppay]

服务器端采用

  • FastJSON:阿里开发的专门用来处理JSON的工具包。
  • Jackson:Jackson公司开发的一套处理JSON的API。(框架阶段使用)

测试类:

public class Book {

  private String name;
  private int price;
  private Date date;

  public Book(String name, int price, Date date) {
    this.name = name;
    this.price = price;
    this.date = date;
  }
  //必须写
  getter()\setter()
}

服务端JSON转为对象:

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("application/json;charset=utf-8");
    //对象必须要写getter与setter方法
    Book book = new Book("图书", 20, new Date());
    //1.把java对象转成Json字符串
    String json = JSON.toJSONString(book);
    response.getWriter().write(json);
  }
  • response.setContentType("text/html;charset=utf-8");
  • response.setContentType("application/json;charset=utf-8");

我们这里使用了后者,明确的告诉浏览器我们传送的JSON字符串,而不是HTML。虽然也可以使用前者,在某些浏览器上没有问题,但是存在兼容性问题。

控制不序列化某些属性:

  • @JSONField(serializable=false)
public class Book {
  private String name;
  //不序列化
  @JSONField(serialize = false)
  private int price;
  private Date date;
  ......//接下类显示的都是去除价钱的
}

控制输出:

  • SerializerFeature.PrettyFormat //美化输出
  • SerializerFeature.WriteMapNullValue //输出null值
  • SerializerFeature.WriteNullStringAsEmpty //将null转成“”
  • SerializerFeature.DisableCircularReferenceDetect //禁用循环引用检测
String json = JSON.toJSONString(book, SerializerFeature.PrettyFormat);

说明:SerializerFeature.DisableCircularReferenceDetect //禁用循环引用检测

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("application/json;charset=utf-8");
    Book book = new Book("图书", 20, new Date());
    Book book2 = new Book("图书", 20, new Date());
    ArrayList<Object> list = new ArrayList<>();
    list.add(book);
    list.add(book2);
    String json = JSON.toJSONString(list, SerializerFeature.PrettyFormat);
    response.getWriter().write(json);
  }
  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("application/json;charset=utf-8");
    Book book = new Book("图书", 20, new Date());
    Book book2 = new Book("图书", 20, new Date());
    ArrayList<Object> list = new ArrayList<>();
    list.add(book);
    list.add(book2);
    list.add(book2);
    String json = JSON.toJSONString(list, SerializerFeature.PrettyFormat);
    response.getWriter().write(json);
  }

处理:全部进行显示

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("application/json;charset=utf-8");
    Book book = new Book("图书", 20, new Date());
    Book book2 = new Book("图书", 20, new Date());
    ArrayList<Object> list = new ArrayList<>();
    list.add(book);
    list.add(book2);
    list.add(book2);
    String json = JSON.toJSONString(list, SerializerFeature.PrettyFormat,SerializerFeature.DisableCircularReferenceDetect);
    response.getWriter().write(json);
  }

将JSON字符串转为java对象

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("application/json;charset=utf-8");
    Book book = new Book("图书", 20, new Date());
    Book book2 = new Book("图书", 20, new Date());
    ArrayList<Object> list = new ArrayList<>();
    list.add(book);
    list.add(book2);
    list.add(book2);
    String json = JSON.toJSONString(list, SerializerFeature.PrettyFormat,SerializerFeature.DisableCircularReferenceDetect);
    response.getWriter().write(json);

    //2.把接收到的JSON字符串转换为java对象
    List<Book> books = JSON.parseArray(json, Book.class);
    for (Book book1 : books) {
      System.out.println(book1.toString());
    }
  }

格式化日期

public class Book {
  private String name;
  //不序列化
  @JSONField(serialize = false)
  private int price;
  @JSONField(format = "yyyy-MM-dd")
  private Date date;
   ....
}

AJAX

概述:

  • AJAX = Asynchronous JavaScript and XML。
  • AJAX是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

AJAX使用步骤

1 创建XMLHttpRequest对象

  • var xhr=new XMLHttpRequest();

2 设置回调函数

  • xhr.onreadystatechange=function(){…}

3 打开连接

  • xhr.open(method,url,async);

4 发送请求

  • xhr.send(data);

GET请求

前端:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>ajax技术访问服务器</title>
</head>
<body>
<input type="button" value="发送get请求" onclick="click1()">

<script>
  function click1() {
    //1.创建XMLHttpRequest对象 (还有个兼容性写法PPT)
    var xhr = new XMLHttpRequest();
    //2.设置回调函数
    //五种状态 一共执行四次
    //0 初始状态,请求未建立连接
    console.log(xhr.readyState);
    //1 服务器连接已建立
    //2 请求已经被接收
    //3 请求处理中
    //4 请求已经完成
    xhr.onreadystatechange = function () {
      console.log("---"+xhr.readyState)
      if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
      }
    }
    //3.打开链接
    // method:请求方式
    // url:请求地址  url前写/还要加项目名
    // async:true 异步
    xhr.open("get", "LoginServlet?username=1&pwd=1", true);
    //4.发送请求
    xhr.send();
  }
</script>
</body>
</html>

兼容各种浏览器写法:

      if (window.XMLHttpRequest) {
        // IE7+, Firefox, Chrome, Opera, Safari 浏览器
        xhr = new XMLHttpRequest();
      } else {
        // IE6, IE5 浏览器执行代码
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
      }

后端:

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    String username = request.getParameter("username");
    String pwd = request.getParameter("pwd");
    if ("1".equals(username) && "1".equals(pwd)) {
      response.getWriter().write("成功");
    } else {
      response.getWriter().write("失败");
    }
  }

status:

  • 200:成功
  • 404:资源未找到
  • 500:服务器错误

POST请求

  • 方式一:添加响应请求头,服务端不用修改
  • 方式二:不添加,客户端发送JSON,服务端用流接

方式一:添加响应请求头,服务端不用修改

<input type="button" value="发送post请求" onclick="click2()">
<script>
  function click2() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText)
      }
    }
    xhr.open("post", "LoginServlet", true);
    xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
    xhr.send("username=1&pwd=1");
  }
</script>

方式二:不添加,客户端发送JSON,服务端用流接

若照着GET方式去写一个POST请求,如下:

  function click2() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText)
      }
    }
    xhr.open("post", "LoginServlet", true);
    xhr.send("username=1&pwd=1");
  }

点击按钮结果是失败。

先说下文件的表单类型,一共有三种:提交表单、文件表单、文本表单。

我们之前用Aajx进行请求相当于模拟了表单的请求,显然我们没有设置过表单类型。GET请求的参数是以URL参数的形式传递的,但POST的参数是用send()的方式发送的。默认表单类型是文本表单,前端发送的是文本表单,后端就要做出修改来接收文本表单的内容。如下

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    ServletInputStream is = request.getInputStream();
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String data = br.readLine();
    System.out.println(data);
    //if ("1".equals(username) && "1".equals(pwd)) {
    //  response.getWriter().write("成功");
    //} else {
    //  response.getWriter().write("失败");
    //}
  }

这里我们打印下数据格式为:username=1&pwd=1 普通的字符串。

我们可以自己处理这个字符串,但是太麻烦,不如客户端端直接传JSON字符串

客户端:

  function click2() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText)
      }
    }
    xhr.open("post", "LoginServlet", true);
    //JSON格式
    xhr.send('{"username":"1","pwd":"1"}');
  }

User类

public class User {
  private String username;
  private String pwd;
   .......getter、setter
}

服务端:

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    ServletInputStream is = request.getInputStream();
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String data = br.readLine();
    System.out.println(data);
    User user = JSON.parseObject(data, User.class);
    if ("1".equals(user.getUsername()) && "1".equals(user.getPwd())) {
      response.getWriter().write("成功");
    } else {
      response.getWriter().write("失败");
    }
  }

F12看一下请求的是什么表单:

浏览器的同源策略

同源策略:

  • AJAX请求地址的协议、域名、端口号必须和页面所在的地址相同。

上图为正确,两个请求的协议、域名、端口号都相同。

什么时候会出现跨域问题?

例如:你当前程序8080端口请求了另一个程序8081端口的程序,这时就会出现跨域问题。这个问题是浏览器的问题,要求不能跨域访问。

解决跨域问题?

  • JSONP(麻烦,不推荐)
  • 在服务器添加("Access-Control-Allow-Origin", "*")响应头
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //添加解决跨域访问的响应头
        response.setHeader("Access-Control-Allow-Origin", "*");
        String username = request.getParameter("username");
        String pwd = request.getParameter("pwd");
        if("admin".equals(username)&&"888".equals(pwd)){
            response.getWriter().write("登录成功");
        }else{
            response.getWriter().write("用户名或密码错误");
        }

[/wppay]