空間站

          北極心空

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

          zhipingch 原創(chuàng)

              去年初,正好負(fù)責(zé)一個(gè)醫(yī)藥信息系統(tǒng)的設(shè)計(jì)開(kāi)發(fā),架構(gòu)設(shè)計(jì)時(shí),采用Struts+JDBC(自定義采用適配器模式封裝了HashMap動(dòng)態(tài)VO實(shí)現(xiàn)的持久層)。后來(lái)ajax熱潮興起,正好系統(tǒng)中有很多地方需要和服務(wù)器端交互數(shù)據(jù),如采購(gòu)銷售系統(tǒng)中的訂單頭/訂單明細(xì)等主從表結(jié)構(gòu)的維護(hù)。
              [color=blue]數(shù)據(jù)交互過(guò)程[/color],我們考慮采用xml來(lái)組織數(shù)據(jù)結(jié)構(gòu),更新/保存:前臺(tái)封裝需要的xml,通過(guò)ajax提交---〉action解析xml ---〉改造原有的持久層實(shí)現(xiàn)xml持久化;
              查詢時(shí):持久層根據(jù)實(shí)際需要返回xml,document對(duì)象,---〉action 處理 --〉前臺(tái)自己封裝js庫(kù)來(lái)解析xml,并刷新部分頁(yè)面。

              ajax:已經(jīng)有很多方法實(shí)現(xiàn)跨瀏覽器的方式,這里只介紹最簡(jiǎn)單的方式,同步模式下提交xmlStr給action(*.do)。

          1. /**
          2.  * 將數(shù)據(jù)同步傳遞給后臺(tái)請(qǐng)求url
          3.  *  @return 返回xmlhttp 響應(yīng)的信息
          4.  *  @param-url = '/web/module/xxx.do?p1=YY&p2=RR';
          5.  *  @param-xmlStr:xml格式的字符串 <data><xpath><![CDATA[數(shù)據(jù)信息]]></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中我們擴(kuò)展了Action,實(shí)現(xiàn)了xmlStr轉(zhuǎn)化成document對(duì)象(dom4j),并且完善了轉(zhuǎn)發(fā)方式。如
          [quote]
          1.DispatchAction
               以一個(gè)Controller響應(yīng)一組動(dòng)作絕對(duì)是Controller界的真理,Struts的DispatchAction同樣可以做到這點(diǎn)。

          [list]
          <action path="/admin/user" name="userForm" scope="request" parameter="method" validate="false">
              <forward name="list" path="/admin/userList.jsp"/>
          </action>
          [/list]
              其中parameter="method" 設(shè)置了用來(lái)指定響應(yīng)方法名的url參數(shù)名為method,即/admin/user.do?method=list 將調(diào)用UserAction的public ActionForward list(....) 函數(shù)。   

              public ActionForward unspecified(....) 函數(shù)可以指定不帶method方法時(shí)的默認(rèn)方法。[/quote]
              但是這樣需要在url后多傳遞參數(shù)[size=18][color=red]method=list [/color][/size];并且action節(jié)點(diǎn)配置中的[color=red]parameter="method" [/color]
          也沒(méi)有被充分利用,反而覺(jué)得是累贅!

              因此我們直接在BaseDispatchAction中增加xml字符串解析,并充分利用action節(jié)點(diǎn)配置中的[color=red]parameter="targetMethod" [/color],使得轉(zhuǎn)發(fā)的時(shí)候,action能夠直接轉(zhuǎn)發(fā)到子類的相應(yīng)方法中,減少了url參數(shù)傳遞,增強(qiáng)了配置信息可讀性,方便團(tuán)隊(duì)開(kāi)發(fā)。
              同樣以上述為例,擴(kuò)展后的配置方式如下:
          [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] 設(shè)置了用來(lái)指定響應(yīng)url=/admin/user.do的方法名,它將調(diào)用UserAction的public ActionForward list(....) 函數(shù)。 
               BaseDispatchDocumentAction 的代碼如下,它做了三件重要的事情:
               1、采用dom4j直接解析xml字符串,并返回document,如果沒(méi)有提交xml數(shù)據(jù),或者采用form形式提交的話,返回null;
               2、采用模版方法處理系統(tǒng)異常,減少了子類中無(wú)盡的try{...}catch(){...};其中異常處理部分另作描述(你可以暫時(shí)去掉異常處理,實(shí)現(xiàn)xml提交和解析,如果你有興趣,我們可以進(jìn)一步交流);

           

           

               3、提供了Spring配置Bean的直接調(diào)用,雖然她沒(méi)有注入那么優(yōu)雅,但是實(shí)現(xiàn)了ajaxstrutsspring的結(jié)合。
          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.  * 系統(tǒng)的Ajax轉(zhuǎn)發(fā)基類。增加模版處理異常信息。
          44.  * 
          45.  * @author 陳志平 chenzp
          46.  * @desc BaseDispatchDocumentAction.java
          47.  * 
          48.  * @說(shuō)明: web 應(yīng)用基礎(chǔ)平臺(tái)
          49.  * @date 2005-03-02 11:18:01 AM
          50.  * @版權(quán)所有: 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.      * 注冊(cè)轉(zhuǎn)換的工具類 使得From中的string --
          64.      * Model中的對(duì)應(yīng)的類型(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.              * 這里直接調(diào)用mapping的parameter配置
          118.              */
          119.             String actionMethod = mapping.getParameter();
          120.             /*
          121.              * 校驗(yàn)配置的方法是否正確、有效
          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 :對(duì)不起,系統(tǒng)出現(xiàn)錯(cuò)誤了,請(qǐng)向管理員報(bào)告以下異常信息." + ex.getMessage() + "]");
          130.             request.setAttribute(Globals.ERRORMSG, "對(duì)不起,系統(tǒng)出現(xiàn)錯(cuò)誤了,請(qǐng)向管理員報(bào)告以下異常信息." + 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異常描述對(duì)象
          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,請(qǐng)檢查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("對(duì)不起,配置的方法名不能為 " + actionMethod);
          219.         }
          220.     }
          221.   /**
          222.      * 解析xml
          223.      * @param request
          224.      * @return Document對(duì)象
          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:沒(méi)有提交獲取XML格式數(shù)據(jù)流! ");
          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對(duì)象
          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("對(duì)不起,您沒(méi)有配置名為:" + name + "的bean。請(qǐng)檢查配置文件!", ex.getRootCause());
          309.         }
          310.         if (null == bean) {
          311.             throw new NoSuchBeanConfigException("對(duì)不起,您沒(méi)有配置名為:" + name + "的bean。請(qǐng)檢查配置文件!");
          312.         }
          313.         return bean;
          314.     }
          315. }


           

           

           

          開(kāi)發(fā)人員只需要繼承它就可以了,我們寫個(gè)簡(jiǎn)單的示例action,如下:

          1. /**
          2.  * 帶Ajax提交xml數(shù)據(jù)的action類模版
          3.  * 
          4.  * @author 陳志平 chenzp
          5.  * 
          6.  * @說(shuō)明: web 應(yīng)用基礎(chǔ)平臺(tái)
          7.  * @date Aug 1, 2006 10:52:13 AM
          8.  * @版權(quán)所有: All Right Reserved 2006-2008
          9.  */
          10. public class UserAction extends BaseDispatchDocumentAction {
          11.          /**
          12.           * 這里 actionForm 和 doc 參數(shù)必有一個(gè)為空,請(qǐng)聰明的你分析一下
          13.           * @param mapping --轉(zhuǎn)發(fā)的映射對(duì)象
          14.           [color=blue]* @param actionForm --仍然支持表單提交,此時(shí)doc == null
          15.           * @param doc document對(duì)象,解析xml后的文檔對(duì)象[/color]
          16.           * @param request --請(qǐng)求
          17.           * @param response --響應(yīng)
          18.           */
          19.     public ActionForward list(ActionMapping mapping, ActionForm actionForm, [color=red]Document doc[/color],HttpServletRequest request, HttpServletResponse response) throws BaseAppException {
          20.         /**
          21.          * 轉(zhuǎn)發(fā)的名稱 userAction.search: 系統(tǒng)上下文 用于異常處理
          22.          */
          23.         expDisplayDetails.set(new ExceptionDisplayDTO(null"userAction.search"));
          24.         /**
          25.          * 處理業(yè)務(wù)邏輯部分:
          26.          * 
          27.          * 獲取各種類型的參數(shù) RequestUtil.getStrParameter(request,"ParameterName");
          28.          * 
          29.          * 調(diào)用父類的 getSpringBean("serviceID")方法獲取spring的配置bean
          30.          * 
          31.          */
          32.         UserManager userManager = (LogManager) getSpringBean("userManager");
          33.         //返回xml對(duì)象到前臺(tái)
          34.         renderXML(response, userManager.findUsersByDoc(doc));        
          35.                      return null;
          36.     }



          至此,我們成功實(shí)現(xiàn)了ajax--struts--spring的無(wú)縫結(jié)合,下次介紹spring的開(kāi)發(fā)應(yīng)用。歡迎大家拍磚!

           

           

               3、提供了Spring配置Bean的直接調(diào)用,雖然她沒(méi)有注入那么優(yōu)雅,但是實(shí)現(xiàn)了ajaxstrutsspring的結(jié)合。
          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.  * 系統(tǒng)的Ajax轉(zhuǎn)發(fā)基類。增加模版處理異常信息。
          44.  * 
          45.  * @author 陳志平 chenzp
          46.  * @desc BaseDispatchDocumentAction.java
          47.  * 
          48.  * @說(shuō)明: web 應(yīng)用基礎(chǔ)平臺(tái)
          49.  * @date 2005-03-02 11:18:01 AM
          50.  * @版權(quán)所有: 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.      * 注冊(cè)轉(zhuǎn)換的工具類 使得From中的string --
          64.      * Model中的對(duì)應(yīng)的類型(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.              * 這里直接調(diào)用mapping的parameter配置
          118.              */
          119.             String actionMethod = mapping.getParameter();
          120.             /*
          121.              * 校驗(yàn)配置的方法是否正確、有效
          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 :對(duì)不起,系統(tǒng)出現(xiàn)錯(cuò)誤了,請(qǐng)向管理員報(bào)告以下異常信息." + ex.getMessage() + "]");
          130.             request.setAttribute(Globals.ERRORMSG, "對(duì)不起,系統(tǒng)出現(xiàn)錯(cuò)誤了,請(qǐng)向管理員報(bào)告以下異常信息." + 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異常描述對(duì)象
          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,請(qǐng)檢查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("對(duì)不起,配置的方法名不能為 " + actionMethod);
          219.         }
          220.     }
          221.   /**
          222.      * 解析xml
          223.      * @param request
          224.      * @return Document對(duì)象
          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:沒(méi)有提交獲取XML格式數(shù)據(jù)流! ");
          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對(duì)象
          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("對(duì)不起,您沒(méi)有配置名為:" + name + "的bean。請(qǐng)檢查配置文件!", ex.getRootCause());
          309.         }
          310.         if (null == bean) {
          311.             throw new NoSuchBeanConfigException("對(duì)不起,您沒(méi)有配置名為:" + name + "的bean。請(qǐng)檢查配置文件!");
          312.         }
          313.         return bean;
          314.     }
          315. }


           

           


          請(qǐng)記住本文永久地址:
          http://www.javaresource.org/struts/struts-75614.html
          posted on 2007-04-19 16:03 蘆葦 閱讀(760) 評(píng)論(0)  編輯  收藏 所屬分類: SpringJAVAStruts
          主站蜘蛛池模板: 明光市| 安岳县| 永福县| 宣汉县| 新乡县| 林甸县| 玉林市| 长寿区| 岳普湖县| 舞阳县| 隆安县| 安化县| 会同县| 东方市| 日照市| 海宁市| 浦江县| 景泰县| 义乌市| 祁连县| 福安市| 兴海县| 青浦区| 隆德县| 景洪市| 额尔古纳市| 梁山县| 麻栗坡县| 五河县| 北京市| 滁州市| 从江县| 广宗县| 张家界市| 日土县| 普兰县| 玉门市| 安多县| 湄潭县| 柳江县| 资源县|