Ajax 9-7

Ajax

一 、Ajax

AJAX的全称是“AsynchronousJavaScript and XML(异步JavaScript与XML)”
• 学习Ajax要求掌握以下知识:
– JavaScript技术
– 使用JavaScript与DOM进行交互操作的技术
– 基于Web标准的页面布局
– XML技术
– JavaScript解析XML的技术
– 利用XMLHttpRequest对象发出异步请求的技术
– 服务器端编程技术(如JSP或Servlet

1 Ajax应用

在这里插入图片描述

2 Ajax原理

异步请求

3 Ajax与传统请求的差异

在这里插入图片描述

4 Ajax引擎:XMLHttpRequest

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

Ajax引擎兼容模式

Ajax引擎兼容模式方式1:

<script type="text/javascript">
    var xmlHttp = null;
    //构建AJAX引擎
    function createXmlHttpRequest() {
        if (window.ActiveXObject) {//判断是不是一个低端浏览器(IE6往下) true:是低端浏览器      false:不是低端浏览器 
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//code for IE6, IE : 支持的浏览器类型
        } else {
            xmlHttp = new XMLHttpRequest();//code for IE7+, Firefox, Chrome, Opera, Safari :  支持的浏览器类型
        }
    }
 </script>

Ajax引擎兼容模式方式二:

	var xmlHttp;
    function createXMLHttpRequest() {
        if (window.XMLHttpRequest) {//判断是不是一个低端浏览器(IE6往下) true:不是低端浏览器      false:是低端浏览器 
            xmlHttp = new XMLHttpRequest();
        } else {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }

发出请求:

通过下边这两个方法发出请求:
xmlHttp.open(请求方式,请求地址,[是否为异步请求]);
xmlHttp.send()

get请求 post请求 put请求 delete请求
AjaxServlet
@WebServlet("/ajax")
public class AjaxServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher("WEB-INF/views/ajax.jsp").forward(req, resp);
    }
}
AjaxRequestServlet
@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("ISO8859-1"),"UTF-8");
        System.out.println("GET" + userName);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String userName = request.getParameter("userName");
        //text/html : <script></script>  刷出类似这中用的是html
        response.setContentType("text/plain;charset=utf-8");//刷出流响应普通文本用的是text/plain;
        PrintWriter out = response.getWriter();
        System.out.println("POST:" + userName);

        out.print("添加成功!");
        out.close();
    }

    @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);
    }
}

ajax.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
    <base href="<%=basePath%>">
    <title>$</title>
</head>
<body>

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

<script type="text/javascript">

    var xmlHttp = null;

    //构建AJAX引擎
    function createXmlHttpRequest() {
        if (window.ActiveXObject) {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//code for IE6, IE : 支持的浏览器类型
        } else {
            xmlHttp = new XMLHttpRequest();//code for IE7+, Firefox, Chrome, Opera, Safari :  支持的浏览器类型
        }
    }

    createXmlHttpRequest();
    document.querySelector("#userName").onchange = function () {
        console.log(xmlHttp);
        let userName = this.value;

        xmlHttp.open("POST", "/ajaxReq", true);//post请求   请求方式,请求地址,是否为异步请求 默认是true可以省略true
        xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
        xmlHttp.onreadystatechange = callback;//callback : 回调函数,内容已发生改变就会自动调用callback函数
        xmlHttp.send("userName=" + userName)

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

        xmlHttp.open("PUT", "ajaxReq?userName=" + userName);
        xmlHttp.send();//put请求

        xmlHttp.open("DELETE", "/ajaxReq?userName=" + userName)
        xmlHttp.send();//delete请求

        //回调函数
        function callback() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    var result = xmlHttp.responseText;
                    alert(result)
                } else {
                    alert("服务器升级中!")
                }
            }
        }
    }
</script>
</body>
</html>

5 接收服务器响应

在这里插入图片描述

6 获取服务器状态码

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

7 获取HTTP状态码

var serverCode = xmlHttp.status
在这里插入图片描述

8 获取服务器端的文本值

<script>

    function callback(){
        if(xmlHttp.readyState == 4){
            if(xmlHttp.status == 200){
                var result = xmlHttp.responseText;
                alert(result);
            }
        }
    }
</script>
    %****web.Servlet******%
    protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.print("OK");
        out.flush();
        out.close();
    }

9 get,post转码乱码问题

对中文的支持 GET:

如图:在这里插入图片描述

对中文的支持 POST:

如图:
在这里插入图片描述

二 、Ajax XML

XML 指可扩展标记语言(EXtensible Markup Language)
• XML 是一种标记语言,很类似 HTML
• XML 的设计宗旨是传输数据,而非显示数据
• XML 标签没有被预定义。您需要自行定义标签。
• XML 被设计为具有自我描述性。
• XML 是 W3C 的推荐标
网页主要有三部分组成:结构(Structure)、表现(Presentation)、行为(Behavior)。

1 XML 与 HTML 的主要差异

XML 指可扩展标记语言(EXtensible Markup Language)
• XML 是一种标记语言,很类似 HTML
• XML 的设计宗旨是传输数据,而非显示数据
• XML 标签没有被预定义。您需要自行定义标签。
• XML 被设计为具有自我描述性。
• XML 是 W3C 的推荐标

2 跨语言间传输数据

图示:
在这里插入图片描述

3 一个XML文档

图示在这里插入图片描述

4 XML语法规则

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

5 使用XML来描述信息

·图示:在这里插入图片描述在这里插入图片描述

一个books.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<books>
	<book id="88">
		<name>编程思想</name>
		<author>java</author>
		<price>90</price>
	</book>
	<book>
		<name>汤姆斯</name>
		<author>美国</author>
		<price>10</price>
	</book>
	<book>
		<name>杰西</name>
		<author>吉某人</author>
		<price>130</price>
	</book>
</books>

运行图示:
在这里插入图片描述

6 服务器返回XML

 response.setContentType("text/xml");
        PrintWriter out = response.getWriter();
        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        out.println("<books>");
        out.println("<book ISBN=\"5197-5742-5657\">");
        out.println("<name>Java编程思想</name>");
        out.println("<price>91.5</price>");
        out.println("<authors>");
        out.println("<author>");
        out.println("<name>汤姆斯</name>");
        out.println("<nation>美国</nation>");
        out.println("</author>");
        out.println("<author>");
        out.println("<name>杰西姆</name>");
        out.println("<nation>美国</nation>");

        out.flush();
        out.close();

7 Ajax接收返回的XML文档

 function callback() {
        if (xmlHttp.readyState == 4) {
            if (xmlHttp.status == 200) {
                var xmlObj = xmlHttp.responseXML;//接受返回的xml文档
        }
    }esle{
		alser("服务器升级中!")
	}
}

8 JavaScript解析XML API

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

例子:解析xml.books文件 与JAXB生成XML文档
dao. BookDao
public class BookDao {

