学习内容:学习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>
var xmlHttp = null;
function createXmlHttpRequest() {
if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else {
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;
xmlHttp.open("GET","ajaxrReq?userName="+userName,true);
xmlHttp.send();
xmlHttp.open("POST", "/ajaxReq");
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.send("userName=" + userName);
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;
xmlHttp.open("GET","ajaxrReq?userName="+userName,true);
xmlHttp.onreadystatechange = callback;
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");
response.setContentType("text/plain;charset=utf-8");
PrintWriter out = response.getWriter();
System.out.println("POST:" + userName);
out.print("添加成功!");
out.close();
}
script
function callback() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 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");
let bookName = book.getElementsByTagName("bookname")[0];
console.log(bookName.childNodes[0]);
console.log(bookName.childNodes[0].nodeValue);
console.log(book.getAttribute("id"));
}
}
}
</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;
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();
}
function callback() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var xmlObj = xmlHttp.responseXML;
let bookList = xmlObj.getElementsByTagName("book");
document.querySelector("#tab").innerHTML = "";
for (var i = 0;i < bookList.length;i++) {
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文档 需要的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);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");
marshaller.marshal(xmlBookList, response.getOutputStream());
实体类中加上注解:
@XmlRootElement
public class Book {
@XmlAttribute
public void setId(int id) {
this.id = id;
}
}
@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);
}
|