空间站

北极心空

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

zhipingch 原创

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

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

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



    struts中我们扩展了Action,实现了xmlStr转化成document对象(dom4j),并且完善了转发方式。如
[quote]
1.DispatchAction
     以一个Controller响应一组动作绝对是Controller界的真理,Struts的DispatchAction同样可以做到这点。

[list]
<action path="/admin/user" name="userForm" scope="request" parameter="method" validate="false">
    <forward name="list" path="/admin/userList.jsp"/>
</action>
[/list]
    其中parameter="method" 设置了用来指定响应方法名的url参数名为method,即/admin/user.do?method=list 将调用UserAction的public ActionForward list(....) 函数。   

    public ActionForward unspecified(....) 函数可以指定不带method方法时的默认方法。[/quote]
    但是这样需要在url后多传递参数[size=18][color=red]method=list [/color][/size];并且action节点配置中的[color=red]parameter="method" [/color]
也没有被充分利用,反而觉得是累赘!

    因此我们直接在BaseDispatchAction中增加xml字符串解析,并充分利用action节点配置中的[color=red]parameter="targetMethod" [/color],使得转发的时候,action能够直接转发到子类的相应方法中,减少了url参数传递,增强了配置信息可读性,方便团队开发。
    同样以上述为例,扩展后的配置方式如下:
[quote]
<action path="/admin/user" scope="request" [color=red]parameter="list"[/color] validate="false">
    <forward name="list" path="/admin/userList.jsp"/>
</action>  
 [/quote]
    其中[color=red]parameter="list"[/color] 设置了用来指定响应url=/admin/user.do的方法名,它将调用UserAction的public ActionForward list(....) 函数。 
     BaseDispatchDocumentAction 的代码如下,它做了三件重要的事情:
     1、采用dom4j直接解析xml字符串,并返回document,如果没有提交xml数据,或者采用form形式提交的话,返回null;
     2、采用模版方法处理系统异常,减少了子类中无尽的try{...}catch(){...};其中异常处理部分另作描述(你可以暂时去掉异常处理,实现xml提交和解析,如果你有兴趣,我们可以进一步交流);

 

 

     3、提供了Spring配置Bean的直接调用,虽然她没有注入那么优雅,但是实现了ajaxstrutsspring的结合。
