构建一个应用(续)

构建一个简单的Shopify应用 Shopify是一个快速发展的电子商务平台,每月增加成千上万的新商人。 Shopify平台的妙处在于Shopify公开表示他们并不关心为商家解决所有问题。 取而代之的是,他们创建了自己的API和App Store,以便独立的开发人员可以构建商户想要的功能(并为其付费)。 这意味着您有机会使用Shopify应用程序扩展和自定义Shopify,无论您有自己要改善的Shopify商店还是想要将... 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> 3.4 构造应用 我们已经详细探讨了应用的驱动,踢了踢轮胎,并检查了引擎盖下面的东西,准备上路了。我们已经知道了要做什么,并且怎样做,但是从那里开始构建的你应用呢? 在这一节,我们回到开头并向你展示可以如何从头至尾建立你的应用。因为我们已经有一个很好的关于我们想要应用干什么的印象,我们从一个实际的需求集开始。这样我们可以创建一个白板计划,包括那些明显的对象以及我们准备叫它们什么名称。然后我们就可以开始为对象编码,精化和扩展所作的计划。这种 计划/编码,再精化-计划/再精化-编码的方法称之为 “螺旋式” 方法。 当然,有其它方式来进行软件开发。其它方法也可以很好的用于Struts。但本节的目的并不是节是软件开发方法论。我们想要的是展示,构架一个简单的Struts 应用需要做些什么。所以,让我们开始上路喽... 3.4.1 定义需求 Requirements are the effects that the computer is to exert in the problem domain, by virtue of the computer’s programming —Practical Software Requirements, by Benjamin L. Kovitz 既然我们已经有一个关于应用需要做些什么的充分理解,从一个需求集开始是一个很好的实践方法。下面的章节,我们将汲取最简单有用的需求集。 我们的简单需求文档包括3个主要部分:目标、需求、规约。 表格 错误!文档中没有指定样式的文字。-1 需求文档的主要标题 标题 目的 目标 我们在问题领域中需要达到的结果 域需求 为达到目标,我们需要实现的东西 编程规约 我们要实现需求需要做的事情 3.4.1.1 目标l 允许有权限的用户向应用标识自己 3.4.1.2 域需求 允许用户递交他们的身份信用信息(username 和password) 检验递交的信息是否有效 允许纠正无效的信用信息 身分信用信息有效时,通知用户 允许校验有效的用户访问需要权限的特征 允许用户在需要时,使访问无效 3.4.1.3 程序规约 可以从标准的web 浏览器访问, 可以使用或不使用JavaScript 为新访问者从welcome 页面提供登陆链接 允许在logon 页面输入用户信用(身份)信息 要求每个身份信息包含1-20个字符 要求输入username 和password 提交信息给业务层方法来进行校验 返回无效的身份信息给用户做纠正 如果身份有效,使用户登入 登陆后,用用户名定制welcome 页面 允许登陆的用户从页面登出 当然,这是一个非常简单的规约。许多规约要消耗大量的纸张,并用很多图, 数据表, 屏幕定义和问题域的详细描述来进行修饰。 3.4.2 规划应用 根据手头的这些需求,我们可以开始勾画应用并规划要用哪些对象来实现这些程序规范。一个方法是列出规约的列表,以及有助于实现他们的组件清单。通常,团队做这种事情是在一个大白板上进行,作为一个初始项目会议的一部分。 注意 这个过程中非常重要的一点是要注意到,规约项目和实现它们的组件之间并不是严格的1:1对应关系。虽然规约和程序都是为了一个相同的目标,它们却是从不同的方面的接近目标。 所以,象这样的列表并不是一个“规范化”的东西。某些规约可能已不止一个组件的方式出现。 3.4.2.1 视图 实际上,大多数应用都是以一个故事板(情节串联板)开始的。JSP定义应用的可见部分。 下面是表现层的大概要求。 表格 错误!文档中没有指定样式的文字。-2 白板视图规划 规约 JSP页面 向新访问者提供从欢迎页面开始的登陆 Welcome.jsp 允许在登陆页面输入用户身份信息(username 和 password) Welcome.jsp 返回无效的身份信息给用户纠正 Logon.jsp 当用户登陆进去时,根据用户名定制欢迎页面 Welcome.jsp 允许将校验的用户从welcome 页面登出 Welcome.jsp 可以从标准浏览器中访问,有或者没用JavaScript Logon.jsp; Welcome.jsp 导引用户到欢迎页面 index.jsp 请注意我们在规约中加了一个自定的规约。这是个小技巧,在 Struts 应用中使应用的welcome 页面重定向到一个Struts action。这尽可能将控制流纳入框架,以便有助于在应用增长时最小化改变。 3.4.2.2 控制器 在一个强壮的分层应用中(见第2章), 所有对页面和数据的请求请求都传递给控制层。表8是我们的控制器( “前端控制器” [Go3])的需求。 表格 错误!文档中没有指定样式的文字。-3 控制器规划 规约 ActionForms 允许在登录页面中输入身份信息(username and password) LogonForm Action 用业务层方法校验身份信息 LogonAction 向返回返回无效身份信息供纠正 LogonForm;LogonAction 如果身份信息有效登入用户 LogonAction 允许经过校验的用户从欢迎页面登出 LogoffAction ActionForwards 向新访问用户提供从欢迎页面的登录 Welcome, logon 允许经过校验的用户从欢迎页面登出 Logoff ActionMappings 提交身份信息给业务方法校验 LogonSubmit Utility 记录所有内部常数 Constants 请注意我们自己添加了一个规约 “记录所有内部常数”。这在多层应用中也非常重要,因为这些常数可以“松散绑定”。Java 编译器不能验证我们在 XML 配置 文件中使用的标志,所以必须仔细跟踪我们所使用的标志。 3.4.2.3 模型 我们对数据访问层仅有一个需要。 表格 错误!文档中没有指定样式的文字。-4 model规划 规约 方法接口 提交身份信息给业务方法校验 boolean isUserLogon(String username,String password); 3.4.3 规划源代码树 现在有了一个基线应用计划,我们可以规划一下应用的代码结构。因为应用很简单,我们可以为页面使用一个单独的子目录,为Java类使用一个单独的包。 我们的结构如图3-6: 注意 Struts希望在classpath中有一个应用资源包。logon 应用将它的属性文件方在其自己的资源包中。国际化应用可能具有多个属性文件。将他们放入包中可以方便进行组织。我们的构建文件(build file )将这些文件拷贝到类文件夹,以便在运行时它们可以在classpath中找到。在进行某些资源改变的时候,请记住要重新构建应用。 图 错误!文档中没有指定样式的文字。-1 代码结构 如果你想跟随我们并建立了你自己的logon应用, 跳到代码结构和Struts classes得好办法是部署一个空白的应用: 下载一个空白应用。 将blank.war拷贝为logon.war。 将 WAR 放入容器的自动部署文件夹 (通常是webapps). 这既是为什么要提供一个 Blank 应用。它们其实是一个通用的应用模板。我们将在第3.4.4到 3.4.8节讨论基本结构。然后再来关注logon 应用。 为了修改和重新部署应用, 需要安装一些开发工具。 3.4.4 设置开发工具 略 3.4.4.1 安装 Ant 略 3.4.4.2 安装jEdit 略 3.4.5 设置 build.xml文件 象现今的其他一些Java 产品,Struts 也希望使用Jakarta Ant工具 [ASF, Ant] 作为构建过程的一部分。Ant 也使用一个XML 配置文件, 名字叫build.xml。 通常,你可以为你的应用设置一个固定的build 文件,自始至终不变。在第4章,我们再表述 logon 应用的构建文件。 3.4.6 设置web.xml文件 Java 2 Servlet 框架使用一个配置文件来帮助设置应用。 web 部署描述符, web.xml, 标明需要的servlets,以及其他应用设定参数。其格式在 servlet 规范[Sun, JST]有描述。大多数 Struts 应用仅需要部署一个单一的servlet和几个标记库,以便保持相对简单。我们在第4章表述logon应用的web.xml 文件。 3.4.7 设置 struts-config.xml 文件 非常象web 部署描述符, Struts 也有一个 XML 配置 文件。你的应用在此注册其 ActionForm, ActionForward, 和ActionMapping。每个类在文件中都有其自己的一个配置段,在这里你可以定义在启动时需要创建的缺省对象。下面是我们的起始Struts 配置文件: 表格 错误!文档中没有指定样式的文字。-5 配置文件 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts configuration 1.0//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd"> <struts-config> <form-beans> <!-- ... --> </form-beans> <global-forwards> <forward name="welcome" path=" /Welcome.do"/> <!-- ... --> </global-forwards> <action-mappings> <action path="/Welcome" type="org.apache.struts.actions.ForwardAction" parameter="/pages/Welcome.jsp"/> <!-- ... --> </action-mappings> </struts-config> 在你配置你的应用时, 你可以从一个空白配置文件开始,就像这个一样,并一步步加入你需要的对象。我们将在本章余下的内容做这个事情,以便你可以看到是如何实际配置Struts 配置文件。第4章将更深入讨论Struts 配置文件。你可能会注意到我们的起始并不是完全空白的。为方便已经提供了一个缺省 welcome forward 。 3.4.7.1 welcome action 通常, 路由页面流要尽可能的通过Struts 控制器。这样将应用总体设计都保持在Struts 配置之中。这样你可以从一个单一的地方来调整应用的控制流。不幸的是, 容器要求一个物理的welcome 页面。在web 部署 描述符 (web.xml) 中列出一个Struts action URI作为welcome 页面是不允许的。 最好的方案是在一个根index.jsp文件中将控制重定向到你的welcome action。struts-blank 就提供了这样一个根。这是一个极其简单页面仅有两行的页面: <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <logic:redirect forward="welcome"/> 空白应用提供 index.jsp 转发页面和一个缺省的welcome 页面。我们将照原样使用index.jsp 弹要对welcome 页面做些改变。然而在开始之前,我们测试一下部署情况。 3.4.8 测试部署情况 在测试一个新的应用之前确保一切OK, 应该打开一个运行的应用作为基线。Struts Blank 应用是一个基线应用的好选择。其缺省welcome 页面包括了一些基本的系统检测,以看看配置文件是否被正确装入,标签扩展是否能找到,以及消息资源文件是否有效。 Struts Blank 应用的 WAR 文件可以在本书的站点或者Struts发布包中找到。将blank.war 文件放入容器的自动部署文件夹并重新启动容器。然后可以使用这个url访问应用的welcome 页面 : http://localhost:8080/blank 如果一切OK, 就会看到页面图3-8一样的页面: 图 错误!文档中没有指定样式的文字。-2 空白应用的欢迎页面 下面是它的源代码: <%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <html:html locale="true"> <head> <title><bean:message key="index.title"/></title> <html:base/> </head> <body bgcolor="white"> <logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application"> <font color="red"> ERROR: Application resources not loaded -- check servlet container logs for error messages. </font> </logic:notPresent> <h3><bean:message key="index.heading"/></h3> <p><bean:message key="index.message"/></p> </body> </html:html> 清单 错误!文档中没有指定样式的文字。-1 空白应用的缺省欢迎页面源代码 3.4.9 构造欢迎页面 大多数软件开发方法的一个基本原则是尽快的得到一个可以工作的原型。如果你同意这点。那么我们应该做的第一件事就是根据我们的规约构造我们的welcome 页面。这个welcome 页面早期版本, 没有逻辑条件,可能看起来像: <%@ taglib uri="/tags/struts-html" prefix="html" %> <html> <head> <title>Welcome World!!</title> <html:base/> </head> <body> </ul> <li><html:link forward="logon">Sign in</html:link</li> </ul> <img src='struts-power.gif' alt='Powered by Struts'> </body> </html> 清单 错误!文档中没有指定样式的文字。-2 欢迎页面的早期版本 因为这里引用到logon ActionForward,我们需要将它添加到我们的Struts配置中去。我们也可以改变缺省 welcome 页面从Index.jsp 到Welcome.jsp: <global-forwards> <forward name="logon" path /Logon.do"/> <forward name="welcome" path /Welcome.do"/> <!-- ... --> </global-forwards> 这时,我们可以重新启动容器装入新的Struts 配置。 某些容器,象 Tomcat,让你重新装入一个单独的应用。 1.0 vs 1.1 在Struts 1.0中,有大量的管理Action,包括重新装入Struts 配置。在Struts 1.1被取消了,因为他们和支持多应用模块相冲突. 一旦新的配置装入, 我们可以打开新的welcome 页面: http://localhost:8080/logon/ 你将看到图3-9的屏幕。 图 错误!文档中没有指定样式的文字。-3 登录前的欢迎屏幕 然而,如果你点击连接,你将无法前进,会得到图3-10的信息。 为修正这个错误,我们需要看看下一个目标,构造logon 页面。 图 错误!文档中没有指定样式的文字。-4 文件未找到错误 3.4.10 构造logon 页面 回去看看3.4.2的白板, 我们看到logon 页面需要收集username 和 password, 并提交到一个名为/LogonSubmit的Mapping。这意味着我们需要创建一个Struts form 来标明 /LogonSubmit action, 作为一个文本域和密码域的输入控件。下面是logon.jsp的源代码: <%@ taglib uri="/tags/struts-html" prefix="html" %> <html><head><title>Sign in, Please!</title></head> <body> <html:errors/> <html:form action="/LogonSubmit" focus="username"> <table border="0" width="100%"> <tr> <th align="right>"Username: </th> <td align="left"><html:text property="username"/></td> </tr> <tr><th align="right">Password: </th> <td align="left"><html:password property="password"/></td> </tr> <tr> <td align="right"><html:submit property="submit" value="Submit"/></td <td align="left"><html:reset/></td> </tr> </table> </html:form> </body> </html> 清单 错误!文档中没有指定样式的文字。-3 Logon页面的源代码 <html:form> 标签记引用一个 ActionMapping 对象, 它再引用其他对象(org.apache.struts.action.ActionMapping)。我们先配置ActionMapping,然后是它使用的对象: <action-mappings <action path="/LogonSubmit" name="logonForm" scope="Request" validate="true" input="/pages/Logon.jsp"/> <!-- ... --> </action-mappings> 两个相关的对象是 logonForm form bean 和 LogonAction。我们也需要在Struts 配置中注册ActionForm Bean。我们使用的名称成为对象在请求上下文中创建时的缺省属性名称。 <form-beans <form-bean name="logonForm" type="app.LogonForm"/> <!-- ... --> </form-beans 这时我们需要加入两个特别的Java 类, LogonForm 和 LogonAction。 3.4.11 构造Constants类 虽然不是严格要求,但是将ActionForward 名称和其他标记记录在文档中则是强烈推荐的。这其实很简单,而且可以使你的代码易于管理。我们展示代码时,通常忽略了 JavaDoc 说明。但是,在这里我们将留下他们。为什么?因为整个类都是记录常数的类。所以,在这里,文档就是代码。下面是整个类的代码: package app; public final class Constants { /** * The session scope attribute under which the Username * for the currently logged in user is stored. */ public static final String USER_KEY = "user"; /** * The value to indicate debug logging. */ public static final int DEBUG = 1; /** * The value to indicate normal logging. */ public static final int NORMAL = 0; /** * The token that represents a nominal outcome * in an ActionForward. */ public static final String SUCCESS= "success"; /** * The token that represents the logon activity * in an ActionForward. */ public static final String LOGON = "logon"; /** * The token that represents the welcome activity * in an ActionForward. */ public static final String WELCOME = "welcome"; } 清单 错误!文档中没有指定样式的文字。-4 Constants类的源代码 3.4.12 构造其他类 我们在3.3.8 和 3.3.9展示了logonForm和logonAction的源代码。我们也需要在第1章中讲述过的UserDirectory 和UserDirectoryException 类。我们可以将他们不经改变的加入到我们的新应用中。在我们的源代码结构中将他们放在/WEB-INF/src/java/app/。 图 错误!文档中没有指定样式的文字。-5 LogonAction,LogonForrm以及其它Java类的位置 LogonAction 也引用 Constants 类。在便以前我们要先加入它。 3.4.13 创建user directory 在第1章,我们引入了一个简单的registration 应用来存储user ID和password。这些登陆账号纪录在一个标准的属性文件中,名为user.properties。它可以从那个应用中引入,或者在 WEB-INF/src/java/resources下重新创建,如图3-12: 图 错误!文档中没有指定样式的文字。-6 用户属性文件的位置 属性文件是一个简单的文本文件。这里是一个简单的例子,使用本书作者的名为用户名,姓为密码。 TED=Husted CEDRIC=Dumoulin GEORGE=Franciscus DAVID=Winterfeldt CRAIG=McClanahan 如果你喜欢,你可以只输入这些,或者你愿意输入的内容,并将他们存放在/WEB-INF/src/java/resources/user.properties。只是保证user ID全部大写,因为这是业务逻辑中要求的。 当然,你的应用也可以容易的根据一个JNDI 服务,或者数据库来进行校验, 或者使用容器的安全领域。我们在第14章说明在Struts中使用数据服务。 3.4.14 配置ActionErrors 可能记得, LogonForm 和 LogonAction 都要产生错误信息。ActionError 系统是集成在应用消息之中的。 在测试LogonForm 和LogonAction 之前,我们需要添加这些消息到Application.properties 文档中: errors.header=<H3><font color="red">Validation Error</font></H3>You must correct the following error(s) before proceeding:<UL> errors.footer=</UL><HR> error.username.required=<LI>Username is required</LI> error.password.required=<LI>Password is required</LI> error.logon.invalid=<LI>Username and password provided not found in user directory. Password must match exactly, including any lower or upper case characters.</LI> 1.0 vs 1.1 Struts 1.1中的新标记允许从消息中忽略标记。见第10章的详细内容。 作为构建过程的一部分,我们将应用资源文档从/WEB-INF/src/java/resource拷贝到 classes 文件夹下的资源包,这里ActionServlet 才能找到它们。 3.4.15 编译并测试logon 页面 在3.4.8中,我们为logonForm创建了 JSP 页面。但为了使他们运行,我们得添加相应的配置元素和JAVA类,如表10。 表格 错误!文档中没有指定样式的文字。-6 Logon 页面配置元素 配置元素 Java 类 LogonSubmit action-mapping logonForm form-bean LogonAction, subclass of Action LogonForm, subclass of ActionForm 现在我们可以编译应用并测试logon页面了。有一个存好的build.xml文件放在 WEB-INF 目录,你可以在Ant使用它。 按缺省方式构建目标,编译它,将从java源代码构建 Java类,并将应用资源消息文件拷贝到classes 目录。 当构建成功,你可以使用下面的链接进到应用中的 logon 页面。 (根据你的容器如何重新装入Java类,你可能需要重新启动容器。如果不确定,就重启它。) logon 应用应该可以工作的象我们原来漫游的一样 (从3.3.3 到 3.3.6)。所不同的是welcome 页面在用户登录后不会发生变化,或者不提供登出的机会。下面我们将修正它,然后我们的应用就完成了。 3.4.16 修改welcome页面 我们先前的welcome 页面忽略关于判断用户是否登陆的条件逻辑。既然,用户已经可以登陆,我们就可以将这些语句加入,以符合3.3.2中的版本 。黑体部分是我们加入的内容: <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <html> <head> <title>Welcome!</title> <html:base/> </head> <body> <logic:present name="user"> <h3>Welcome <bean:write name="user" property="username"/>!</h3> </logic:present> <logic:notPresent scope="session" name="user"/> <h3>Welcome World!</h3> </logic:notPresent> <html:errors/> <ul> <li><html:link forward="logon">Sign in</html:link></li> <logic:present name="user"> <li><html:link forward="logoff">Sign out</html:link></li> </logic:present> </ul> <img src='struts-power.gif' alt='Powered by Struts'> </body> </html> 清单 错误!文档中没有指定样式的文字。-5 welcome 页面 (/页面s/Welcome.jsp)的修订版本 如图3-13, 这使我们回到了原来的情形。当用户到来时,他被邀请登录进去。一旦登录进去,则按名字欢迎它并提供登出的机会。这是你的进步! 3.4.17 Struts ActionForward Action 如果你注意到你浏览器的地址栏,你可能会注意到我们一直没有暴露JSP 页面的地址。 许多应用可能不注意这个方式,但如果你想要严格的MVC架构(见第2章), 你可能不希望暴露一些关于你的视图的实现,包括你是否使用JSP 页面或者你如和存储它们。理想情况下,所有的导航都应该通过.do Action进行,因为他们都通过控制器管理。 当然,并不是所有的事情控制器都能干的很好。这也是为何使用logon 和 welcome 页面。他们并不需要任何来自于model的信息,直接提供显示JSP 页面的连接。 但这也使用户可以将页面的位置存为书签。接下来,你可能在显示logon 页面之前需要执行一些背景动作,或者你可能需要移动或者将JSP 页面改名。如果用户将这些页面存为书签了,他们就会回到旧的地址,绕开你的逻辑,并返回一个 File not found 错误。在实践中,通常导致将遗留检查放入服务器页面并重定向到web server—事情发生错误的方式更多了,并有更多代码需要维护。 道德?我们必须尽可能虚拟化详细的导航。否则,我们就会不断的为浏览器是否进行缓存或者存储进行补偿。不要直接连接到物理的JSP, 我们应该总是连接到一个虚拟的 Struts Action, 然后由它提供相应的页面。 当然,不管是否需要,为每个页面编写一个Action, 会是一个非常繁琐的工作。一个更有效的办法是,部署一个有用的 Action,它可以在Struts 配置中定制,并在需要的地方可以重用。因为Struts 为每个Action创建一个多线程实例,这是一个非常有效的办法,确保控制保留在控制器之中。我们需要做的就是将Action 和 path传递给页面。 高兴的是,你可以使用struts.jar 中的标准的ForwardAction 对象。你可以简单的目标路径作为ActionMappin的parameter属性进行传递: <action path=" /Welcome" type="org.apache.struts.action.ForwardAction" parameter="/pages/Welcome.jsp"/> ForwardAction 将会从mapping 中查找目标路径,并使用它来返回一个ActionForward 给servlet。 实际结果是http://localhost:8080/logon/pages/Welcome.jsp不会出现在浏览器的地址栏中,那样的话就可以被标为书签直接访问,浏览其中的Action URI 会出现: http://localhost:8080/logon/Welcome.do 用户仍然可以把这个地址记为书签,但是现在你有更多的控制了。你可以logon 活动的实现而不用担心有什么被浏览器记为书签了。之前,你可能不得不考虑如果他们直接访问原来的服务器地址,会发生什么事情。 在MVC架构中,action就是你的API。服务器页面是一个实现细节。如果JSP作为导航系统的一部分暴露给了浏览器,控制器和试图层就混合了,MVC的优势被削弱。 在需要直接导航至其他页面时,我们也可以加入其他ForwardAction实例。因为应用仅仅实例化一个ForwardAction,我们所添加的实际上是一个ActionMapping 对象。如果要求使用ForwardAction通常的MVC架构原因还不充分,Struts 1.1引入的模块化特征要求所有的 JSP 请求都要通过Action。这是因为每个模块有其自己的配置上下文并且控制必须通过ActionServlet 控制器传递,以便为JSP页面选择配置。当然,如果你使用单个的缺省应用,这并不是必须的。但是如果从一开始便遵循这个实践,那么你便可以在不改变任何东西的情况下将你的应用变成一个模块。 3.5 小结 不管你在开发团队中担任何种角色—工程师,设计员,架构师,QA—对整个应用是如何运行的有个总体印象总是有帮助的。在这一章,我们综合的解剖了一个小而有用的应用 。 通过漫游,解剖,然后构造一个logon 应用,我们向你展示了 Struts 框架实际上是如何工作的。作为构造阶段的一部分,我们还创建了一个设计文档,来规划我们的目标、客户需求和程序规约。要使一个应用能运行,我们还构建了应用的 web.xml,Ant的build.xml脚本,以及Struts配置文件。 为了使正确的构建部件到位,我们按需要的顺序构建了每个组件。 在此过程中,我们也指出了最好的实践方法,并强调分离模型、视图和控制器的重要性。 在第4章,我们会详细探讨 Struts配置文件。如我们在此所见,配置扮演了一个强有力的角色,使应用易于设计和维护。
Cursor全攻略——下载安装、无限续杯及企业级应用实战 本文系统性地讲解了Cursor的下载安装流程、核心功能使用技巧及企业级开发实战方案,特别针对"无限续杯"机制进行了深度解析。帮助开发者从零基础快速掌握这一革命性AI编程工具,适用于个人开发者、初创团队及企业级项目开发场景。 阅读详情

