学习日志day43(2021-09-07)(1、Ajax 2、Ajax解析xml文档)

学习内容:学习JavaWeb(Day43)

1、Ajax
2、Ajax解析xml文档


1、Ajax

(1)AJAX的全称是“AsynchronousJavaScript and XML(异步JavaScript与XML)”,AJAX 是一种从网页访问 Web 服务器的技术。
在这里插入图片描述

(2)Ajax与传统请求的差异

不同点常规操作Ajax操作
是否刷新刷新页面不刷新页面
用户操作中断,等待新页面下载后继续不中断
性能服务器返回整个新页面(包 括HTML代码、CSS代码、 相关图片等)服务器仅返回需要的数据
编码复杂度较简单较复杂

(3)Ajax引擎
能够被JavaScript调用。JavaScript需要指定请求地址、请求方式 与参数,同时JavaScript还需要能够从“引擎”中得到服务器返回的数据。
能够异步请求服务器并接受返回的数据。JavaScript本身并不能访 问网络,这部分功能必须委托“引擎”实现。
“引擎”也要能够调用JavaScript。这样才是实现当服务器数据返回时通知JavaScript进行处理。
“引擎”不会处理用户的请求,也不会处理业务逻辑,只是将请求转发给服务器,由服务器端的程序进行处理。
当服务器端数据返回后,“引擎”不会代替JavaScript完成页面显示工作,只是将通知JavaScript,由JavaScript进行后续的处理。

(4)构建Ajax引擎

<script>
//构建AJAX引擎
var xmlHttp = null;
function createXmlHttpRequest() {
    if (window.ActiveXObject) {// code for IE6, IE5
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    } else {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlHttp = new XMLHttpRequest();
    }
}
</script>

(5)发出请求
xmlHttp.open(请求方式,请求地址,[是否为异步请求]);
xmlHttp.send()
是否为异步请求可以省略不写。

<body>
请输入用户名:<input type="text" name="" id="userName" value="">

<script type="text/javascript">
document.querySelector("#userName").onchange = function () {
    let userName = this.value;
    //Get请求
    xmlHttp.open("GET","ajaxrReq?userName="+userName,true); 
    xmlHttp.send();
    
    //Post请求 
    xmlHttp.open("POST", "/ajaxReq");
    //表单enctype的默认值application/x-www-form-urlencoded
    xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xmlHttp.send("userName=" + userName);

    //put和delete请求
    xmlHttp.open("PUT","/ajaxReq?userName="+userName);
    xmlHttp.send();
    xmlHttp.open("DELETE","/ajaxReq?userName="+userName);
    xmlHttp.send();
}
</script>
</body>

AjaxRequestServlet.java

@WebServlet("/ajaxReq")
public class AjaxRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userName = request.getParameter("userName");
        userName = new String(userName.getBytes("ISO-8859-1"),"UTF-8");
        System.out.println("GET:" + userName);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userName = request.getParameter("userName");
        response.setContentType("text/plain;charset=utf-8");
        System.out.println("POST:" + userName);
   }

    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userName = request.getParameter("userName");
        System.out.println("PUT:" + userName);
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userName = request.getParameter("userName");
        System.out.println("DELETE:" + userName);
    }
}

(6)在发出请求之前设置回调函数

<script type="text/javascript">
document.querySelector("#userName").onchange = function () {
    let userName = this.value;
    //Get请求
    xmlHttp.open("GET","ajaxrReq?userName="+userName,true);
    //设置回调函数,onreadystatechange是监听服务器状态码的改变
    //readyState是xmlHttp的属性,表示当前服务器状态码
    //获取服务器状态码: var code = xmlHttp.readyState;
    //获取HTTP状态码:var serverCode = xmlHttp.status;
    xmlHttp.onreadystatechange = callback;//先弹出2,再弹出200,再弹出4,再弹出200
    xmlHttp.send();
    
    function callback(){ 
        alert(xmlHttp.readyState); 
        alert(xmlHttp.status); 
    }
}
</script>

不同浏览器对状态码的实现不同
服务器状态码:
0: 请求未初始化 (还未调用open方法)
1: 服务器连接已建立(已调用open正发送请求)
2: 请求已接收(send方法完成已收到响应)
3: 请求处理中(正在解析响应内容)
4: 请求已完成,且响应已就绪(解析完成)