BaseDispatchDocumentAction 的源码如下:

  1. package com.ufida.haisheng.struts;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.math.BigDecimal;
  7. import java.sql.Timestamp;
  8. import java.util.Date;
  9. import java.util.HashMap;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import javax.servlet.http.HttpSession;
  13. import org.apache.commons.beanutils.ConvertUtils;
  14. import org.apache.commons.beanutils.converters.BigDecimalConverter;
  15. import org.apache.commons.beanutils.converters.ClassConverter;
  16. import org.apache.commons.beanutils.converters.IntegerConverter;
  17. import org.apache.commons.beanutils.converters.LongConverter;
  18. import org.apache.log4j.Logger;
  19. import org.apache.struts.action.Action;
  20. import org.apache.struts.action.ActionForm;
  21. import org.apache.struts.action.ActionForward;
  22. import org.apache.struts.action.ActionMapping;
  23. import org.apache.struts.util.MessageResources;
  24. import org.dom4j.Document;
  25. import org.dom4j.io.SAXReader;
  26. import org.hibernate.HibernateException;
  27. import org.springframework.beans.BeansException;
  28. import org.springframework.context.ApplicationContext;
  29. import org.springframework.dao.DataAccessException;
  30. import org.springframework.web.context.support.WebApplicationContextUtils;
  31. import com.ufida.haisheng.constants.Globals;
  32. import com.ufida.haisheng.converter.DateConverter;
  33. import com.ufida.haisheng.converter.TimestampConverter;
  34. import com.ufida.haisheng.exp.ExceptionDTO;
  35. import com.ufida.haisheng.exp.ExceptionDisplayDTO;
  36. import com.ufida.haisheng.exp.exceptionhandler.ExceptionHandlerFactory;
  37. import com.ufida.haisheng.exp.exceptionhandler.ExceptionUtil;
  38. import com.ufida.haisheng.exp.exceptionhandler.IExceptionHandler;
  39. import com.ufida.haisheng.exp.exceptions.BaseAppException;
  40. import com.ufida.haisheng.exp.exceptions.MappingConfigException;
  41. import com.ufida.haisheng.exp.exceptions.NoSuchBeanConfigException;
  42. /**
  43.  * 系统的Ajax转发基类。增加模版处理异常信息。
  44.  * 
  45.  * @author 陈志平 chenzp
  46.  * @desc BaseDispatchDocumentAction.java
  47.  * 
  48.  * @说明: web 应用基础平台
  49.  * @date 2005-03-02 11:18:01 AM
  50.  * @版权所有: All Right Reserved 2006-2008
  51.  */
  52. public abstract class BaseDispatchDocumentAction extends Action {
  53.     protected Class clazz = this.getClass();
  54.     protected static Logger log = Logger.getLogger(BaseDispatchDocumentAction.class);
  55.     /**
  56.      * 异常信息
  57.      */
  58.     protected static ThreadLocal<ExceptionDisplayDTO> 
    expDisplayDetails = new ThreadLocal<ExceptionDisplayDTO>();
  59.     
  60.     private static final Long defaultLong = null;
  61.     private static ApplicationContext ctx = null;
  62.     /**
  63.      * 注册转换的工具类 使得From中的string --
  64.      * Model中的对应的类型(Date,BigDecimal,Timestamp,Double...)
  65.      */
  66.     static {
  67.         ConvertUtils.register(new ClassConverter(), Double.class);
  68.         ConvertUtils.register(new DateConverter(), Date.class);
  69.         ConvertUtils.register(new DateConverter(), String.class);
  70.         ConvertUtils.register(new LongConverter(defaultLong), Long.class);
  71.         ConvertUtils.register(new IntegerConverter(defaultLong), Integer.class);
  72.         ConvertUtils.register(new TimestampConverter(), Timestamp.class);
  73.         ConvertUtils.register(new BigDecimalConverter(defaultLong), BigDecimal.class);
  74.     }
  75.     /**
  76.      * The message resources for this package.
  77.      */
  78.     protected static MessageResources messages = MessageResources.getMessageResources("org.apache.struts.actions.LocalStrings");
  79.     /**
  80.      * The set of Method objects we have introspected for this class, keyed by
  81.      * method name. This collection is populated as different methods are
  82.      * called, so that introspection needs to occur only once per method name.
  83.      */
  84.     protected HashMap<StringMethod> methods = new HashMap<StringMethod>();
  85.     /**
  86.      * The set of argument type classes for the reflected method call. These are
  87.      * the same for all calls, so calculate them only once.
  88.      */
  89.     protected Class[] types = { ActionMapping.class, ActionForm.classDocument.classHttpServletRequest.class,
  90.             HttpServletResponse.class };
  91.     /**
  92.      * Process the specified HTTP request, and create the corresponding HTTP
  93.      * response (or forward to another web component that will create it).
  94.      * Return an <code>ActionForward</code> instance describing where and how
  95.      * control should be forwarded, or <code>null</code> if the response has
  96.      * already been completed.
  97.      * 
  98.      * @param mapping
  99.      *            The ActionMapping used to select this instance
  100.      * @param form
  101.      *            The optional ActionForm bean for this request (if any)
  102.      * @param request
  103.      *            The HTTP request we are processing
  104.      * @param response
  105.      *            The HTTP response we are creating
  106.      * 
  107.      * @exception Exception
  108.      *                if an exception occurs
  109.      */
  110.     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
  111.             HttpServletResponse response) throws Exception {
  112.         response.setContentType("text/html; charset=UTF-8");
  113.         ExceptionDisplayDTO expDTO = null;
  114.         try {
  115.             Document doc = createDocumentFromRequest(request);
  116.             /*
  117.              * 这里直接调用mapping的parameter配置
  118.              */
  119.             String actionMethod = mapping.getParameter();
  120.             /*
  121.              * 校验配置的方法是否正确、有效
  122.              */
  123.             isValidMethod(actionMethod);
  124.             return dispatchMethod(mapping, form, doc, request, response, actionMethod);
  125.         } catch (BaseAppException ex) {
  126.             expDTO = handlerException(request, response, ex);
  127.         } catch (Exception ex) {
  128.             ExceptionUtil.logException(this.getClass(), ex);
  129.             renderText(response,"[Error :对不起,系统出现错误了,请向管理员报告以下异常信息." + ex.getMessage() + "]");
  130.             request.setAttribute(Globals.ERRORMSG, "对不起,系统出现错误了,请向管理员报告以下异常信息." + ex.getMessage());
  131.             expDTO = handlerException(request,response, ex);
  132.         } finally {
  133.             expDisplayDetails.set(null);
  134.         }
  135.         return null == expDTO ? null : (expDTO.getActionForwardName() == null ? null : mapping.findForward(expDTO.getActionForwardName()));
  136.     }
  137.     /**
  138.      * 直接输出纯字符串
  139.      */
  140.     public void renderText(HttpServletResponse response, String text) {
  141.         PrintWriter out = null;
  142.         try {
  143.             out = response.getWriter();
  144.             response.setContentType("text/plain;charset=UTF-8");
  145.             out.write(text);
  146.         } catch (IOException e) {
  147.             log.error(e);
  148.         } finally {
  149.             if (out != null) {
  150.                 out.flush();
  151.                 out.close();
  152.                 out = null;
  153.             }
  154.         }
  155.     }
  156.     
  157.     /**
  158.      * 直接输出纯HTML
  159.      */
  160.     public void renderHtml(HttpServletResponse response, String text) {
  161.         PrintWriter out = null;
  162.         try {
  163.             out = response.getWriter();
  164.             response.setContentType("text/html;charset=UTF-8");
  165.             out.write(text);
  166.         } catch (IOException e) {
  167.             log.error(e);
  168.         } finally {
  169.             if (out != null) {
  170.                 out.flush();
  171.                 out.close();
  172.                 out = null;
  173.             }
  174.         }
  175.     }
  176.     /**
  177.      * 直接输出纯XML
  178.      */
  179.     public void renderXML(HttpServletResponse response, String text) {
  180.         PrintWriter out = null;
  181.         try {
  182.             out = response.getWriter();
  183.             response.setContentType("text/xml;charset=UTF-8");
  184.             out.write(text);
  185.         } catch (IOException e) {
  186.             log.error(e);
  187.         } finally {
  188.             if (out != null) {
  189.                 out.flush();
  190.                 out.close();
  191.                 out = null;
  192.             }
  193.         }
  194.     }
  195.     /**
  196.      * 异常处理
  197.      * @param request
  198.      * @param out
  199.      * @param ex
  200.      * @return ExceptionDisplayDTO异常描述对象
  201.      */
  202.     private ExceptionDisplayDTO handlerException(HttpServletRequest request,HttpServletResponse response, Exception ex) {
  203.         ExceptionDisplayDTO expDTO = (ExceptionDisplayDTO) expDisplayDetails.get();
  204.         if (null == expDTO) {            
  205.             expDTO = new ExceptionDisplayDTO(null,this.getClass().getName());
  206.         }
  207.         IExceptionHandler expHandler = ExceptionHandlerFactory.getInstance().create();
  208.         ExceptionDTO exDto = expHandler.handleException(expDTO.getContext(), ex);
  209.         request.setAttribute("ExceptionDTO", exDto);
  210.         renderText(response,"[Error:" + (exDto == null ? "ExceptionDTO is null,请检查expinfo.xml配置文件." : exDto.getMessageCode())
  211.                 + "]");
  212.         return expDTO;
  213.     }
  214.     private void isValidMethod(String actionMethod) throws MappingConfigException {
  215.         if (actionMethod == null || "execute".equals(actionMethod) || "perform".equals(actionMethod)) {
  216.             log.error("[BaseDispatchAction->error] parameter = " + actionMethod);
  217.             expDisplayDetails.set(new ExceptionDisplayDTO(null"MappingConfigException"));
  218.             throw new MappingConfigException("对不起,配置的方法名不能为 " + actionMethod);
  219.         }
  220.     }
  221.   /**
  222.      * 解析xml
  223.      * @param request
  224.      * @return Document对象
  225.      */
  226.     protected static Document createDocumentFromRequest(HttpServletRequest request) throws Exception {
  227.         try {
  228.             request.setCharacterEncoding("UTF-8");
  229.             Document document = null;
  230.             SAXReader reader = new SAXReader();
  231.             document = reader.read(request.getInputStream());
  232.             return document;
  233.         } catch (Exception ex) {
  234.             log.warn("TIPS:没有提交获取XML格式数据流! ");
  235.             return null;
  236.         }
  237.     }
  238.     /**
  239.      * Dispatch to the specified method.
  240.      * 
  241.      * @since Struts 1.1
  242.      */
  243.     protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, Document doc,HttpServletRequest request, 
    HttpServletResponse response, String name) throws Exception {
  244.         Method method = null;
  245.         try {
  246.             method = getMethod(name);
  247.         } catch (NoSuchMethodException e) {
  248.             String message = messages.getMessage("dispatch.method", mapping.getPath(), name);
  249.             log.error(message, e);
  250.             expDisplayDetails.set(new ExceptionDisplayDTO(null"MappingConfigException"));
  251.             throw new MappingConfigException(message, e);
  252.         }
  253.         ActionForward forward = null;
  254.         try {
  255.             Object args[] = { mapping, form, doc, request, response };
  256.             log.debug("[execute-begin] -> " + mapping.getPath() + "->[" + clazz.getName() + "->" + name + "]");
  257.             forward = (ActionForward) method.invoke(this, args);
  258.             log.debug(" [execute-end] -> " + (null == forward ? "use ajax send to html/htm" : forward.getPath()));
  259.         } catch (ClassCastException e) {
  260.             String message = messages.getMessage("dispatch.return", mapping.getPath(), name);
  261.             log.error(message, e);
  262.             throw new BaseAppException(message, e);
  263.         } catch (IllegalAccessException e) {
  264.             String message = messages.getMessage("dispatch.error", mapping.getPath(), name);
  265.             log.error(message, e);
  266.             throw new BaseAppException(message, e);
  267.         } catch (InvocationTargetException e) {
  268.             Throwable t = e.getTargetException();
  269.             String message = messages.getMessage("dispatch.error", mapping.getPath(), name);
  270.             throw new BaseAppException(message, t);
  271.         }
  272.         return (forward);
  273.     }
  274.     /**
  275.      * Introspect the current class to identify a method of the specified name
  276.      * that accepts the same parameter types as the <code>execute</code>
  277.      * method does.
  278.      * 
  279.      * @param name
  280.      *            Name of the method to be introspected
  281.      * 
  282.      * @exception NoSuchMethodException
  283.      *                if no such method can be found
  284.      */
  285.     protected Method getMethod(String name) throws NoSuchMethodException {
  286.         synchronized (methods) {
  287.             Method method = (Method) methods.get(name);
  288.             if (method == null) {
  289.                 method = clazz.getMethod(name, types);
  290.                 methods.put(name, method);
  291.             }
  292.             return (method);
  293.         }
  294.     }
  295.   /**
  296.    * 返回spring bean对象
  297.    * @param name Spring Bean的名称
  298.    * @exception BaseAppException
  299.    */
  300.     protected Object getSpringBean(String name) throws BaseAppException {
  301.         if (ctx == null) {
  302.             ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());
  303.         }
  304.         Object bean = null;
  305.         try {
  306.             bean = ctx.getBean(name);
  307.         } catch (BeansException ex) {
  308.             throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!", ex.getRootCause());
  309.         }
  310.         if (null == bean) {
  311.             throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!");
  312.         }
  313.         return bean;
  314.     }
  315. }


 

 

 

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

  1. /**
  2.  * 带Ajax提交xml数据的action类模版
  3.  * 
  4.  * @author 陈志平 chenzp
  5.  * 
  6.  * @说明: web 应用基础平台
  7.  * @date Aug 1, 2006 10:52:13 AM
  8.  * @版权所有: All Right Reserved 2006-2008
  9.  */
  10. public class UserAction extends BaseDispatchDocumentAction {
  11.          /**
  12.           * 这里 actionForm 和 doc 参数必有一个为空,请聪明的你分析一下
  13.           * @param mapping --转发的映射对象
  14.           [color=blue]* @param actionForm --仍然支持表单提交,此时doc == null
  15.           * @param doc document对象,解析xml后的文档对象[/color]
  16.           * @param request --请求
  17.           * @param response --响应
  18.           */
  19.     public ActionForward list(ActionMapping mapping, ActionForm actionForm, [color=red]Document doc[/color],HttpServletRequest request, HttpServletResponse response) throws BaseAppException {
  20.         /**
  21.          * 转发的名称 userAction.search: 系统上下文 用于异常处理
  22.          */
  23.         expDisplayDetails.set(new ExceptionDisplayDTO(null"userAction.search"));
  24.         /**
  25.          * 处理业务逻辑部分:
  26.          * 
  27.          * 获取各种类型的参数 RequestUtil.getStrParameter(request,"ParameterName");
  28.          * 
  29.          * 调用父类的 getSpringBean("serviceID")方法获取spring的配置bean
  30.          * 
  31.          */
  32.         UserManager userManager = (LogManager) getSpringBean("userManager");
  33.         //返回xml对象到前台
  34.         renderXML(response, userManager.findUsersByDoc(doc));        
  35.                      return null;
  36.     }



至此,我们成功实现了ajax--struts--spring的无缝结合,下次介绍spring的开发应用。欢迎大家拍砖!

 

 

     3、提供了Spring配置Bean的直接调用,虽然她没有注入那么优雅,但是实现了ajaxstrutsspring的结合。
BaseDispatchDocumentAction 的源码如下:

  1. package com.ufida.haisheng.struts;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.math.BigDecimal;
  7. import java.sql.Timestamp;
  8. import java.util.Date;
  9. import java.util.HashMap;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import javax.servlet.http.HttpSession;
  13. import org.apache.commons.beanutils.ConvertUtils;
  14. import org.apache.commons.beanutils.converters.BigDecimalConverter;
  15. import org.apache.commons.beanutils.converters.ClassConverter;
  16. import org.apache.commons.beanutils.converters.IntegerConverter;
  17. import org.apache.commons.beanutils.converters.LongConverter;
  18. import org.apache.log4j.Logger;
  19. import org.apache.struts.action.Action;
  20. import org.apache.struts.action.ActionForm;
  21. import org.apache.struts.action.ActionForward;
  22. import org.apache.struts.action.ActionMapping;
  23. import org.apache.struts.util.MessageResources;
  24. import org.dom4j.Document;
  25. import org.dom4j.io.SAXReader;
  26. import org.hibernate.HibernateException;
  27. import org.springframework.beans.BeansException;
  28. import org.springframework.context.ApplicationContext;
  29. import org.springframework.dao.DataAccessException;
  30. import org.springframework.web.context.support.WebApplicationContextUtils;
  31. import com.ufida.haisheng.constants.Globals;
  32. import com.ufida.haisheng.converter.DateConverter;
  33. import com.ufida.haisheng.converter.TimestampConverter;
  34. import com.ufida.haisheng.exp.ExceptionDTO;
  35. import com.ufida.haisheng.exp.ExceptionDisplayDTO;
  36. import com.ufida.haisheng.exp.exceptionhandler.ExceptionHandlerFactory;
  37. import com.ufida.haisheng.exp.exceptionhandler.ExceptionUtil;
  38. import com.ufida.haisheng.exp.exceptionhandler.IExceptionHandler;
  39. import com.ufida.haisheng.exp.exceptions.BaseAppException;
  40. import com.ufida.haisheng.exp.exceptions.MappingConfigException;
  41. import com.ufida.haisheng.exp.exceptions.NoSuchBeanConfigException;
  42. /**
  43.  * 系统的Ajax转发基类。增加模版处理异常信息。
  44.  * 
  45.  * @author 陈志平 chenzp
  46.  * @desc BaseDispatchDocumentAction.java
  47.  * 
  48.  * @说明: web 应用基础平台
  49.  * @date 2005-03-02 11:18:01 AM
  50.  * @版权所有: All Right Reserved 2006-2008
  51.  */
  52. public abstract class BaseDispatchDocumentAction extends Action {
  53.     protected Class clazz = this.getClass();
  54.     protected static Logger log = Logger.getLogger(BaseDispatchDocumentAction.class);
  55.     /**
  56.      * 异常信息
  57.      */
  58.     protected static ThreadLocal<ExceptionDisplayDTO> 
    expDisplayDetails = new ThreadLocal<ExceptionDisplayDTO>();
  59.     
  60.     private static final Long defaultLong = null;
  61.     private static ApplicationContext ctx = null;
  62.     /**
  63.      * 注册转换的工具类 使得From中的string --
  64.      * Model中的对应的类型(Date,BigDecimal,Timestamp,Double...)
  65.      */
  66.     static {
  67.         ConvertUtils.register(new ClassConverter(), Double.class);
  68.         ConvertUtils.register(new DateConverter(), Date.class);
  69.         ConvertUtils.register(new DateConverter(), String.class);
  70.         ConvertUtils.register(new LongConverter(defaultLong), Long.class);
  71.         ConvertUtils.register(new IntegerConverter(defaultLong), Integer.class);
  72.         ConvertUtils.register(new TimestampConverter(), Timestamp.class);
  73.         ConvertUtils.register(new BigDecimalConverter(defaultLong), BigDecimal.class);
  74.     }
  75.     /**
  76.      * The message resources for this package.
  77.      */
  78.     protected static MessageResources messages = MessageResources.getMessageResources("org.apache.struts.actions.LocalStrings");
  79.     /**
  80.      * The set of Method objects we have introspected for this class, keyed by
  81.      * method name. This collection is populated as different methods are
  82.      * called, so that introspection needs to occur only once per method name.
  83.      */
  84.     protected HashMap<StringMethod> methods = new HashMap<StringMethod>();
  85.     /**
  86.      * The set of argument type classes for the reflected method call. These are
  87.      * the same for all calls, so calculate them only once.
  88.      */
  89.     protected Class[] types = { ActionMapping.class, ActionForm.classDocument.classHttpServletRequest.class,
  90.             HttpServletResponse.class };
  91.     /**
  92.      * Process the specified HTTP request, and create the corresponding HTTP
  93.      * response (or forward to another web component that will create it).
  94.      * Return an <code>ActionForward</code> instance describing where and how
  95.      * control should be forwarded, or <code>null</code> if the response has
  96.      * already been completed.
  97.      * 
  98.      * @param mapping
  99.      *            The ActionMapping used to select this instance
  100.      * @param form
  101.      *            The optional ActionForm bean for this request (if any)
  102.      * @param request
  103.      *            The HTTP request we are processing
  104.      * @param response
  105.      *            The HTTP response we are creating
  106.      * 
  107.      * @exception Exception
  108.      *                if an exception occurs
  109.      */
  110.     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
  111.             HttpServletResponse response) throws Exception {
  112.         response.setContentType("text/html; charset=UTF-8");
  113.         ExceptionDisplayDTO expDTO = null;
  114.         try {
  115.             Document doc = createDocumentFromRequest(request);
  116.             /*
  117.              * 这里直接调用mapping的parameter配置
  118.              */
  119.             String actionMethod = mapping.getParameter();
  120.             /*
  121.              * 校验配置的方法是否正确、有效
  122.              */
  123.             isValidMethod(actionMethod);
  124.             return dispatchMethod(mapping, form, doc, request, response, actionMethod);
  125.         } catch (BaseAppException ex) {
  126.             expDTO = handlerException(request, response, ex);
  127.         } catch (Exception ex) {
  128.             ExceptionUtil.logException(this.getClass(), ex);
  129.             renderText(response,"[Error :对不起,系统出现错误了,请向管理员报告以下异常信息." + ex.getMessage() + "]");
  130.             request.setAttribute(Globals.ERRORMSG, "对不起,系统出现错误了,请向管理员报告以下异常信息." + ex.getMessage());
  131.             expDTO = handlerException(request,response, ex);
  132.         } finally {
  133.             expDisplayDetails.set(null);
  134.         }
  135.         return null == expDTO ? null : (expDTO.getActionForwardName() == null ? null : mapping.findForward(expDTO.getActionForwardName()));
  136.     }
  137.     /**
  138.      * 直接输出纯字符串
  139.      */
  140.     public void renderText(HttpServletResponse response, String text) {
  141.         PrintWriter out = null;
  142.         try {
  143.             out = response.getWriter();
  144.             response.setContentType("text/plain;charset=UTF-8");
  145.             out.write(text);
  146.         } catch (IOException e) {
  147.             log.error(e);
  148.         } finally {
  149.             if (out != null) {
  150.                 out.flush();
  151.                 out.close();
  152.                 out = null;
  153.             }
  154.         }
  155.     }
  156.     
  157.     /**
  158.      * 直接输出纯HTML
  159.      */
  160.     public void renderHtml(HttpServletResponse response, String text) {
  161.         PrintWriter out = null;
  162.         try {
  163.             out = response.getWriter();
  164.             response.setContentType("text/html;charset=UTF-8");
  165.             out.write(text);
  166.         } catch (IOException e) {
  167.             log.error(e);
  168.         } finally {
  169.             if (out != null) {
  170.                 out.flush();
  171.                 out.close();
  172.                 out = null;
  173.             }
  174.         }
  175.     }
  176.     /**
  177.      * 直接输出纯XML
  178.      */
  179.     public void renderXML(HttpServletResponse response, String text) {
  180.         PrintWriter out = null;
  181.         try {
  182.             out = response.getWriter();
  183.             response.setContentType("text/xml;charset=UTF-8");
  184.             out.write(text);
  185.         } catch (IOException e) {
  186.             log.error(e);
  187.         } finally {
  188.             if (out != null) {
  189.                 out.flush();
  190.                 out.close();
  191.                 out = null;
  192.             }
  193.         }
  194.     }
  195.     /**
  196.      * 异常处理
  197.      * @param request
  198.      * @param out
  199.      * @param ex
  200.      * @return ExceptionDisplayDTO异常描述对象
  201.      */
  202.     private ExceptionDisplayDTO handlerException(HttpServletRequest request,HttpServletResponse response, Exception ex) {
  203.         ExceptionDisplayDTO expDTO = (ExceptionDisplayDTO) expDisplayDetails.get();
  204.         if (null == expDTO) {            
  205.             expDTO = new ExceptionDisplayDTO(null,this.getClass().getName());
  206.         }
  207.         IExceptionHandler expHandler = ExceptionHandlerFactory.getInstance().create();
  208.         ExceptionDTO exDto = expHandler.handleException(expDTO.getContext(), ex);
  209.         request.setAttribute("ExceptionDTO", exDto);
  210.         renderText(response,"[Error:" + (exDto == null ? "ExceptionDTO is null,请检查expinfo.xml配置文件." : exDto.getMessageCode())
  211.                 + "]");
  212.         return expDTO;
  213.     }
  214.     private void isValidMethod(String actionMethod) throws MappingConfigException {
  215.         if (actionMethod == null || "execute".equals(actionMethod) || "perform".equals(actionMethod)) {
  216.             log.error("[BaseDispatchAction->error] parameter = " + actionMethod);
  217.             expDisplayDetails.set(new ExceptionDisplayDTO(null"MappingConfigException"));
  218.             throw new MappingConfigException("对不起,配置的方法名不能为 " + actionMethod);
  219.         }
  220.     }
  221.   /**
  222.      * 解析xml
  223.      * @param request
  224.      * @return Document对象
  225.      */
  226.     protected static Document createDocumentFromRequest(HttpServletRequest request) throws Exception {
  227.         try {
  228.             request.setCharacterEncoding("UTF-8");
  229.             Document document = null;
  230.             SAXReader reader = new SAXReader();
  231.             document = reader.read(request.getInputStream());
  232.             return document;
  233.         } catch (Exception ex) {
  234.             log.warn("TIPS:没有提交获取XML格式数据流! ");
  235.             return null;
  236.         }
  237.     }
  238.     /**
  239.      * Dispatch to the specified method.
  240.      * 
  241.      * @since Struts 1.1
  242.      */
  243.     protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, Document doc,HttpServletRequest request, 
    HttpServletResponse response, String name) throws Exception {
  244.         Method method = null;
  245.         try {
  246.             method = getMethod(name);
  247.         } catch (NoSuchMethodException e) {
  248.             String message = messages.getMessage("dispatch.method", mapping.getPath(), name);
  249.             log.error(message, e);
  250.             expDisplayDetails.set(new ExceptionDisplayDTO(null"MappingConfigException"));
  251.             throw new MappingConfigException(message, e);
  252.         }
  253.         ActionForward forward = null;
  254.         try {
  255.             Object args[] = { mapping, form, doc, request, response };
  256.             log.debug("[execute-begin] -> " + mapping.getPath() + "->[" + clazz.getName() + "->" + name + "]");
  257.             forward = (ActionForward) method.invoke(this, args);
  258.             log.debug(" [execute-end] -> " + (null == forward ? "use ajax send to html/htm" : forward.getPath()));
  259.         } catch (ClassCastException e) {
  260.             String message = messages.getMessage("dispatch.return", mapping.getPath(), name);
  261.             log.error(message, e);
  262.             throw new BaseAppException(message, e);
  263.         } catch (IllegalAccessException e) {
  264.             String message = messages.getMessage("dispatch.error", mapping.getPath(), name);
  265.             log.error(message, e);
  266.             throw new BaseAppException(message, e);
  267.         } catch (InvocationTargetException e) {
  268.             Throwable t = e.getTargetException();
  269.             String message = messages.getMessage("dispatch.error", mapping.getPath(), name);
  270.             throw new BaseAppException(message, t);
  271.         }
  272.         return (forward);
  273.     }
  274.     /**
  275.      * Introspect the current class to identify a method of the specified name
  276.      * that accepts the same parameter types as the <code>execute</code>
  277.      * method does.
  278.      * 
  279.      * @param name
  280.      *            Name of the method to be introspected
  281.      * 
  282.      * @exception NoSuchMethodException
  283.      *                if no such method can be found
  284.      */
  285.     protected Method getMethod(String name) throws NoSuchMethodException {
  286.         synchronized (methods) {
  287.             Method method = (Method) methods.get(name);
  288.             if (method == null) {
  289.                 method = clazz.getMethod(name, types);
  290.                 methods.put(name, method);
  291.             }
  292.             return (method);
  293.         }
  294.     }
  295.   /**
  296.    * 返回spring bean对象
  297.    * @param name Spring Bean的名称
  298.    * @exception BaseAppException
  299.    */
  300.     protected Object getSpringBean(String name) throws BaseAppException {
  301.         if (ctx == null) {
  302.             ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());
  303.         }
  304.         Object bean = null;
  305.         try {
  306.             bean = ctx.getBean(name);
  307.         } catch (BeansException ex) {
  308.             throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!", ex.getRootCause());
  309.         }
  310.         if (null == bean) {
  311.             throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!");
  312.         }
  313.         return bean;
  314.     }
  315. }


 

 


请记住本文永久地址:
http://www.javaresource.org/struts/struts-75614.html
posted on 2007-04-19 16:03 芦苇 阅读(743) 评论(0)  编辑  收藏 所属分类: SpringJAVAStruts

只有注册用户登录后才能发表评论。


网站导航: