簡介
Ajax有人形容為“新瓶里的老酒”,這一點也不為過,這里就不多介紹了。在這技術日新月異的世界里,真是不g不知道,一g嚇一跳。給大家推薦一個實惠的:http://www.aygfsteel.com/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 怎么實現;