    JdbcUtil jdbcUtil = new JdbcUtil();
    /**
     * 根据id查询书籍
     * @param id
     * @return
     */
    public Book findBook(int id) {
        String sql = "select id,bookname,author,publisher from book where id = ?";
        Book book = jdbcUtil.executeQueryForObject(sql, new RowMapperImpl<Book>(Book.class), id);
        return book;
    }
    /**
     * 查询所有书籍
     * @return
     */
    public List<Book> findBookList() {
        String sql = "select id,bookname,author,publisher from book";
        List<Book> bookList = jdbcUtil.executeQueryForList(sql, new RowMapperImpl<Book>(Book.class));
        return bookList;
    }
}
dto. XmlBookList
@XmlRootElement(name = "bookList")//name属性可以定义标签的名字<bookList></bookList>
public class XmlBookList {

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

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

刷出单本书的: AjaxXmlBookRequestServlet
@WebServlet("/ajaxXmlBook")
public class AjaxXmlBookRequestServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /**
         * 刷出单个对象(单本书)
         */
        BookDao bookdao = new BookDao();
        Book book = bookdao.findBook(88);
        response.setContentType("text/xml;charset=utf-8");//响应乱码     使用JAXB生成XML文档
        JAXBContext ctx = null;

        try {
            ctx = JAXBContext.newInstance(Book.class);//使用JAXB生成XML文档  Book.class:反射你要操作的对象
            Marshaller marshaller = ctx.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            //marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");解决乱码问题,乱码了就加上这句话试试
            marshaller.marshal(book, response.getOutputStream());//marshal():需要的参数:查到的对象,一个流

            //marshaller.marshal(book, System.out);//System.out:输出流    System.in:输入流
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

刷出多本书的:AjaxXmlBookRequestServlet
@WebServlet("/ajaxXmlBook")
public class AjaxXmlBookRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        BookDao bookDao = new BookDao();
        List<Book> bookList = bookDao.findBookList();
        XmlBookList xmlBookList = new XmlBookList();
        xmlBookList.setBookList(bookList);

        response.setContentType("text/xml;charset=utf-8");
        JAXBContext jaxbContext = null;

        try {
            jaxbContext = JAXBContext.newInstance(XmlBookList.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            //marshaller.setProperty(Marshaller.JAXB_ENCODING,"GNK");响应乱码问题
            marshaller.marshal(xmlBookList, response.getOutputStream());
        } catch (JAXBException e) {
            e.printStackTrace();
        }
}        
在这里插入代码片
a 解析books.xml文件(单本书)
<body>
<input type="button" value="ajax请求" id="btn"/>
<div class="container">
    <table class="table table-striped">
        <tbody id="tab">
        
        </tbody>
    </table>
</div>
<script type="text/javascript">

    var xmlHttp = null;
    //构建AJAX引擎
    function createXmlHttpRequest() {
        if (window.ActiveXObject) {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
        } else {
            xmlHttp = new XMLHttpRequest();
        }
    }

    createXmlHttpRequest();//执行方法
    document.getElementById("btn").onclick = function () {
        xmlHttp.open("GET", "/ajaxXmlBook");
        xmlHttp.onreadystatechange = callback;
        xmlHttp.send();

    }

    /**
     * ajax请求回调函数
     */
    function callback() {

        if (xmlHttp.readyState == 4) {
            if (xmlHttp.status == 200) {
  			var result= xmlHttp.responseXML;
               
                //获取xml文件中的元素 , 返回的book中有:id bookname author publisher 四个子元素                      
                 let book = result.getElementsByTagName("book")[0]//返回当前元素中有指定标记名的子元素数组 [0]:代表第一个位置的元素
                 let id = book.getElementsByTagName("id") [0];

                 let bookName = book.getElementsByTagName("bookname")[0];
                 let author = book.getElementsByTagName("author")[0];
                 let publisher = book.getElementsByTagName("publisher")[0];

                 /!*获取各个元素中的值*!/
                 let valId = id.childNodes[0].nodeValue;//childNodes:返回当前元素所有子元素的数组  nodeValue:获取节点值
                 let valBookName = bookName.childNodes[0].nodeValue;                 let valAuthor = author.childNodes[0].nodeValue;
                 let valPublisher = publisher.childNodes[0].nodeValue;

                 //将获取到的值封装成一个对象
                 let obj = {
                     id: valId,
                     bookName: valBookName,
                     author: valAuthor,
                     publisher: valPublisher
                 }
                 createHtml(obj);//调用创建标签的方法,把封装的对象通过创建的标签以html形式展示到页面上
            } else {
                alert("服务器升级中!")
            }
        }

        /**
         * 动态生成标签
         */
        function createHtml(obj) {
            let tr = document.createElement("tr");
            let idTd = document.createElement("td");
            let bookNameTd = document.createElement("td");
            let authorTd = document.createElement("td");
            let publisherTd = document.createElement("td");

            //创建文本节点,用于放入从obj中获取到的值
            let texId = document.createTextNode(obj.id);
            let texBookName = document.createTextNode(obj.bookName);
            let texAuthor = document.createTextNode(obj.author);
            let textPublisher = document.createTextNode(obj.publisher);
            //将文本节点放入td标签中
            idTd.appendChild(texId);
            bookNameTd.appendChild(texBookName);
            authorTd.appendChild(texAuthor);
            publisherTd.appendChild(textPublisher);

            //将td标签放入tr标签中
            tr.appendChild(idTd);
            tr.appendChild(bookNameTd);
            tr.appendChild(authorTd);
            tr.appendChild(publisherTd);

            let tbody = document.querySelector("#tab")
            tbody.appendChild(tr);
        }
    }
b解析books.xml文件(多本本书)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="<%=basePath%>">
    <title>$</title>
    <link rel="stylesheet" href="/css/bootstrap.min.css"/>
</head>
<body>
<input type="button" value="ajax请求" id="btn"/>
<div class="container">
    <table class="table table-striped">
        <tbody id="tab">

        </tbody>
    </table>
</div>
<script type="text/javascript">
    var xmlHttp = null;
    //构建AJAX引擎
    function createXmlHttpRequest() {
        if (window.ActiveXObject) {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
        } else {
            xmlHttp = new XMLHttpRequest();
        }
    }

    createXmlHttpRequest();//执行方法
    document.getElementById("btn").onclick = function () {
        xmlHttp.open("GET", "/ajaxXmlBook");
        xmlHttp.onreadystatechange = callback;
        xmlHttp.send();
    }
    /**
     * ajax请求回调函数
     */
    function callback() {
        if (xmlHttp.readyState == 4) {
            if (xmlHttp.status == 200) {
                var xmlObj = xmlHttp.responseXML;//获取到xml对象  从Servlet刷出的  xmlObj是一个Object类型
                
                document.getElementById("tab").innerHTML = "";//每次遍历前进行清空一下,避免跟上一次响应的数据一起展示
                //获取到xmlObj中的所有书籍数组
                let bookList = xmlObj.getElementsByTagName("book");//注意对应到传的时候定义的name标签名
                //遍历数组中的所有书籍
                for (var i = 0; i < bookList.length; i++) {
                    let book = bookList[i]//获取当前i位置的<book>,    (书籍数组中有好多个book)
                    
                    let id = book.getElementsByTagName("id")[0].childNodes[0].nodeValue;
                    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 obj = {
                        id: id,
                        bookName: bookName,
                        author: author,
                        publisher: publisher
                    }
                    createHtml(obj);//每循环一次调用一次该方法创建标签进行塞值
                }
            } else {
                alert("服务器升级中!")
            }
        }

        /**
         * 动态生成标签
         */
        function createHtml(obj) {
            let tr = document.createElement("tr");
            let idTd = document.createElement("td");
            let bookNameTd = document.createElement("td");
            let authorTd = document.createElement("td");
            let publisherTd = document.createElement("td");

            //创建文本节点,用于放入从obj中获取到的值
            let texId = document.createTextNode(obj.id);
            let texBookName = document.createTextNode(obj.bookName);
            let texAuthor = document.createTextNode(obj.author);
            let textPublisher = document.createTextNode(obj.publisher);
            //将文本节点放入td标签中
            idTd.appendChild(texId);
            bookNameTd.appendChild(texBookName);
            authorTd.appendChild(texAuthor);
            publisherTd.appendChild(textPublisher);

            //将td标签放入tr标签中
            tr.appendChild(idTd);
            tr.appendChild(bookNameTd);
            tr.appendChild(authorTd);
            tr.appendChild(publisherTd);

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

9 使用JAXB生成XML文档

JAXBContext ctx = JAXBContext.newInstance(User.class);
Marshaller marshaller = ctx.createMarshaller();
//格式化输出
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//输出中文编码
marshaller.setProperty(Marshaller.JAXB_ENCODING,
"GBK");
marshaller.marshal(user, System.out)//输出在控制台
marshaller.marshal(user, rsponse.getUotputStream());//刷到页面


dto层中的类设置
@XmlRootElement
public class User {
	@XmlAttribute
	public void setId(int id) {
		this.id = id;
}
	@XmlElement(name="username")
	public void setName(String name) {
		this.name = name;
}
	//忽略属性
	@XmlTransient
	public void setAddress(Address address) {
		this.address = address;
}

10 XML的验证—DTD

“*”代表子元素可以出现0到多次;
“+”代表子元素可以出现1到多次;
“?”代表子元素可以出现一次、也可以不出现;
如果没有修饰,代表子元素必须出现1次
图示:
在这里插入图片描述

引用DTD

图示:
在这里插入图片描述

11 XML的验证—schema

图示:
在这里插入图片描述

引用schema

图示:
在这里插入图片描述

三 、 Ajax 跨域

什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
在这里插入图片描述
跨域:
在这里插入图片描述

1 使用代理模式进行跨域操作

·图示:
在这里插入图片描述

2 API

有道翻译API
第一步:在有道官方网站申请一个API key
http://fanyi.youdao.com/openapi?path=data-mode
http://ai.youdao.com/
keyfrom:xxxxxxx
key:1618693256
keyfrom:dsfesdfesdff
key:1068666577
keyfrom:neverland
key:969918857
API用法:https://fanyi.youdao.com/openapi.do?keyfrom=neverland&key=969918857&type=data&doctype=xml&version=1.1&q=hello
q=要翻译的内容,这里翻译的是hello
·聚合数据*(·百度搜索集合数据可以搜到其他的跨域操作API及用法)

跨域请求有道云翻译例子
util. HttpRequestTranslateUtil
package com.hisoft.utiil;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.IOException;
//跨域请求翻译的工具类
public class HttpRequestTranslateUtil {//Closeable:可关闭的
//java发送http请求有三种方式,除了原生连接方式HttpURLConnection
//还有另外两种方式:HTTPClient和CloseableHttpClient

    public String getHttpRequest(String url) throws IOException {//Client:客户端
		//1.获得一个httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.生成一个get请求
        HttpGet httpGet = new HttpGet(url);
		 //3.执行get请求并返回结果
        CloseableHttpResponse response1 = httpClient.execute(httpGet);
         //4.处理结果,这里将结果返回为字符串
        HttpEntity entity = response1.getEntity();
        //entity.getContent():返回类型:InputStream
        String result = IOUtils.toString(entity.getContent(), "UTF-8");
        
        response1.close();
        return result;
    }
web. TranslateAjaxReqServlet

@WebServlet("/translate")
public class TranslateAjaxReqServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String transValue = request.getParameter("q");
        transValue = transValue.replace(" ", "%20");//空格替换%号,值以参数形式传过来的时候空格会被转成%,所以这里重新替换%为空格
        response.setContentType("text/xml;charset=utf-8");

        HttpRequestTranslateUtil httpReq = new HttpRequestTranslateUtil();
        String result = httpReq.getHttpRequest("https://fanyi.youdao.com/openapi.do?keyfrom=neverland&key=969918857&type=data&doctype=xml&version=1.1&q=" + transValue);

        PrintWriter out = response.getWriter();
        out.print(result);
        out.close();
    }
}

translation.jsp
<html>
<head>
    <base href="<%=basePath%>">
    <title>$</title>
</head>
<body>
跳转到百度:<input type="button" id="baidu" value="百度"/><br><br>
请输入要翻译的内容:<input type="text" id="cont" value=""/><input type="button" id="btn" value="点击翻译"/>
<div id="di" style="color: red"></div>
<script type="text/javascript">

    var httpRequest = null;

    function createHttpRequest() {
        if (window.ActiveXObject) {
            httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        } else {
            httpRequest = new XMLHttpRequest();
        }
    }

    createHttpRequest();
    document.querySelector("#btn").onclick = function () {

        let value = document.getElementById("cont").value;
        httpRequest.open("GET", "/translate?q=" + value)
        httpRequest.onreadystatechange = callback;
        httpRequest.send();
    }

    /**
     * 回调函数
     */
    function callback() {

        if (httpRequest.readyState == 4) {
            if (httpRequest.status == 200) {
                let result = httpRequest.responseXML;
                //console.log(result.getElementsByTagName("paragraph")[0].childNodes[0].nodeValue);
                let paragraph = result.getElementsByTagName("paragraph")[0].childNodes[0].nodeValue;

                let p = document.createElement("p");
                let pText = document.createTextNode(paragraph);
                p.appendChild(pText);
                let div = document.getElementById("di");
                div.appendChild(p);

            } else {
                alert("服务区升级中!")
            }
        }

        /**
         * 通过js dom操作访问外部链接
         */
        document.getElementById("baidu").onclick = function () {
            window.location.href = "http://www.baidu.com";
        }
    }
</script>
</body>
</html>

有道云例子运行图示:
在这里插入图片描述

jquery操作json数据格式的有道云翻译
jqueryJson.jsp

<script type="text/javascript">
    $(function () {//json数据,jquery:代理模式有道云翻译
        $("#btn").click(function () {
            let content = $("#content").val()
            $.getJSON("/jsonTrans", {q:content}, function (json) {
                let result = json.translation;
                $("#result").text(result[0]);
            });
        });
    });
</script>
jsonTrans

@WebServlet("/jsonTrans")
public class JsonTranslationServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String q = request.getParameter("q");
        HttpRequestTranslateUtil http = new HttpRequestTranslateUtil();
        String result = http.getHttpRequest("http://fanyi.youdao.com/openapi.do?keyfrom=neverland&key=969918857&type=data&doctype=json&version=1.1&q="+q);
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print(result);
        out.close();

    }
}

创建一个复杂结构的json格式对象
Map<String,Object> map = new HashMap<String, Object>();

        List<String> address = new ArrayList<>();
        address.add("中国");
        Book book = new Book();
        book.setBookname("编程思想");
        book.setAuthor("一只鸟");
        book.setAddress(address);

        List<String> list = new ArrayList<>();
        list.add("china");

        map.put("translation",list);
        map.put("basic",book);

        ObjectMapper mapper = new ObjectMapper();
        String mapJson = mapper.writeValueAsString(map);
        System.out.println(mapJson);
        //{"translation":["china"],"basic":{"id":0,"bookname":"编程思想","author":"一只鸟","publisher":null,"address":["中国"]}}


***********************************************
        //一般使用Map集合存放json数据
       	map.put("code",200);
        map.put("msg","查询成功");
        map.put("data",new ArrayList<>());

3 Apache HttpComponen

Apache HttpComponents项目负责创建和维护以HTTP和相关协议为重点的底层Java组件的工具集。
点击链接可以: 跳转到http://hc.apache.org/.官网查看更多信息

四 、 Ajax Json

JSON的全称是JavaScript Object Notation(即JavaScript对象标识),实际上是通过组合使用JavaScript中的数组与键值对(hash)对象来描述数据的结构。
JSON中两种结构:

  1. 数组用来表示有序结构
  2. 键值对用来表示对应关系
    官网JSON链接: http://json.org/json-zh.html

JSON结构:
在这里插入图片描述

1 JSON类库

• Json-lib
• Gson
FastJson:常用
Jackson: 常用

Jackson : json数据与 对象,集合之间互转
A 把一个对象转成json格式
        BookDao bookdao = new BookDao();
        Book book = bookdao.findBook(88);

        ObjectMapper mapper = new ObjectMapper();
        String jsonBook = mapper.writeValueAsString(book);//对象中的数据转成json格式
        System.out.println(jsonBook);*///{"id":88,"bookname":"杀死一只知更鸟","author":"小次郎","publisher":"东京大版出版"}

json转对象
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hisoft.pojo.Book;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

        String jsonBook = "{\"id\":88,\"bookname\":\"杀死一只知更鸟\",\"author\":\"小次郎\",\"publisher\":\"东京大版出版\"}";
        Book book = mapper.readValue(jsonBook,Book.class);
        System.out.println(book.getId());//88
B Map集合转成json格式
  //Map集合转成json格式
        Map<String , Object> map = new HashMap<>();
        map.put("name","Rose");
        map.put("age","12");
        map.put("msg","登录成功!");

        ObjectMapper mapper = new ObjectMapper();
        String jsonMap = mapper.writeValueAsString(map);//Map集合转成json格式
        System.out.println(jsonMap);//{"msg":"登录成功!","name":"Rose","age":"12"}
json转map集合
        Map<String, Object> stringObjectMap = mapper.readValue(jsonMap, new TypeReference<Map<String, Object>>() {});
        System.out.println(stringObjectMap);//{msg=登录成功!, name=Rose, age=12}
        System.out.println(jsonMap);
C List集合转换成json格式数据
        BookDao bookdao = new BookDao();
        List<Book> bookList = bookdao.findBookList();

        ObjectMapper mapper = new ObjectMapper();
        String jsonBookList = mapper.writeValueAsString(bookList);//List集合转换成json格式数据
        System.out.println(jsonBookList);//返回的是一个字符串数组
        //[{"id":1,"bookname":"java编程","author":"James-Gosling","publisher":"人民邮政出版社"},{"id":4,"bookname":"三国演义","author":"罗贯中","publisher":"人民邮电出版社"},{...},...,{...}]

json转list集合
        String jsonBookList = "[{\"id\":88,\"bookname\":\"杀死一只知更鸟\",\"author\":\"小次郎\",\"publisher\":\"东京大版出版\"}]";
        List<Book> listBook = mapper.readValue(jsonBookList, new TypeReference<List<Book>>(){});
        System.out.println(listBook);//[com.hisoft.pojo.Book@158da8e]

Json-lib

数组和集合
boolean[] boolArray = new boolean[]{true,false,true};
JSONArray jsonArray = JSONArray.fromObject( boolArray );
System.out.println( jsonArray );
// prints [true,false,true]
List list = new ArrayList();
list.add( "first" );
list.add( "second" );
JSONArray jsonArray = JSONArray.fromObject( list );
System.out.println( jsonArray );
// prints ["first","second"]
JSONArray jsonArray = JSONArray.fromObject( "['json','is','easy']" );
System.out.println( jsonArray ); //["json","is","easy"]


***********************************
MapMap map = new HashMap();
map.put( "name", "json" );
map.put( "bool", Boolean.TRUE );
map.put( "int", new Integer(1) );
map.put( "arr", new String[]{"a"
,
"b"} );
map.put( "func", "func2" );
JSONObject jsonObject = JSONObject.fromObject( map );
System.out.println( jsonObject );
//{"arr":["a","b"],"int":1,"name":"json","func":"func2","bool":true}

********************************************************Object
Type t = new Type();
t.setFid(3);
t.setId(21);
t.setTypeName("计算机类");
JSONObject jsonObject = JSONObject.fromObject( t );
System.out.println( jsonObject );
//{"fid":3,"id":21,"typeName":"计算机类"}

Google-gson

Gson gson = new Gson();
String json = gson.toJson(object);

**********Servlet输出JSON****************
response.setContentType("application/json");
Gson gson = new Gson();
String json = gson.toJson(obj);
PrintWriter out = response.getWriter();
out.print(json);
out.flush();
out.close();

3 Servlet输出JSON

package com.hisoft.web;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hisoft.dao.BookDao;
import com.hisoft.pojo.Book;
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.io.PrintWriter;
import java.util.List;

@WebServlet("/json")
public class JsonServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String name = request.getParameter("name");
        BookDao bookDao = new BookDao();
        List<Book> bookList = bookDao.findBookList();

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(bookList);

        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print(json);
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

       /* try {
            Thread.sleep(5000);//线程睡眠
        } catch (InterruptedException e) {
        }*/
        String name = request.getParameter("name");
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();
        out.print("Hello");
        out.close();
    }
}

4 使用JQuery操作JSON。解析json

$.getJson
 $.getJSON("/json", {name: "Rose", age: 12}, function (data){})
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="<%=basePath%>">
    <title>$</title>
    //<%-- jquery框架   --%>
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    //<%--  使用JavaScript模板简化操作 :Handlebars.js:http://handlebarsjs.com  --%>
    <script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
    <link rel="stylesheet" href="/css/bootstrap.min.css"/>
</head>
<body>
<input type="button" id="btn" value="ajax点击">

<div style="display: none" id="imgId">
    <img src="/imges/ajax-loader.gif"/>
</div>
<div class="container">
    <table class="tab table-striped" id="tab">
        <tbody>

        </tbody>
    </table>
</div>
<%--//注意:type为:text/template--%>:模板
<script type="text/template" id="temp">
   <tr>//模板简化操作模式
       <td>{{id}}</td>
       <td>{{bookname}}</td>
       <td>{{author}}</td>
       <td>{{publisher}}</td>
   </tr>
</script>

<script type="text/javascript">
    $(function () {

        $("#btn").click(function () {

            $.getJSON("/json", {name: "Rose", age: 12}, function (data) {
                $("#tab").html("");//每次点击前清空一下页面
                var template = Handlebars.compile($("#temp").text())//text():获取文本节点的值  编译模板
                $(data).each(function(){//遍历
                    let tr = template(this);//获取到的值放入当前对象代表的标签中
                    $("#tab").append(tr);//tr标签放入tbody
                });
            });
    });
</script>


</body>
</html>

、、、

在这里插入代码片

5 JQuery和Ajax

1 $.ajax()
$.ajax({
                type: "POST",//或GET请求
                url: "/json",//请求路径
                data: "name=John&location=Boston",//携带的参数
                success: function (msg) {//相当于在ajax引擎中时的 4 & 200 请求已完成,且响应已就绪,如果服务器报错的话不会执行
                    alert("Data Saved:" + msg)
                },
                error: function () {
                    alert("服务器升级中!");
                },
                complete: function () {//完成 ,如果服务器报错的或也会正常弹出
                    alert("ajax 请求完成!");
                    $("#imgId").hide()
                },
                beforeSend: function () {//请求后等待响应的那段时间
                    $("#imgId").show();
                }
            });
2 GET
 $.get("/json",{name:"Jack"},function(data){//data:代表的是从Servlet传过来的数据
                 alert(data);
             });
3 POST
 $.post("/json",{name:"Jack"},function(data){//请求地址,请求携带的参数,回调函数data是Servlet传过来的json数据
                 alert(data);
             });

6 使用JavaScript模板简化操作

1 Mustache.js:https://github.com/janl/mustache.js/
2 Handlebars.js:http://handlebarsjs.com/

7 使用json.js进行转换

var json = JSON.parse(xmlHttp.responseText);
            for (var i = 0; i < json.length; i++) {
                var js = json[i];
                var id = js.id;
                var title = js.title;
                var typeid = js.typeid;

五 、 Ajax Jsonp

1 jsonp

JSONP(JSON with Padding),用来解决跨域问题的另一种解决方案,需要服务器端的支持

图示:
在这里插入图片描述

客户端
<script type="text/javascript">//Handler:调用者
    function jsonpHandler(data) {//data是从服务端返回的数据
        alert(data.name);
    }
</script>
//返回一个在服务端拼接的函数jsonHandler(data); 函数式自己的定义的可以是xxx()
<script type="text/javascript" src="/jsonTrans?callback=jsonpHandler"></script>

服务端
@WebServlet("/jsonTrans")
public class JsonTranslationServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
	 String callback = request.getParameter("callback");
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print(callback + "({name:'Jerry',age:12})");//({name:'Jerry',age:12})":相当于在客户端那边的data数据
        out.flush();
        out.close();
	}
}

2 JQuery对JSONP的支持

JQuery会自动将callback后面的问号替换成生成的函数名称:
在这里插入图片描述

<script type="text/javascript">
    $("#btn").click(function () {
        $.getJSON("/jsonTrans?callback=?", function (data) {
            alert(data.name);
        });
    });
</script>

3 调用有道词典JSONP API

原理:和利用返回一个拼接的callback()函数类似,jQuery ajax方式以jsonp类型发起跨域请求,其原理跟<script>脚本请求一样。跨域请求需要服务端配合,设置callback,才能完成跨域请求

transJsonp.jsp

请输入要翻译的内容:<input type="text" id="content"><input type="button" value="点击翻译" id="btn"/>

<script type="text/javascript">

        $(function () {
            $(function () {
                $("#btn").click(function () {
                    let content = document.querySelector("#content").value;//获取到你输入要翻译的值
                    let url = "http://fanyi.youdao.com/openapi.do?keyfrom=neverland&key=969918857&type=data&doctype=jsonp&callback=?&version=1.1&q=" + content;

                    $.getJSON(url, function (data) {
                        alert(data.translation);
                    });
                });
            });
</script>

六 Ajax 上传文件及表单

1 异步上传文件

A 普通表单

客户端

form.jsp
<form action="" id="myForm">
    <input type="text" name="userName"/>
    <input type="text" name="password"/>
    <div id="btn">登录</div>
</form>

<script type="text/javascript">
    $(function () {
        $("#btn").click(function () {

            $.ajax({
                url : "/ajaxform",
                type : "POST",
                data : $("#myForm").serialize()//序列化,这样服务端可以name属性直接获取到form中的除了文件表单控件外的普通控件的值
            })
        });
    })
</script>

服务端:

/ajaxform
@WebServlet("/ajaxform")
public class FormServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        String userName = request.getParameter("userName");
        String password = request.getParameter("password");
		
        System.out.println(userName + "\t" + password);
    }
}
B 文件表单

.Ajax属性:
·1 cache: 缓存
当发起一次请求后,会把获得的结果以缓存的形式进行存储,当再次发起请求时,如果 cache 的值是 true ,那么会直接从缓存中读取,而不是再次发起一个请求了。
从 cache 的工作原理可以得出,cache 的作用一般只在 get 请求中使用。
2 processData:处理数据
默认情况下,processData 的值是 true,其代表以对象的形式上传的数据都会被转换为字符串的形式上传。而当上传文件的时候,则不需要把其转换为字符串,因此要改成false
3contentType:发送数据的格式
和 contentType 有个类似的属性是 dataType , 代表的是期望从后端收到的数据的格式,一般会有 json 、text……等
而 contentType 则是与 dataType 相对应的,其代表的是 前端发送数据的格式
默认值:application/x-www-form-urlencoded
代表的是 ajax 的 data 是以字符串的形式 如 id=2019&password=123456
使用这种传数据的格式,无法传输复杂的数据,比如多维数组、文件等

ajaxform.jsp
<form action="" id="myForm">
    <input type="text" name="userName"/>
    <input type="text" name="password"/>
    <input type="file"/>
    <div id="btn">登录</div>
</form>
<script type="text/javascript">

    $(function () {
        $("#btn").click(function () {
			//创建一个formData对象:	formdata.append('name','value'); //使用append的方法为 formdata 对象赋值

            let formData= new FormData($("#myForm")[0]);//获取到form中的所有数据
            $.ajax({
                url: "/ajaxform",
                type: "POST",
                data: formData,
                cache: false, //Jquery不要去处理发送的数据
                processData: false,
                contentType: false //Jquery不要去设置 contentTypet
            })
        });
    })
</script>
/ajaxform
@WebServlet("/ajaxform")
@MultipartConfig//3.0版本上上传文件需要加这句话
public class FormServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

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

        //Collection<Part> parts = request.getParts();//获取全部文件表单
        Part myFile = request.getPart("myFile");//获取指定name属性为myFiled的form表单  part:部分
        System.out.println(userName + "\t" + password);
    }
}

