据我了解,Struts2动作类实例(与Struts1不同)可以是有状态的,因为动作的每个GET或POST都会创建一个支持动作类的新实例。
我还看到有一个标准(?)成语(模式?)来提供输入表单:相同的.jsp用作两个不同操作的View组件,如下所示:
<action name="showForm" class="defaultActionThatDoesNothingExceptReturnSuccess">
<result name="success">inputForm.jsp</result>
</action>
<action name="validateAndProcessForm" class="realAction">
<result name="input">inputForm.jsp</result>
<result name="success">formProcessed.jsp</result>
</action>
第一个操作只显示表单,而不验证输入或处理它。 .jsp中的表单发布到第二个操作:
<s:form action="validateAndProcessForm" method="post">
并且第二个操作验证已发布的字段/参数,如果表单的输入不完整或无效则返回“input”,或者如果输入完整且有效,则实际调用操作类的execute
,从而处理表单并返回(例如)formProcessed.jsp
,显示类似“感谢您的输入!”。
所以我们有这种“尖桩篱笆”的习语:
defaultAction- -> realAction-
| | | |
-> input.jsp- <--- -> success.jsp
这样做是为了第一次显示input.jsp
,不调用验证(因此未显示验证错误),但是在点击该jsp上的提交按钮后,“真实”动作将验证输入,可能会传回错误,调出input.jsp
将显示的无效输入。
这使我们回到有状态的,非单身的行为;因为该操作是有状态的,因此不能在GET或POST之间共享,并且每个实例仅针对该GET或POST实例化,所以该操作无法知道特定会话是否多次“GET”同一页面。因此,GETting showForm.action
永远不会验证,并且GETing validateAndProcessForm
将始终验证(如果参数无效则显示错误),甚至如果 GET是第一次特定会话“GET”该URL。
这就是为什么我们需要“围栏帖子”:第一个动作只是为了显示表格,第二个动作是为了捕捉输入。
我的理解是否正确?是否有一种不那么冗长的方法来做到这一点,不是在初始GET上验证输入,而是在POST上验证,而不必为每个表单都有两个动作?
答案 0 :(得分:9)
还有另一种方法可以在没有尖桩篱栅的情况下执行您想要的任务。默认情况下,验证拦截器不会为输入方法触发。因此,您可以将struts.xml更新为以下内容:
<action name="*MyForm" method="{1}" class="realAction">
<result name="input">inputForm.jsp</result>
<result name="success">formProcessed.jsp</result>
</action>
使用此设置,您根本不需要空操作。当您第一次转到表单时,您将转到URL“inputMyForm”,并将表单操作指向“MyForm”。方法块中的{1}只意味着框架将调用与动作名称中的*匹配的任何方法。如果* match为空,则默认为execute方法。所以你会得到以下几种行动:
由于验证器拦截器排除了对输入法进行的任何操作,因此您可以为此操作设置所需的任何验证,并且只有在您提交表单时才会查找它。由于每次提交表单时都会执行execute方法,因此每次提交表单时都会进行验证。
此外,如果要扩展ActionSupport类,该类已经定义了input()方法,因此您甚至不需要更改操作类来完成此操作。
答案 1 :(得分:0)
可以采用不同的方式做事,但是假设你让struts2处理所有请求。 struts2处理的所有内容都是“动作”。
不要担心GET或POST它们只是将数据发送到动作的两种不同方法,如果有参数(无论它们是否被获取或设置),那么struts2将尝试将该数据放到actions类上(假设有一个)。如果存在验证方法(或正确命名的验证xml文件),则将在设置类属性后运行验证。然后调用类的execute()方法(假设有一个类)。在此之后,通常会呈现一个jsp,它具有动作方法中的所有公共数据。
执行“showForm”操作...您可以将xml缩小为:
<action name="showForm">
<result>inputForm.jsp</result>
</action>
您可以看到您不需要定义类。此外,默认结果是成功,因此我们也不需要提及。
因此,在考虑hmtl时,我们会考虑页面。当我们在struts中思考时,我们只考虑行动,他们只需要尽可能复杂。也就是说,如果你需要显示一个表单,那么你需要一个show form动作,如果你想要一个使用表单数据的显示页面,那么你需要一个“displayPage”动作来处理表单数据。
因此,请将每个操作视为以url开头&gt; -----------&gt;以返回日期结束(通常呈现jsp)。破折号是您可以定义的可选部分,但如果您不这样做,它们将明智地默认为您。要查看为您提供的功能,您需要查看struts2-core-x.x.x.x.jar并查看定义“defaultStack”的struts-default.xml的内容。每个拦截器依次被调用,知道它们提供什么(以及其他拦截器提供的)让你知道你从盒子里拿出什么(我不会深入研究它们只是知道它们在那里所以你会知道例如如果你需要上传一个文件,那么“fileUpload”拦截器在默认堆栈中的简单事实应该足以表明必须有内置的文件上传功能。
因此,输入表单中没有“错误操作”。这是一个简单的实际行动。在您学习如何定义包的包,操作,默认操作以及可能全局并学习如何定义拦截器之后,您应该查看插件的约定。它使生活变得更加容易!
答案 2 :(得分:0)
你的问题很有道理。但是你的模式是正确的:
正如Quaternion指出的那样,很少或根本没有“冗长”。你的第一个“showForm”是一个虚拟的“动作映射”,它的“无所事事”类不需要特定的类定义(默认的ActionSupport就足够了)。
还有其他可能的模式;有些人可能更喜欢你指出的成语(而且它有很长的历史 - 我记得几个世纪以前就用这种方式做了一些CGI页面):使用单个url(因此单个动作映射)用于两个“步骤” “(显示初始形式并处理表单),通过在动作方法内部(或在验证器中)猜测当前步骤,可能通过检查某些参数是否存在(可能是隐藏字段)或者可能通过区分POST / GET。在Struts2中,我更喜欢其他方式。