百度搜索栏下方的提示效果如下: 实现路线:
trie 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 package songsong.host.food.util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; class Node { public Map<String, Node> nexts; // 子节点 public int end; public Node() { this.nexts = new HashMap<String, Node>(); this.end = 0; } } public class Trie { private Node root; private List<String> list; public Trie(){ root = new Node(); list = new ArrayList<String>(); } public void insert(String word) { if (word == null) return; Node node = root; for (int i = 0; i < word.length(); i++) { String str = "" + word.charAt(i); if (node.nexts.get(str) == null) node.nexts.put(str, new Node()); node = node.nexts.get(str); } node.end = 1; } public boolean startWith(String preWord) { Node node = root; for (int i = 0; i < preWord.length(); i++) { String str = "" + preWord.charAt(i); if (node.nexts.get(str) == null) return false; node = node.nexts.get(str); } return true; } public List<String> getData(String preword) { list.clear(); if (!startWith(preword)) return null; else { StringBuilder str = new StringBuilder(""); str.append(preword); Node node = root; for (int i = 0; i < preword.length(); i++) node = node.nexts.get("" + preword.charAt(i)); dfs(node, str); } return list; } private void dfs(Node root, StringBuilder str) { if (root.end == 1) { list.add(str.toString()); if (root.nexts.size() == 0) return; } Node node = root; for (String s : node.nexts.keySet()) { str.append(s); dfs(node.nexts.get(s), str); str.delete(str.length() - 1, str.length()); } } // public static void main(String[] args) { // System.out.println("ok"); // Trie test = new Trie(); // test.insert("what"); // test.insert("what do you do"); // test.insert("what is your name"); // test.insert("宫保鸡丁"); // test.insert("烧烤"); // test.insert("鱼香肉丝"); // test.insert("红烧鸡"); // test.insert("红焖鸡"); // System.out.println("输入a"); // System.out.println(test.getData("a")); // System.out.println(test.startWith("a")); // // } }
有了这就好说了,启动浏览器的时候,直接从数据库的search表里把关键字拿出来构建trie树,当然可以将关键字进行排序等处理,拿热搜等等。ajax异步请求,搜索栏发生变化,补全提示词实时变化。
请求数据 1 2 3 4 5 6 7 8 9 10 //实现打开浏览器就加载热搜,并构建trie树 @RequestMapping("/search") public void search(HttpServletResponse response){ //查询前X的热搜: List<Search> searcheList=commonService.selectAllSearch(100); //构建trie树 for (int i = 0;i<searcheList.size();i++) { test.insert(searcheList.get(i).getWords()); } }
1 2 3 4 5 6 7 8 9 10 11 12 //给前端写回json数据 private void writeBack(HttpServletResponse response,Object o){ //解决:拒绝引用 String json = JSON.toJSONString(o, SerializerFeature.DisableCircularReferenceDetect); response.setCharacterEncoding("utf-8"); response.setContentType("application/json; charset=utf-8"); try { response.getWriter().print(json); } catch (IOException e) { e.printStackTrace(); } }
1 2 3 4 5 6 7 /补全提示 @RequestMapping("/search/{word}") public void search(HttpServletResponse response,@PathVariable("word") String word){ //查询联想词 List<String> words = test.getData(word); writeBack(response,words); }
search.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 $(function(){ $.ajax({ url : "/common/search/", type : 'get', dataType : 'json', success : function(data) { alert("构建trie成功!") } }) }); $(function(){ $('#keyword').blur(function() { setTimeout(function() { //进行延时处理,时间单位为千分之一秒 clearContent(); }, 500) }).focus(function(){ if($(this).val() != ''){ getMoreContents(); } }); //激活新加进来的元素点击事件 $('body').on("click", "#content_table_body tr", function () { var td = $(this).find("td"); var data = td.eq(0).text(); $("#keyword").val(data.toString()); }) }) function getMoreContents() { setLocation(); var content = $("#keyword").val(); if (content == "") { return; } submit(content); } //清空数据 function clearContent() { $("#popdiv").attr("style","display: none"); } function setLocation() { //关联信息的显示位置 var content = document.getElementById("keyword"); var width = content.offsetWidth;//输入框的宽度 $("#popdiv").attr("style","position:absolute;z-index: 9999"); document.getElementById("content_table").style.width = width + "px"; } function submit(word) { $.ajax({ url : "/common/search/"+word, type : 'get', dataType : 'json', success : function(data) { $("#content_table_body").html(""); $.each(data, function (i, item) { $("#content_table_body").append(searchTable(item)); }); } }) } function searchTable(item){ var tr = '<tr><td>' + item +'</td></tr>'; return tr; }
部分html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> <script type="text/javascript" th:src="@{/js/jquery-3.2.1.min.js}"></script> <script type="text/javascript" th:src="@{/js/bootstrap.min.js}"></script> <script type="text/javascript" th:src="@{/js/search.js}"></script> <div class="col-lg-5 col-md-8 col-sm-5 m-auto" id="search"> <form action="/common/search/s" method="post" class="input-group input-group-lg mt-3"> <!--onblur="keywordBlur()" onfocus="getMoreContents()"--> <input type="text" autocomplete='off' class="form-control input-lg" id="keyword" name="keyword" onkeyup="getMoreContents()" placeholder="请输入..." /> <button type="submit" class="btn btn-primary">搜 索</button> </form> <div id="popdiv" class="bg-light text-dark"> <table id="content_table" class="table table-hover bg-secondary text-white"> <tbody id="content_table_body"> </tbody> </table> </div> </div>
效果
-------------
Thank you for reading
-------------