2 组件 web uploader文件上传

WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。
采用大文件分片并发上传,极大的提高了文件上传效率。

Web Uploader内部类的详细说明:http://fex.baidu.com/webuploader/document.html接口文档地址

使用Web Uploader文件上传需要引入三种资源:JS, CSS, SWF。

<!--引入CSS-->
<link rel="stylesheet" type="text/css" href="webuploader文件夹/webuploader.css">

<!--引入JS-->
<script type="text/javascript" src="webuploader文件夹/webuploader.js"></script>

<!--SWF在初始化的时候指定,在后面将展示-->

图示:
在这里插入图片描述

WebUploaderServlet
@WebServlet("/uploader")
public class WebUploaderServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        UploadUtil uploadUtil = new UploadUtil();
        boolean upload = uploadUtil.upload(request);
    }
}
webupload.jsp
<html>
<head>
    <base href="<%=basePath%>">
    <title>$</title>
    <link rel="stylesheet" href="/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="js/webuploader/webuploader.js"></script>
    <link href="js/webuploader/webuploader.css" type="text/css" rel="stylesheet"/>
</head>
<body>

<div class="container">
    <div id="uploader" class="wu-example" style="margin-top: 50px">
        <div class="btns">
            <div id="picker" class="pull-left">选择文件</div>
            <botton id="ctlBtn" class="btn btn-default pull-left">开始上传</botton>
            <div class="clearfix"></div>
        </div>
    </div>
    <div id="fileList" class="clearfix"></div>
