智能搜索

功能:

1、通过搜索记录,自动在搜索框下方弹出下拉框,框中记录原来的搜索历史
2、点击搜索记录,可直接搜索

实现原理:

1、ajax
2、cookie
原生js代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script type="text/javascript">
    //由于以后常用,故定义全局
    var XHR;
    function getKeyContent() {
        //得到输入值
        var content = document.getElementById("keyword");
        if (content.value == "") {
            clearContents();
            return;
        }
        //通过获取浏览器中xmlhttprequest对象实现ajax异步处理
        XHR = creatXHR();
        //通过XHR向服务器发送信息

        var url = "search?keyword=" + content.value;
        /* var url = "search"; */

        var words = "keyword=" + content.value;
        //true标示为异步处理,即 sent()方法后依然可以执行
        XHR.open("get", url, true);
        /* XHR.setRequestHeader("Content-Type",
                "application/x-www-form-urlencoded"); */
        //通过XHR状态码(0-4)确定服务器可以响应时执行回调
        //绑定回调函数
        XHR.onreadystatechange = callBack;

        XHR.send();
    }
    //获取到回调函数
    function callBack() {
        //标示请求成功可以响应
        if (XHR.readyState == 4) {
            //服务器连接成功
            if (XHR.status == 200) {
                //获取响应文本
                var result = XHR.responseText;
                //解析文本获取数据
                var json = eval("(" + result + ")");
                //获取数据后动态展示
                setContents(json);
            }
        }
    }
    //设置动态显示的页面数据
    function setContents(contents) {
        //清空原来的内容
        clearContents();
        //定位确定popDiv位置,并使其宽度与输入框一致
        setLocation();
        //获取内容的长度
        var size = contents.length;
        for (var i = 0; i < size; i++) {
            //获取到内容
            var nextNode = contents[i];
            var tr = document.createElement("tr");
            var td = document.createElement("td");

            //鼠标滑入的动作
            td.onmouseover = function() {
                this.className = 'mouseOver';
            };
            //鼠标滑出的动作
            td.onmouseout = function() {
                this.className = 'mouseOut';
            };
            //将td中的字段放入文本框
            td.onmousedown = function() {
                var content = this.innerText;
                var keyword = document.getElementById("keyword").value;
                keyword = content;
                //点击并跳转
                window.location.href = "https://www.baidu.com/s?wd=" + keyword;
            };

            //一层一层将数据放入节点容器
            //创建文本内容
            var text = document.createTextNode(nextNode);
            //将文本内容放入列中
            td.appendChild(text);
            //将列内容放入行中
            tr.appendChild(td);
            //将行内容放入tbody中
            document.getElementById("table_content_body").appendChild(tr);
        }
    }
    //定位并一致的具体操作
    function setLocation() {
        //获取输入框的位置和宽度,并确认所需相应材料
        var keyword = document.getElementById("keyword");
        var width = keyword.offsetWidth;
        //将popDiv调整
        var popDiv = document.getElementById("popDiv");
        popDiv.style.border = "black 1px solid";
        popDiv.style.width = width - 2 + "px";

        document.getElementById("table_content").style.width = width - 2 + "px";
    }
    //获取到XHR
    function creatXHR() {
        var XHR;
        if (window.XMLHttpRequest) {
            XHR = new XMLHttpRequest();
        }
        return XHR;
    }

    function clearContents() {
        var contents = document.getElementById("table_content_body");
        var size = contents.childNodes.length;
        for (var i = size - 1; i >= 0; i--) {
            contents.removeChild(contents.childNodes[i]);
        }
    }
    //失去焦点时清空
    function keyBlur() {
        clearContents();
    }
    function redirect() {
        var kvalue = document.getElementById("keyword").value;
        window.location.href = "https://www.baidu.com/s?wd=" + kvalue;
    }
</script>
<style type="text/css">
#xjDiv {
    position: relative;
    top: 50%;
    left: 50%;
    margin-top: 200px;
}

#popDiv {
    margin-top: -4px;
}

#popDiv table_content {
    position: relative;
    margin-top: -4px;
}

.mouseOver {
    background: #FFAFAF;
}

.mouseOut {
    background: #00000;
}
</style>

<title>智能搜索</title>
</head>
<body>
    <div id="xjDiv">
        <input type="text" id="keyword" name="keyword"
            onkeyup="getKeyContent()" onblur="keyBlur()"
            onfocus="getKeyContent()"> <input type="button"
            onclick="redirect()" value="xjSearch">
        <!-- 动态展示区域 -->
        <div id="popDiv">
            <table id="table_content" border="0" cellpadding="0" cellspacing="0">
                <tbody id="table_content_body">
                </tbody>
            </table>
        </div>
    </div>
</body>
</html>

Servlet代码:

package com.ajax;

import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONArray;

/**
 * Servlet implementation class searchServlet
 */
@WebServlet("/search")
public class searchServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    // 数据
    static String keyList;
    static Set<String> datas = new HashSet<String>();

    // 获取关联数据
    public List<String> getData(String keyword) {
        List<String> raData = new ArrayList<String>();
        for (String rd : datas) {
            if (rd.contains(keyword)) {
                raData.add(rd);
            }
        }
        return raData;
    }

    public searchServlet() {
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 设置编码集
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String keyword;

        keyword = req.getParameter("keyword");

        // System.out.println(keyword);

        // 将cookie中的输入框中的值添加进datas
        Cookie cookies[] = req.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                if (c.getName().equals("keywords")) {
                    String arr[] = URLDecoder.decode(c.getValue(), "utf-8")
                            .split(",");
                    for (String s : arr) {
                        datas.add(s);
                    }
                    break;
                }
            }
        }

        // 将输入框中的数据加入到cookie中
        keyList += keyword + ",";
        Cookie key = new Cookie("keywords", URLEncoder.encode(keyList, "utf-8"));
        // System.out.println(keyList);
        resp.addCookie(key);

        // System.out.println(req.getCookies()[1].getValue());

        // 得到关联数据
        List<String> resultList;
        try {
            resultList = getData(keyword);
        } catch (NullPointerException e) {
            resultList = getData("");
            System.out.println("没获取到keyword");
        }
        List<String> result = new ArrayList<String>();
        // 若数据>4只显示前四个数据
        if (resultList.size() > 4) {
            result = resultList.subList(0, 4);
        } else {
            result = resultList;
        }
        // System.out.println(datas);
        datas.clear();
        // resp.getWriter().write(result.toString());
        resp.getWriter().write(JSONArray.fromObject(result).toString());
    }

}

总结:

1、小bug:
问题:
1.1 搜索记录中,英文可以完整实现,中文不可以
1.2 美化真费劲2333
解决过程:
猜想1:
get方法的编码问题:
解决方案:将Apache中的servel.xml中添加 URIEncoding=”utf-8”
结果:无果
猜想2:
json转换编码问题:
解决方案:去除json,原生传递数据
结果:无果
猜想3:
cookie编码问题:
吐槽:众里寻百度,总算让我逮到了你……
解决方案:编码、解码
方法:发送cookie并对其编码为URLEncoder,接收时URLDecoder对其解码
原因:cookie保存在客户端,客户端与服务端进行交互时,会涉及到数据传输,而中文在网络传输中,易发生异常,故需要对传输的url或者报头数据进行编码,来保障数据的完整性
结果:bingo

解决时涉及的查询资料:
常见编码格式:
js编码总结:
json详解:

原文地址:https://www.cnblogs.com/xieji233/p/6155611.html