简介
Ajax有人形容为“新瓶里的老酒”,这一点也不为过,这里就不多介绍了。在这技术日新月异的世界里,真是不g不知道,一g吓一跳。给大家推荐一个实惠的:http://www.blogjava.net/eamoi。
AjaxTags是一个开源的项目,目前进展你自己看吧:http://ajaxtags.sourceforge.net/,里面有源码、demo和doc。
背景
历史解决方法
1、
在父select元素的onChange事件中增加方法,调用action去填充子select元素。
2、
方法1 的改进,将两个或多个连动select元素放到一个iframe中。
3、
将父select元素和子select元素的内容,在页面初始化时装载到js的变量中,由父select元素的onChange事件直接调用js实现。
4、
方法3 的变形,将父select元素和子select元素的内容,写成独立的js。
历史方法缺点
方法
|
缺点
|
方法1
|
页面得全部刷新,须记住其他已填的内容
|
方法2
|
页面复杂,iframe得全部刷新
|
方法3
|
对于用户的每一次界面操作都得全部加载数据,资源浪费,代码繁多
|
方法4
|
数据库的字典表和js同步有很大问题,更新麻烦
|
我们的目的
1、
页面无需全部刷新;
2、
与字典表更新同步;
3、
减少网络传输资源损耗;
使用方法
准备工作
1、
从http://ajaxtags.sourceforge.net/上下载AjaxTags的最新版本,有源码、demo和doc。
2、
按照demo所示,拷贝资源文件:css、js和lib,还要注意WEB-INF 目录下的ajaxtags.tld。
开始使用
1、
在web.xml文件中加入
<taglib>
<taglib-uri>/WEB-INF/ajaxtags.tld</taglib-uri>
<taglib-location>/WEB-INF/ajaxtags.tld</taglib-location>
</taglib>
|
2、
如果你的连动会多处使用,就写成一个.inc文件,使用时就引进来:<%@ include file="/inc/fathertoson.inc"%>
<%@ page contentType="text/html;charset=GBK"%>
<!--ajax的标签库-->
<%@ taglib uri="/WEB-INF/ajaxtags.tld" prefix="ajax"%>
<!--ajax的css-->
<link href="css/ajaxtags.css" rel="stylesheet" type="text/css" />
<link href="css/displaytag.css" rel="stylesheet" type="text/css" />
<!--ajax的js-->
<script src="js/prototype-1.3.1.js"></script>
<script src="js/ajaxtags-1.1.5.js"></script>
<tr>
<td>父select</td>
<td>
<!—struts的标签-->
<html:select property="father" value="">
<html:option value=""> </html:option>
<html:options collection="fatherCollection" property="id" labelProperty="name" />
</html:select>
</td>
<td>子select</td>
<td>
<select name="son">
<option selected> </option>
</select>
</td>
</tr>
<!--父子连动-->
<ajax:select
baseUrl="fatherToSon.do"
source="father"
target="son"
parameters="fathername={father}" />
|
解释一下:
baseUrl 调用action的url;
source 父select
target 子select
parameters="fathername={father}" fathername为action中获得父select值的参数
3、
Action的写法
public class FatherToSonAction extends BaseAjaxAction {
public String getXmlContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 从界面获得父select的值,注意该处使用的是"fathername"而不是"father"
String selectValue = request.getParameter("fathername");
// 从数据库中得到子select的列表
ArrayList list = (ArrayList) ...;
// 子select的列表中的对象为子字典对象,具有"name", "id"属性
return new AjaxXmlBuilder().addItems(list, "name", "id").toString();
}
}
|
其中BaseAjaxAction和AjaxXmlBuilder可以参照ajax源码进行修改,修改后代码如下:
//================================ AjaxXmlBuilder======================
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
/**
* Helper class to build valid XML typically returned in a response to the client.
*
* 生成xml类型文件的帮助类,我们可以将xml文件放到response中返回给客户端
*
* @author Darren Spurgeon
* @version $Revision$ $Date$
*/
public class AjaxXmlBuilder {
private String encoding = "UTF-8";
private List items = new ArrayList();
public String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* Add item to XML.
*
* @param name
* The name of the item
* @param value
* The value of the item
* @return
*/
public AjaxXmlBuilder addItem(String name, String value) {
items.add(new Item(name, value, false));
return this;
}
/**
* Add item wrapped with inside a CDATA element.
*
* @param name
* The name of the item
* @param value
* The value of the item
* @return
*/
public AjaxXmlBuilder addItemAsCData(String name, String value) {
items.add(new Item(name, value, true));
return this;
}
/**
* Add items from a collection.
*
* @param collection
* @param nameProperty
* @param valueProperty
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public AjaxXmlBuilder addItems(Collection collection, String nameProperty,
String valueProperty) throws IllegalAccessException,
InvocationTargetException, NoSuchMethodException {
return addItems(collection, nameProperty, valueProperty, false);
}
/**
* Add items from a collection.
*
* @param collection
* @param nameProperty
* @param valueProperty
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public AjaxXmlBuilder addItems(Collection collection, String nameProperty,
String valueProperty, boolean asCData)
throws IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object element = (Object) iter.next();
String name = BeanUtils.getProperty(element, nameProperty);
String value = BeanUtils.getProperty(element, valueProperty);
if (asCData) {
items.add(new Item(name, value, false));
} else {
items.add(new Item(name, value, true));
}
}
return this;
}
/**
* Add items from a collection as CDATA element.
*
* @param collection
* @param nameProperty
* @param valueProperty
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public AjaxXmlBuilder addItemsAsCData(Collection collection,
String nameProperty, String valueProperty)
throws IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
return addItems(collection, nameProperty, valueProperty, true);
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer xml = new StringBuffer().append("<?xml version=/"1.0/"");
if (encoding != null) {
xml.append(" encoding=/"");
xml.append(encoding);
xml.append("/"");
}
xml.append(" ?>");
xml.append("<ajax-response>");
xml.append("<response>");
for (Iterator iter = items.iterator(); iter.hasNext();) {
Item item = (Item) iter.next();
xml.append("<item>");
xml.append("<name>");
if (item.isAsCData()) {
xml.append("<![CDATA[");
}
xml.append(item.getName());
if (item.isAsCData()) {
xml.append("]]>");
}
xml.append("</name>");
xml.append("<value>");
if (item.isAsCData()) {
xml.append("<![CDATA[");
}
xml.append(item.getValue());
if (item.isAsCData()) {
xml.append("]]>");
}
xml.append("</value>");
xml.append("</item>");
}
xml.append("</response>");
xml.append("</ajax-response>");
return xml.toString();
}
}
/**
* A generic item class, basically representing a name-value pair.
*
* 一个通用的item类,代表了一个name-value对
*
* @author Darren Spurgoen
* @version $Revision$ $Date$
*/
class Item {
private String name;
private String value;
private boolean asData;
/**
* Constructor for Item.
*/
public Item() {
super();
}
/**
* Constructor for Item.
*
* @param name
* @param value
*/
public Item(String name, String value, boolean asData) {
super();
this.name = name;
this.value = value;
this.asData = asData;
}
/**
* @return Returns the name.
*/
public String getName() {
return this.name;
}
/**
* @param name
* The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* @return Returns the value.
*/
public String getValue() {
return this.value;
}
/**
* @param value
* The value to set.
*/
public void setValue(String value) {
this.value = value;
}
/**
* @return Returns the asCData.
*/
public boolean isAsCData() {
return this.asData;
}
/**
* @param asData
* The asData to set.
*/
public void setAsData(boolean asData) {
this.asData = asData;
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
return new ToStringBuilder(this).append("name", name).append("value",
value).append("asData", asData).toString();
}
}
|
//========================== BaseAjaxAction==============================
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
/**
* Ajax应用的祖先抽象类,将xml文件类型数据放到响应流中
*
* @author luzhilin
*
*/
public abstract class BaseAjaxAction extends Action {
/**
* @see Action#execute(ActionMapping, ActionForm, HttpServletRequest,
* HttpServletResponse)
*/
public final ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String xml = null;
try {
xml = getXmlContent(mapping, form, request, response);
} catch (Exception ex) {
// Send back a 500 error code.
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Can not create response");
return null;
}
// Set content to xml
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintWriter pw = response.getWriter();
pw.write(xml);
pw.close();
return null;
}
/**
* Each child class should override this method to generate the specific XML
* content necessary for each AJAX action.
*
* 每一个子类都必须重写此方法,用于生成特定的xml文件数据流
*
* @param mapping
* @param form
* @param request
* the {@javax.servlet.http.HttpServletRequest} object
* @param response
* the {@javax.servlet.http.HttpServletResponse} object
* @return a {@java.lang.String} representation of the XML response/content
* @throws Exception
*/
public abstract String getXmlContent(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
|
进一步思考的问题
1、
多层连动怎么实现;
2、
多组连动,我们的
action
怎么实现;