Servlet+Ajax实现搜索智能提示
一般在百度搜索框输入关键词时,会弹出一些相关信息提示,方便点选:
页面(search.jsp):
1 <input type="text" name="keyWords" id="keyWords" style="width:200px; height:20px;" /> 2 <input type="button" id="button" value="百度一下">
创建新的div层,用以放置获取到的提示内容:
1 <div> 2 <input type="text" name="keyWords" id="keyWords" style="width:200px; height:20px;" /> 3 <input type="button" id="button" value="百度一下"> 4 <div id="popDiv"> 5 <table id="content_table"> 6 <tbody id="content_table_body"> 7 </tbody> 8 </table> 9 </div> 10 </div>
创建XMLHttpRequest对象:
1 function createXmlHttp() 2 { 3 var xmlHttp; 4 //创建XMLHttpRequest 5 if(window.XMLHttpRequest) 6 { 7 xmlHttp = new XMLHttpRequest(); 8 //兼容某些Mozilla浏览器的响应头,强制设置为text/xml,具体参看:http://www.cnblogs.com/perseverancevictory/p/3690769.html 9 if(xmlHttp.overrideMimeType){ 10 xmlHttp.overrideMimeType("text/xml"); 11 } 12 } 13 //兼容IE 14 else if(window.ActiveXObject) 15 { 16 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 17 if(!xmlHttp) 18 { 19 xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 20 } 21 } 22 return xmlHttp; 23 }
当输入时出现提示,因此需要在input框中添加onkeyup事件,用以获取相关提示:
1 <input type="text" name="keyWords" id="keyWords" style="width:200px; height:20px;" onkeyup="getMoreContens()" />
实现onkeyup事件:
1 var xmlHttp; 2 //获取用户输入的关联信息的函数 3 function getMoreContens() { 4 //获取用户输入 5 var content = document.getElementById("keyWords").value; 6 if (content == "") { 7 clearContent(); 8 return; 9 } 10 xmlHttp = createXmlHttp(); 11 //给服务器发送数据 12 var url = "search?keyword="+encodeURI(content); 13 xmlHttp.open("GET",url,true); 14 xmlHttp.onreadystatechange = //回调函数 15 function callback() 16 { 17 if(xmlHttp.readyState == 4) 18 { 19 if(xmlHttp.status == 200){ 20 var result = decodeURIComponent(xmlHttp.responseText); 21 var json = eval("("+result+")"); 22 clearContent(json); 23 intelliSense(json); 24 } 25 } 26 }; 27 /* 28 xmlhttp的send是传递参数用的,但是只有在使用post方式提交请求的时候才有用 29 如下: 30 xmlhttp.open("post",url,true); 31 ... 32 xmlhttp.send("data=data&data2=data2"); 33 34 用get的话一般就是: 35 xmlhttp.open("get",url,true); 36 ... 37 xmlhttp.send(null); 38 */ 39 xmlHttp.send(null); 40 }
可以看到,getMoreConten()方法中有clearContent()和intelliSense(json)两个自定义方法,它们的作用分别是清空提示和根据输入智能获取关键字,实现如下:
intelliSense(获取智能提示并放置在输入框下方table中):
1 function intelliSense(json) 2 { 3 //获取关联数据的长度 4 var size = json.length; 5 for(var i=0;i<size;i++) 6 { 7 var nextNode = json[i]; 8 var tr= document.createElement("tr"); 9 var td= document.createElement("td"); 10 tr.setAttribute("border", "0"); 11 tr.setAttribute("bgcolor", "#EDEDED"); 12 td.setAttribute("width", "200px"); 13 td.onmouseover=function() 14 { 15 this.className = 'mouseOver'; 16 } 17 td.onmouseout=function() 18 { 19 this.className = 'mouseOut'; 20 } 21 td.onclick=function() 22 { 23 document.getElementById("keyWords").value=this.innerText; 24 } 25 var text=document.createTextNode(nextNode); 26 td.appendChild(text); 27 tr.appendChild(td); 28 document.getElementById("content_table_body").appendChild(tr); 29 } 30 }
clearContent:
1 function clearContent() 2 { 3 var contentTableBody = document.getElementById("content_table_body"); 4 var size = contentTableBody.childNodes.length; 5 for(var i=size-1;i>0;i--) 6 { 7 contentTableBody.removeChild(contentTableBody.childNodes[i]); 8 } 9 }
页面上基本完成,接下来需要实现getMoreContens方法中定义的名叫search的Servlet:
在web.xml中配置:
1 <servlet-mapping> 2 <servlet-name>search</servlet-name> 3 <url-pattern>/search</url-pattern> 4 </servlet-mapping> 5 <servlet> 6 <description>搜索</description> 7 <servlet-name>search</servlet-name> 8 <servlet-class>com.yan.search.SearchServlet</servlet-class> 9 </servlet>
Servlet实现:
1 private static List<String> keyWordList = new ArrayList<String>(); 2 static { 3 // 模拟数据 4 keyWordList.add("yanwei"); 5 keyWordList.add("yantian"); 6 keyWordList.add("yanpeng"); 7 keyWordList.add("yanweichao"); 8 keyWordList.add("yanweiqi"); 9 keyWordList.add("yanyurong"); 10 keyWordList.add("yanmeirong"); 11 keyWordList.add("yanweichen"); 12 keyWordList.add("电影"); 13 keyWordList.add("电影 66ys"); 14 } 15 private static final long serialVersionUID = 1L; 16 17 @Override 18 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 19 throws ServletException, IOException { 20 doGet(req, resp); 21 } 22 23 @Override 24 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 25 throws ServletException, IOException { 26 27 String keyWord = req.getParameter("keyword"); 28 System.out.println(keyWord); 29 List<String> list = keyWord==null?new ArrayList<String>():getDatas(keyWord); 30 String json = JSON.toJSONString(list); 31 //防止乱码 32 String encodeJSON = URLEncoder.encode(json,"UTF-8"); 33 resp.getWriter().write(encodeJSON); 34 } 35 36 public static List<String> getDatas(String keyWord) { 37 List<String> list = new ArrayList<String>(); 38 for (int i = 0; i < keyWordList.size(); i++) { 39 if (keyWordList.get(i).contains(keyWord)) { 40 list.add(keyWordList.get(i)); 41 } 42 } 43 return list; 44 }
此时基本功能已经实现,但还有一些小细节需要处理:
1.当文本框失去焦点时,提示应该消失
在输入框属性中添加onblur事件,触发clearContent方法;
2.获得焦点时再次出现提示
在输入框属性中添加onfocus事件,触发intelliSense方法;
3.当鼠标滑过载有提示信息的table时,应加一些样式显得更友好:
我们在intelliSense方法中已经为td元素设置了类名mouseOver和mouseOut,因此添加css样式即可:
1 .mouseOver { 2 background: #00B2EE; 3 color: white; 4 width: 200px; 5 } 6 .mouseOut { 7 background: #EDEDED; 8 width: 200px; 9 }
呈现效果:
最终代码:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 3 <welcome-file-list> 4 <welcome-file>index.jsp</welcome-file> 5 </welcome-file-list> 6 <servlet-mapping> 7 <servlet-name>search</servlet-name> 8 <url-pattern>/search</url-pattern> 9 </servlet-mapping> 10 <servlet> 11 <description>搜索</description> 12 <servlet-name>search</servlet-name> 13 <servlet-class>com.yan.search.SearchServlet</servlet-class> 14 </servlet> 15 </web-app>
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 <title>smart search</title> 8 <style type="text/css"> 9 .mouseOver { 10 background: #00B2EE; 11 color: white; 12 width: 200px; 13 } 14 .mouseOut { 15 background: #EDEDED; 16 width: 200px; 17 } 18 </style> 19 <script type="text/javascript"> 20 var xmlHttp; 21 //获取用户输入的关联信息的函数 22 function getMoreContens() { 23 //获取用户输入 24 var content = document.getElementById("keyWords").value; 25 if (content == "") { 26 clearContent(); 27 return; 28 } 29 xmlHttp = createXmlHttp(); 30 //给服务器发送数据 31 var url = "search?keyword="+encodeURI(content); 32 xmlHttp.open("GET",url,true); 33 xmlHttp.onreadystatechange = //回调函数 34 function callback() 35 { 36 if(xmlHttp.readyState == 4) 37 { 38 if(xmlHttp.status == 200){ 39 var result = decodeURIComponent(xmlHttp.responseText); 40 var json = eval("("+result+")"); 41 clearContent(json); 42 intelliSense(json); 43 } 44 } 45 }; 46 /* 47 xmlhttp的send是传递参数用的,但是只有在使用post方式提交请求的时候才有用 48 如下: 49 xmlhttp.open("post",url,true); 50 ... 51 xmlhttp.send("data=data&data2=data2"); 52 53 用get的话一般就是: 54 xmlhttp.open("get",url,true); 55 ... 56 xmlhttp.send(null); 57 */ 58 xmlHttp.send(null); 59 } 60 61 //创建XMLHttpRequest 62 function createXmlHttp() 63 { 64 var xmlHttp; 65 if(window.XMLHttpRequest) 66 { 67 xmlHttp = new XMLHttpRequest(); 68 //兼容某些Mozilla浏览器的响应头,强制设置为text/xml,具体参看:http://www.cnblogs.com/perseverancevictory/p/3690769.html 69 if(xmlHttp.overrideMimeType){ 70 xmlHttp.overrideMimeType("text/xml"); 71 } 72 } 73 //兼容IE 74 else if(window.ActiveXObject) 75 { 76 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 77 if(!xmlHttp) 78 { 79 xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 80 } 81 } 82 return xmlHttp; 83 } 84 85 function clearContent() 86 { 87 var contentTableBody = document.getElementById("content_table_body"); 88 var size = contentTableBody.childNodes.length; 89 for(var i=size-1;i>0;i--) 90 { 91 contentTableBody.removeChild(contentTableBody.childNodes[i]); 92 } 93 } 94 function intelliSense(json) 95 { 96 //获取关联数据的长度 97 var size = json.length; 98 for(var i=0;i<size;i++) 99 { 100 var nextNode = json[i]; 101 var tr= document.createElement("tr"); 102 var td= document.createElement("td"); 103 tr.setAttribute("border", "0"); 104 tr.setAttribute("bgcolor", "#EDEDED"); 105 td.setAttribute("width", "200px"); 106 td.onmouseover=function() 107 { 108 this.className = 'mouseOver'; 109 } 110 td.onmouseout=function() 111 { 112 this.className = 'mouseOut'; 113 } 114 td.onclick=function() 115 { 116 document.getElementById("keyWords").value=this.innerText; 117 } 118 var text=document.createTextNode(nextNode); 119 td.appendChild(text); 120 tr.appendChild(td); 121 document.getElementById("content_table_body").appendChild(tr); 122 } 123 } 124 </script> 125 </head> 126 <body> 127 <div> 128 <input type="text" name="keyWords" id="keyWords" style="width:200px; height:20px;" onkeyup="getMoreContens()" onfocus="getMoreContens()" onblur="clearContent()" /> <input 129 type="button" id="button" value="百度一下"> 130 <div id="popDiv"> 131 <table id="content_table"> 132 <tbody id="content_table_body"> 133 </tbody> 134 </table> 135 </div> 136 </div> 137 </body> 138 </html>
1 package com.yan.search; 2 3 import java.io.IOException; 4 import java.net.URLEncoder; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import javax.servlet.ServletException; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 13 import com.alibaba.fastjson.JSON; 14 15 public class SearchServlet extends HttpServlet { 16 17 private static List<String> keyWordList = new ArrayList<String>(); 18 static { 19 // 模拟数据 20 keyWordList.add("yanwei"); 21 keyWordList.add("yantian"); 22 keyWordList.add("yanpeng"); 23 keyWordList.add("yanweichao"); 24 keyWordList.add("yanweiqi"); 25 keyWordList.add("yanyurong"); 26 keyWordList.add("yanmeirong"); 27 keyWordList.add("yanweichen"); 28 keyWordList.add("电影"); 29 keyWordList.add("电影 66ys"); 30 } 31 private static final long serialVersionUID = 1L; 32 33 @Override 34 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 35 throws ServletException, IOException { 36 doGet(req, resp); 37 } 38 39 @Override 40 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 41 throws ServletException, IOException { 42 43 String keyWord = req.getParameter("keyword"); 44 System.out.println(keyWord); 45 List<String> list = keyWord==null?new ArrayList<String>():getDatas(keyWord); 46 String json = JSON.toJSONString(list); 47 //防止乱码 48 String encodeJSON = URLEncoder.encode(json,"UTF-8"); 49 resp.getWriter().write(encodeJSON); 50 } 51 52 public static List<String> getDatas(String keyWord) { 53 List<String> list = new ArrayList<String>(); 54 for (int i = 0; i < keyWordList.size(); i++) { 55 if (keyWordList.get(i).contains(keyWord)) { 56 list.add(keyWordList.get(i)); 57 } 58 } 59 return list; 60 } 61 }
God, Grant me the SERENITY, to accept the things I cannot change,
COURAGE to change the things I can, and the WISDOM to know the difference.