</div>

<script type="text/javascript">
    $(function () {//初始化配置,创建一个upload对象
        var uploader = WebUploader.create({

            auto: true,//自动上传
            swf: 'js.webuploader/Uploader.swf',//swf文件路径
            server: '/uploader',//文件接受服务端,要走的servlet,自己定义的
            method: 'POST',
            pick: '#picker',//选择文件的按钮。可选。// 内部根据当前运行时创建,可能是input元素,也可能是flash.
            resize: false,// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!

            accept: {//只允许选择图片文件。  
                title: 'Images',
                extensions: 'gif,jpg,jpeg,bmp,png',
                mimeTypes: 'image/*'
            }

        });
		//由于webuploader不处理UI逻辑,所以需要去监听fileQueued事件来实现。  Queued:排队
		//当文件被加入队列以后触发
        uploader.on('fileQueued', function (file) {//file.id:自动创建一个id属性
            $("#fileList").append('<div id="' + file.id + '" class="item">' +
                '<h4 class="info">' + file.name + '<h4>' +
                '<p class="state"> 等待上传...</p>' +
                '</div>'
            );
			//动态创建标签用于进度条的设置  progress:进度条  role:角色
            let perage = "<div class=\"progress\">\n" +
                "    <div class=\"progress-bar\" role=\"progressbar\" >0%</div>\n" +
                "</div>\n";
            $("#" + file.id).append(perage);

        });
		
		//文件上传过程中创建进度条实时显示,上传过程中触发,携带上传进度
        uploader.on('uploadProgress', function (file, percentage) {//percentage:上传进度 file对象
            /*$("#" + file.id + " .progress-bar").css('width', percentage * 100 + '%');
            $("#" + file.id + " .progress-bar").text(Math.floor(percentage * 100) + '%');*/

            $("#" + file.id).find(".progress-bar").css('width', percentage * 100 + '%');
            $("#" + file.id).find(".progress-bar").text(Math.floor(percentage * 100) + '%');
        });//Math.floor():向下取整


		//文件成功、失败处理
//文件上传失败会派送uploadError事件,成功则派送uploadSuccess事件。不管成功或者失败,在文件上传完后都会触发uploadComplete事件。
		//不管成功或者失败
        uploader.on('uploadComplete', function (file) {
            $('#fileList').fadeOut(5000);
        });

		//当文件上传成功时触发。
        uploader.on('uploadSuccess', function (file) {
            alert("恭喜上传成功!");
        });
		//当文件上传失败时触发。
		uploader.on( 'uploadError', function( file ) {
    		$( '#'+file.id ).find('p.state').text('上传出错');
		});

        $("#ctlBtn").click(function () {
            uploader.upload();
        });

    })
</script>
</body>
</html>
util 工具类. UploadUtil
package com.hisoft.utiil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.List;
import java.util.UUID;

public class UploadUtil {

    public boolean upload(HttpServletRequest request) throws UnsupportedEncodingException {

        request.setCharacterEncoding("UTF-8");
        //判断当前提交的表单是不是一个文件表单
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);//multi:多用

        if (isMultipart) {

            try {
                //1 构建factory对象用于ServletFileUpload构造方法中,设置环境:创建一个DiskFileItemFactory工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                //2 设置上传文件时用的临时空间  repository:仓库
                File repository = new File("d:/img");
                factory.setSizeThreshold(1024); //设置临时空间大小
                factory.setRepository(repository);

                ServletFileUpload upload = new ServletFileUpload(factory);//2、核心操作类:创建一个文件上传解析器
                //upload.setSizeMax(1024 * 1024 * 20);//设置表单提交的所有内容的总长度

                //获取表单中的所有控件  //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
                List<FileItem> fileItems = upload.parseRequest(request);
                for (FileItem fileItem : fileItems) {
                    String contentType = fileItem.getContentType();//获取上传的文件类型
                    String fieldName = fileItem.getFieldName();//获取控件name属性值
                    String name = fileItem.getName();//获取上传的文件的名字
                    long size = fileItem.getSize();//获取文件或文本的大小

                    if (fileItem.isFormField()) {//判断该表单是否为普通类型的表单
                        String values = fileItem.getString();//表单普通输入项的值
                        values = new String(values.getBytes("ISO8859-1"), "UTF-8");//解决普通输入项的数据的中文乱码问题
                        System.out.println(fieldName);

                    } else {//否:该表单项是file类型的
                        int index = name.lastIndexOf("."); //获取上传文件的后缀名.xxx
                        String suffixName = name.substring(index);//指定重.(index)出开始到结束  suffixName:后缀名
                        String randomName = UUID.randomUUID().toString();//生成唯一的文件名称
                        String newName = randomName + suffixName;//拼接上传路径。存放路径+上传的文件名后缀            唯一名.xxx

                        File directory = new File("D:/img");//构建目录
                        if (!directory.exists()) {//判断此目录是否存在
                            directory.mkdir();//没有则创建一个单层目录 ;  mkdirs() 创建多层目录
                        }

                        File file = new File(directory, newName);//构建文件

                        InputStream is = fileItem.getInputStream();
                        OutputStream os = new FileOutputStream(file);

                        BufferedInputStream bis = new BufferedInputStream(is);
                        byte[] buffer = new byte[1024 * 1024];
                        BufferedOutputStream bos = new BufferedOutputStream(os);

                        int len = -1;
                        while ((len = is.read(buffer)) != -1) {
                            os.write(buffer, 0, len);
                        }

                        bos.flush();
                        bos.close();
                        bis.close();
                    }
                }

            } catch (FileUploadException | IOException e) {
                e.printStackTrace();
            }
            return true;
        }else{
            return false;
        }

        
    }
}

富文本编辑器操作

官方网站https://simditor.tower.im/参考需要下载官方提供的组件

1 前端页面代码

simditor.jsp
<head>
    <link rel="stylesheet" href="/css/bootstrap.min.css"/>
    <link rel="stylesheet" type="text/css" href="js/simditor-2.3.28/site/assets/styles/simditor.css"/>

    <script type="text/javascript" src="js/simditor-2.3.28/site/assets/scripts/jquery.min.js"></script>
    <script type="text/javascript" src="js/simditor-2.3.28/site/assets/scripts/module.js"></script>
    <script type="text/javascript" src="js/simditor-2.3.28/site/assets/scripts/hotkeys.js"></script>
    <script type="text/javascript" src="js/simditor-2.3.28/site/assets/scripts/uploader.js"></script>
    <script type="text/javascript" src="js/simditor-2.3.28/site/assets/scripts/simditor.js"></script>   
</head>
<body>
 <div class="container">
        <form action="/simditor" method="post">
            //<%--placeholder:文本域初始默认显示的内容   autofocus:光标自动聚焦--%>
            <textarea id="editor" placeholder="babalba" autofocus name="msg"></textarea>
            <input type="submit" value="发表">
        </form>
    </div>
    
