`
abei1
  • 浏览: 21111 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

转贴:主题:ajax、Struts、spring的无缝结合

阅读更多

作者:zhipingch      出处:http://zhipingch.iteye.com/


去年初,正好负责一个医药信息系统的设计开发,架构设计时,采用Struts+JDBC(自定义采用适配器模式封装了HashMap动态VO实现的持久 层)。后来ajax热潮兴起,正好系统中有很多地方需要和服务器端交互数据,如采购销售系统中的订单头/订单明细等主从表结构的维护。
数据交互过程,我们考虑采用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. }  
<script type="text/javascript">render_code();</script>

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

至此,我们成功实现了ajax--struts--spring的无缝结合。欢迎大家拍砖!

分享到:
评论
1 楼 elvishehai 2008-11-19  
有没有一包啊,  顾··

相关推荐

    Struts-menu源码分析(转贴).rar

    Struts-menu是一个基于Apache Struts框架的菜单管理组件,它为Web应用提供了动态生成和管理菜单的功能。在分析Struts-menu的源码时,我们可以深入理解Struts框架的工作原理、MVC模式的应用以及如何实现自定义标签库...

    转贴:随心所欲的Web页面打印技术

    因此,本文探讨了一种通过结合javascript、ActiveX、ASP.NET和GDI+技术来实现自定义打印的方法。 首先,基本架构包括三个页面:`main.htm`作为框架页面,上面有打印按钮,下面是待打印的内容;`header.htm`用于设置...

    转贴:利用钩子技术控制进程创建.txt

    根据提供的文件信息,可以看出标题与描述均指向了“利用钩子技术控制进程创建”的主题,但实际内容似乎并未直接涉及这一技术细节,而是包含了大量非结构化和个人化的文本信息。因此,下面将基于标题和描述中提及的...

    转贴:四十岁的男人要像孩子一样养.doc

    【知识点详解】 1. **情感需求的重视**:40岁的男性在工作和生活中积累了丰富的经验,他们开始渴望更多的家庭温暖和情感互动。他们会喜欢与家人,尤其是孩子一起度过时光,寻找简单快乐,如游戏、亲子活动等。...

    jquery的转贴功能实现

    在本主题中,我们将深入探讨如何利用jQuery实现“转贴”功能,这是一种常见的社交媒体分享功能,允许用户将网页内容轻松分享到各种社交网络。 首先,让我们了解一下jQuery的核心概念。jQuery通过一种简洁的语法提供...

    易语言动网转贴.rar

    总的来说,"易语言动网转贴"可能是一个结合了网络爬虫、数据解析、数据库操作等多个技术领域的项目。对于初学者,可以通过学习这个项目了解易语言的编程实践;对于有经验的开发者,它可以作为一个研究网络数据迁移和...

    asp.net中的并发控制

    转贴:asp.net中的并发控制 并发控制的类型 通常,管理数据库中的并发有三种常见的方法: 保守式并发控制 开放式并发控制 最后的更新生效

    易语言源码动网转贴.rar

    "动网转贴"这个主题可能指的是在论坛或者社交网络中实现帖子转发或分享的功能。 动网转贴的源码可能涉及到以下几个方面的知识点: 1. **网络通信**:在实现动网转贴功能时,首先需要与服务器进行交互,发送用户的...

    ZZ: 时间管理方法(转贴)

    【时间管理方法(转贴)】 时间管理是个人和团队高效工作的关键,它涉及到如何规划、组织和优化日常活动,以便在有限的时间内完成更多的任务并实现目标。在这个快速发展的IT行业中,良好的时间管理能力可以帮助程序员...

    cics整理总结(中文)

    转贴:作者按:当时业界都说CICS思想博大精深,引得版主下大力气苦苦探索,昨日偶然翻了出来,愿意贡献给有需要的网友。后来迫于形式,开始学习使用J2EE、dot NET、XML、PKI、UML、CMM、LINUX等新玩意儿,功夫尚未练...

    怎样配置Windowsxp中的iis使其支持asp_net

    转贴:配置Windowsxp中的iis使其支持asp_net

    动易系统的论坛转贴工具

    《动易系统的论坛转贴工具详解与应用》 在互联网信息交流日益频繁的今天,论坛作为用户互动的重要平台,其内容分享与传播的作用不容忽视。动易系统的论坛转贴工具,便是为了解决用户在论坛间便捷分享内容而设计的一...

    电子政务-导电泡棉转贴装置.zip

    在“导电泡棉转贴装置”这个特定的场景下,我们可能是在讨论一种用于电子政务设备或系统中的特殊组件。 导电泡棉是一种具有导电性能的泡沫材料,通常用于电子设备的屏蔽、接地或防静电保护。在电子政务设备中,这种...

    完全删除sql2005

    完全删除sql2005,转贴:【应用】如何彻底删除SQL Server2005 百度空间_应用平台

Global site tag (gtag.js) - Google Analytics