`
sumongh
  • 浏览: 226527 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Spring的魅力及与struts的整合

阅读更多

 Spring的魅力及与struts的整合

Spring 的创立者 Rod Johnson 以一种批判的眼光看待 Java™ 企业软件开发,并且提议很多企业难题都能够通过战略地使用 IOC 模式(也称作依赖注入)来解决。当 Rod 和一个具有奉献精神的开放源码开发者团队将这个理论应用于实践时,结果就产生了 Spring 框架。简言之,Spring 是一个轻型的容器,利用它可以使用一个外部 XML 配置文件方便地将对象连接在一起。每个对象都可以通过显示一个 JavaBean 属性收到一个到依赖对象的引用,留给您的简单任务就只是在一个 XML 配置文件中把它们连接好。

IOC 和 Spring

IOC 是一种使应用程序逻辑外在化的设计模式,所以它是被注入而不是被写入客户机代码中。将 IOC 与接口编程应用结合,就像 Spring 框架那样,产生了一种架构,这种架构能够减少客户机对特定实现逻辑的依赖。请参阅 参考资料 了解更多关于 IOC 和 Spring 的信息。

依赖注入是一个强大的特性,但是 Spring 框架能够提供更多特性。Spring 支持可插拔的事务管理器,可以给您的事务处理提供更广泛的选择范围。它集成了领先的持久性框架,并且提供一个一致的异常层次结构。Spring 还提供了一种使用面向方面代码代替正常的面向对象代码的简单机制。

Spring AOP 允许您使用拦截器 在一个或多个执行点上拦截应用程序逻辑。加强应用程序在拦截器中的日志记录逻辑会产生一个更可读的、实用的代码基础,所以拦截器广泛用于日志记录。您很快就会看到,为了处理横切关注点,Spring AOP 发布了它自己的拦截器,您也可以编写您自己的拦截器。





回页首


整合 Struts 和 Spring

与 Struts 相似,Spring 可以作为一个 MVC 实现。这两种框架都具有自己的优点和缺点,尽管大部分人同意 Struts 在 MVC 方面仍然是最好的。很多开发团队已经学会在时间紧迫的时候利用 Struts 作为构造高品质软件的基础。Struts 具有如此大的推动力,以至于开发团队宁愿整合 Spring 框架的特性,而不愿意转换成 Spring MVC。没必要进行转换对您来说是一个好消息。Spring 架构允许您将 Struts 作为 Web 框架连接到基于 Spring 的业务和持久层。最后的结果就是现在一切条件都具备了。

在接下来的小窍门中,您将会了解到三种将 Struts MVC 整合到 Spring 框架的方法。我将揭示每种方法的缺陷并且对比它们的优点。 一旦您了解到所有三种方法的作用,我将会向您展示一个令人兴奋的应用程序,这个程序使用的是这三种方法中我最喜欢的一种。





回页首


三个小窍门

接下来的每种整合技术(或者窍门)都有自己的优点和特点。我偏爱其中的一种,但是我知道这三种都能够加深您对 Struts 和 Spring 的理解。在处理各种不同情况的时候,这将给您提供一个广阔的选择范围。方法如下:

  • 使用 Spring 的 ActionSupport 类整合 Structs
  • 使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor
  • 将 Struts Action 管理委托给 Spring 框架

装载应用程序环境

无论您使用哪种技术,都需要使用 Spring 的 ContextLoaderPlugin 为 Struts 的 ActionServlet 装载 Spring 应用程序环境。就像添加任何其他插件一样,简单地向您的 struts-config.xml 文件添加该插件,如下所示:

            <plug-in className=            "org.springframework.web.struts.ContextLoaderPlugIn">            <set-property property=            "contextConfigLocation" value="/WEB-INF/beans.xml"/>            </plug-in>            

前面已经提到过,在 下载 部分,您能够找到这三个完全可使用的例子的完整源代码。每个例子都为一个书籍搜索应用程序提供一种不同的 Struts 和 Spring 的整合方法。您可以在这里看到例子的要点,但是您也可以下载应用程序以查看所有的细节。





回页首


窍门 1. 使用 Spring 的 ActionSupport

手动创建一个 Spring 环境是一种整合 Struts 和 Spring 的最直观的方式。为了使它变得更简单,Spring 提供了一些帮助。为了方便地获得 Spring 环境,org.springframework.web.struts.ActionSupport 类提供了一个 getWebApplicationContext() 方法。您所做的只是从 Spring 的 ActionSupport 而不是 Struts Action 类扩展您的动作,如清单 1 所示:


清单 1. 使用 ActionSupport 整合 Struts

            package ca.nexcel.books.actions;            import java.io.IOException;            import javax.servlet.ServletException;            import javax.servlet.http.HttpServletRequest;            import javax.servlet.http.HttpServletResponse;            import org.apache.struts.action.ActionError;            import org.apache.struts.action.ActionErrors;            import org.apache.struts.action.ActionForm;            import org.apache.struts.action.ActionForward;            import org.apache.struts.action.ActionMapping;            import org.apache.struts.action.DynaActionForm;            import org.springframework.context.ApplicationContext;            import org.springframework.web.struts.ActionSupport;            import ca.nexcel.books.beans.Book;            import ca.nexcel.books.business.BookService;            public class SearchSubmit extends ActionSupport {   |(1)            public ActionForward execute(            ActionMapping mapping,            ActionForm form,            HttpServletRequest request,            HttpServletResponse response)            throws IOException, ServletException {            DynaActionForm searchForm = (DynaActionForm) form;            String isbn = (String) searchForm.get("isbn");            //the old fashion way            //BookService bookService = new BookServiceImpl();            ApplicationContext ctx =            getWebApplicationContext();    |(2)            BookService bookService =            (BookService) ctx.getBean("bookService");   |(3)            Book book = bookService.read(isbn.trim());            if (null == book) {            ActionErrors errors = new ActionErrors();            errors.add(ActionErrors.GLOBAL_ERROR,new ActionError            ("message.notfound"));            saveErrors(request, errors);            return mapping.findForward("failure") ;            }            request.setAttribute("book", book);            return mapping.findForward("success");            }            }            

让我们快速思考一下这里到底发生了什么。在 (1) 处,我通过从 Spring 的 ActionSupport 类而不是 Struts 的 Action 类进行扩展,创建了一个新的 Action。在 (2) 处,我使用 getWebApplicationContext() 方法获得一个 ApplicationContext。为了获得业务服务,我使用在 (2) 处获得的环境在 (3) 处查找一个 Spring bean。

这种技术很简单并且易于理解。不幸的是,它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉 Spring,那么您必须重写代码。并且,由于 Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优势。当使用多重独立的 Spring 环境时,这种技术可能有用,但是在大多数情况下,这种方法不如另外两种方法合适。





回页首


窍门 2. 覆盖 RequestProcessor

将 Spring 从 Struts 动作中分离是一个更巧妙的设计选择。分离的一种方法是使用 org.springframework.web.struts.DelegatingRequestProcessor 类来覆盖 Struts 的 RequestProcessor 处理程序,如清单 2 所示:


清单 2. 通过 Spring 的 DelegatingRequestProcessor 进行整合

            <?xml version="1.0" encoding="ISO-8859-1" ?>            <!DOCTYPE struts-config PUBLIC            "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"            "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">            <struts-config>            <form-beans>            <form-bean name="searchForm"            type="org.apache.struts.validator.DynaValidatorForm">            <form-property name="isbn"    type="java.lang.String"/>            </form-bean>            </form-beans>            <global-forwards type="org.apache.struts.action.ActionForward">            <forward   name="welcome"                path="/welcome.do"/>            <forward   name="searchEntry"            path="/searchEntry.do"/>            <forward   name="searchSubmit"           path="/searchSubmit.do"/>            </global-forwards>            <action-mappings>            <action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>            <action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>            <action    path="/searchSubmit"            type="ca.nexcel.books.actions.SearchSubmit"            input="/searchEntry.do"            validate="true"            name="searchForm">            <forward name="success" path="/WEB-INF/pages/detail.jsp"/>            <forward name="failure" path="/WEB-INF/pages/search.jsp"/>            </action>            </action-mappings>            <message-resources parameter="ApplicationResources"/>            <controller processorClass="org.springframework.web.struts.            DelegatingRequestProcessor"/> |(1)            <plug-in className="org.apache.struts.validator.ValidatorPlugIn">            <set-property property="pathnames"            value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>            </plug-in>            <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">            <set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/>            </plug-in>            </struts-config>            

我利用了 <controller> 标记来用 DelegatingRequestProcessor 覆盖默认的 Struts RequestProcessor。下一步是在我的 Spring 配置文件中注册该动作,如清单 3 所示:


清单 3. 在 Spring 配置文件中注册一个动作

            <?xml version="1.0" encoding="UTF-8"?>            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"            "http://www.springframework.org/dtd/spring-beans.dtd">            <beans>            <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>            <bean name="/searchSubmit"            class="ca.nexcel.books.actions.SearchSubmit"> |(1)            <property name="bookService">            <ref bean="bookService"/>            </property>            </bean>            </beans>            

注意:在 (1) 处,我使用名称属性注册了一个 bean,以匹配 struts-config 动作映射名称。SearchSubmit 动作揭示了一个 JavaBean 属性,允许 Spring 在运行时填充属性,如清单 4 所示:


清单 4. 具有 JavaBean 属性的 Struts 动作

            package ca.nexcel.books.actions;            import java.io.IOException;            import javax.servlet.ServletException;            import javax.servlet.http.HttpServletRequest;            import javax.servlet.http.HttpServletResponse;            import org.apache.struts.action.Action;            import org.apache.struts.action.ActionError;            import org.apache.struts.action.ActionErrors;            import org.apache.struts.action.ActionForm;            import org.apache.struts.action.ActionForward;            import org.apache.struts.action.ActionMapping;            import org.apache.struts.action.DynaActionForm;            import ca.nexcel.books.beans.Book;            import ca.nexcel.books.business.BookService;            public class SearchSubmit extends Action {            private BookService bookService;            public BookService getBookService() {            return bookService;            }            public void setBookService(BookService bookService) { | (1)            this.bookService = bookService;            }            public ActionForward execute(            ActionMapping mapping,            ActionForm form,            HttpServletRequest request,            HttpServletResponse response)            throws IOException, ServletException {            DynaActionForm searchForm = (DynaActionForm) form;            String isbn = (String) searchForm.get("isbn");            Book book = getBookService().read(isbn.trim());  |(2)            if (null == book) {            ActionErrors errors = new ActionErrors();            errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));            saveErrors(request, errors);            return mapping.findForward("failure") ;            }            request.setAttribute("book", book);            return mapping.findForward("success");            }            }            

在清单 4 中,您可以了解到如何创建 Struts 动作。在 (1) 处,我创建了一个 JavaBean 属性。DelegatingRequestProcessor自动地配置这种属性。这种设计使 Struts 动作并不知道它正被 Spring 管理,并且使您能够利用 Sping 的动作管理框架的所有优点。由于您的 Struts 动作注意不到 Spring 的存在,所以您不需要重写您的 Struts 代码就可以使用其他控制反转容器来替换掉 Spring。

DelegatingRequestProcessor 方法的确比第一种方法好,但是仍然存在一些问题。如果您使用一个不同的 RequestProcessor,则需要手动整合 Spring 的 DelegatingRequestProcessor。添加的代码会造成维护的麻烦并且将来会降低您的应用程序的灵活性。此外,还有过一些使用一系列命令来代替 Struts RequestProcessor 的传闻。 这种改变将会对这种解决方法的使用寿命造成负面的影响。





回页首


窍门 3. 将动作管理委托给 Spring

一个更好的解决方法是将 Strut 动作管理委托给 Spring。您可以通过在 struts-config 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查找 Struts 动作。由于动作在 Spring 的控制之下,所以它可以填充动作的 JavaBean 属性,并为应用诸如 Spring 的 AOP 拦截器之类的特性带来了可能。

清单 5 中的 Action 类与清单 4 中的相同。但是 struts-config 有一些不同:


清单 5. Spring 整合的委托方法

            <?xml version="1.0" encoding="ISO-8859-1" ?>            <!DOCTYPE struts-config PUBLIC            "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"            "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">            <struts-config>            <form-beans>            <form-bean name="searchForm"            type="org.apache.struts.validator.DynaValidatorForm">            <form-property name="isbn"    type="java.lang.String"/>            </form-bean>            </form-beans>            <global-forwards type="org.apache.struts.action.ActionForward">            <forward   name="welcome"                path="/welcome.do"/>            <forward   name="searchEntry"            path="/searchEntry.do"/>            <forward   name="searchSubmit"           path="/searchSubmit.do"/>            </global-forwards>            <action-mappings>            <action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>            <action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>            <action    path="/searchSubmit"            type="org.springframework.web.struts.DelegatingActionProxy" |(1)            input="/searchEntry.do"            validate="true"            name="searchForm">            <forward name="success" path="/WEB-INF/pages/detail.jsp"/>            <forward name="failure" path="/WEB-INF/pages/search.jsp"/>            </action>            </action-mappings>            <message-resources parameter="ApplicationResources"/>            <plug-in className="org.apache.struts.validator.ValidatorPlugIn">            <set-property            property="pathnames"            value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>            </plug-in>            <plug-in            className="org.springframework.web.struts.ContextLoaderPlugIn">            <set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>            </plug-in>            </struts-config>            

清单 5 是一个典型的 struts-config.xml 文件,只有一个小小的差别。它注册 Spring 代理类的名称,而不是声明动作的类名,如(1)处所示。DelegatingActionProxy 类使用动作映射名称查找 Spring 环境中的动作。这就是我们使用 ContextLoaderPlugIn 声明的环境。

将一个 Struts 动作注册为一个 Spring bean 是非常直观的,如清单 6 所示。我利用动作映射使用 <bean> 标记的名称属性(在这个例子中是 "/searchSubmit")简单地创建了一个 bean。这个动作的 JavaBean 属性像任何 Spring bean 一样被填充:


清单 6. 在 Spring 环境中注册一个 Struts 动作

            <?xml version="1.0" encoding="UTF-8"?>            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"            "http://www.springframework.org/dtd/spring-beans.dtd">            <beans>            <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>            <bean name="/searchSubmit"            class="ca.nexcel.books.actions.SearchSubmit">            <property name="bookService">            <ref bean="bookService"/>            </property>            </bean>            </beans>            





回页首


动作委托的优点

动作委托解决方法是这三种方法中最好的。Struts 动作不了解 Spring,不对代码作任何改变就可用于非 Spring 应用程序中。RequestProcessor 的改变不会影响它,并且它可以利用 Spring AOP 特性的优点。

动作委托的优点不止如此。一旦让 Spring 控制您的 Struts 动作,您就可以使用 Spring 给动作补充更强的活力。例如,没有 Spring 的话,所有的 Struts 动作都必须是线程安全的。如果您设置 <bean> 标记的 singleton 属性为“false”,那么不管用何种方法,您的应用程序都将在每一个请求上有一个新生成的动作对象。您可能不需要这种特性,但是把它放在您的工具箱中也很好。您也可以利用 Spring 的生命周期方法。例如,当实例化 Struts 动作时,<bean> 标记的 init-method 属性被用于运行一个方法。类似地,在从容器中删除 bean 之前,destroy-method 属性执行一个方法。这些方法是管理昂贵对象的好办法,它们以一种与 Servlet 生命周期相同的方式进行管理。





回页首


拦截 Struts

前面提到过,通过将 Struts 动作委托给 Spring 框架而整合 Struts 和 Spring 的一个主要的优点是:您可以将 Spring 的 AOP 拦截器应用于您的 Struts 动作。通过将 Spring 拦截器应用于 Struts 动作,您可以用最小的代价处理横切关注点。

虽然 Spring 提供很多内置拦截器,但是我将向您展示如何创建自己的拦截器并把它应用于一个 Struts 动作。为了使用拦截器,您需要做三件事:

  1. 创建拦截器。
  2. 注册拦截器。
  3. 声明在何处拦截代码。

这看起来非常简单的几句话却非常强大。例如,在清单 7 中,我为 Struts 动作创建了一个日志记录拦截器。 这个拦截器在每个方法调用之前打印一句话:


清单 7. 一个简单的日志记录拦截器

            package ca.nexcel.books.interceptors;            import org.springframework.aop.MethodBeforeAdvice;            import java.lang.reflect.Method;            public class LoggingInterceptor implements MethodBeforeAdvice {            public void before(Method method, Object[] objects, Object o) throws Throwable {            System.out.println("logging before!");            }            }            

这个拦截器非常简单。before() 方法在拦截点中每个方法之前运行。在本例中,它打印出一句话,其实它可以做您想做的任何事。下一步就是在 Spring 配置文件中注册这个拦截器,如清单 8 所示:


清单 8. 在 Spring 配置文件中注册拦截器

            <?xml version="1.0" encoding="UTF-8"?>            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"            "http://www.springframework.org/dtd/spring-beans.dtd">            <beans>            <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>            <bean name="/searchSubmit"            class="ca.nexcel.books.actions.SearchSubmit">            <property name="bookService">            <ref bean="bookService"/>            </property>            </bean>            <!--  Interceptors -->            <bean name="logger"            class="ca.nexcel.books.interceptors.LoggingInterceptor"/> |(1)            <!-- AutoProxies -->            <bean name="loggingAutoProxy"            class="org.springframework.aop.framework.autoproxy.            BeanNameAutoProxyCreator"> |(2)            <property name="beanNames">            <value>/searchSubmit</valuesgt; |(3)            </property>            <property name="interceptorNames">            <list>            <value>logger</value> |(4)            </list>            </property>            </bean>            </beans>            

您可能已经注意到了,清单 8 扩展了 清单 6 中所示的应用程序以包含一个拦截器。具体细节如下:

  • 在 (1) 处,我注册了这个拦截器。
  • 在 (2) 处,我创建了一个 bean 名称自动代理,它描述如何应用拦截器。还有其他的方法定义拦截点,但是这种方法常见而简便。
  • 在 (3) 处,我将 Struts 动作注册为将被拦截的 bean。如果您想要拦截其他的 Struts 动作,则只需要在 "beanNames" 下面创建附加的 <value> 标记。
  • 在 (4) 处,当拦截发生时,我执行了在 (1) 处创建的拦截器 bean 的名称。这里列出的所有拦截器都应用于“beanNames”。

就是这样。就像这个例子所展示的,将您的 Struts 动作置于 Spring 框架的控制之下,为处理您的 Struts 应用程序提供了一系列全新的选择。在本例中,使用动作委托可以轻松地利用 Spring 拦截器提高 Struts 应用程序中的日志记录能力。





回页首


结束语

在本文中,您已经学习了将 Struts 动作整合到 Spring 框架中的三种窍门。使用 Spring 的 ActionSupport 来整合 Struts(第一种窍门中就是这样做的)简单而快捷,但是会将 Struts 动作与 Spring 框架耦合在一起。如果您需要将应用程序移植到一个不同的框架,则需要重写代码。第二种解决方法通过委托 RequestProcessor 巧妙地解开代码的耦合,但是它的可扩展性不强,并且当 Struts 的 RequestProcessor 变成一系列命令时,这种方法就持续不了很长时间。第三种方法是这三种方法中最好的:将 Struts 动作委托给 Spring 框架可以使代码解耦,从而使您可以在您的 Struts 应用程序中利用 Spring 的特性(比如日志记录拦截器)。

三种 Struts-Spring 整合窍门中的每一种都被实现成一个完整可用的应用程序



分享到:
评论

相关推荐

    【数据驱动】复杂网络的数据驱动控制附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    (源码)基于Qt框架的智能家居管理系统.zip

    # 基于Qt框架的智能家居管理系统 ## 项目简介 本项目是一个基于Qt框架开发的智能家居管理系统,旨在提供一个集成的平台来监控和管理家庭环境中的各种传感器数据,如温度、湿度、烟雾状态、红外状态等。系统通过图形界面实时展示数据,并提供警报功能以应对异常情况。 ## 项目的主要特性和功能 1. 实时数据监控通过Qt和Qwt库创建的曲线图,实时显示温度和湿度数据。 2. 多传感器支持支持温度、湿度、烟雾、红外等多种传感器的监控。 3. 警报系统当传感器数据超过设定阈值时,系统会触发警报,并通过界面显示警告信息。 4. 用户交互提供滑动条和复选框,允许用户调整警报阈值或关闭警报。 5. 网络通信通过TCP套接字与服务器通信,获取和发送传感器数据及网络拓扑信息。 6. 蓝牙数据读取支持通过蓝牙读取传感器数据并更新界面显示。 ## 安装使用步骤 1. 环境准备 确保已安装Qt开发环境。 安装Qwt库以支持曲线图功能。

    【路径规划】一种考虑拥塞的改进路径规划算法CCPF-RRT附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    基于springboot高性能计算中心的高性能集群共享平台源码数据库文档.zip

    基于springboot高性能计算中心的高性能集群共享平台源码数据库文档.zip

    (源码)基于JavaFX的图片管理系统.zip

    # 基于JavaFX的图片管理系统 ## 项目简介 本项目是一个基于JavaFX的图片管理系统,旨在提供一个用户友好的界面来管理和浏览图片。系统支持图片的预览、重命名、删除、复制、粘贴等操作,并提供了多种排序和展示方式。 ## 项目的主要特性和功能 1. 预览窗口 目录树展示 缩略图预览 单选、多选(Ctrl+左键)、框选功能 图片信息显示(如文件名、大小、最后修改时间等) 2. 右键菜单 复制粘贴图片 单选和多选重命名 删除图片 3. 展示窗口 图片放大缩小 左右切换图片 幻灯片播放功能 4. 排序功能 按文件名排序 按文件大小排序 按最后修改时间排序 5. 其他功能 图片信息封装(ImageBean) 文件树节点管理(FileTreeItem)

    (源码)基于Windows窗体的披萨店厨房管理系统.zip

    # 基于Windows窗体的披萨店厨房管理系统 ## 项目简介 这是一个基于Windows窗体的应用程序,主要用于披萨店的厨房管理。该系统通过WebSocket与服务器进行实时通信,显示从服务器接收到的订单信息。用户界面简洁明了,易于操作。 ## 项目的主要特性和功能 1. 实时通信: 通过WebSocket与服务器进行实时数据交换,获取订单信息。 2. 订单显示: 在窗体上实时显示订单信息,包括订单号和菜品等。 3. 界面简洁: 用户界面设计简洁,易于操作。 4. 定时刷新: 定时器用于定时从服务器获取消息,确保数据的实时性。 5. 错误处理: 在连接过程中遇到技术问题时会显示错误消息框。 6. 退出功能: 提供退出按钮,点击后程序会退出。 ## 安装和使用步骤 1. 下载项目源码文件: 从相关仓库或网站下载此项目的源码文件。 2. 准备开发环境: 确保你的开发环境已经安装了必要的软件和工具,如Visual Studio等。

    基于springboot高校创新创业课程体系源码数据库文档.zip

    基于springboot高校创新创业课程体系源码数据库文档.zip

    基于springboot汽车美容与保养网站源码数据库文档.zip

    基于springboot汽车美容与保养网站源码数据库文档.zip

    基于springboot校友录管理系统源码数据库文档.zip

    基于springboot校友录管理系统源码数据库文档.zip

    Cocos2d-x教程视频使用Eclipse在Ubuntu下搭建Cocos2d-x 3集成开发环境

    Cocos2d-x教程视频使用Eclipse在Ubuntu下搭建Cocos2d-x 3集成开发环境提取方式是百度网盘分享地址

    毕业设计&课设_基于 vue.js 与 node.js 的毕业设计项目,含多模块功能,用于大学信息交流平台开发 .zip

    该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

    基于springboot服装生产管理信息系统源码数据库文档.zip

    基于springboot服装生产管理信息系统源码数据库文档.zip

    (源码)基于Spring Boot和Redis的高并发秒杀系统.zip

    # 基于Spring Boot和Redis的高并发秒杀系统 ## 项目简介 本项目是一个基于Spring Boot框架开发的高并发限时抢购秒杀系统。系统实现了基本的登录、查看商品列表、秒杀、下单等功能,并针对高并发场景进行了优化,包括系统缓存、降级和限流等措施。通过Redis、RabbitMQ等中间件技术,确保系统在高并发情况下的稳定性和性能。 ## 项目的主要特性和功能 ### 核心功能 用户登录用户可以通过手机号和密码进行登录,系统支持两次MD5加密确保密码安全。 商品列表展示用户可以查看所有商品的列表,包括商品的详细信息、库存数量、秒杀价格等。 商品详情展示用户可以查看单个商品的详细信息,包括秒杀状态和剩余时间。 秒杀下单用户可以参与秒杀活动,系统通过本地标记、Redis预处理、RabbitMQ异步下单等技术确保高并发下的系统稳定。 订单详情用户可以查看自己的订单详情,包括订单状态、商品信息等。 ### 技术优化

    基于springboot校园论坛系统源码数据库文档.zip

    基于springboot校园论坛系统源码数据库文档.zip

    飞利浦CT机自动推送配置

    飞利浦CT机自动推送配置

    PHP 学习教程(入门到实践)

    本教程介绍了 PHP 的基础语法、函数与面向对象编程、文件操作、以及与 MySQL 的交互。通过实例与练习,帮助您快速入门 PHP 开发,为动态网站和 Web 应用打下坚实基础。

    (源码)基于Android的玩具租赁系统.zip

    # 基于Android的玩具租赁系统 ## 项目简介 本项目是一个基于Android平台的玩具租赁系统,旨在为用户提供一个便捷的玩具租赁服务。系统涵盖了用户注册、登录、玩具浏览、租赁、个人信息管理等功能,通过前后端分离的架构实现。 ## 项目的主要特性和功能 1. 用户管理 用户注册与登录支持通过昵称、手机号等多种方式进行注册和登录。 找回密码用户可以通过手机验证码找回密码。 个人信息管理用户可以修改个人信息,包括姓名、密码等。 2. 玩具租赁 玩具浏览用户可以浏览不同分类的玩具,查看玩具详情。 租赁功能用户可以选择玩具进行租赁,并查看租赁订单。 3. 搜索与推荐 搜索功能用户可以通过关键词搜索玩具。 推荐系统根据用户的历史行为推荐相关玩具。 4. 测试与集成 单元测试确保基础功能的正确性。 集成测试测试Spring Boot应用的上下文加载情况。

    65-MarkdownEditorsPart1-Code.zip

    6个免费的所见即所得Markdown桌面编辑器的实用指南,用于在Windows平台上编写GitHub Readme.md文件(截至2024年9月)。

    【路径规划】基于深度学习DQN的机器人路径规划附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    (源码)基于Arduino IDE和Flutter的电动汽车充电监控系统.zip

    # 基于Arduino IDE和Flutter的电动汽车充电监控系统 ## 一、项目简介 这是一个电动汽车充电监控项目,旨在通过Arduino IDE创建一个HTTP Web服务器,结合ESP32芯片、电源管理集成电路(IC)、电流和电压传感器,实现对电动汽车充电过程的实时监控和管理。同时,该项目还包括一个基于Flutter开发的移动应用,方便用户通过移动设备查看和控制充电过程。 ## 二、项目的主要特性和功能 1. HTTP Web服务器通过Arduino IDE创建HTTP Web服务器,实现与ESP32芯片的通信。 2. ESP32芯片连接WiFi,并作为中间设备连接电源管理集成电路(IC)、电流和电压传感器。 3. 远程监控与控制用户可以通过移动设备访问特定的网页,输入充电瓦数并提交,实现远程监控和控制充电过程。 4. Flutter应用项目中的Flutter应用提供了用户友好的界面,方便用户查看充电状态、调整充电参数等。

Global site tag (gtag.js) - Google Analytics