<script type="text/javascript">
    $(function () {
        //editor:编辑
        var editor = new Simditor({
            textarea: $("#editor"),
            //toolbar:工具栏   显示工具栏按钮。接受一个按钮数组,其中包括:如:标题、加粗、下划线、删除线....
            toolbar: [
                'title',
                'bold',
                'italic',
                'underline',
                'strikethrough',
                'fontScale',
                'color',
                'ol',
                'ul',
                'blockquote',
                'code' ,
                'table',
                'link',
                'image',
                'hr'  ,
                'indent',
                'outdent',
                'alignment'
            ],
            upload : {//上传完成后的JSON响应: 一点上传的东西就会执行这个servlet
                url : "/simditorUpload",  //post请求
                connectionCount: 3,//指定能同时上传的多少张图片
                leaveConfirm: 'Uploading is in progress, are you sure to leave this page?'//如果有人在上传文件时离开页面,将显示消息;

				/%%%由后端返回的json数据信息消息
                //"success" : true,//成功状态 true/false
                //"msg" : "error message",//错误消息或正确消息
                //"file_path" : "[real file path]"//真正的文件路径,最终上传时的那个路径,用于展示
            },
            pasteImage:true//允许可以直接粘贴图片上传
        });
    })
</script>
</body>
simditorList.jsp
<div class="container">
    <table class="table-striped">
        <thead>
        <tr>
            <th>ID</th>&nbsp;&nbsp;&nbsp;&nbsp;
            <th>内容</th>
        </tr>
        </thead>
        <tbody>
        <c:forEach items="${msgList}" var="msg">
            <tr>
                <td>${msg.id}</td>
                <td>${msg.msg}</td>
            </tr>
        </c:forEach>
        </tbody>
    </table>
</div>

2 后端代码

web servlet

SimditorServlet 添加的文本信息展示

@WebServlet("/simditor")
public class SimditorServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        MsgDao msgDao = new MsgDao();
        List<Msg> msgList = msgDao.findAllMas();
        request.setAttribute("msgList", msgList);
        request.getRequestDispatcher("simditorList.jsp").forward(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

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

        Msg ms = new Msg();
        ms.setMsg(msg);
        MsgDao msgDao = new MsgDao();
        msgDao.saveMsg(ms);

        response.sendRedirect("/simditor");//重定向
        
    }
}

SimditorUploadServlet富文本文件上传

@WebServlet("/simditorUpload")
public class SimditorUploadServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        SimditorUploadUtil su = new SimditorUploadUtil();
        Map<String, Object> uploadMap = su.upload(request);

        boolean success = (boolean) uploadMap.get("success");
        if (success) {
            String imgName = (String) uploadMap.get("imgName");

            Map<String, Object> map = new HashMap<>();
            map.put("success", true);
            map.put("file_path", "http://localhost:8080/img/show?img=" + imgName);

            response.setContentType("application/json;charset=UTF-8");//
            ObjectMapper mapper = new ObjectMapper();
            String jsonMap = mapper.writeValueAsString(map);

            PrintWriter out = response.getWriter();
            out.print(jsonMap);
            out.flush();
            out.close();
        }

    }
}

工具show

·SimditorUploadUtil文件上传

public class SimditorUploadUtil {

    public Map<String, Object> upload(HttpServletRequest request) throws UnsupportedEncodingException {

        request.setCharacterEncoding("UTF-8");

        Map<String, Object> uploadMap = new HashMap<>();

        //判断当前提交的表单是不是一个文件表单
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);

        if (isMultipart) {

            try {
                //1 构建factory对象用于ServletFileUpload构造方法中,设置环境:创建一个DiskFileItemFactory工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                //2 设置上传文件时用的临时空间  repository:仓库
                File repository = new File("d:/img");
                factory.setSizeThreshold(1024); //设置临时空间大小
                factory.setRepository(repository);

                ServletFileUpload upload = new ServletFileUpload(factory);//2、核心操作类:创建一个文件上传解析器
                //upload.setSizeMax(1024 * 1024 * 20);//设置表单提交的所有内容的总长度

                //获取表单中的所有控件  //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
                List<FileItem> fileItems = upload.parseRequest(request);
                for (FileItem fileItem : fileItems) {
                    String contentType = fileItem.getContentType();//获取上传的文件类型
                    String fieldName = fileItem.getFieldName();//获取控件name属性值
                    String name = fileItem.getName();//获取上传的文件的名字
                    long size = fileItem.getSize();//获取文件或文本的大小

                    if (fileItem.isFormField()) {//判断该表单是否为普通类型的表单
                        String values = fileItem.getString();//表单普通输入项的值
                        values = new String(values.getBytes("ISO8859-1"), "UTF-8");//解决普通输入项的数据的中文乱码问题
                        System.out.println(fieldName);

                    } else {//否:该表单项是file类型的
                        int index = name.lastIndexOf("."); //获取上传文件的后缀名.xxx
                        String suffixName = name.substring(index);//指定重.(index)出开始到结束  suffixName:后缀名
                        String randomName = UUID.randomUUID().toString();//生成唯一的文件名称
                        String newName = randomName + suffixName;//拼接上传路径。存放路径+上传的文件名后缀            唯一名.xxx

                        File directory = new File("D:/img");//构建目录
                        if (!directory.exists()) {//判断此目录是否存在
                            directory.mkdir();//没有则创建一个单层目录 ;  mkdirs() 创建多层目录
                        }

                        File file = new File(directory, newName);//构建文件

                        InputStream is = fileItem.getInputStream();
                        OutputStream os = new FileOutputStream(file);

                        BufferedInputStream bis = new BufferedInputStream(is);
                        byte[] buffer = new byte[1024 * 1024];
                        BufferedOutputStream bos = new BufferedOutputStream(os);

                        int len = -1;
                        while ((len = is.read(buffer)) != -1) {
                            os.write(buffer, 0, len);
                        }
                        bos.flush();
                        bos.close();
                        bis.close();

                        //将图片路径存入Mag集合中
                        uploadMap.put("success", true);
                        uploadMap.put("imgName", newName);
                    }
                }

            } catch (FileUploadException | IOException e) {
                e.printStackTrace();
            }
            return uploadMap;
        } else {
            uploadMap.put("success", false);
            uploadMap.put("imgName", null);
            return uploadMap;
        }

    }
}

FileShowServlet文件展示

@WebServlet("/img/show")
public class FileShowServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        /*String dir = DirectoryUtil.FILE_DIR;//借用路径名工具类的做法
        File file = new File(dir + "c7d0ab25-6b8e-4db2-9a1f-162074a85875.jpg");*/

            String img = request.getParameter("img");
            File file = new File("d:/img/" + img);
            InputStream is = new FileInputStream(file);
            byte[] buffer = new byte[1024*1024];
            OutputStream os = response.getOutputStream();

            int len = -1;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer,0,len);
            }
            is.close();
            os.close();
        }

}

大题:微博评论

1 前端页面代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
    <base href="<%=basePath%>">
    <title>欢迎</title>
    <link rel="stylesheet" href="/css/bootstrap.min.css">

    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
</head>
<body>

