最近搞的一个通讯录想要加一个Ajax的自动完成功能,看起来功能虽小,可给用户的体验会改进不少。在一个介绍了几十种java的Ajax框架的网页里面,我找到了AjaxTags这个小东西,开始了我的第一次Ajax之旅。
从AjaxTags的官方网站上面http://ajaxtags.sourceforge.net/可以下载到其最新的版本,目前是AjaxTags1.3顺便下载了一个官方的小例子看了看,确实很好阿,例子中使用Ajax完成了11种功能,然而我需要的是自动完成(autocomplete)部分的代码,所以重点研究这一部分
jsp页面中,首先当然是要添加AjaxTags的标签支持,需要如下语句
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><%@ taglib uri="http://ajaxtags.org/tags/ajax" prefix="ajax"%>
然后在页面中加入如下的标签
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><ajax:autocomplete
source="model"//从控件"model"中获得输入的字符
target="make"//通过Ajax自动完成控件"make"的内容
baseUrl="${contextPath}/autocomplete.view"//Ajax执行时调用的请求路径
className="autocomplete"//css类名
indicator="indicator"
minimumCharacters="1"//Ajax执行需要输入的最小字符数
/>
在官方的例子中使用的是Servlet来完成Ajax,而对于使用struts就不适用了,后面说这个问题。
在 autocomplete.view对应的Servlet类中需要建立xml来供页面调取,代码如下
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public class AutocompleteServlet extends BaseAjaxServlet {
public String getXmlContent(HttpServletRequest request, HttpServletResponse response)
throws Exception {
String model = request.getParameter("model");//从页面获取控件"model"的输入值
CarService service = new CarService();
List<Car> list = service.getModelsByName(model);//调用CarService的方法获得汽车的List
// Create xml schema
return new AjaxXmlBuilder().addItems(list, "model", "make",true).toString();//生成xml
}
}
其实还是很简单的,接下来看CarService的代码吧,重点其实只有一段,然后在下面显示出自动提示,于是可以把刚才的那个ajax标签修改如下
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public class CarService {
private static List<Car> cars = new ArrayList<Car>();
static {
cars.add(new Car("Ford", "Escape"));
cars.add(new Car("Ford", "Expedition"));
cars.add(new Car("Ford", "Explorer"));
cars.add(new Car("Ford", "Focus"));
cars.add(new Car("Ford", "Mustang"));
cars.add(new Car("Ford", "Thunderbird"));
cars.add(new Car("Honda", "Accord"));
cars.add(new Car("Honda", "Civic"));
cars.add(new Car("Honda", "Element"));
cars.add(new Car("Honda", "Ridgeline"));
cars.add(new Car("Mazda", "Mazda 3"));
cars.add(new Car("Mazda", "Mazda 6"));
cars.add(new Car("Mazda", "RX-8"));
}//其实把上面这个地方改为数据库查询就可以从数据库中得到List来供页面显示
public CarService() {
super();
}
public List<Car> getModelsByMake(String make) {
.
}
public List<Car> getModelsByName(String name) {
..
}
public List<Car> getAllCars() {
return cars;
}
}
例子看完了,开始实际操作吧,在我的页面中,需要通过一个名为"name"的文本框输入要查询的人的姓名
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><ajax:autocomplete
source="name"
target="name"
baseUrl="ajaxfinduser.do"
className="autocomplete"
indicator="indicator"
minimumCharacters="1"
/>
接下来是我的Action,在写Action的时候,我以为只需要把原来Servlet继承的BaseAjaxServlet改为BaseAjaxAction就可以了,可后来才发现,jar包中根本就没有BaseAjaxAction这个类,无语,去官方网站上看了后才知道,在1.2更新到1.3的时候,把对Struts的支持去掉了,如果想支持Struts的话需要建立自己的BaseAjaxAction
(Struts removed, to use it create your own BaseAjaxAction.java and implement BaseAjaxXmlAction then just call xml = AjaxActionHelper.invoke(this, request, response);)
下载了一份AjaxTags的源码来看,原来AjaxActionHelper.invoke();这个方法需要调用Action中的getXmlContent方法来完成xml的写入,那就好说了,代码如下:
Code
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->package com.txl.action;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ajaxtags.servlets.BaseAjaxXmlAction;
import org.ajaxtags.xml.AjaxXmlBuilder;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.ajaxtags.servlets.AjaxActionHelper;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.txl.service.AjaxFindUserService;
import com.vo.User;
public class AjaxFindUserAction extends Action implements BaseAjaxXmlAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, Exception {
response.setCharacterEncoding("utf-8");
response.getOutputStream().print(new String(AjaxActionHelper.invoke(this, request, response).getBytes("UTF-8"),"ISO-8859-1"));//这里需要转换编码,不然无法支持中文查询
response.getOutputStream().flush();
return null;
}
public String getXmlContent(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String realname = request.getParameter("name");
ApplicationContext ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(servlet.getServletContext());//用ssh时需要在这里引入spring的配置文件,不然会在调用dao的时候报空指针异常
AjaxFindUserService service = (AjaxFindUserService) ctx
.getBean("AjaxFindUserService");
List<User> list = service.getUsersByRealname(realname);
return new AjaxXmlBuilder()
.addItems(list, "realname", "realname", true).toString();
}
}
剩下工作就是在struts-config.xml中配置对应的action,在spring中配置对应的bean就ok拉