第三章 使用Struts 2 Action
3.1 Struts 2 Action简介
Action 的作用:
- Action封装工作单元,或者至少是业务逻辑的入口点(如果业务逻辑很复杂,我们可能会把业务逻辑构建成一个业务组件,再把这个业务组件注入到Action中去)。
- Action为数据转移提供场所,Action只需把每一个期望承载的数据实现为JavaBean属性。除了这些简单的JavaBean属性,还有两种技术可以把Action作为数据转移对象使用(后续会讲到)。
- Action为结果路由选择返回控制字符串。
3.2 打包Action
1. Struts 2的包提供了一种继承机制,让你能够继承框架已经定义的组件。
<package name="packageName" namespace="/packageNamespace" extends="struts-default">
2. 可以为多个不同的包设置相同的命名空间。
3. 如果不设置namespace属性,你的Action就会进入默认命名空间。默认命名空间在所有其他的命名空间之下,用来解决不能与任何显示声明的命名空间匹配的请求。默认命名空间实际上是空字符串” ”。
4. 你也可以定义叫做”/”的根命名空间。根命名空间和其他显示声明的命名空间相同,必须被完全匹配。
5. 大部分智能默认值定义在系统内建的一个叫做struts-default的包中。虽然当你创建自定义的包时不是一定要扩展struts-default,但是省略了继承就等于拒绝了框架的核心功能。
3.3 实现Action
ActionSupport类。它是一个提供了Action接口和其他几个有用接口的默认实现的便利类,提供了诸如数据验证、错误消息本地化等功能。数据验证和文本本地化服务是通过拦截器和接口的协作实现的。拦截器控制服务的执行,Action实现接口提供被拦截器调用的方法。
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { //.... }
1.基本验证
在默认的拦截器栈中我们可以看到params拦截器在workflow拦截器之前定义。params拦截器将请求数据转移到Action对象上。之后,workflow拦截器在这些数据被模型接受之前验证这些数据。
workflow拦截器称为工作流拦截器,因为如果验证出错,它会把请求工作流重新定向到输入页面。
注意:workflow拦截器必须在params拦截器将数据从请求转移到Action对象之后触发。
当workflow拦截器触发时,它首先会在Action上查找要调用的validate()方法。你会把验证逻辑放在validate()方法中。这个方法通过com.opensymphony.xwork2.Validateable公开出来。从技术上讲ActionSupport实现了validate()方法,你只需用特定的验证逻辑覆盖这个空方法。
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { /** * A default implementation that validates nothing. * Subclasses should override this method to provide validations. */ public void validate() { } }
注意validate()方法没有返回值,秘密在于验证过程生成的错误消息。在调用完validate()方法之后,workflow拦截器检查验证逻辑是否生成了错误消息。如果找到了错误消息,workflow拦截器会改变请求的工作流。它会立即终止请求处理,将用户带回到输入表单,并在表单中显示错误消息。
那么错误消息保存到哪里?workflow如何检查是否有错误消息被创建?
com.opensymphony.xwork2.ValidationAware接口定义了存储和获取错误消息的方法。
public interface ValidationAware { /** * Set the Collection of Action-level String error messages. * * @param errorMessages Collection of String error messages */ void setActionErrors(Collection<String> errorMessages); /** * Get the Collection of Action-level error messages for this action. Error messages should not * be added directly here, as implementations are free to return a new Collection or an * Unmodifiable Collection. * * @return Collection of String error messages */ Collection<String> getActionErrors(); /** * Set the Collection of Action-level String messages (not errors). * * @param messages Collection of String messages (not errors). */ void setActionMessages(Collection<String> messages); /** * Get the Collection of Action-level messages for this action. Messages should not be added * directly here, as implementations are free to return a new Collection or an Unmodifiable * Collection. * * @return Collection of String messages */ Collection<String> getActionMessages(); /** * Set the field error map of fieldname (String) to Collection of String error messages. * * @param errorMap field error map */ void setFieldErrors(Map<String, List<String>> errorMap); /** * Get the field specific errors associated with this action. Error messages should not be added * directly here, as implementations are free to return a new Collection or an Unmodifiable * Collection. * * @return Map with errors mapped from fieldname (String) to Collection of String error messages */ Map<String, List<String>> getFieldErrors(); /** * Add an Action-level error message to this Action. * * @param anErrorMessage the error message */ void addActionError(String anErrorMessage); /** * Add an Action-level message to this Action. * * @param aMessage the message */ void addActionMessage(String aMessage); /** * Add an error message for a given field. * * @param fieldName name of field * @param errorMessage the error message */ void addFieldError(String fieldName, String errorMessage); /** * Check whether there are any Action-level error messages. * * @return true if any Action-level error messages have been registered */ boolean hasActionErrors(); /** * Checks whether there are any Action-level messages. * * @return true if any Action-level messages have been registered */ boolean hasActionMessages(); /** * Checks whether there are any action errors or field errors. * <p/> * <b>Note</b>: that this does not have the same meaning as in WW 1.x. * * @return <code>(hasActionErrors() || hasFieldErrors())</code> */ boolean hasErrors(); /** * Check whether there are any field errors associated with this action. * * @return whether there are any field errors */ boolean hasFieldErrors(); }
实现这个重要接口的类必须为每一个可以验证的字段维护一系列错误消息和一系列与action整体相关的通用错误消息。幸运的是ActionSupport替我们做到了这一点。为了使用它们,我们只需调用下面两个方法。
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { //.... public void addActionError(String anErrorMessage) { validationAware.addActionError(anErrorMessage); } public void addFieldError(String fieldName, String errorMessage) { validationAware.addFieldError(fieldName, errorMessage); } //.... }
2.使用资源包处理文本消息
最佳实践是将字符串消息集中放入外部可维护的资源包中。ActionSupport提供了内建的功能可以轻松地管理。ActionSupport实现了两个接口,它们协作提供了本地化消息文本功能。第一个接口com.opensymphony.xwork2.TextProvider提供了对这些消息的访问。这个接口提供了一系列灵活的方法,使用这些方法可以从资源包中取得消息。
public interface TextProvider { /** * Checks if a message key exists. * * @param key message key to check for * @return boolean true if key exists, false otherwise. */ boolean hasKey(String key); /** * Gets a message based on a message key, or null if no message is found. * * @param key the resource bundle key that is to be searched for * @return the message as found in the resource bundle, or null if none is found. */ String getText(String key); /** * Gets a message based on a key, or, if the message is not found, a supplied * default value is returned. * * @param key the resource bundle key that is to be searched for * @param defaultValue the default value which will be returned if no message is found * @return the message as found in the resource bundle, or defaultValue if none is found */ String getText(String key, String defaultValue); /** * Gets a message based on a key using the supplied obj, as defined in * {@link java.text.MessageFormat}, or, if the message is not found, a supplied * default value is returned. * * @param key the resource bundle key that is to be searched for * @param defaultValue the default value which will be returned if no message is found * @param obj obj to be used in a {@link java.text.MessageFormat} message * @return the message as found in the resource bundle, or defaultValue if none is found */ String getText(String key, String defaultValue, String obj); /** * Gets a message based on a key using the supplied args, as defined in * {@link java.text.MessageFormat}, or null if no message is found. * * @param key the resource bundle key that is to be searched for * @param args a list args to be used in a {@link java.text.MessageFormat} message * @return the message as found in the resource bundle, or null if none is found. */ String getText(String key, List<?> args); /** * Gets a message based on a key using the supplied args, as defined in * {@link java.text.MessageFormat}, or null if no message is found. * * @param key the resource bundle key that is to be searched for * @param args an array args to be used in a {@link java.text.MessageFormat} message * @return the message as found in the resource bundle, or null if none is found. */ String getText(String key, String[] args); /** * Gets a message based on a key using the supplied args, as defined in * {@link java.text.MessageFormat}, or, if the message is not found, a supplied * default value is returned. * * @param key the resource bundle key that is to be searched for * @param defaultValue the default value which will be returned if no message is found * @param args a list args to be used in a {@link java.text.MessageFormat} message * @return the message as found in the resource bundle, or defaultValue if none is found */ String getText(String key, String defaultValue, List<?> args); /** * Gets a message based on a key using the supplied args, as defined in * {@link java.text.MessageFormat}, or, if the message is not found, a supplied * default value is returned. * * @param key the resource bundle key that is to be searched for * @param defaultValue the default value which will be returned if no message is found * @param args an array args to be used in a {@link java.text.MessageFormat} message * @return the message as found in the resource bundle, or defaultValue if none is found */ String getText(String key, String defaultValue, String[] args); /** * Gets a message based on a key using the supplied args, as defined in * {@link java.text.MessageFormat}, or, if the message is not found, a supplied * default value is returned. Instead of using the value stack in the ActionContext * this version of the getText() method uses the provided value stack. * * @param key the resource bundle key that is to be searched for * @param defaultValue the default value which will be returned if no message is found * @param args a list args to be used in a {@link java.text.MessageFormat} message * @param stack the value stack to use for finding the text * @return the message as found in the resource bundle, or defaultValue if none is found */ String getText(String key, String defaultValue, List<?> args, ValueStack stack); /** * Gets a message based on a key using the supplied args, as defined in * {@link java.text.MessageFormat}, or, if the message is not found, a supplied * default value is returned. Instead of using the value stack in the ActionContext * this version of the getText() method uses the provided value stack. * * @param key the resource bundle key that is to be searched for * @param defaultValue the default value which will be returned if no message is found * @param args an array args to be used in a {@link java.text.MessageFormat} message * @param stack the value stack to use for finding the text * @return the message as found in the resource bundle, or defaultValue if none is found */ String getText(String key, String defaultValue, String[] args, ValueStack stack); /** * Get the named bundle, such as "com/acme/Foo". * * @param bundleName the name of the resource bundle, such as <code>"com/acme/Foo"</code>. * @return the bundle */ ResourceBundle getTexts(String bundleName); /** * Get the resource bundle associated with the implementing class (usually an action). * * @return the bundle */ ResourceBundle getTexts(); }
ActionSupport实现了这些方法,使你可以通过关键字引用资源包中的对应的消息。
第二个接口com.opensymphony.xwork2.LocaleProvider只提供了一个方法getLocale()。
public interface LocaleProvider { /** * Gets the provided locale. * * @return the locale. */ Locale getLocale(); }
ActionSupport也为本地化消息文本提供了一个基本的国际化解决方案。ActionSupport实现了这个接口,根据浏览器发送来的地域设置取得用户所在的地域。
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { public Locale getLocale() { ActionContext ctx = ActionContext.getContext(); if (ctx != null) { return ctx.getLocale(); } else { if (LOG.isDebugEnabled()) { LOG.debug("Action context not initialized"); } return null; } } }
你还是用以前的方式取得消息文本。甚至我们还没有使用它的时候,ActionSupport的TextProvider实现已经开始在每次为我们取得文本消息的时候通过调用LocalProvider接口的getLocale()方法检查地域。使用得到的地域,TextProvider(也就是ActionSupport)会尝试为这个地域定位属性文件。
3.4 向Action传递数据
1. 前面的内容,Action把从请求接收到的所有数据放在简单的JavaBean属性上。另外还有两种方式来传递数据。
- 第一种选择也是基于JavaBean。可以公开一个复杂对象作为JavaBean属性,让数据直接传输到这个对象上。
- 另一种选择是使用被称为ModelDriven的Action。
2. 使用域对象做数据转移存在危险。如果请求中的参数与域对象属性匹配,那么数据会被移动到这些属性上。但是域对象可能会包含一些敏感数据(如ID),我们不想把它们公开给自动数据转移机制。这个问题现在并没有很好地解决方案。
3.5 案例研究:文件上传
fileUpload拦截器创建了我们之前看到过的数据自动转移机制的一种特别版本。在默认拦截器栈defaultStack中可以看到fileUpload拦截器在params拦截器之前。当fileUpload拦截器执行时,它处理一个多重请求(multipart request)并且将文件与其他一些元数据一起转换到请求参数中(params拦截器会自动将数据转移到Action上)。在后加工阶段fileUpload拦截器再次出发时,用来消除上传文件的临时版本。
相关推荐
### Struts2框架核心概念与工作原理 #### 一、框架概述 Struts2是Apache组织维护的一个开源项目,它是Struts1的升级版本,在设计理念和技术实现上都有较大的改进。Struts2是一个基于MVC(Model-View-Controller)...
### Struts2学习笔记知识点概览 #### 一、环境搭建 **1.1 Struts2简介** - **Struts2概述**:Struts2是一个开源的MVC框架,...通过学习这些知识点,可以帮助开发者更好地理解和掌握Struts2框架的核心概念和技术细节。
- **配置文件**:`struts.xml`文件用于配置Action映射、拦截器等信息。 - **Jar包管理**:列出项目所需的所有Struts2相关Jar包,确保版本兼容性。 #### JBPM4.0工作流 - **基本示例**:通过示例了解JBPM的基本使用...
内容概要:本文详细探讨了在主从博弈框架下,共享储能与综合能源微网的优化运行及其仿真复现。通过MATLAB和CPLEX的联合使用,展示了微网运营商和用户聚合商之间的动态博弈过程。上层模型关注微网运营商的定价策略,旨在最大化利润,考虑售电收益、储能运维成本等因素。下层模型则聚焦于用户聚合商的响应,根据电价调整电热负荷并参与共享储能调度。文中还介绍了电热耦合约束、充放电互斥约束等关键技术细节,并通过迭代博弈实现了策略更新。最终仿真结果显示,在引入电制热设备后,用户侧热负荷弹性提升,博弈收敛速度加快,达到双赢效果。 适合人群:从事能源系统优化、博弈论应用、MATLAB编程的研究人员和技术人员。 使用场景及目标:适用于希望深入了解主从博弈在综合能源系统中应用的学者和工程师。目标是掌握如何通过数学建模和编程实现复杂的能源系统优化,理解电热耦合机制和共享储能的作用。 其他说明:文章提供了详细的代码片段和仿真结果,帮助读者更好地理解和复现实验。此外,还讨论了一些常见的调试问题和解决方案,如约束冲突等。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
内容概要:深度学习在多个领域有着广泛应用。在计算机视觉方面,涵盖图像分类、目标检测、图像分割等任务,应用于自动驾驶、医疗影像分析等领域;在自然语言处理上,包括机器翻译、文本分类、文本生成等功能,服务于信息检索、内容创作等;语音识别与合成领域,实现了语音到文本的转换以及文本到语音的生成,推动了智能交互的发展;医疗领域,深度学习助力医学影像分析、疾病预测、个性化治疗及健康监测;金融领域,深度学习用于信用风险评估、欺诈检测、高频交易等,保障金融安全并优化投资策略;自动驾驶方面,环境感知与决策控制系统确保车辆安全行驶;娱乐与媒体领域,个性化推荐和内容生成提升了用户体验;工业与制造业中,质量检测和预测性维护提高了生产效率和产品质量。 适合人群:对深度学习及其应用感兴趣的初学者、研究人员以及相关领域的从业者。 使用场景及目标:帮助读者全面了解深度学习在不同行业的具体应用场景,明确各领域中深度学习解决的实际问题,为后续深入研究或项目实施提供方向指引。 其他说明:随着深度学习技术的持续进步,其应用范围也在不断扩大,文中提及的应用实例仅为当前主要成果展示,未来还有更多潜力待挖掘。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
周梁伟-大模型在融合通信中的应用实践
内容概要:本文详细介绍了利用西门子S7-200 PLC和组态王软件构建的一个花式喷泉控制系统的设计与实现。首先阐述了系统的硬件组成,包括三个环形喷泉组、七彩LED灯带以及功放喇叭等组件,并给出了详细的IO分配表。接着深入解析了关键的梯形图程序逻辑,如自动模式循环、灯光控制、喷泉舞步等部分的具体实现方法。此外,还分享了一些实际调试过程中遇到的问题及其解决方案,例如电源隔离、电磁干扰处理等。最后展示了组态王界面上生动有趣的动画效果设计思路。 适合人群:对PLC编程和工业自动化感兴趣的工程师和技术爱好者。 使用场景及目标:适用于需要设计类似互动娱乐设施的专业人士,旨在帮助他们掌握从硬件选型、程序编写到界面美化的完整流程,从而能够独立完成类似的工程项目。 其他说明:文中不仅提供了理论知识讲解,还包括了许多实践经验教训,对于初学者来说非常有价值。同时,作者还在系统中加入了一些趣味性的元素,如隐藏模式等,增加了项目的吸引力。
内容概要:本文详细介绍了利用COMSOL进行电弧熔池多物理场耦合仿真的方法和技术要点。首先解释了电弧熔池的本质及其复杂性,然后依次讲解了几何建模、材料属性设置、求解器配置以及后处理等方面的具体步骤和注意事项。文中提供了大量实用的MATLAB、Java和Python代码片段,帮助用户更好地理解和应用相关技术。此外,作者分享了许多实践经验,如分阶段激活物理场、使用光滑过渡函数处理相变、优化网格划分等,强调了参数选择和边界条件设定的重要性。 适合人群:从事电弧熔池仿真研究的专业人士,尤其是有一定COMSOL使用经验的研究人员。 使用场景及目标:适用于需要精确模拟电弧熔池行为的研究项目,旨在提高仿真精度并减少计算时间。主要目标是掌握多物理场耦合仿真的关键技术,解决实际工程中遇到的问题。 其他说明:文章不仅提供了详细的理论指导,还包括许多实用的操作技巧和常见错误的解决方案,有助于读者快速上手并深入理解电弧熔池仿真的难点和重点。
9f148310e17f2960fea3ff60af384a37_098bb292f553b9f4ff9c67367379fafd
# 【spring-ai-hanadb-store-1.0.0-M7.jar中文-英文对照文档.zip】 中包含: 中文-英文对照文档:【spring-ai-hanadb-store-1.0.0-M7-javadoc-API文档-中文(简体)-英语-对照版.zip】 jar包下载地址:【spring-ai-hanadb-store-1.0.0-M7.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【spring-ai-hanadb-store-1.0.0-M7.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【spring-ai-hanadb-store-1.0.0-M7.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【spring-ai-hanadb-store-1.0.0-M7-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: spring-ai-hanadb-store-1.0.0-M7.jar中文-英文对照文档.zip,java,spring-ai-hanadb-store-1.0.0-M7.jar,org.springframework.ai,spring-ai-hanadb-store,1.0.0-M7,org.springframework.ai.vectorstore.hanadb,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,springframework,spring,ai,hanadb,store,中文-英文对照API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【spring-ai-hanadb-store-1.0.0-M7.jar中文-英文
# 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
3dmax插件
内容概要:本文详细介绍了单相全桥PWM整流器采用双闭环控制策略的具体实现方法和技术要点。电压环采用PI控制器来稳定直流侧电压,电流环则使用PR控制器确保交流电流与电压同相位并实现单位功率因数。文中提供了详细的MATLAB、C和Python代码片段,解释了各个控制器的设计思路和参数整定方法。此外,文章还讨论了突加负载测试、电压前馈补偿、PWM生成以及硬件选型等方面的内容,强调了系统的稳定性和快速响应能力。 适合人群:从事电力电子、自动控制领域的工程师和技术人员,尤其是对PWM整流器和双闭环控制感兴趣的读者。 使用场景及目标:适用于需要精确控制直流电压和交流电流的应用场景,如工业电源、新能源发电等领域。目标是提高系统的电能质量和动态响应速度,确保在负载变化时仍能保持稳定的输出。 其他说明:文章不仅提供了理论分析,还包括了大量的实际测试数据和波形图,帮助读者更好地理解和掌握双闭环控制的实际效果。同时,文中提到的一些调试技巧和注意事项对于实际工程应用非常有价值。
easyocr安装包和模型
AC_DIMMER交流调光灯stm32.7z
仲量联行-负责任的房地产:实现社会价值,赋能建筑环境,创造积极的环境和社会影响
C语言全部知识点复习资料.doc