相关推荐

构建第一个XR 应用

将Assets–> Samples –> Rokid Unity XR SDK–> x.x.x –>UXR Sample –> Scenes 目录下的所有场景拖到Build Settings 中,点击Build,配置APK 名称即可完成编译。导入成功后,会在项目工程中添加Assets–> Samples –> Rokid Unity XR SDK 文件夹,该文件夹即为Sample 工程。Tips:Sample 使用过程中,注意各脚本的配置,如果发现脚本丢失需要重新搭配。这里以创建一个Cube 为例。

soso1968的博客 1171

Android 程序框架设计

这篇文章主要内容来自于之前我讲的一个PPT文档,现在将其整理如下。欢迎指正。以下的内容都是来自于我自身的经验,欢迎大家多提自己的建议。 1、一些概念 模式的定义: 每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心。通过这种方式,你可以无数次地使用那些已有的解决方案,无需在重复相同的工作。 什么是设计模式? 设计模式是在某种特别的情况下,针对某种问

永远即等待的专栏 4万+

React 入门教程:构建第一个 React 应用

本教程将带你从零开始构建你的第一个 React 应用。我们将创建一个简单的计数器应用,涵盖 React 的基本概念和开发流程。

vvilkin的学习备忘 1696

从头开始构建一个应用

using System; using System.Collections.Generic; using System.IO; using System.Linq; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Control

Shinichi51的博客 432

基于近场动力学的二维疲劳裂纹扩展模型_近场动力学数值模拟的程序实现(1)——引言...

参考书目W. H. Gerstle. 2015. Introduction to Practical Peridynamic: Computational Solid Mechanics Without Stress and Strain.E.Madenci, A.Barut, M.Dorduncu. Peridynamic Differential Operator for Numerical ...

weixin_39764603的博客 1204

蛋白质组学实战指南 | (八)从数据到洞见:差异蛋白筛选与功能解析全流程

本文系统阐述了蛋白质组学数据分析中,从原始数据质控到差异蛋白筛选与功能解析的全流程。重点介绍了数据质量评估、差异蛋白筛选的统计方法(包括多重检验校正)、功能注释与富集分析,以及蛋白互作网络构建与关键节点识别。最后,为如何将生物信息学洞见转化为实验验证提供了清晰的规划思路,助力研究者完成从数据到生物学知识的闭环。

weixin_29250573的博客 372

闪电开发:用Cursor无限续杯10分钟构建可运行原型

在整个过程中,每当我觉得UI不够美观,或者逻辑有点小瑕疵,我只需要继续用自然语言提出要求,比如“把消息列表的样式调整一下,用户消息靠右显示,灰色背景;这听起来简单,但要在一个原型里实现,需要包含前端界面(输入框、对话历史展示)、简单的逻辑判断,以及一个可以交互的后端服务。然后,我直接对AI说:“创建一个简单的聊天机器人界面,包含一个顶部的标题、一个展示聊天历史的消息列表、一个底部的输入框和发送按钮。”几乎在几秒钟内,一个基础的React组件框架就生成了,包含了必要的HTML结构和基础的CSS样式。

SilvermistFalcon19的博客 51

从零开始:手把手教你用Verilog搭建一个可配置的Cache模块(以Vortex GPGPU为例)

本文详细介绍了如何使用Verilog从零开始搭建一个可配置的Cache模块,以Vortex GPGPU为例。内容涵盖Cache设计基础、模块接口与参数化设计、核心子模块实现、仲裁与一致性机制、功能验证与性能调优等关键环节,适合RTL设计初学者和希望深入理解Cache工作原理的工程师。通过实战指南,读者可以掌握硬件代码分析技巧,提升Cache模块的设计能力。

weixin_42552315的博客 441

构建一个ArkTS应用

随着鸿蒙(Harmony OS)的演进发展,先后提供了两种应用模型,FA模型和Stage模型。

W20240618_优快云的博客 1862

RK3588 MPP视频编码实战:从环境搭建到高效封装

本文详细介绍了在RK3588平台上利用MPP(Media Process Platform)进行硬件视频编码的完整实战流程。从MPP库的环境搭建、编译安装,到核心编码参数(如码率控制、GOP、图像对齐)的深入解析,并提供了一个可复用的C++编码器类封装方案,帮助开发者快速实现高效的H.264/H.265视频编码,显著降低CPU占用。

weixin_29192211的博客 350

Kalibr标定避坑指南:如何用AprilGrid板快速完成双目IMU标定

本文详细介绍了使用AprilGrid板进行Kalibr双目IMU联合标定的实战技巧,包括标定工具选型、数据采集优化、标定流程及结果验证。通过AprilGrid板的唯一标识性和抗遮挡优势,结合IMU静止标定和运动激励设计,显著提升标定精度。文章还提供了常见报错处理和高级优化技巧,帮助开发者高效完成传感器标定。

sunny的博客 282

如何用electron构建一个exe应用

在使用 Electron 开发桌面应用时,最终目标通常是将应用打包成一个可执行文件(如.exe文件),以便分发给用户。以下是用 Electron 构建.exe。

zru_9602的博客 2692

李宏毅2025《机器学习》第一讲-生成式AI:技术突破和未来发展

本文基于台湾大学李宏毅教授的“一堂课搞懂生成式人工智慧的技术突破与未来发展”课程内容,系统性地梳理了生成式AI的核心概念、技术原理、发展演进以及未来趋势。文章从AI的“行为”入手,通过生动的实例展示了其强大的生成与推理能力;进而深入剖析其底层运作机制,阐释了“万物皆为令牌(Token)”、自回归生成、Transformer架构等核心原理;接着,文章追溯了通用AI模型从“专才”到“通才”的演进历程;最后,探讨了如何通过微调(Fine-tuning)、模型编辑(Model Editing)等技术赋予AI新的能力

