`
zhangljerry
  • 浏览: 144437 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

struts ajax

阅读更多
转贴请保留作者--简单就好,和出处。谢谢!
去年初,正好负责一个医药信息系统的设计开发,架构设计时,采用Struts+JDBC(自定义采用适配器模式封装了HashMap动态VO实现的持久层)。后来ajax热潮兴起,正好系统中有很多地方需要和服务器端交互数据,如采购销售系统中的订单头/订单明细等主从表结构的维护。
数据交互过程,我们考虑采用xml来组织数据结构,更新/保存:前台封装需要的xml,通过ajax提交---〉action解析xml ---〉改造原有的持久层实现xml持久化;
查询时:持久层根据实际需要返回xml,document对象,---〉action 处理 --〉前台自己封装js库来解析xml,并刷新部分页面。

ajax:已经有很多方法实现跨浏览器的方式,这里只介绍最简单的方式,同步模式下提交xmlStr给action(*.do)。


代码
/**  
* 将数据同步传递给后台请求url  
*  @return 返回xmlhttp 响应的信息  
*  @param-url = '/web/module/xxx.do?p1=YY&p2=RR';  
*  @param-xmlStr:xml格式的字符串 <data><xpath><![CDATA[数据信息]]></xpath></data> 
* @author zhipingch  
* @date 2005-03-17  
*/  
function sendData(urlStr, xmlStr) {  
    var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");  
    xmlhttp.open("POST", urlStr, false);  
    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
    if (xmlStr) {  
        xmlhttp.send(xmlStr);  
    } else {  
        xmlhttp.send();  
    }  
    return xmlhttp.responseXml;  



struts中我们扩展了Action,实现了xmlStr转化成document对象(dom4j),并且完善了转发方式。如


引用

1.DispatchAction
以一个Controller响应一组动作绝对是Controller界的真理,Struts的DispatchAction同样可以做到这点。



<action path="/admin/user" name="userForm" scope="request" parameter="method" validate="false">
<forward name="list" path="/admin/userList.jsp"/>
</action>


其中parameter="method" 设置了用来指定响应方法名的url参数名为method,即/admin/user.do?method=list 将调用UserAction的public ActionForward list(....) 函数。

public ActionForward unspecified(....) 函数可以指定不带method方法时的默认方法。


但是这样需要在url后多传递参数method=list ;并且action节点配置中的parameter="method"
也没有被充分利用,反而觉得是累赘!

因此我们直接在BaseDispatchAction中增加xml字符串解析,并充分利用action节点配置中的parameter="targetMethod" ,使得转发的时候,action能够直接转发到子类的相应方法中,减少了url参数传递,增强了配置信息可读性,方便团队开发。
同样以上述为例,扩展后的配置方式如下:


引用

<action path="/admin/user" scope="request" parameter="list" validate="false">
<forward name="list" path="/admin/userList.jsp"/>
</action>


其中parameter="list" 设置了用来指定响应url=/admin/user.do的方法名,它将调用UserAction的public ActionForward list(....) 函数。
BaseDispatchDocumentAction 的代码如下,它做了三件重要的事情:
1、采用dom4j直接解析xml字符串,并返回document,如果没有提交xml数据,或者采用form形式提交的话,返回null;
2、采用模版方法处理系统异常,减少了子类中无尽的try{...}catch(){...};其中异常处理部分另作描述(你可以暂时去掉异常处理,实现xml提交和解析,如果你有兴趣,我们可以进一步交流);
3、提供了Spring配置Bean的直接调用,虽然她没有注入那么优雅,但是实现了ajax、struts、spring的结合。
BaseDispatchDocumentAction 的源码如下:

代码
package com.ufida.haisheng.struts;  
 
import java.io.IOException;  
import java.io.PrintWriter;  
import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
import java.math.BigDecimal;  
import java.sql.Timestamp;  
import java.util.Date;  
import java.util.HashMap;  
 
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import javax.servlet.http.HttpSession;  
 
import org.apache.commons.beanutils.ConvertUtils;  
import org.apache.commons.beanutils.converters.BigDecimalConverter;  
import org.apache.commons.beanutils.converters.ClassConverter;  
import org.apache.commons.beanutils.converters.IntegerConverter;  
import org.apache.commons.beanutils.converters.LongConverter;  
import org.apache.log4j.Logger;  
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.apache.struts.util.MessageResources;  
import org.dom4j.Document;  
import org.dom4j.io.SAXReader;  
import org.hibernate.HibernateException;  
import org.springframework.beans.BeansException;  
import org.springframework.context.ApplicationContext;  
import org.springframework.dao.DataAccessException;  
import org.springframework.web.context.support.WebApplicationContextUtils;  
 
import com.ufida.haisheng.constants.Globals;  
import com.ufida.haisheng.converter.DateConverter;  
import com.ufida.haisheng.converter.TimestampConverter;  
import com.ufida.haisheng.exp.ExceptionDTO;  
import com.ufida.haisheng.exp.ExceptionDisplayDTO;  
import com.ufida.haisheng.exp.exceptionhandler.ExceptionHandlerFactory;  
import com.ufida.haisheng.exp.exceptionhandler.ExceptionUtil;  
import com.ufida.haisheng.exp.exceptionhandler.IExceptionHandler;  
import com.ufida.haisheng.exp.exceptions.BaseAppException;  
import com.ufida.haisheng.exp.exceptions.MappingConfigException;  
import com.ufida.haisheng.exp.exceptions.NoSuchBeanConfigException;  
 
/**  
* 系统的Ajax转发基类。增加模版处理异常信息。  
*   
* @author   
* @desc BaseDispatchDocumentAction.java  
*   
* @说明: web 应用基础平台  
* @date 2005-03-02 11:18:01 AM  
* @版权所有: All Right Reserved 2006-2008  
*/  
public abstract class BaseDispatchDocumentAction extends Action {  
 
    protected Class clazz = this.getClass();  
 
    protected static Logger log = Logger.getLogger(BaseDispatchDocumentAction.class);  
 
    /**  
     * 异常信息  
     */  
    protected static ThreadLocal<ExceptionDisplayDTO> expDisplayDetails = new ThreadLocal<ExceptionDisplayDTO>();  
      
    private static final Long defaultLong = null;  
 
    private static ApplicationContext ctx = null;  
    /**  
     * 注册转换的工具类 使得From中的string --  
     * Model中的对应的类型(Date,BigDecimal,Timestamp,Double...)  
     */  
    static {  
        ConvertUtils.register(new ClassConverter(), Double.class);  
        ConvertUtils.register(new DateConverter(), Date.class);  
        ConvertUtils.register(new DateConverter(), String.class);  
        ConvertUtils.register(new LongConverter(defaultLong), Long.class);  
        ConvertUtils.register(new IntegerConverter(defaultLong), Integer.class);  
        ConvertUtils.register(new TimestampConverter(), Timestamp.class);  
        ConvertUtils.register(new BigDecimalConverter(defaultLong), BigDecimal.class);  
    }  
 
    /**  
     * The message resources for this package.  
     */  
    protected static MessageResources messages = MessageResources.getMessageResources("org.apache.struts.actions.LocalStrings");  
 
    /**  
     * The set of Method objects we have introspected for this class, keyed by  
     * method name. This collection is populated as different methods are  
     * called, so that introspection needs to occur only once per method name.  
     */  
    protected HashMap<String, Method> methods = new HashMap<String, Method>();  
 
    /**  
     * The set of argument type classes for the reflected method call. These are  
     * the same for all calls, so calculate them only once.  
     */  
    protected Class[] types = { ActionMapping.class, ActionForm.class, Document.class, HttpServletRequest.class,  
            HttpServletResponse.class };  
 
    /**  
     * Process the specified HTTP request, and create the corresponding HTTP  
     * response (or forward to another web component that will create it).  
     * Return an <code>ActionForward</code> instance describing where and how  
     * control should be forwarded, or <code>null</code> if the response has  
     * already been completed.  
     *   
     * @param mapping  
     *            The ActionMapping used to select this instance  
     * @param form  
     *            The optional ActionForm bean for this request (if any)  
     * @param request  
     *            The HTTP request we are processing  
     * @param response  
     *            The HTTP response we are creating  
     *   
     * @exception Exception  
     *                if an exception occurs  
     */  
    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,  
            HttpServletResponse response) throws Exception {  
        response.setContentType("text/html; charset=UTF-8");  
        ExceptionDisplayDTO expDTO = null;  
        try {  
            Document doc = createDocumentFromRequest(request);  
            /*  
             * 这里直接调用mapping的parameter配置  
             */  
            String actionMethod = mapping.getParameter();  
            /*  
             * 校验配置的方法是否正确、有效  
             */  
            isValidMethod(actionMethod);  
 
            return dispatchMethod(mapping, form, doc, request, response, actionMethod);  
        } catch (BaseAppException ex) {  
            expDTO = handlerException(request, response, ex);  
        } catch (Exception ex) {  
            ExceptionUtil.logException(this.getClass(), ex);  
            renderText(response,"[Error :对不起,系统出现错误了,请向管理员报告以下异常信息.\n" + ex.getMessage() + "]");  
            request.setAttribute(Globals.ERRORMSG, "对不起,系统出现错误了,请向管理员报告以下异常信息.\n" + ex.getMessage());  
            expDTO = handlerException(request,response, ex);  
        } finally {  
            expDisplayDetails.set(null);  
        }  
        return null == expDTO ? null : (expDTO.getActionForwardName() == null ? null : mapping.findForward(expDTO.getActionForwardName()));  
    }  
 
    /**  
     * 直接输出纯字符串  
     */  
    public void renderText(HttpServletResponse response, String text) {  
        PrintWriter out = null;  
        try {  
            out = response.getWriter();  
            response.setContentType("text/plain;charset=UTF-8");  
            out.write(text);  
        } catch (IOException e) {  
            log.error(e);  
        } finally {  
            if (out != null) {  
                out.flush();  
                out.close();  
                out = null;  
            }  
        }  
    }  
      
    /**  
     * 直接输出纯HTML  
     */  
    public void renderHtml(HttpServletResponse response, String text) {  
        PrintWriter out = null;  
        try {  
            out = response.getWriter();  
            response.setContentType("text/html;charset=UTF-8");  
            out.write(text);  
        } catch (IOException e) {  
            log.error(e);  
        } finally {  
            if (out != null) {  
                out.flush();  
                out.close();  
                out = null;  
            }  
        }  
    }  
 
    /**  
     * 直接输出纯XML  
     */  
    public void renderXML(HttpServletResponse response, String text) {  
        PrintWriter out = null;  
        try {  
            out = response.getWriter();  
            response.setContentType("text/xml;charset=UTF-8");  
            out.write(text);  
        } catch (IOException e) {  
            log.error(e);  
        } finally {  
            if (out != null) {  
                out.flush();  
                out.close();  
                out = null;  
            }  
        }  
    }  
 
    /**  
     * 异常处理  
     * @param request  
     * @param out  
     * @param ex  
     * @return ExceptionDisplayDTO异常描述对象  
     */  
    private ExceptionDisplayDTO handlerException(HttpServletRequest request,HttpServletResponse response, Exception ex) {  
        ExceptionDisplayDTO expDTO = (ExceptionDisplayDTO) expDisplayDetails.get();  
        if (null == expDTO) {             
            expDTO = new ExceptionDisplayDTO(null,this.getClass().getName());  
        }  
        IExceptionHandler expHandler = ExceptionHandlerFactory.getInstance().create();  
        ExceptionDTO exDto = expHandler.handleException(expDTO.getContext(), ex);  
        request.setAttribute("ExceptionDTO", exDto);  
        renderText(response,"[Error:" + (exDto == null ? "ExceptionDTO is null,请检查expinfo.xml配置文件." : exDto.getMessageCode())  
                + "]");  
        return expDTO;  
    }  
 
    private void isValidMethod(String actionMethod) throws MappingConfigException {  
        if (actionMethod == null || "execute".equals(actionMethod) || "perform".equals(actionMethod)) {  
            log.error("[BaseDispatchAction->error] parameter = " + actionMethod);  
            expDisplayDetails.set(new ExceptionDisplayDTO(null, "MappingConfigException"));  
            throw new MappingConfigException("对不起,配置的方法名不能为 " + actionMethod);  
        }  
    }  
 
  /**  
     * 解析xml流  
     * @param request  
     * @return Document对象  
     */  
    protected static Document createDocumentFromRequest(HttpServletRequest request) throws Exception {  
        try {  
            request.setCharacterEncoding("UTF-8");  
            Document document = null;  
            SAXReader reader = new SAXReader();  
            document = reader.read(request.getInputStream());  
            return document;  
        } catch (Exception ex) {  
            log.warn("TIPS:没有提交获取XML格式数据流! ");  
            return null;  
        }  
    }  
 
    /**  
     * Dispatch to the specified method.  
     *   
     * @since Struts 1.1  
     */  
    protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, Document doc,HttpServletRequest request, HttpServletResponse response, String name) throws Exception {  
        Method method = null;  
        try {  
            method = getMethod(name);  
        } catch (NoSuchMethodException e) {  
            String message = messages.getMessage("dispatch.method", mapping.getPath(), name);  
            log.error(message, e);  
            expDisplayDetails.set(new ExceptionDisplayDTO(null, "MappingConfigException"));  
            throw new MappingConfigException(message, e);  
        }  
 
        ActionForward forward = null;  
        try {  
            Object args[] = { mapping, form, doc, request, response };  
            log.debug("[execute-begin] -> " + mapping.getPath() + "->[" + clazz.getName() + "->" + name + "]");  
            forward = (ActionForward) method.invoke(this, args);  
            log.debug(" [execute-end] -> " + (null == forward ? "use ajax send to html/htm" : forward.getPath()));  
        } catch (ClassCastException e) {  
            String message = messages.getMessage("dispatch.return", mapping.getPath(), name);  
            log.error(message, e);  
            throw new BaseAppException(message, e);  
 
        } catch (IllegalAccessException e) {  
            String message = messages.getMessage("dispatch.error", mapping.getPath(), name);  
            log.error(message, e);  
            throw new BaseAppException(message, e);  
 
        } catch (InvocationTargetException e) {  
            Throwable t = e.getTargetException();  
            String message = messages.getMessage("dispatch.error", mapping.getPath(), name);  
            throw new BaseAppException(message, t);  
        }  
 
        return (forward);  
    }  
 
    /**  
     * Introspect the current class to identify a method of the specified name  
     * that accepts the same parameter types as the <code>execute</code> 
     * method does.  
     *   
     * @param name  
     *            Name of the method to be introspected  
     *   
     * @exception NoSuchMethodException  
     *                if no such method can be found  
     */  
    protected Method getMethod(String name) throws NoSuchMethodException {  
        synchronized (methods) {  
            Method method = (Method) methods.get(name);  
            if (method == null) {  
                method = clazz.getMethod(name, types);  
                methods.put(name, method);  
            }  
            return (method);  
        }  
    }  
 
  /**  
   * 返回spring bean对象  
   * @param name Spring Bean的名称  
   * @exception BaseAppException  
   */  
    protected Object getSpringBean(String name) throws BaseAppException {  
        if (ctx == null) {  
            ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());  
        }  
        Object bean = null;  
        try {  
            bean = ctx.getBean(name);  
        } catch (BeansException ex) {  
            throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!", ex.getRootCause());  
        }  
        if (null == bean) {  
            throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!");  
        }  
        return bean;  
    }  
}  


开发人员只需要继承它就可以了,我们写个简单的示例action,如下:

代码
/** 
* 带Ajax提交xml数据的action类模版 
*  
* @author 陈志平 chenzp 
*  
* @说明: web 应用基础平台 
* @date Aug 1, 2006 10:52:13 AM 
* @版权所有: All Right Reserved 2006-2008 
*/ 
public class UserAction extends BaseDispatchDocumentAction {  
         /** 
          * 这里 actionForm 和 doc 参数必有一个为空,请聪明的你分析一下 
          * @param mapping --转发的映射对象 
          <span style="color:blue;">* @param actionForm --仍然支持表单提交,此时doc == null 
          * @param doc document对象,解析xml后的文档对象</span> 
          * @param request --请求 
          * @param response --响应 
          */ 
    public ActionForward list(ActionMapping mapping, ActionForm actionForm, <span style="color:red;">Document doc</span>,HttpServletRequest request, HttpServletResponse response) throws BaseAppException {  
        /** 
         * 转发的名称 userAction.search: 系统上下文 用于异常处理 
         */ 
        expDisplayDetails.set(new ExceptionDisplayDTO(null, "userAction.search"));  
        /** 
         * 处理业务逻辑部分: 
         *  
         * 获取各种类型的参数 RequestUtil.getStrParameter(request,"ParameterName"); 
         *  
         * 调用父类的 getSpringBean("serviceID")方法获取spring的配置bean 
         *  
         */ 
        UserManager userManager = (LogManager) getSpringBean("userManager");  
        //返回xml对象到前台  
        renderXML(response, userManager.findUsersByDoc(doc));       return null;  
    }  


至此,我们成功实现了ajax--struts--spring的无缝结合。欢迎大家拍砖!
分享到:
评论
1 楼 日头的影子 2008-07-08  
虽然不是我想要的,但对作者的劳动表示尊敬,以后有机会在仔细阅读,相信一定会有所收获,感谢!加油

相关推荐

    struts-ajax.rar_ajax struts _struts ajax_struts ajax war

    标题"struts-ajax.rar_ajax struts _struts ajax_struts ajax war"暗示了这是一个关于如何在Struts框架中集成Ajax技术的示例项目。这个项目可能包含了完成这种集成所需的配置文件、Java源代码、JSP页面等资源,帮助...

    Struts AJAX文件上传

    Struts AJAX 文件上传是一种在Java Web开发中实现异步数据传输的技术,它结合了Struts框架和AJAX(Asynchronous JavaScript and XML)的优势,提供了一种用户友好的、无刷新的文件上传方式。这种方式可以显著提升...

    extjs最全项目 js struts Ajax

    **标题详解:** "extjs最全项目 js struts Ajax" 这个标题暗示了这是一个综合性的IT项目,主要涉及EXTJS框架、JavaScript(js)、Struts框架以及Ajax技术。EXTJS是一个用于构建用户界面的前端JavaScript库,它提供...

    Struts ajax

    Struts AJAX 是一个基于 Apache Struts 框架与 AJAX 技术的示例项目,展示了如何在 Struts 应用程序中实现异步数据交换和页面更新。在这个项目中,我们可以看到各种文件,包括 HTML、JSP、JSTL 和 XSL 文件,它们...

    spring hibernate struts ajax整合项目源代码

    整合的四大框架项目 spring hibernate struts ajax整合项目源代码 spring hibernate struts ajax整合项目源代码

    struts-ajax.zip_ajax struts _javascript_struts ajax_struts-aj_ti

    Struts和Ajax是两种在Web应用开发中广泛使用的技术,它们各自有其独特的优势和应用场景。结合使用,可以实现更高效、用户体验更好的交互式Web应用。在这个名为"struts-ajax.zip"的压缩包中,我们可以推测它包含了...

    struts2+jquery+ajax文件异步上传

    Struts2、jQuery和Ajax是Web开发中的三个关键组件,它们共同构成了文件异步上传的基础框架。这个项目是在MyEclipse环境下实现的一个简单的文件上传功能,让我们深入了解一下这些技术及其在文件上传中的应用。 首先...

    聊天室管理系统(struts ajax)(update)

    对上次发布的"聊天室管理系统(struts ajax)"修正了个bug 本人花了一个多月的结晶,功能有聊天室/用户管理,公/私聊、表情、屏/解蔽讲话、踢人(管理员)、在线会员显示,聊天室介绍...

    Struts+ajax

    Struts和Ajax是两种在Web开发中常用的框架和技术,它们结合使用可以构建出高效、动态且用户友好的应用程序。在本篇文章中,我们将深入探讨Struts与Ajax的整合及其在增删查改(CRUD)操作中的应用。 首先,让我们...

    Struts2 ajax json使用介绍

    在Struts2中,我们可以利用Ajax和JSON来实现数据的异步交互。 **一、引入所需库** 首先,为了在Struts2中使用Ajax和JSON,我们需要引入以下库: 1. Struts2的核心库:`struts2-core.jar` 2. Struts2的JSON插件:`...

    Struts-Ajax整合案例

    Struts2.0和AJAX的整合是Web开发中常用的技术组合,主要用于构建动态、交互性强的Web应用程序。Struts2作为MVC框架,提供了一种组织应用逻辑和视图的有效方式,而AJAX(Asynchronous JavaScript and XML)则允许在不...

    struts ajax 彩色验证码

    Struts和Ajax是两种在Java Web开发中广泛使用的技术,它们在构建动态、交互式的用户界面方面发挥着关键作用。彩色验证码则是为了防止自动化程序(如机器人)进行恶意操作而设计的安全机制。在这个项目中,Struts框架...

    struts2 jqurey ajax简单实例

    在这个"struts2 jqurey ajax简单实例"中,我们将探讨如何将这三个技术结合,以实现一个动态且高效的Web应用。 首先,Struts2中的Action类是业务逻辑的核心。当你在页面上触发一个事件,比如点击一个按钮,这个事件...

    服装定制流程 struts ajax 服装定制流程

    在IT行业中,服装定制流程与技术的结合是一个有趣的话题,特别是在使用Struts、JSP和Ajax框架时。这里,我们将深入探讨如何利用这些技术来构建一个高效、用户友好的服装定制平台。 首先,Struts是一个Java开源框架...

    收集的超经典教程:spring hibernate struts ajax xml

    这些文件涵盖了Java Web开发中的几个核心框架和技术,包括Spring、Hibernate、Struts、Ajax以及XML。以下是关于这些技术的详细知识点: 1. **Spring**: Spring是一个全面的Java企业级应用开发框架,它提供了IOC...

    Struts2+ajax+json返回list.docx

    在Web开发中,Struts2、Ajax和JSON的结合使用能实现异步数据交互,提高用户体验。本实例展示了如何在Struts2框架下,通过Ajax发送请求获取JSON数据,并将数据返回到JSP页面,以填充下拉列表(`&lt;s:select/&gt;`标签)。 ...

    struts2ajax项目

    本项目"struts2ajax"是基于Struts2框架,利用jQuery库实现的Ajax功能示例。jQuery是一个轻量级的JavaScript库,它简化了DOM操作、事件处理以及Ajax交互,使得开发者更容易实现复杂的前端效果和交互。 首先,我们...

    Struts+Jquery+Ajax+Json应用实例

    Struts、jQuery、Ajax以及JSON是Web开发中的四个关键技术,它们在构建动态、交互式的Web应用程序中发挥着重要作用。下面将分别介绍这些技术的核心概念及其在实际应用中的结合使用。 **Struts框架**:Struts是Apache...

Global site tag (gtag.js) - Google Analytics