这篇文章中完成一个搜索城市的示例程序,输入城市名称或者拼音首字母,返回城市的智能提示。使用了JQuery UI AutoComplete插件。
首先,看一下效果图,了解程序完成后是一个什么样子。
汉字搜索
拼音首字母搜索
看完了效果图,下面一步一步介绍如何完成这个程序。
Step 1 数据库表及函数(SQL Server 2008)
先来建立数据库表City,它包含两个字段CityID,CityName。
1 CREATE TABLE City 2 ( 3 CityID INT IDENTITY(1,1) Primary KEY , --城市主键 4 CityName NVARCHAR(50) NOT NULL, --城市名称 5 )
然后再插入一些示例数据
1 INSERT City(CityName) Values('北京市') 2 INSERT City(CityName) Values('天津市') 3 INSERT City(CityName) Values('上海市') 4 INSERT City(CityName) Values('重庆市') 5 INSERT City(CityName) Values('邯郸市') 6 INSERT City(CityName) Values('石家庄市') 7 INSERT City(CityName) Values('保定市') 8 INSERT City(CityName) Values('张家口市') 9 INSERT City(CityName) Values('承德市') 10 INSERT City(CityName) Values('唐山市') 11 //省略...
从表结构及示例数据来看,这里没有城市名称拼音首字母字段,那如何完成拼音搜索呢?不要着急,这得在数据库中建立一个函数,用来返回汉字的拼音首字母。
返回汉字拼音首字母函数 f_GetPy [注1]
1 create function f_GetPy(@str nvarchar(4000)) 2 returns nvarchar(4000) 3 as 4 begin 5 declare @strlen int,@re nvarchar(4000) 6 declare @t table(chr nchar(1) collate Chinese_PRC_CI_AS,letter nchar(1)) 7 insert into @t(chr,letter) 8 select '吖', 'A ' union all select '八', 'B ' union all 9 select '嚓', 'C ' union all select '咑', 'D ' union all 10 select '妸', 'E ' union all select '发', 'F ' union all 11 select '旮', 'G ' union all select '铪', 'H ' union all 12 select '丌', 'J ' union all select '咔', 'K ' union all 13 select '垃', 'L ' union all select '嘸', 'M ' union all 14 select '拏', 'N ' union all select '噢', 'O ' union all 15 select '妑', 'P ' union all select '七', 'Q ' union all 16 select '呥', 'R ' union all select '仨', 'S ' union all 17 select '他', 'T ' union all select '屲', 'W ' union all 18 select '夕', 'X ' union all select '丫', 'Y ' union all 19 select '帀', 'Z ' 20 select @strlen=len(@str),@re= ' ' 21 while @strlen> 0 22 begin 23 select top 1 @re=letter+@re,@strlen=@strlen-1 24 from @t a where chr <=substring(@str,@strlen,1) 25 order by chr desc 26 if @@rowcount=0 27 select @re=substring(@str,@strlen,1)+@re,@strlen=@strlen-1 28 end 29 return(@re) 30 end
如果调用f_GetPy('北京'),则返回拼音首字母 'bj'
Step 2 前端页面
前端页面非常简单,只需要一个输入框就可以了。这里使用的Struts2 html标签。当然,你也可以使用原生html标签。
1 <s:textfield name="cityName" id="cityName"></s:textfield>
cityName的值提交到服务器,作为搜索关键字。为了实现Ajax智能提示,需要用到JQuery UI AutoComplete插件,它要求返回JSON格式的数据。所以,下一步就是要在Action中返回JSON数据。
Step 3 Action
CityAction接收搜索关键字,并返回JSON数据。
1 package com.dong.action; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import org.apache.struts2.json.annotations.JSON; 6 import com.dong.po.City; 7 import com.dong.service.ICityService; 8 import com.opensymphony.xwork2.ActionSupport; 9 10 /** 11 * 城市搜索Action 12 * @version 1.0 2013/01/12 13 * @author dongliyang 14 * 15 */ 16 public class CityAction extends ActionSupport{ 17 18 /** SerialVersionUID*/ 19 private static final long serialVersionUID = -8042695641942800870L; 20 /** 城市Service */ 21 private ICityService cityService; 22 /** 搜索关键字,城市名称 */ 23 private String cityName; 24 /** 城市列表 */ 25 private List<City> cityList; 26 /** 智能提示列表,以JSON数据格式返回 */ 27 private List<String> autoSuggests = new ArrayList<String>(); 28 29 /** 30 * 智能提示,自动补全功能 31 * @return String 32 */ 33 public String autoComplete(){ 34 35 cityList = cityService.findByName(cityName); 36 37 for(City city : cityList){ 38 autoSuggests.add(city.getCityName()); 39 } 40 41 return SUCCESS; 42 } 43 44 public void setCityService(ICityService cityService) { 45 this.cityService = cityService; 46 } 47 48 //搜索关键字不作为JSON数据返回,设置serialize=false 49 @JSON(serialize=false) 50 public String getCityName() { 51 return cityName; 52 } 53 54 public void setCityName(String cityName) { 55 this.cityName = cityName; 56 } 57 58 //搜索结果列表不作为JSON数据返回,设置serialize=false 59 @JSON(serialize=false) 60 public List<City> getCityList() { 61 return cityList; 62 } 63 64 public void setCityList(List<City> cityList) { 65 this.cityList = cityList; 66 } 67 68 //智能提示列表作为JSON数据返回,设置serialize=true 69 @JSON(serialize=true) 70 public List<String> getAutoSuggests() { 71 return autoSuggests; 72 } 73 74 public void setAutoSuggests(List<String> autoSuggests) { 75 this.autoSuggests = autoSuggests; 76 } 77 }
CityAction中,cityName接收搜索关键字,不需要向页面返回数据,因此需要设置serialize=false,不进行序列化。
Action返回的JSON数据,格式是这样的 {"autoSuggests":["北京市","毕节地区","宝鸡市"]}
由于CityAction返回的是JSON数据,因此需要在struts.xml中进行一些特殊配置,Action所在包需要继承自json-default。
struts.xml配置文件
<package name="search" namespace="/search" extends="json-default"> <action name="cityAction" class="cityAction"> <result name="success" type="json"></result> </action> </package>
CityAction依靠CityService返回城市列表,Service层没有什么可介绍的,只是简单调用了一下Dao层。重点看一下Dao层是如何实现搜索的。
CityDaoImpl
1 package com.dong.dao.impl; 2 3 import java.util.List; 4 5 import com.dong.dao.ICityDao; 6 import com.dong.framework.BaseDao; 7 import com.dong.po.City; 8 9 public class CityDaoImpl extends BaseDao<City> implements ICityDao { 10 11 /** 12 * 根据名称或拼音搜索城市 13 * @param cityName 14 * @return List<City> 城市列表 15 */ 16 public List<City> findByName(String cityName){ 17 18 String hql = "from City c where c.cityName like ? or dbo.f_GetPy(c.cityName) like ?"; 19 return find(hql, "%" + cityName + "%",cityName + "%"); 20 21 } 22 23 }
hql语句中,使用cityName和f_GetPy(cityName) 来跟关键字进行like匹配。
比如:汉字搜索时,关键字"北京"传入方法,hql where子句中的c.cityName将能够匹配。
拼音搜索时,关键字"BJ"传入方法,hql where子句中的dbo.f_GetPy(c.cityName)将能够匹配。
特别说明:Hibernate有一些内置函数,比如max、min,Hibernate能够将这些函数转换成对应数据库的函数。当不能识别函数名时(本例中f_GetPy),将交给底层数据库来处理。
到现在为止,数据库已经能够正确返回JSON数据了。应该集成JQuery UI AutoComplete了。
Step 4 JQuery UI AutoComplete
Search.jsp页面如下
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%@ taglib uri="/struts-tags" prefix="s" %> 3 <% 4 String path = request.getContextPath(); 5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 6 %> 7 8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 9 <html> 10 <head> 11 <base href="<%=basePath%>"> 12 <title>城市搜索页</title> 13 <link rel="stylesheet" href="css/jquery-ui.css" /> 14 <script type="text/javascript" src="js/jquery-1.8.3.js"></script> 15 <script type="text/javascript" src="js/jquery-ui-1.9.2.custom.js"></script> 16 <style type="text/css"> 17 body { text-align:center;background:#efefef;} 18 h2 { color:#676463;} 19 #cityDiv { margin-right:auto;margin-left:auto;} 20 #cityName 21 { 22 font-family: Verdana,Arial,sans-serif; 23 font-size: 1.1em; 24 } 25 </style> 26 <script type="text/javascript"> 27 $(function(){ 28 $("#cityName").autocomplete({ 29 minLength:1, 30 autoFocus:true, 31 source:function(request,response){ 32 $.ajax({ 33 type:"POST", 34 url:"search/cityAction!autoComplete.action", 35 dataType:"json", 36 data:{ cityName : $("#cityName").val() }, 37 success:function(json){ 38 response($.map(json.autoSuggests,function(item){ 39 return { 40 label:item, 41 value:item 42 }; 43 })); 44 } 45 }); 46 } 47 }); 48 }); 49 </script> 50 </head> 51 <body> 52 <h2>JQuery UI AutoComplete + Struts2 智能提示</h2> 53 <div id="cityDiv"> 54 <div id="noteDiv"> 55 <img alt="where are you from?" src="images/searchMap.png"> 56 </div> 57 <s:textfield name="cityName" id="cityName"></s:textfield> 58 </div> 59 </body> 60 </html>
首先,引入css、js文件。
其次,在输入框元素上调用autocomplete方法。minLength指定文本框中有多少个字符时,发送请求。autoFocus:true,选中第一个匹配结果。source指定数据来源。JQuery UI Autocomplete插件需要返回带有label和value的对象。success函数的参数json是服务器端传过来的数据,比如是{"autoSuggests":["北京市","毕节地区","宝鸡市"]},因此,使用$.map处理的时候,应该定位到json.autoSuggests。item就是"北京市"、"毕节地区"、"宝鸡市"。
结束:本示例使用了SSH + JQuery UI AutoComplete完成了智能提示效果,限于篇幅,Hibernate、Spring略去不提。下面提供了示例程序的下载,包括数据库脚本及可运行的程序。为了在你的机器上运行,请修改hibernate.properties文件,填写正确的数据库用户名及密码。
下载:百度网盘 (大小:17.97MB)
注1:获取汉字拼音首字母的函数,来自:http://www.cnblogs.com/wuhuacong/archive/2010/01/25/1655916.html。