HTTP状态码:
200 服务器正常处理了请求并响应
404 请求的页面未找到
403 没有权限访问请求的页面
405 页面不接收该请求方式(比如用GET请求一个只支持doPost方法的Servlet)
408 请求超时
500 服务器处理请求时遇到错误(可能因为应用程序抛出异常导致)
503 服务暂时不可用(可能出现在服务器尚未初始化完成时)
304 网页未修改

(7)获取服务器端的文本值

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String userName = request.getParameter("userName");
    //text/html:是将文件的content-type设置为text/html的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。
    //text/plain:是将文件设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理。
    response.setContentType("text/plain;charset=utf-8");
    PrintWriter out = response.getWriter();
    System.out.println("POST:" + userName);
    out.print("添加成功!");
    out.close();
}
function callback() {
    if (xmlHttp.readyState == 4) {//服务器状态码为4
        if (xmlHttp.status == 200) {//HTTP状态码为200
            var result = xmlHttp.responseText;//获取服务器端的文本值
            alert(result);//添加成功!
        }else{
            alert("服务器升级中!");
        }
    }
}

(8)防止出现乱码
1.GET请求:
先对客户端进行转码

xmlHttp.open("GET","/ajaxReq?userName="+encodeURIComponent(userName));
xmlHttp.send();

再对每个参数分别进行转码

String userName = request.getParameter("userName");
userName = new String(userName.getBytes("ISO-8859-1"),"UTF-8");

2.POST请求
客户端不用转码

xmlHttp.open("POST", "/ajaxReq");
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.send("userName=张三丰");

在servlet中统一进行转码

request.setCharacterEncoding("UTF-8");
String userName = requset.getParameter("userName");

(9)避免GET缓存
在低版本浏览器中,GET请求会进行缓存,如果多次请求同一个url地址,那么浏览器会认为已经发送过这个请求,使用上次请求获取到的结果。
解决方法:
1.在客户端使用无意义参数避免缓存

xmlHttp.open("GET","/ajaxReq?userName="+encodeURIComponent(userName)+"&time="+new Date().getTime());
xmlHttp.send();

2.在服务端添加响应头,告诉浏览器不要缓存响应的结果

response.addHeader("pragma","no-cache");
response.addHeader("cache-control","no-cache");
response.addHeader("expires","0");

2、Ajax解析xml文档

(1)跨语言间传输数据需要使用xml文档,语法规则如下
• 所有 XML 元素都须有关闭标签
• XML 标签对大小写敏感
• XML 必须正确地嵌套
• XML 文档必须有根元素
• XML 的属性值须加引号
• 元素名称不能以数字和"_"(下划线)开头、不能以XML开头、不能包含空格与冒号
• HTML中的转义符在XML中也可以使用,如果文本中需要转义的字符太多,还可以使用 “<![CDATA[ 需要转义的文本 ]]>”进行转义

(2)服务器返回xml

response.setContentType("text/xml;charset=utf-8"); 
PrintWriter out = response.getWriter(); 
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); 
out.println("<book id=\"88\">"); 
out.println("<id>88</id>"); 
out.println("<bookName>老人与海</bookName>"); 
out.println("<author>海明威</author>"); 
out.println("<publisher>北京出版</publisher>"); 
out.println("</book>"); 
out.flush(); 
out.close();

(3)Ajax接收返回的XML文档

<script>
  function callback() {
        if (xmlHttp.readyState == 4) {
            if (xmlHttp.status == 200) {
                var result = xmlHttp.responseXML;
                let bookList = result.getElementsByTagName("book");//bookList是数组
                let bookName = book.getElementsByTagName("bookname")[0];//bookName是<bookName>老人与海</bookName>
                console.log(bookName.childNodes[0]);//“老人与海”
                console.log(bookName.childNodes[0].nodeValue);//老人与海
                console.log(book.getAttribute("id"));//88
            }
        }
    }
</script>

(4)JavaScript解析XML API

名称类型作用
getElementsByTagName(name)方法返回当前元素中有指定标记名的子元素数组
childNodes属性返回当前元素所有子元素的数组
nodeValue字符串获取节点值:如果节点为元素,返回null或 undefined;如果节点为文本,返回文本值
getAttribute(name)方法返回元素的属性值,属性有name指定

(5)将xml输出在jsp页面上