木鱼时刻的专栏 2295

构建第一个ArkTS应用

,在main_pages.json文件中的“src”下配置第二个页面的路由“pages/Second”。页面路由router根据页面url找到目标页面,从而实现跳转。在默认页面基础上,我们添加一个Button组件,作为按钮响应用户点击,从而实现跳转到另一个页面。参照第一个页面,在第二个页面添加Text组件、Button组件等,并设置其样式。在第一个页面中,跳转按钮绑定onClick事件,点击按钮时跳转到第二页。在第二个页面中,返回按钮绑定onClick事件,点击按钮时返回到第一页。配置第二个页面的路由。

qq_45789342的博客 870

【OpenClaw企业级智能体实战】第16篇:电商“龙虾”掘金记:用OpenClaw实现小红书/抖音/淘宝全自动矩阵运营(2026实测版)

2026年,OpenClaw(小龙虾)已成为电商运营的核心效率工具——从公众号文案3分钟生成到TikTok爆款视频1小时复刻,从多平台内容同步到自动比价加购,彻底重构了电商运营的工作模式。本文基于真实商业案例(元岳科技、TikTok跨境卖家、淘宝MCP工具),系统拆解电商智能体的落地路径:先详解OpenClaw在电商场景的核心原理与变现模式(代部署、模板售卖、轻定制、内容套利),再提供阿里云/本地双部署方案,完整实现小红书/抖音/淘宝的自动化运营(热点抓取、内容生成、多平台分发、数据分析)。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2300

