在Struts中使用AjaxTags解决连动问题

简介
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="">&nbsp;</html:option>
            <html:options collection="fatherCollection" property="id" labelProperty="name" />
        </html:select>
    </td>
   
    <td>子select</td>
    <td>
        <select name="son">
            <option selected>&nbsp;</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 怎么实现;
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值