<input type="button" value="ajax请求" id="btn"/>
<script type="text/javascript">
    var xmlHttp = null;

    //构建AJAX引擎
    function createXmlHttpRequest() {
        if (window.ActiveXObject) {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } else {
            xmlHttp = new XMLHttpRequest();
    }
}
    createXmlHttpRequest();
    document.querySelector("#btn").onclick = function () {
        xmlHttp.open("GET", "/ajaxReq");
        xmlHttp.onreadystatechange = callback;
        xmlHttp.send();//发送请求
    }
    /*
    * ajax请求回调函数
    * */
    function callback() {
    if (xmlHttp.readyState == 4) {
       if (xmlHttp.status == 200) {
           var xmlObj = xmlHttp.responseXML;//接收服务端返回的xml文档

           let bookList = xmlObj.getElementsByTagName("book");
           document.querySelector("#tab").innerHTML = "";//每次点击将之前的清空
           for (var i = 0;i < bookList.length;i++) {//循环获取书籍信息
           //这里的循环不能使用for(var index in bookList){},增强循环会多出一个length项
               let book = bookList[i];

               let bookName = book.getElementsByTagName("bookname")[0].childNodes[0].nodeValue;
               let author = book.getElementsByTagName("author")[0].childNodes[0].nodeValue;
               let publisher = book.getElementsByTagName("publisher")[0].childNodes[0].nodeValue;
               let id = book.getElementsByTagName("id")[0].childNodes[0].nodeValue;
               let obj = {
                   id: id,
                   bookName: bookName,
                   author: author,
                   publisher: publisher
               }
               createHtml(obj);
           }
       } else {
           alert("服务器升级中!");
       }
   }

   /*
   * 创建标签
   * */
   function createHtml(data) {
       let tr = document.createElement("tr");
       let idTd = document.createElement("td");
       let nameTd = document.createElement("td");
       let authorTd = document.createElement("td");
       let publTd = document.createElement("td");

       let textId = document.createTextNode(data.id);
       let textName = document.createTextNode(data.bookName);
       let textAuthor = document.createTextNode(data.author);
       let textPub = document.createTextNode(data.publisher);

       idTd.appendChild(textId);
       nameTd.appendChild(textName);
       authorTd.appendChild(textAuthor);
       publTd.appendChild(textPub);

       tr.appendChild(idTd);
       tr.appendChild(nameTd);
       tr.appendChild(authorTd);
       tr.appendChild(publTd);

       let tbody = document.querySelector("#tab");
       tbody.appendChild(tr);
   }
}
</script>

(6)JAXB用于将XML转换为java对象,并将java对象转换为XML。需要的jar包:
jaxb-api.jar
jaxb-core.jar
jaxb-impl.jar
jaxb-jxc.jar
jaxb-xjc.jar

servlet中使用JAXB:

BookService bookService = new BookService();
List<Book> bookList = bookService.findAll();
XmlBookList xmlBookList = new XmlBookList();
xmlBookList.setBookList(bookList);
response.setContentType("text/xml;charset=utf-8");
JAXBContext ctx = JAXBContext.newInstance(XmlBookList.class);//将XmlBookList对象解析成xml文档
Marshaller marshaller = ctx.createMarshaller(); //创建Marshaller对象
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);//格式化输出
marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");//输出中文编码
marshaller.marshal(xmlBookList, response.getOutputStream());//调用marshal方法把对象放入输出流

实体类中加上注解:

//给实体类添加注解,使Book成为根节点
@XmlRootElement 
public class Book { 

    //使id成为属性
    @XmlAttribute 
    public void setId(int id) { 
        this.id = id; 
    }
} 

    //使Name成为bookname节点
    @XmlElement(name="bookname") 
    public void setName(String name) { 
        this.name = name; 
    }
    
    //忽略属性
    @XmlTransient 
    public void setAddress(Address address) { 
        this.address = address; 
    }

数据传输类dto中:因为查询到的数据是一个集合,所以要把集合加上注解,此时解析集合,Book实体类中的注解失效

@XmlRootElement(name = "bookList")
public class XmlBookList {

    private List<Book> bookList;

    public List<Book> getBookList() {
        return bookList;
    }

    @XmlElement(name="book")
    public void setBookList(List<Book> bookList) {
        this.bookList = bookList;
    }
}

service中:

public Book findById(int id) {
   return bookDao.findById(id);
}

dao中:

public Book findById(int id) {
    String sql = "select id,bookname,author,publisher from book where id = ?";
    return dbHelp.executeQueryForObject(sql,new BeanRowMapper<Book>(Book.class),id);
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值