图神经网络学习笔记-点云数据处理(专题七)

本教程解释了如何利用图神经网络(Graph Neural Networks,GNNs)来处理和训练点云数据。尽管点云默认情况下不具有图结构,但我们可以利用 PyG 的转换工具,将其转化为适合 PyG 所提供的全套 GNN 模型的形式。关键思想是从点云数据中创建一个,通过 GNN 的消息传递机制,从中学习有意义的局部几何结构。这些点的表示可以被用于例如点云分类或分割等任务。

351

如何构建一个简单的图谱式 RAG 应用

知识图谱( KGs)和大语言模型(LLMs)可谓是天作之合。这两种技术之间的互补性,但简而言之就是, LLM 的一些主要弱点,比如它们是黑箱模型、在事实知识方面表现不佳,恰恰是知识图谱最擅长的领域。知识图谱本质上是“事实的集合”,而且完全可解释。

weixin_58753619的博客 1093

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

连锁咖啡店如何用AI实现真正无限续杯?

实际运营两周后发现个有趣现象:下午茶时段的续杯满足率提升后,甜品销售额增加了17%。这套系统最让我惊喜的是开发效率——从原型到上线只用了一周,快马平台的容器化部署真的帮了大忙,不用折腾服务器配置就能让AI模型和Web服务稳定运行。传统"无限续杯"有两个痛点:一是顾客频繁走动接咖啡影响体验,二是店家无法精准控制成本。最近帮一家连锁咖啡品牌做了个有趣的智能续杯系统,分享下从构思到落地的全过程。如果有餐饮行业的朋友想尝试类似方案,建议先从小规模试点开始,重点观察续杯频次与顾客停留时间的平衡点。