<div class="container">
    <div style="width: 600px;margin-top: 30px">
        <textarea class="form-control" rows="8" id="msg"></textarea><br>
        <input type="button" id="btn" value="发表" class="pull-right">
    </div>

    <div class="alert alert-danger" style="width: 500px;display: none" id="aId">
        <a href="" class="aMsg"></a>
    </div>

    <div style="width: 500px;margin-top: 20px;" id="showMsg">
        //<%--遍历查询的信息--%>
        <c:forEach items="${msgList}" var="msg">
            <div class="alert alert-success">
                <strong>${msg.msg}</strong><br>
                <small class="sTime">${msg.createtime}</small>
            </div>
        </c:forEach>

    </div>

    <%--  //  handlebars模板--%>
    <script type="text/template" style="width: 500px" id="template">
        <div class="alert alert-success">
            <strong>{{msg}}</strong><br>
            <small class="sTime">{{strCreateTime}}</small>
        </div>
    </script>

</div>

script代码

<script type="text/javascript">
    $(function () {

        $("#aId").hide();//一开始登录时隐藏a标签
        /**
         * 发表信息操作
         * */
        $("#btn").click(function () {
           
            let crateTime = new Date();
            $.post("/msg", {msg: $("#msg").val(), time: crateTime}, function (data) {
                let jsonData = JSON.parse(data);//将从服务端传过来的字符串数据转成json对象是形式的,JSON.parse()方法用于将一个 JSON 字符串转换为对象

                let template = Handlebars.compile($("#template").text());//解析模板

                let tempDiv = template(jsonData);//jsonData数据一放进去解析的模板就会把数据内容添加上
                console.log(tempDiv);
                $(tempDiv).prependTo($("#showMsg"));//将tempDiv追加到showMsg div里的最前边,append():追加到后边
            });

        });
        /**
         * 间歇调用函数用于查看别人新发的未查看的消息:打开两个浏览器模拟两个人发表评论操作
        **/
        var json = null;
        setInterval(function () {

            let endTime = $(".sTime:first").text();
            $.getJSON("/newMsg?time=" + endTime, function (jsonData) {

                if (jsonData.length) {
                    json = jsonData
                    $("#aId a").text("你有" + json.length + "条消息未查看!")
                    $("#aId").show();
                }
            });
        }, 5000);

        /**
         * 显示未查看的消息
         */
        $("#showAId").click(function () {

            let template = Handlebars.compile($("#template").text());
            $(json).each(function() {
                let aDiv = template(this);
                $(aDiv).prependTo($("#showMsg"));
            });
        });

    })
</script>
</body>
</html>

效果运行图:
在这里插入图片描述

2 后端代码

1 实体类

WeiBoMsg

public class WeiBoMsg {

    private int id;
    private String msg;//发布的消息
    private Date createtime;//存进数据库时候的时间Date类型
    private String strCreateTime;//存进去的时候同时要返回给前端的时间,两个时间一样,类型不同,日期格式的话转json的时候会被自动转成时间戳

2 Dao

WeiBoMsgDao

package com.hisoft.dao;
import com.hisoft.pojo.WeiBoMsg;
import com.hisoft.util.JdbcUtil;
import com.hisoft.util.impl.RowMapperImpl;
import java.util.Date;
import java.util.List;

public class WeiBoMsgDao {

    JdbcUtil jdbcUtil = new JdbcUtil();
    /**
     * 根据时间和内容添加
     * @param content
     * @param time
     */
    public void saveMsg(String content, Date time) {
        String sql = "insert into t_weibo(msg,createtime) values(?,?)";
        jdbcUtil.executeUpdate(sql, content, time);

    }

    /**
     * 查找所有消息内容
     * @return
     */
    public List<WeiBoMsg> findAllMsg() {

        String sql = "select id,msg,createtime  from t_weibo order by createtime desc ";
        List<WeiBoMsg> msgList = jdbcUtil.executeQueryForList(sql, new RowMapperImpl<WeiBoMsg>(WeiBoMsg.class));
        return msgList;
    }

    /**
     * 查找大于enTime时间的消息
     * @param enTime
     * @return
     */
    public List<WeiBoMsg> findNewMsg(String enTime) {
        String sql = "select * from t_weibo where createtime > ? ";
        List<WeiBoMsg> newMsgList = jdbcUtil.executeQueryForList(sql, new RowMapperImpl<>(WeiBoMsg.class), enTime);
        return newMsgList;
    }

}

3 Service

WeiBoDaoService

public class WeiBoDaoService {

    WeiBoMsgDao weiBoMsgDao = new WeiBoMsgDao();
    public void saveMsg(String content, Date time) {
        weiBoMsgDao.saveMsg(content, time);
    }
    public List<WeiBoMsg> findAllMSg() {
        List<WeiBoMsg> msgList = weiBoMsgDao.findAllMsg();
        return msgList;
    }
    public List<WeiBoMsg> findNewMsg(String enTime) {
        List<WeiBoMsg> newMsg = weiBoMsgDao.findNewMsg(enTime);
        return newMsg;
    }
}

4 web servlet

MsgServlet 消息的添加及初始展示
package com.hisoft.web;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hisoft.pojo.WeiBoMsg;
import com.hisoft.service.WeiBoDaoService;
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.io.PrintWriter;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@WebServlet("/msg")
public class MsgServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        WeiBoDaoService service = new WeiBoDaoService();
        List<WeiBoMsg> msgList = service.findAllMSg();
        request.setAttribute("msgList", msgList);
        request.getRequestDispatcher("/msg.jsp").forward(request, response);
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.getRequestDispatcher("UTF-8");
        WeiBoDaoService weiBoDaoService = new WeiBoDaoService();

        String msg = request.getParameter("msg");
        String crateTime1 = request.getParameter("time");//Mon Sep 13 11:39:14 CST 2021 字符串型
        Date crateTime = new Date(crateTime1 );
        System.out,println(createTime);//Mon Sep 13 11:39:14 CST 2021
   
        weiBoDaoService.saveMsg(msg, crateTime);//添加信息
        
        
        //添加完之后把数据也给前端返回用于添加完可以直接显示发布的内容
        WeiBoMsg weiBoMsg = new WeiBoMsg();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String strTime = sdf.format(crateTime);//转换成String类型的时间格式,不然json转化的时候会把Date格式转成时间戳

        weiBoMsg.setMsg(msg);
        weiBoMsg.setStrCreateTime(strTime);
        
        ObjectMapper mapper = new ObjectMapper();
        String msgJson = mapper.writeValueAsString(weiBoMsg);
        //以(plain)文本的形式响应,而不是以application/json形式是因为如果以json格式的话时间会被转成一个时间戳
        response.setContentType("text/plain;charset=utf-8");
        PrintWriter out = response.getWriter();

        out.print(msgJson);
        out.flush();
        out.close();
    }

}

NewMsgServlet 未查看的信息
@WebServlet("/newMsg")
public class NewMsgServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        String endTime = request.getParameter("time");

        WeiBoDaoService weiBoDaoService = new WeiBoDaoService();
        List<WeiBoMsg> newMsgList = weiBoDaoService.findNewMsg(endTime);

        ObjectMapper mapper = new ObjectMapper();
        String jsonNewMsg = mapper.writeValueAsString(newMsgList);
        response.setContentType("application/json;charset=utf-8");

        PrintWriter out = response.getWriter();
        out.print(jsonNewMsg);
        out.flush();
        out.close();

    }


}

需要jar包:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值