JetRaven12的博客 1064

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Flutter Assets Audio Player在播客应用中的应用:实现断点续听和播放进度同步

Flutter Assets Audio Player是一款功能强大的音频播放插件,支持从资产、网络或本地文件播放音乐/音频,兼容Android、iOS、Web和macOS平台,并能显示通知。对于播客应用开发者来说,它提供了实现断点续听和播放进度同步的核心功能,让用户体验更加流畅和便捷。 ## 播客应用的核心需求:断点续听与进度同步 播客内容通常时长较长,用户可能需要分多次收听。断点续听功能允

gitblog_00561的博客 896

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

使用Vue CLI构建你的第一个Vue应用

Vue CLI是一个官方推荐的脚手架工具,它可以用来快速生成Vue项目的骨架,提供了一套完整的开发、构建和测试的工具链。使用Vue CLI,你可以更为高效地进行开发,避免手动配置Webpack、Babel等工具的繁琐步骤。src文件夹:这里是你进行开发的主要地方,所有的Vue组件、样式和其他代码均在此文件夹中。public文件夹:用于存放静态资源,包括图标、HTML模板等。:这是Vue CLI的配置文件,你可以在这里进行一些项目的配置。

有我更精彩的博客 1508

用Cursor无限续杯快速构建项目原型

比如描述一个电商首页需求后,可以追加"加入购物车动画"、"商品分类筛选"等新指令,AI会在原有代码基础上智能补充,避免重复造轮子。在快速迭代的互联网时代,产品原型开发的速度往往决定了项目的成败。实际体验中,用这个方式三天就完成了社区团购App从登录页到订单系统的全流程原型,相比传统开发节省了70%时间。无需配置环境,浏览器里就能完成原型开发到部署的全流程,我的项目最终就是在这里一键部署成了可公开访问的演示站点。:通过连续对话修改细节,比如把"圆形头像"改为"方形带边框",代码会即时响应变更。

StarfallRaven13的博客 941

如何构建一个简单的React应用?

本文介绍了如何构建一个简单的 React 应用,从环境准备、创建组件到使用 Chrome 浏览器进行调试。通过这些步骤,你可以快速上手 React 开发并构建自己的 Web 应用。对于开发者来说,Chrome浏览器和React 开发者工具是非常有用的工具,它们能帮助你更高效地开发和调试 React 应用。

weixin_43772292的博客 1445

构建一个Java应用的Docker镜像

编写Dockerfile,将Java项目构建成一个Docker镜像。

jason9211的专栏 1426

Flatpak打包(6)——构建一个简单的应用

创建应用 构建 完成构建 全部文章目录: Flatpak打包(1)——Flatpak 介绍 Flatpak打包(2)——Flatpak应用元素 Flatpak打包(3)——应用Flatpak Flatpak打包(4)——构建第一个Flatpak Flatpak打包(5)——开始配置 Flatpak打包(6)——构建一个简单的应用 Flatpak打包(7)——Flatp...

beyond_zhangna的博客 1566

总结 Django 一个项目构建多个应用

单个项目,多个应用的需求是很常见的,总结下如何建立: 1,把多个apps目录组织好 比如多个apps folders(Learning_logs, meal_apps, pizzas)与project_folder (learning_log)平行,不能放进子目录 这里,manage.py 指向了 learning_log 里的setting.py. 2,Project_folder\setting.py 添加多个app INSTALLED_APPS = [ 'django.con...

秋~二十年后 2606

从 0 到 1 构建一个自己的 Docker 应用

Docker,可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 Docker“真香定律”:不会用的时候觉得复杂,用顺手了就再也放不下了。 今天我们就带大家从 0 到 1 构建一个自己的 Docker 应用。 使用的语言和应用的版本如下:Python 3.8.1,Flask库 1.1.1,Redis库 3.4.1。 1. web 应用 这次我们使用 Python 来编写我们的 web 应用,上一次我们使用的是 Go 语言。 由于

mukewangguanfang的博客 2448
上一篇: Sun发布Java路线 更好地支持Web服务和XML
下一篇: IBM公司已经参与开放源代码Java项目Harmony
java169
博客等级 码龄19年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值