﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Samuel LearningStruts2学习</title><link>http://www.blogjava.net/nobody_am/category/33157.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 21 Jul 2008 23:33:58 GMT</lastBuildDate><pubDate>Mon, 21 Jul 2008 23:33:58 GMT</pubDate><ttl>60</ttl><item><title>Struts2 架构：ActionMapper [笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114596.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 08:12:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114596.html</guid><description><![CDATA[<p>Provide a mapping between HTTP requests and action invocation requests and vice-versa.</p>
<p>提供HTTP请求和Action调用映射<br>
</p>
<p>
When given an HttpServletRequest, the ActionMapper may return null if no action invocation request matches,
or it may return an ActionMapping that describes an action invocation for the framework to try.</p>
<p>当有一个HttpServletRequest的化，有配置的action，就返回一个ActionMapping，否则就返回null。<br>
</p>
<p>
The ActionMapper is not required to guarantee that the ActionMapping returned be a real action or otherwise
ensure a valid request.
Accordingly, most ActionMappers do not need to consult the Struts configuration
just to determine if a request should be mapped.</p>
<p>
Just as requests can be mapped from HTTP to an action invocation, the opposite is true as well.
However, because HTTP requests (when shown in HTTP responses) must be in String form,
a String is returned rather than an actual request object.</p>
<h2><br></h2>
<h2>DefaultActionMapper</h2>
<p>By default, the DefaultActionMapper is used:</p>
<p>Default action mapper implementation, using the standard *.[ext] (where ext
usually "action") pattern. The extension is looked up from the Struts
configuration key <strong>struts.action.exection</strong>.</p>
<p> To help with dealing with buttons and other related requirements, this
mapper (and other ActionMappers, we hope) has the ability to name a
button with some predefined prefix and have that button name alter the
execution behaviour. The four prefixes are:</p>
<ul>
    <li>Method prefix - <em>method:default</em></li>
    <li>Action prefix - <em>action:dashboard</em></li>
    <li>Redirect prefix - <em>redirect:cancel.jsp</em></li>
    <li>Redirect-action prefix - <em>redirect-action:cancel</em></li>
</ul>
<p> In addition to these four prefixes, this mapper also understands the
action naming pattern of <em>foo!bar</em> in either the extension form (eg:
foo!bar.action) or in the prefix form (eg: action:foo!bar). This syntax tells
this mapper to map to the action named <em>foo</em> and the method <em>bar</em>.</p>
<h3>Method prefix</h3>
<p>With method-prefix, instead of calling baz action's execute() method (by
default if it isn't overriden in struts.xml to be something else), the baz
action's anotherMethod() will be called. A very <span style="color: red;">elegant</span> way determine which
button is clicked. Alternatively, one would have submit button set a
particular value on the action when clicked, and the execute() method decides
on what to do with the setted value depending on which button is clicked.</p>
<p><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;a:form action="baz"&gt;</span><br>    <span class="code-tag">&lt;a:textfield label="Enter your name" name="person.name"/&gt;</span><br>    <span class="code-tag">&lt;a:submit value="Create person"/&gt;</span><br>    <span class="code-tag">&lt;a:submit name="<span style="color: red; font-weight: bold;">method:anotherMethod</span>" value="Cancel"/&gt;</span><br><span class="code-tag">&lt;/a:form&gt;</span></pre>
</div>
</div>
<h3><a name="ActionMapper-Actionprefix"></a>Action prefix</h3>
<p>With action-prefix, instead of executing baz action's execute() method (by
default if it isn't overriden in struts.xml to be something else), the
anotherAction action's execute() method (assuming again if it isn't overriden
with something else in struts.xml) will be executed.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;a:form action="baz"&gt;</span><br>    <span class="code-tag">&lt;a:textfield label="Enter your name" name="person.name"/&gt;</span><br>    <span class="code-tag">&lt;a:submit value="Create person"/&gt;</span><br>    <span class="code-tag">&lt;a:submit name="<span style="font-weight: bold; color: red;">action:anotherAction</span>" value="Cancel"/&gt;</span><br><span class="code-tag">&lt;/a:form&gt;</span></pre>
</div>
</div>
<h3><a name="ActionMapper-Redirectprefix"></a>Redirect prefix</h3>
<p>With redirect-prefix, instead of executing baz action's execute() method (by
default it isn't overriden in struts.xml to be something else), it will get
redirected to, in this case to www.google.com. Internally it uses
ServletRedirectResult to do the task.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;a:form action="baz"&gt;</span><br>    <span class="code-tag">&lt;a:textfield label="Enter your name" name="person.name"/&gt;</span><br>    <span class="code-tag">&lt;a:submit value="Create person"/&gt;</span><br>    <span class="code-tag">&lt;a:submit name="<span style="color: red; font-weight: bold;">redirect:www.google.com</span>" value="Cancel"/&gt;</span><br><span class="code-tag">&lt;/a:form&gt;</span></pre>
</div>
</div>
<h3><a name="ActionMapper-Redirectactionprefix"></a>Redirect-action prefix</h3>
<p>With redirect-action-prefix, instead of executing baz action's execute()
method (by default it isn't overriden in struts.xml to be something else), it
will get redirected to, in this case 'dashboard.action'. Internally it uses
ServletRedirectResult to do the task and read off the extension from the
struts.properties.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;a:form action="baz"&gt;</span><br>    <span class="code-tag">&lt;a:textfield label="Enter your name" name="person.name"/&gt;</span><br>    <span class="code-tag">&lt;a:submit value="Create person"/&gt;</span><br>    <span class="code-tag">&lt;a:submit name="<span style="font-weight: bold; color: red;">redirect-action:dashboard</span>" value="Cancel"/&gt;</span><br><span class="code-tag">&lt;/a:form&gt;</span></pre>
</div>
</div>
<h2><a name="ActionMapper-CustomActionMapper"></a>Custom ActionMapper</h2>
<p>You can define <span style="color: red;">your own ActionMapper</span> by implementing <tt>org.apache.struts2.dispatcher.mapper.<span style="color: red;">ActionMapper</span></tt> then configuring Struts 2 to use the new class in struts.xml</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.ActionMapper"</span> name=<span class="code-quote">"struts"</span> class=<span class="code-quote">"com.mycompany.myapp.MyActionMapper"</span> /&gt;</span></pre>
</div>
</div>
<p>Possible uses of the ActionMapper include defining your own, cleaner namespaces, such as URLs like <strong>/person/1</strong>, which would be similar to a request to <strong>/getPerson.action?personID=1</strong> using the DefaultActionMapper.</p>
<h2><a name="ActionMapper-CompositeActionMapper"></a>CompositeActionMapper</h2>
<p>A composite action mapper that is capable of delegating to a series of ActionMapper if the former
failed to obtained a valid ActionMapping or uri.</p>
<p>如果前面的在获得一个有效的ActionMapper或Uri失败，一个复合的映射器能委托一系列的ActionMapper。<br>
</p>
<p>
It is configured through struts.properties.
</p>
<p>
For example, with the following entries in struts.properties
</p>
<p>
</p>
<pre>&lt;bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" <br>      class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" /&gt;<br>&lt;constant name="struts.mapper.composite" <br>      value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper,org.apache.struts2.dispatcher.mapper.RestfulActionMapperorg.apache.struts2.dispatcher.mapper.Restful2ActionMapper" /&gt;<br></pre>
<p>
When CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager) or
CompositeActionMapper#getUriFromActionMapping(ActionMapping) is invoked,
CompositeActionMapper would go through these ActionMappers in sequence
starting from ActionMapper identified by 'struts.mapper.composite.1', followed by
'struts.mapper.composite.2' and finally 'struts.mapper.composite.3' (in this case) until either
one of the ActionMapper return a valid result (not null) or it runs out of ActionMapper
in which case it will just return null for both&nbsp; CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager) and
CompositeActionMapper#getUriFromActionMapping(ActionMapping) methods.
</p>
<p>For example with the following in struts-*.xml :-
</p>
<pre>   &lt;bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" <br>      class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" /&gt;<br>   &lt;constant name="struts.mapper.composite" <br>      value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper,foo.bar.MyActionMapper,foo.bar.MyAnotherActionMapper" /&gt;<br></pre>
<p>
<code>CompositeActionMapper</code> will be configured with 3 ActionMapper, namely
"DefaultActionMapper", "MyActionMapper" and "MyAnotherActionMapper".
<code>CompositeActionMapper</code> would consult each of them in order described above.</p>
<h2><a name="ActionMapper-ActionMapperandActionMappingobjets"></a>ActionMapper and ActionMapping objets</h2>
<p>The ActionMapper fetches the ActionMapping object corresponding to a
given request. Essentially, the ActionMapping is a data transfer object
that collects together details such as the Action class and method to
execute. The mapping is utilized by the Dispatcher and various user
interface components. It is customizable through <tt>struts.mapper.class</tt> entry in <tt>struts.properties</tt>.</p>
<h3><a name="ActionMapper-Customize"></a>Customize</h3>
<table class="warningMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/forbidden.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>Custom ActionMapper must implement ActionMapper interface and have a default constructor.</td>
        </tr>
    </tbody>
</table>
<div class="code">
<div class="codeContent">
<pre class="code-java">struts.mapper.class=foo.bar.MyCustomActionMapper</pre>
</div>
</div>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyCustomActionMapper <span class="code-keyword">implements</span> ActionMapper {<br>  <span class="code-keyword">public</span> ActionMapping getMapping(HttpServletRequest request, <br>                                  ConfigurationManager configManager) {<br>    ....<br>  }<br><br>  <span class="code-keyword">public</span> <span class="code-object">String</span> getUriFromActionMapping(ActionMapping mapping) { <br>    ....<br>  }<br>}</pre>
</div>
</div>
<p><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/lightbulb_on.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> See also: <a href="http://struts.apache.org/2.0.6/docs/restfulactionmapper.html" title="RestfulActionMapper">RestfulActionMapper</a></p>   <img src ="http://www.blogjava.net/nobody_am/aggbug/114596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 16:12 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 架构：ObjectFactory [笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114585.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 07:47:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114585.html</guid><description><![CDATA[<p>All objects created by the framework are instantiated by the
ObjectFactory. The ObjectFactory provides the means of integrating the
framework with IoC containers like Spring, Pico, Plexus, and so forth.</p>
<p><span style="background-color: #101fff;">框架创建的所有对象都是有ObjectFactory实例化的。ObjectFactory提供了和其他IoC框架整合的方法。</span><br></p>
<h2><a name="ObjectFactory-Customize"></a>Customize</h2>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>
            <p>Customized ObjectFactory must extend ObjectFactory or any of its descendants and have a default, no-argument constructor.</p>
            </td>
        </tr>
    </tbody>
</table>
<p>To register a customized ObjectFactory, add or edit an entry in <tt>struts.properties</tt></p>
<p><tt><span style="background-color: #101fff;">Samuel说：在struts.xml中可以指定objectfactory="spring"</span><br></tt></p>
<div class="code">
<div class="codeContent">
<pre class="code-java">struts.objectFactory=foo.bar.MyCustomObjectFactory</pre>
</div>
</div>
<p>where foo.bar.MyCustomObjectFactory is the custom object factory. </p>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyObjectFactory <span class="code-keyword">extends</span> ObjectFactory {<br>    .....<br>}</pre>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 15:47 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 架构：架构图解 [笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114580.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 07:26:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114580.html</guid><description><![CDATA[<p>The diagram describes the framework's architecture.</p>
<p><img src="http://www.blogjava.net/images/blogjava_net/nobody_am/tmp/Struts2-Architecture.gif" border="0"><br></p>
<p>In the diagram, an initial request goes to the Servlet container
(such as Jetty or Resin) which is passed through a standard filter
chain. <br></p>
<p><span style="background-color: #0817ff;">这个图中，初始需求到了Servlet容器，通过了标准的filter链。</span><br></p>
<p>The chain includes the (optional) <strong>ActionContextCleanUp</strong> filter, which is useful when integrating technologies such as <a href="http://struts.apache.org/2.0.6/S2PLUGINS/sitemesh-plugin.html" title="Sitemesh Plugin">SiteMesh Plugin</a>. <br></p>
<p><span style="background-color: #0817ff;">这个链包括ActionContextClean的filter，它在整合技术方面例如：SiteMesh插件非常有用。</span><br></p>
<p>Next, the required <strong>FilterDispatcher</strong> is called, which in turn consults the <a href="http://struts.apache.org/2.0.6/docs/actionmapper.html" title="ActionMapper">ActionMapper</a> to determine if the request should invoke an action.</p>
<p><span style="background-color: #0817ff;">接着，FilterDispatcher被调用，它查询ActionMapper决定请求应该调用action。</span><br></p>
<p>If the ActionMapper determines that an Action should be invoked, the FilterDispatcher delegates control to the <strong>ActionProxy</strong>. The ActionProxy consults the framework <a href="http://struts.apache.org/2.0.6/docs/configuration-files.html" title="Configuration Files">Configuration Files</a> manager (initialized from the <a href="http://struts.apache.org/2.0.6/docs/strutsxml.html" title="struts.xml">struts.xml</a> file). Next, the ActionProxy creates an <strong>ActionInvocation</strong>, which is responsible for the command pattern implementation. This includes invoking any <strong>Interceptors</strong> (the <em>before</em> clause) in advance of invoking the <strong>Action</strong> itself.</p>
<p><span style="background-color: #0817ff;">如果ActionMapper决定Action应该被调用，FilterDispatcher把控制委托给ActionProxy。ActionProxy咨询配置文件管理器（从struts.xml文件初始化）。接着，ActionProxy创建一个ActionInvocation，它负责命令格式实现，包括在调用Action自己前面调用任何Interceptors。</span><br></p>
<p>Once the Action returns, the ActionInvocation is responsible for looking up the proper <strong>result</strong> associated with the <strong>Action result code</strong> mapped in <tt>struts.xml</tt>. The result is then executed, which often (but not always, as is the case for <a href="http://struts.apache.org/2.0.6/docs/action-chaining.html" title="Action Chaining">Action Chaining</a>) involves a template written in <a href="http://struts.apache.org/2.0.6/docs/jsp.html" title="JSP">JSP</a> or <a href="http://struts.apache.org/2.0.6/docs/freemarker.html" title="FreeMarker">FreeMarker</a> to be rendered. While rendering, the templates can use the <a href="http://struts.apache.org/2.0.6/docs/struts-tags.html" title="Struts Tags">Struts Tags</a>
provided by the framework. Some of those components will work with the
ActionMapper to render proper URLs for additional requests.</p>
<p><span style="background-color: #0817ff;">一旦Action返回，ActionInvocation负责查询在struts.xml中映射的关于Action Result code相关的合适的result，它一般调用JSP或FreeMarker模板做渲染。在渲染的时候，模板可以用Struts标签。部分组建将和ActionMapper工作来渲染合适的URL给请求。</span><br></p>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>All objects in this architecture (Actions, <a href="http://struts.apache.org/2.0.6/docs/result-types.html" title="Result Types">Results</a>, <a href="http://struts.apache.org/2.0.6/docs/interceptors.html" title="Interceptors">Interceptors</a>, and so forth) are created by an <a href="http://struts.apache.org/2.0.6/docs/objectfactory.html" title="ObjectFactory">ObjectFactory</a>.
            This ObjectFactory is pluggable. We can provide our own ObjectFactory
            for any reason that requires knowing when objects in the framework are
            created. A popular ObjectFactory implementation uses Spring as provided
            by the <a href="http://struts.apache.org/2.0.6/S2PLUGINS/spring-plugin.html" title="Spring Plugin">Spring Plugin</a>.</td>
        </tr>
    </tbody>
</table>
<p>Interceptors are executed again (in reverse order, calling the <em>after</em> clause).</p>
<p><span style="background-color: #0817ff;">Interceptor以相反的顺序在执行一遍。</span><br></p>
<p> Finally, the response returns through the filters configured in the <tt>web.xml</tt>. If the ActionContextCleanUp filter is present, the FilterDispatcher will <em>not</em> clean up the ThreadLocal <strong>ActionContext</strong>. If the ActionContextCleanUp filter is not present, the FilterDispatcher will cleanup all ThreadLocals.</p>
<p><span style="background-color: #0817ff;">最后通过在Web.xml中配置的filter返回响应。如果ActionContextCleanUp过滤器也用了，那么FilterDispatcher不清理ActionContext本地线程。否则FilterDispatcher清理所有的本地线程。</span><br></p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114580.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 15:26 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114580.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2: 何为OGNL？[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114519.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 02:45:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114519.html</guid><description><![CDATA[<p>OGNL is the Object Graph Navigation Language (see <span class="nobr"><a href="http://www.ognl.org/" title="Visit page outside confluence" rel="nofollow">http://www.ognl.org/<sup><img src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span>
for the full documentation of OGNL). Here, we will cover a few examples
of OGNL features that co-exist with the framework. To review basic
concepts, refer to <a href="http://struts.apache.org/2.x/docs/ognl-basics.html" title="OGNL Basics">OGNL Basics</a>.</p>
<p><span style="background-color: #1a05ac;">OGNL是对象图形定位语言.这里将设计一个OGNL和框架并存的例子。</span><br></p>
<p>The framework uses a standard naming context to evaluate OGNL
expressions. The top level object dealing with OGNL is a Map (usually
referred as a context map or context). OGNL has a notion of there being
a root (or default) object within the context. In expression, the
properties of the root object can be referenced without any special
"marker" notion. References to other objects are marked with a pound
sign (<tt>#</tt>).</p>
<p><span style="background-color: #160492;">框架用一个标准命名上下文来计算OGNL表达式。处理OGNL的高层对象是Map。OGNL在上下文内有个根的概念。在表达式里，不需要任何&#8220;标志&#8221;关联到根对象的属性。关联到其他对象得用#标识。</span><br></p>
<p>The framework sets the OGNL context to be our ActionContext, and the
value stack to be the OGNL root object. (The value stack is a set of
several objects, but to OGNL it appears to be a single object.) Along
with the value stack, the framework places other objects in the
ActionContext, including Maps representing the application, session,
and request contexts. These objects coexist in the ActionContext,
alongside the value stack (our OGNL root).</p>
<p><span style="background-color: #160492;">框架设置OGNLcontext为我们的 ActionContext, value stack 是OGNL根对象。（value stack是一系列的值，但对OGNL，它表现为一个对象）连同value stack，框架放置其他对象到ActionContext,包括展示application,session和request上下文。这些对象与value stack一起共存在ActionContext。</span><br></p>
<div class="preformatted">
<div class="preformattedContent">
<pre>                     |<br>                     |--application<br>                     |<br>                     |--session<br>       context map---|<br>                     |--value stack(root)<br>                     |<br>                     |--request<br>                     |<br>                     |--parameters<br>                     |<br></pre>
</div>
</div>
<p><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> There are other objects in the context map. The diagram is for example only.</p>
<p>The Action instance is always pushed onto the value stack. Because
the Action is on the stack, and the stack is the OGNL root, references
to Action properties can omit the <tt>#</tt> marker. But, to access other objects in the ActionContext, we must use the <tt>#</tt> notation so OGNL knows not to look in the root object, but for some other object in the ActionContext.</p>
<p><span style="background-color: #160492;">Action 实例被推入value stack。因为Action在stack里，并且statck是OGNL的根，和Action关联的属性忽略#标记。但访问ActionContext的其他对象，我们必须用#标识，OGNL知道不应该区根对象查找，而是到ActionCopntext的其他对象里查找。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Referencing an Action property<br><br></strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:property value=<span class="code-quote">"postalCode"</span>/&gt;</span></pre>
</div>
</div>
<p>Other (non-root) objects in the ActionContext can be rendered use the <tt>#</tt> notation.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:property value=<span class="code-quote">"#session.mySessionPropKey"</span>/&gt;</span> or<br><span class="code-tag">&lt;s:property value=<span class="code-quote">"#session["</span>mySessionPropKey<span class="code-quote">"]"</span>/&gt;</span> or<br><span class="code-tag">&lt;s:property value=<span class="code-quote">"#request["</span>mySessionPropKey"]/&gt;</span></pre>
</div>
</div>
<p>The ActionContext is also exposed to Action classes via a static method.</p>
<p><span style="background-color: #1c099e;">ActionContext也通过静态方法被暴露给Action类</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-java">ActionContext.getContext().getSession().put(<span class="code-quote">"mySessionPropKey"</span>, mySessionObject);</pre>
</div>
</div>
<h2>Collections (Maps, Lists, Sets)</h2>
<p>Dealing with Collections (Maps, Lists, and Sets) in the framework comes often, so here are a few examples using the select tag.</p>
<p><span style="background-color: #15048a;">声明集合在框架中经常用到，所以这里是用select标签的例子。</span><br></p>
<p>Syntax for list: {e1,e2,e3}. This idiom creates a List containing
the String "name1", "name2" and "name3". It also selects "name2" as the
default value.</p>
<p><span style="background-color: #15048a;">list语法:{e1,e2,e3}.这个习惯创建一个包括&#8220;name1&#8221;，&#8220;name2&#8221;和&#8220;name3&#8221;。它也选择&#8220;name2&#8221;作为默认值。</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:select label=<span class="code-quote">"label"</span> name=<span class="code-quote">"name"</span> list=<span class="code-quote">"{'name1','name2','name3'}"</span> value=<span class="code-quote">"%{'name2'}"</span> /&gt;</span></pre>
</div>
</div>
<p>Syntax for map: #{key1:value1,key2:value2}. This idiom creates a map
that maps the string "foo" to the string "foovalue" and "bar" to the
string "barvalue":</p>
<p><span style="background-color: #15048a;">map语法：#{key1:value1,key2:value2}.这个创建map，把字符传&#8220;foo&#8221;到字符串"foovalue",&#8220;bar&#8221;到字符串"barvalue".</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:select label=<span class="code-quote">"label"</span> name=<span class="code-quote">"name"</span> list=<span class="code-quote">"#{'foo':'foovalue', 'bar':'barvalue'}"</span> /&gt;</span></pre>
</div>
</div>
<p>To determine if an element exists in a Collection, use the operations <tt>in</tt> and <tt>not in</tt>.</p>
<p><span style="background-color: #15048a;">用in 和 not in 检验元素是否在一个集合里面</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:if test=<span class="code-quote">"'foo' in {'foo','bar'}"</span>&gt;</span><br>   muhahaha<br><span class="code-tag">&lt;/s:if&gt;</span><br><span class="code-tag">&lt;s:else&gt;</span><br>   boo<br><span class="code-tag">&lt;/s:else&gt;</span><br><br><span class="code-tag">&lt;s:if test=<span class="code-quote">"'foo' not in {'foo','bar'}"</span>&gt;</span><br>   muhahaha<br><span class="code-tag">&lt;/s:if&gt;</span><br><span class="code-tag">&lt;s:else&gt;</span><br>   boo<br><span class="code-tag">&lt;/s:else&gt;</span></pre>
</div>
</div>
<p>To select a subset of a collection (called projection), use a wildcard within the collection.</p>
<ul class="alternate" type="square">
    <li>? - All elements matching the selection logic</li>
    <li>^ - Only the first element matching the selection logic</li>
    <li>$ - Only the last element matching the selection logic</li>
</ul>
<p>To obtain a subset of just male relatives from the object person:</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml">person.relatives.{? #this.gender == 'male'}</pre>
</div>
</div>
<h2><a name="OGNL-LambdaExpressions"></a>
<p>OGNL supports basic lamba expression syntax enabling you to write simple functions.</p>
<p>(Dedicated to all you math majors who didn't think you would ever see this one again.)</p>
<p>Fibonacci: if n==0 return 0; elseif n==1 return 1; else return fib(n-2)+fib(n-1);<br>
fib(0) = 0<br>
fib(1) = 1<br>
fib(11) = 89</p>
<table class="infoMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">How the expression works</strong><br>
            <p>The lambda expression is everything inside the brackets. The #this
            variable holds the argument to the expression, which is initially
            starts at 11.</p>
            </td>
        </tr>
    </tbody>
</table>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:property value=<span class="code-quote">"#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)"</span> /&gt;</span></pre>
</div>
</div>
<h2><a name="OGNL-JSP2.1"></a>JSP 2.1 </h2>
<p>Under JSP 2.1 the # character is now used by the JSP EL. </p>
<p>This may cause problems with some applications that use the OGNL # operator. </p>
<p>One quick-fix is to disable the JSP EL in a JSP 2.1 container (like GlassFish) by adding a jsp-config element to the web.xml</p>
<p><span style="background-color: #15048a;">和JSP2.1的兼容问题处理</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;jsp-config&gt;<br>    &lt;jsp-property-group&gt;<br>      &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;<br>      &lt;el-ignored&gt;<span class="code-keyword">true</span>&lt;/el-ignored&gt;<br>    &lt;/jsp-property-group&gt;<br>  &lt;/jsp-config&gt;</pre>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114519.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 10:45 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114519.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2： 怎样格式化数字和日期[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114506.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 02:28:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114506.html</guid><description><![CDATA[<p>A frequently asked question is how best to display dates and numbers
using a specified format. There are a number of approaches for this,
the most naive of which would be to add a method to your action class
to do the formatting for you. This method would take in a Date (or
subclass) object as a parameter, and return a formatted String.</p>
<p><span style="background-color: #3e05ba;">最通用的方式是：给Action类添加一个方法来格式化？</span><br></p>
<p>That approach however suffers from a number of flaws. For example,
it is not i18n aware. The date format specified is rigid, and will not
adapt to different locales easily (assuming you're not using a default
formatter that is). It also clutters up your actions with code that has
nothing to do with the action itself.</p>
<p><span style="background-color: #3e05ba;">指出添加Action中format方法的缺点n多</span><br></p>
<p>Instead, the recommended approach is to use Java's built-in date formatting features via use of the s:text tag.</p>
<p><span style="background-color: #3e05ba;">所以，用s:text标签才是王道</span><br></p>
<p>The s:text tag should be used for all i18n values. It will look up
the properties file for your action, and from that select the value for
the key that you specify. This is best illustrated in an example:</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;!-- display the number of items in a cart --&gt;<br>&lt;s:text name=<span class="code-quote">"'cart.items'"</span> value0=<span class="code-quote">"cartItems"</span> /&gt;</pre>
</div>
</div>
<p>The above tag will work as follows. value0 will result in a call to <strong>getCartItems()</strong> on your action class. The <strong>cart.items</strong>
name is escaped, so it is treated as a literal key into the actions'
properties file. Your MyAction.properties file will contain the
following:</p>
<p><strong>cart.items=You have {0} items in your cart.</strong></p>
<p>Normal Java <strong>MessageFormat</strong> behaviour will correctly substitute {0} with the value obtained from getCartItems.</p>
<p>Needless to say, this can get a lot more elaborate, with the ability
to specify both date and number formatting. Let us consider another
example. The goal here is to display a greeting to the user, as well as
the date of their last visit.</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;s:text name=<span class="code-quote">"'last.visit'"</span> value0=<span class="code-quote">"userName"</span> value1=<span class="code-quote">"lastVisit(userName)"</span> /&gt;</pre>
</div>
</div>
<p><strong>MyAction.java</strong> contains:</p>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-object">String</span> getUserName() { ... };<br><span class="code-keyword">public</span> Date getLastVisit(<span class="code-object">String</span> userName) { ... };</pre>
</div>
</div>
<p>Your <strong>MyAction.properties</strong> file will then contain:</p>
<p><strong>last.visit=Welcome back {0}, your last visit was at <span style="color: red;">{1,date,HH:mm dd-MM-yyyy}</span></strong></p>
<p>As you can see, this is a very powerful mechanism and allows you to
easily display numbers and dates using any formatting rules that Java
allows.<br><br><span style="background-color: #0aa013;">正如你看到的，这是一个非常强大的机制，允许你容易第展示数字和日期，而且用特定的格式化方式.<br>Samuel说：在Struts2里，每个Action都可以对应一个资源文件，用s:text也是不错地。就是教条了点，比如设定数字是money方式显示的话在中国自然用￥,在美国自然是$,但这里，必须显式地写两份资源文件里：一份美国：format.money = {0,number,$##0.00}，另一份中国：format.money = {0,number,￥##0.00}</span></p>
<span style="background-color: #3e05ba;">
<span style="background-color: #3e05ba;">
<span style="background-color: #000aaa;">
<span style="background-color: #000aaa;">
<p>&#160;</p>
<span style="background-color: #0aa013;">
</span>
<p>&#160;</p>
</span>
</span></span>
<pre class="code-java"></pre>
</span>
<table class="infoMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">value0 interface deprecated</strong><br>
            <p>The examples above pass in the values as:</p>
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">&lt;s:text name=<span class="code-quote">"'text.message'"</span> value0=<span class="code-quote">"userName"</span>/&gt;</pre>
            </div>
            </div>
            <p>These values should now (&gt;2.1.7?) be passed as params:</p>
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">&lt;s:text name=<span class="code-quote">"'text.message'"</span>&gt; <br>    &lt;s:param value=<span class="code-quote">"'userName'"</span>/&gt;<br>&lt;/s:text&gt;</pre>
            </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">Some message format examples</strong><br>
            <p>Here are some examples of formatting in the properties file:</p>
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">format.date = {0,date,MM/dd/yy}<br>format.time = {0,date,MM/dd/yy ha}<br>format.percent = {0,number,##0.00'%'}<br>format.money = {0,number,$##0.00}</pre>
            </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>   <img src ="http://www.blogjava.net/nobody_am/aggbug/114506.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 10:28 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114506.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2:JSP中获取Application，Session和Request范围的值[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114497.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 01:59:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114497.html</guid><description><![CDATA[<p>The application, session and request objects are available from within <tt>s</tt>
tags in jsp wherever ognl can be evaluated. Use the #application,
#session, or #request syntax to get the object and access values by
their keys using ['key'].</p>
<p><span style="background-color: #1600b6;">任何ognl能被计算的值，在jsp中用s标签都可以获得application,session和request对象。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Accessing scoped variables via &lt;s:property.../&gt; tags</strong></div>
<div class="codeContent">
<pre class="code-java">&lt;s:property value=<span class="code-quote">"#application\['foo'\]"</span>/&gt;<br>&lt;s:property value=<span class="code-quote">"#session\['baz'\]"</span>/&gt;</pre>
</div>
</div>
<p>Conversely, if you would like to make Struts 2 objects available to a JSP/JSTL scope, the <tt>s:set</tt> tag may be used like this:</p>
<p><span style="background-color: #1600b6;">相反，如果你项是的Struts2对象能在JSP/JSTL范围内获得，s:set标签可能这样用：</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Expose OGNL 'jobs' value to JSP/JSTL scope 'jobz'<br><span style="background-color: #1600b6;">把OGNL'jobs'值放入JSP/JSTL范围命名'jobz'</span><br></strong></div>
<div class="codeContent">
<pre class="code-java">&lt;s:set name=<span class="code-quote">"jobz"</span> value=<span class="code-quote">"jobs"</span> scope=<span class="code-quote">"request"</span> /&gt;<br>&lt;c:forEach items=<span class="code-quote">"${jobz} <span class="code-keyword">var</span>="</span>job"&gt;<br>...<br>&lt;/c:forEach&gt;</pre>
</div>
</div>
<table class="infoMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">"Auto-exposure"</strong><br>
            <p>In Struts 2 OGNL values are automagically exposed to JSP/JSTL; using <tt>&lt;s:set.../&gt;</tt> as described above may not be necessary.</p>
            <p><span style="background-color: #1600b6;">在Struts2 OGNL的值被自动暴露给JSP/JSTL;上面例子中&lt;s:set .../&gt;可能不需要</span>。<br></p>
            </td>
        </tr>
    </tbody>
</table>
<p><span style="background-color: #a60505; font-weight: bold;">疑问啊：Struts2 OGNL和OGNL难道是两回事？</span><br> </p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 09:59 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2：访问Application，Session和Request范围内的值[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114493.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 01:48:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114493.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>The framework provides several access helpers to access Session, Application, Request scopes.</p>
<p><span style="background-color: #1c05b8;">框架提供了多种访问Session，Application和Request范围内值的帮助器。</span><br></p>
<p>
Web agnostic (independent of the servlet API) with a single line of code.</p>
<p><span style="background-color: #1c05b8;">Web agnostic (独立于Servlet API)用一个简单的代码。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Access session via a context entry<br><span style="background-color: #1c05b8;">通过context entry</span><br></strong></div>
<div class="codeContent">
<pre class="code-java">Map session = (Map) ActionContext.getContext().get(<span class="code-quote">"session"</span>);<br>session.put(<span class="code-quote">"myId"</span>,myProp);</pre>
</div>
</div>
<div class="code">
<div class="codeHeader"><strong>Access session via a helper method (avoids cast)<br><span style="background-color: #1c05b8;">通过帮助器方法</span><br></strong></div>
<div class="codeContent">
<pre class="code-java">ServletActionContext.getRequest().getSession()</pre>
</div>
</div>
<table class="warningMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/forbidden.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>
            <p>Do not use <tt>ActionContext.getContext()</tt> in the constructor of your Action class. The values may not be set up, and the call may return null for <tt>getSession()</tt>.</p>
            <p><span style="background-color: #1c05b8;">别在Action的构造函数里用ActionContext.getContext()，那个值可能没有建立，可能返回null。</span><br></p>
            </td>
        </tr>
    </tbody>
</table>
<p>If you must have get access to the HttpSession, use the ServletConfigInterceptor (see <span class="nobr"><a href="http://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=test&amp;title=Interceptors" title="Create page in space test: interceptors" class="createlink">test:Interceptors<sup><img src="http://cwiki.apache.org/confluence/images/icons/plus.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span>).</p>
<p><span style="background-color: #1c05b8;">如果你必须访问HttpSession,用ServletConfigInterceptor。</span><br></p>
<p>In your views, you can access with your JavaServer Pages with calls to the implicit properties <tt>session</tt> and <tt>request</tt>.</p>
<p><span style="background-color: #1c05b8;">下面展示了在jsp中如果和访问session和request</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Accessing the Session or Request from a JSP</strong></div>
<div class="codeContent">
<pre class="code-java">&lt;saf: property value=<span class="code-quote">"#session.myId"</span> /&gt;<br><br>&lt;saf: property value=<span class="code-quote">"#request.myId"</span> /&gt;</pre>
</div>
</div>
<p>All the servlet scopes can be accessed via the ActionContext.</p>
<p><span style="background-color: #1c05b8;">下面展示了在servlet范围如何通过ActonContext访问：</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Accessing servlet scopes</strong></div>
<div class="codeContent">
<pre class="code-java">Map request = (Map) ActionContext.getContext().get(<span class="code-quote">"request"</span>);<br>request.put(<span class="code-quote">"myId"</span>,myProp);<br><br>Map application = (Map) ActionContext.getContext().get(<span class="code-quote">"application"</span>);<br>application.put(<span class="code-quote">"myId"</span>,myProp);<br><br>Map session = (Map) ActionContext.getContext().get(<span class="code-quote">"session"</span>);<br>session.put(<span class="code-quote">"myId"</span>, myProp);<br><br>Map attr = (Map) ActionContext.getContext().get(<span class="code-quote">"attr"</span>);<br>attr.put(<span class="code-quote">"myId"</span>,myProp);</pre>
</div>
</div>
<p>The <tt>attr</tt> map will search the <tt>javax.servlet.jsp.PageContext</tt> for the specified key. If the PageContext doean't exist, it will search <tt>request}, {{session</tt>, and <tt>application</tt> respectively.</p>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 09:48 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2:在Struts2和XWork1中用JSP2和JSTL[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114489.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 01:39:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114489.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>S2/X1 and its taglib is oriented towards OGNL, which is using a value stack <br>
for all action properties. These values are not direct available for the<br>
expression language of JSP2/JSTL1.1.</p>
<p><span style="background-color: #1905a6;">S2/X1和他们的标签库是面向OGNL的，它对所有Action属性用Value栈的。这些值不能直接在JSP2和JSTL1.1种获取。</span><br> </p>
<p>However, it's easy to populate the request attribute set, with all gettable properties of an action object. You need to provide an interceptor that does the job, by register a PreResultListener which is invoked after the return of Action.execute() but before the rendering of the result .</p>
<p><span style="background-color: #1905a6;">但是，在一个Action对象中所有可get的属性，是很容易更新请求属性集的。你需要提供一个interceptor来作这件工作，在调用Action.execute之后，渲染结果之前，注册一个PreResultListener。</span><br></p>
<p>The interceptor below is using Jakarta BeanUtils. It first extracts all getters<br>
of the current action, invokes them one at the time and stores the values into a map.</p>
<p><span style="background-color: #1905a6;">下面的interceptor用了Jakarta BeanUtils. 它首先获取所有当前action的getters，调用他们，并且把值保存到map中。</span><br></p>
<p>
Then it iterates over the map and populates the request attribute set.<br>
<em>The double iteration is not needed, it's just there for clarity.</em></p>
<p><span style="background-color: #1905a6;">然后遍历map，组装请求属性集，双重遍历是不需要的，这儿仅仅未了清晰。</span><br>
</p>
<h2><a name="UsingStrutsandXWorkwithJSP2.0andJSTL1.1-classActionPropertyExportInterceptor"></a>
</h2>
<h2>class ActionPropertyExportInterceptor</h2>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">package</span> com.whatever.interceptors;<br><br><span class="code-keyword">import</span> org,apache.struts2.StrutsStatics;<br><span class="code-keyword">import</span> com.opensymphony.xwork.Action;<br><span class="code-keyword">import</span> com.opensymphony.xwork.ActionInvocation;<br><span class="code-keyword">import</span> com.opensymphony.xwork.interceptor.AroundInterceptor;<br><span class="code-keyword">import</span> com.opensymphony.xwork.interceptor.PreResultListener;<br><span class="code-keyword">import</span> org.apache.commons.beanutils.PropertyUtils;<br><span class="code-keyword">import</span> javax.servlet.http.HttpServletRequest;<br><span class="code-keyword">import</span> java.beans.PropertyDescriptor;<br><span class="code-keyword">import</span> java.util.*;<br><br>/**<br> * Populates HTTP Request Attributes with all gettable properties of the current action.<br> */<br><span class="code-keyword">public</span> class ActionPropertyExportInterceptor <span class="code-keyword">extends</span> AroundInterceptor {<br>    <span class="code-keyword">protected</span> void before(ActionInvocation invocation) <span class="code-keyword">throws</span> Exception {<br>        invocation.addPreResultListener( <span class="code-keyword">new</span> PropertyExporter() );<br>    }<br>    <span class="code-keyword">protected</span> void after(ActionInvocation dispatcher, <span class="code-object">String</span> result) <span class="code-keyword">throws</span> Exception { }<br><br>    <span class="code-keyword">public</span> <span class="code-keyword">static</span> class PropertyExporter <span class="code-keyword">implements</span> PreResultListener {<br>        <span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-keyword">final</span> List   ignore = Arrays.asList(<span class="code-keyword">new</span> <span class="code-object">String</span>[] {<span class="code-quote">"class"</span>, <span class="code-quote">"texts"</span>}); <span class="code-comment">//skip getClass,...<br></span><br>        <span class="code-comment">//Invoked after Action.execute() but before Result<br></span>        <span class="code-comment">//Calls all getters of the action and insert the values into the request<br></span>        <span class="code-keyword">public</span> void beforeResult(ActionInvocation invocation, <span class="code-object">String</span> resultCode) {<br>            Map                 props   = extractGetterPropertyValues( invocation.getAction() );<br>            HttpServletRequest  request = getRequest(invocation);<br>            <span class="code-keyword">for</span> (Iterator it = props.entrySet().iterator(); it.hasNext();) {<br>                Map.Entry   e = (Map.Entry) it.next();<br>                request.setAttribute((<span class="code-object">String</span>) e.getKey(), e.getValue());<br>            }<br>        }<br><br>        <span class="code-keyword">public</span> Map extractGetterPropertyValues(<span class="code-object">Object</span> bean) {<br>            PropertyDescriptor[]  descr = PropertyUtils.getPropertyDescriptors(bean);<br>            Map                   props = <span class="code-keyword">new</span> HashMap();<br>            <span class="code-keyword">for</span> (<span class="code-object">int</span> i = 0; i &lt; descr.length; i++) {<br>                PropertyDescriptor d = descr[i];<br>                <span class="code-keyword">if</span> (d.getReadMethod() == <span class="code-keyword">null</span>) <span class="code-keyword">continue</span>;<br>                <span class="code-keyword">if</span> (ignore.contains(d.getName())) <span class="code-keyword">continue</span>;<br><br>                <span class="code-keyword">try</span> {<br>                    props.put(d.getName(), PropertyUtils.getProperty(bean, d.getName()));<br>                } <span class="code-keyword">catch</span> (Exception e) { }<br>            }<br>            <span class="code-keyword">return</span> props;<br>        }<br><br>        <span class="code-keyword">public</span> HttpServletRequest getRequest(ActionInvocation invocation) {<br>            <span class="code-keyword">return</span> (HttpServletRequest) invocation.getInvocationContext().get(WebWorkStatics.HTTP_REQUEST);<br>        }<br>    }<br>}</pre>
</div>
</div>
<p>Don't forget to <em>declare</em> the interceptor in your struts.xml file and <em>insert</em> it <br>
into your interceptor stack.</p>
<p><span style="background-color: #1905a6;">别忘了在struts.xml里声明interceptor，把它插入你interceptor栈中。</span><br></p>
<h2><a name="UsingStrutsandXWorkwithJSP2.0andJSTL1.1-struts.xmlsnippet"></a>struts.xml snippet</h2>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;interceptor name=<span class="code-quote">"export"</span> class=<span class="code-quote">"com.whatever.interceptors.ActionPropertyExportInterceptor"</span> /&gt;<br>. . .<br>&lt;interceptor-stack name=<span class="code-quote">"standard-interceptors"</span>&gt;<br>    &lt;interceptor-ref name=<span class="code-quote">"timer"</span> /&gt;<br>    &lt;interceptor-ref name=<span class="code-quote">"logger"</span> /&gt;<br>    &lt;interceptor-ref name=<span class="code-quote">"params"</span> /&gt;<br>*    &lt;interceptor-ref name=<span class="code-quote">"export"</span>/&gt;*<br>    &lt;interceptor-ref name=<span class="code-quote">"validateParams"</span>/&gt;<br>    &lt;interceptor-ref name=<span class="code-quote">"awarePlugger"</span> /&gt;<br>&lt;/interceptor-stack&gt;</pre>
</div>
</div>
<p>Your action need to provide getters for all properties that should be exported into the request attribute set.</p>
<p><span style="background-color: #1905a6;">你的action中需要未被放入request范围的属性提供get方法</span><br></p>
<h2><a name="UsingStrutsandXWorkwithJSP2.0andJSTL1.1-classViewUser"></a>class ViewUser</h2>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class ViewUser <span class="code-keyword">extends</span> ActionSupport {<br>    <span class="code-keyword">private</span> <span class="code-object">int</span>                         id;<br>    <span class="code-keyword">private</span> User                        user;<br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> execute() <span class="code-keyword">throws</span> Exception {<br>        user = findUser( getId() );<br>        <span class="code-keyword">return</span> Action.SUCCESS;<br>    }<br><br>    <span class="code-keyword">public</span>  <span class="code-object">int</span>   getId()          {<span class="code-keyword">return</span> id;}<br>    <span class="code-keyword">public</span>  void  setId(<span class="code-object">int</span> id)    {<span class="code-keyword">this</span>.id = id;}<br>*    <span class="code-keyword">public</span>  User  getUser()        {<span class="code-keyword">return</span> user;}*<br><br>    <span class="code-keyword">private</span> User  findUser(<span class="code-object">int</span> id) {...}<br>}</pre>
</div>
</div>
<p>The User class might look like this</p>
<p><span style="background-color: #1905a6;">User类可能如下所示：</span><br></p>
<h2><a name="UsingStrutsandXWorkwithJSP2.0andJSTL1.1-classUser"></a>class User</h2>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">import</span> java.util.Date;<br><span class="code-keyword">public</span> class User {<br>    <span class="code-keyword">private</span> <span class="code-object">int</span>     id;<br>    <span class="code-keyword">private</span> <span class="code-object">String</span>  firstName, lastName, email;<br>    <span class="code-keyword">private</span> <span class="code-object">String</span>  street, zip, city;<br>    <span class="code-keyword">private</span> Date    date;<br>    <br>    <span class="code-keyword">public</span> <span class="code-object">String</span>  getFirstName() {<span class="code-keyword">return</span> firstName;}<br>    <span class="code-comment">//..._getters and setters_...<br></span>}</pre>
</div>
</div>
<p>Finally, using the samples above you can write your JSP2 page like this.</p>
<p><span style="background-color: #1905a6;">最后，通过上面的例子，你可以写自己的jsp2，类似下面：</span><br></p>
<h2><a name="UsingStrutsandXWorkwithJSP2.0andJSTL1.1-ViewUser.jsp"></a>ViewUser.jsp</h2>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;%@ taglib prefix=<span class="code-quote">"c"</span>   uri=<span class="code-quote">"http:<span class="code-comment">//java.sun.com/jsp/jstl/core"</span> %&gt;<br></span>&lt;%@ taglib prefix=<span class="code-quote">"fmt"</span> uri=<span class="code-quote">"http:<span class="code-comment">//java.sun.com/jsp/jstl/fmt"</span> %&gt;<br></span>&lt;%@ taglib prefix=<span class="code-quote">"fn"</span>  uri=<span class="code-quote">"http:<span class="code-comment">//java.sun.com/jsp/jstl/functions"</span> %&gt;<br></span>&lt;html&gt;<br>&lt;head&gt;<br>    &lt;title&gt;Info about ${user.firstName}&lt;/title&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>    &lt;h1&gt;Info about ${user.firstName} ${user.lastName} [OS:ID=${user.id}]&lt;/h1&gt;<br>    &lt;table border=<span class="code-quote">"1"</span> cellspacing=<span class="code-quote">"0"</span> cellpadding=<span class="code-quote">"2"</span> width=<span class="code-quote">"90%"</span> &gt;<br>    &lt;tr&gt;<br>        &lt;th&gt;Name&lt;/th&gt; &lt;td&gt;${user.firstName} ${user.lastName}&lt;/td&gt;<br>    &lt;/tr&gt;<br>    &lt;tr&gt;<br>        &lt;th&gt;Created&lt;/th&gt; &lt;td&gt;&lt;fmt:formatDate value=<span class="code-quote">"${user.date}"</span> pattern=<span class="code-quote">"yyyy-MM-dd HH:mm"</span>/&gt;&lt;/td&gt;<br>    &lt;/tr&gt;<br>    &lt;tr&gt;<br>        &lt;th&gt;Email&lt;/th&gt; &lt;td&gt;${user.email}&lt;/td&gt;<br>    &lt;/tr&gt;<br>    &lt;tr&gt;<br>        &lt;th&gt;Address&lt;/th&gt; &lt;td&gt;${user.street} ${user.zip} ${fn:toUpperCase(user.city)}&lt;/td&gt;<br>    &lt;/tr&gt;<br>    &lt;/table&gt;<br>&lt;/body&gt;<br>&lt;/html&gt;</pre>
</div>
</div>
<h2><a name="UsingStrutsandXWorkwithJSP2.0andJSTL1.1-DisplayingvalidationerrorswithJSTL"></a>Displaying validation errors with JSTL</h2>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;c:<span class="code-keyword">if</span> test=<span class="code-quote">"${!empty fieldErrors || !empty actionErrors}"</span>&gt;<br>  &lt;div class=<span class="code-quote">"red"</span>&gt;<br>    &lt;ul&gt;<br>      &lt;c:forEach items=<span class="code-quote">"${fieldErrors}"</span> <span class="code-keyword">var</span>=<span class="code-quote">"fieldError"</span>&gt;<br>        &lt;c:forEach items=<span class="code-quote">"${fieldError.value}"</span> <span class="code-keyword">var</span>=<span class="code-quote">"error"</span>&gt;<br>          &lt;li&gt;${error}&lt;/li&gt;<br>        &lt;/c:forEach&gt;<br>      &lt;/c:forEach&gt;<br>      &lt;c:forEach items=<span class="code-quote">"${actionErrors}"</span> <span class="code-keyword">var</span>=<span class="code-quote">"actionError"</span>&gt;<br>        &lt;li&gt;${actionError}&lt;/li&gt;<br>      &lt;/c:forEach&gt;<br>    &lt;/ul&gt;<br>  &lt;/div&gt;<br>&lt;/c:<span class="code-keyword">if</span>&gt;</pre>
</div>
</div>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114489.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 09:39 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114489.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2: 用JSTL和DisplayTag在Struts2应用中显示数据[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/29/114485.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Sun, 29 Apr 2007 01:15:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/29/114485.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;s:set name=<span class="code-quote">"jobz"</span> value=<span class="code-quote">"jobs"</span> scope=<span class="code-quote">"request"</span> /&gt;</pre>
</div>
</div>
<p>The full example below shows a Struts 2/OGNL variable "jobs" being
exposed as "jobz" to the request scope and being used with jstl and the
display tag.</p>
<p>下面整个例子显示了把Struts2/OGNL&#8220;jobs&#8221;变量作为&#8220;jobz&#8221;放入request范围内，并且用jstl和display tag显示。<br></p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;%@ taglib uri=<span class="code-quote">"/WEB-INF/tlds/c.tld"</span> prefix=<span class="code-quote">"c"</span> %&gt;<br>&lt;%@ taglib uri=<span class="code-quote">"/WEB-INF/tlds/fmt.tld"</span> prefix=<span class="code-quote">"fmt"</span> %&gt;<br>&lt;%@ taglib uri=<span class="code-quote">"/WEB-INF/tlds/displaytag-el-12.tld"</span> prefix=<span class="code-quote">"display"</span> %&gt;<br>&lt;%@ taglib uri=<span class="code-quote">"/struts-tags"</span> prefix=<span class="code-quote">"s"</span> %&gt;<br><br>&lt;s:set name=<span class="code-quote">"jobz"</span> value=<span class="code-quote">"jobs"</span> scope=<span class="code-quote">"request"</span> /&gt;<br><br>&lt;h1&gt;&lt;fmt:message key=<span class="code-quote">"title.listAllJobs"</span>/&gt;&lt;/h1&gt;<br>&lt;display:table name=<span class="code-quote">"jobz"</span> class=<span class="code-quote">"simple"</span> id=<span class="code-quote">"row"</span> &gt;<br>  &lt;display:column  titleKey=<span class="code-quote">"label.global.actions"</span> &gt;<br>  		&lt;c:url <span class="code-keyword">var</span>=<span class="code-quote">"viewurl"</span> value=<span class="code-quote">"/viewJobDetail.action"</span>&gt;<br>			&lt;c:param name=<span class="code-quote">"name"</span> value=<span class="code-quote">"${row.name}"</span>/&gt;<br>  			&lt;c:param name=<span class="code-quote">"groupName"</span> value=<span class="code-quote">"${row.group}"</span>/&gt;<br>		&lt;/c:url&gt;<br>  		&lt;c:url <span class="code-keyword">var</span>=<span class="code-quote">"exeurl"</span> value=<span class="code-quote">"/viewJobDetail.action"</span>&gt;<br>			&lt;c:param name=<span class="code-quote">"name"</span> value=<span class="code-quote">"${row.name}"</span>/&gt;<br>  			&lt;c:param name=<span class="code-quote">"groupName"</span> value=<span class="code-quote">"${row.group}"</span>/&gt;<br>  			&lt;c:param name=<span class="code-quote">"executeJobAction"</span> value=<span class="code-quote">"execute"</span>/&gt;<br>		&lt;/c:url&gt;<br>  		&lt;c:url <span class="code-keyword">var</span>=<span class="code-quote">"editurl"</span> value=<span class="code-quote">"/viewJobDetail.action"</span>&gt;<br>			&lt;c:param name=<span class="code-quote">"name"</span> value=<span class="code-quote">"${row.name}"</span>/&gt;<br>  			&lt;c:param name=<span class="code-quote">"groupName"</span> value=<span class="code-quote">"${row.group}"</span>/&gt;<br>  			&lt;c:param name=<span class="code-quote">"editAction"</span> value=<span class="code-quote">"edit"</span>/&gt;<br>		&lt;/c:url&gt;<br>	&lt;a href='&lt;c:out value=<span class="code-quote">"${viewurl}"</span>/&gt;'&gt;&lt;fmt:message key=<span class="code-quote">"label.global.view"</span>/&gt;&lt;/a&gt; |<br>	&lt;a href='&lt;c:out value=<span class="code-quote">"${editurl}"</span>/&gt;'&gt;&lt;fmt:message key=<span class="code-quote">"label.global.edit"</span>/&gt;&lt;/a&gt; |<br>	&lt;a href='&lt;c:out value=<span class="code-quote">"${exeurl}"</span>/&gt;'&gt;&lt;fmt:message key=<span class="code-quote">"label.global.execute"</span>/&gt;&lt;/a&gt; &amp;nbsp;<br>  &lt;/display:column&gt; <br><br>  &lt;display:column property=<span class="code-quote">"group"</span> titleKey=<span class="code-quote">"label.job.group"</span> sortable=<span class="code-quote">"<span class="code-keyword">true</span>"</span>   /&gt;<br>  &lt;display:column property=<span class="code-quote">"name"</span> titleKey=<span class="code-quote">"label.job.name"</span> sortable=<span class="code-quote">"<span class="code-keyword">true</span>"</span>  /&gt;<br>  &lt;display:column property=<span class="code-quote">"description"</span> titleKey=<span class="code-quote">"label.job.description"</span> /&gt;<br>  &lt;display:column property=<span class="code-quote">"jobClass"</span> titleKey=<span class="code-quote">"label.job.jobClass"</span> sortable=<span class="code-quote">"<span class="code-keyword">true</span>"</span>  /&gt;<br><br>&lt;/display:table&gt;</pre>
</div>
</div>
<p>Please note, at the time of this writing the "titleKey" attribute of
the display tag's column tag is not yet released into a final version.
It is a feature that is currently only available through cvs.</p>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-29 09:15 <a href="http://www.blogjava.net/nobody_am/news/2007/04/29/114485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 Tag: Generic Tags[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114103.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 07:42:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114103.html</guid><description><![CDATA[<p>Generic tags are used for controlling the execution flow when the pages render. These tags also allow for data extraction from places other than your action or the value stack, such as <a title=Localization href="http://struts.apache.org/2.x/docs/localization.html">Localization</a>, JavaBeans, and including additional URLs or action executions.</p>
<p><span style="BACKGROUND-COLOR: #008000">Generic 标签用来控制页面渲染是的执行流程，还用来允许获取某个地方（不是action和value stack）的数据，例如：Loaclization，JavaBean，和 including additional URLs or action executions.</span></p>
<ul>
    <li>Control Tags provide control flow, such as <tt>if</tt>, <tt>else</tt>, and <tt>iterator</tt>. </li>
</ul>
<span style="BACKGROUND-COLOR: #008000">&nbsp;&nbsp;&nbsp; 控制Tag提供控制流程，例如if,else,iterator</span><br>
<ul>
    <li>Data Tags allow for data manipulation or creation, such as <tt>bean</tt>, <tt>push</tt>, and <tt>i18n</tt>. </li>
</ul>
<span style="BACKGROUND-COLOR: #008000">&nbsp;&nbsp;&nbsp; 数据Tag允许数据操控或创建，例如bean，push，和i18n</span><br>
  <img src ="http://www.blogjava.net/nobody_am/aggbug/114103.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 15:42 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114103.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 Tag: Introduction[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114100.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114100.html</guid><description><![CDATA[<p>The framework provides a tag library decoupled from the view
technology. In this section, we describe each tag in general terms,
such as the attributes it supports, what the behaviors are, and so
forth. Most tags are supported in all template languages (see <a  href="http://struts.apache.org/2.x/docs/jsp-tags.html" title="JSP Tags">JSP Tags</a>, <a  href="http://struts.apache.org/2.x/docs/velocity-tags.html" title="Velocity Tags">Velocity Tags</a>, and <a  href="http://struts.apache.org/2.x/docs/freemarker-tags.html" title="FreeMarker Tags">FreeMarker Tags</a>),
but some are currently only specific to one language. Whenever a tag
doesn't have complete support for every language, it is noted on the
tag's reference page.</p>
<p><br></p>
<p>The types of tags can be broken in to two types: generic and UI.
Besides function and responsibility, the biggest difference between the
two is that the HTML tags support <em>templates</em> and <em>themes</em>.
In addition to the general tag reference, we also provide examples for
using these generic tags in each of the support languages.</p>
<p><span style="background-color: #120092;">Tag类型能被分成两种：Generic和UI。除了功能和指责，他们之间的最大不同在预HTML标签支持模板和主题。除了通用的标签参考之外，我们提供了例子。</span><br></p>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> Be sure to read the <a  href="http://struts.apache.org/2.x/docs/tag-syntax.html" title="Tag Syntax">Tag Syntax</a> document to learn how tag attribute syntax works.</p>
<p>The tags are designed to display dynamic data. To create a input
field that displays the property "postalCode", we'd pass the String
"postalCode" to the textfield tag.</p>
<p><span style="background-color: #120092;">标签被设计用来展示动态数据。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Creating a dynamic input field</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:textfield name=<span class="code-quote">"postalCode"</span>/&gt;</span></pre>
</div>
</div>
<p>If there is a "postalCode" property on the value stack, its value
will be set to the input field. When the field is submitted back to the
framework, the value of the control will be set back to the
"postalCode" property.</p>
<span style="background-color: #120092;">
<p><span style="background-color: #120092;">如果value栈里有一个postalCode属性，他的值将被放到input字段，当字段被提交回框架，值将被设置到postalCode属性（注：有点服务端和客户端绑定的味道）</span><br></p>
</span>
<p>Sometimes, we want to pass the dynamic data to a tag. For example,
we might want to display a label with the input field, and we might
want to obtain the label from the application's messages resources.
Accordingly, the framework will parse expressions found in the tag
attributes, so that we can merge dynamic data into the tag attributes
at runtime. The expression escape sequence is "%{ ... }". Any text
embedded in the escape sequence is evalulated as an expression.</p>
<p>有时，我们象传递动态数据到tag。例如，我们象显示Label和input在一起，我们从系统的资源文件获取Lable，框架将解析表达式，所以我们能把动态数据整合到标签属性上。表达式样子是&#8220;%{}&#8221;.在大括弧里的表达式将被计算。<br></p>
<div class="code">
<div class="codeHeader"><strong>Using an expression to set the label</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:textfield key=<span class="code-quote">"postalCode.label"</span> name=<span class="code-quote">"postalCode"</span>/&gt;</span></pre>
</div>
</div>
<p>The expression language (<a  href="http://struts.apache.org/2.x/docs/ognl.html" title="OGNL">OGNL</a>) lets us call methods and evaluate properties. The method <tt>getText</tt>
is provided by ActionSupport, which is the base class for most Actions.
Since the Action is on the stack, we can call any of its methods from
an expression, including <tt>getText</tt>.</p>
<h2><a name="TagSyntax-NonStringAttributes"></a>Non-String Attributes</h2>
<p>The HTTP protocol is text-based, but some tags have non-String attribute types, like <tt>bool</tt> or <tt>int</tt>. To make using non-String attributes intuitative, the framework evaulates <strong>all</strong>
non-String attributes as an expression. In this case, you do not need
to use the escape notation. (But, if you do anyway , the framework will
just strip it off.)</p>
<div class="code">
<div class="codeHeader"><strong>Evaluating booleans</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:select key=<span class="code-quote">"state.label"</span> name=<span class="code-quote">"state"</span> multiple=<span class="code-quote">"true"</span>/&gt;</span></pre>
</div>
</div>
<p>Since the attribute <tt>multiple</tt> maps to a boolean property,
the framework does not interpret the value as a String. The value is
evaluated as an expression and automtically converted to a boolean.</p>
<p>Since it's easy to forget which attributes are String and which are non-String, you can still use the escape notation.</p>
<div class="code">
<div class="codeHeader"><strong>Evaluating booleans (verbose)</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:select key=<span class="code-quote">"state.label"</span> name=<span class="code-quote">"state"</span> multiple=<span class="code-quote">"%{true}"</span>/&gt;</span></pre>
</div>
</div>
<div class="code">
<div class="codeHeader"><strong>Evaluating booleans (with property)</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:select key=<span class="code-quote">"state.label"</span> name=<span class="code-quote">"state"</span> multiple=<span class="code-quote">"allowMultiple"</span>/&gt;</span></pre>
</div>
</div>
<div class="code">
<div class="codeHeader"><strong>Evaluating booleans (verbose with property)</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:select key=<span class="code-quote">"state.label"</span> name=<span class="code-quote">"state"</span> multiple=<span class="code-quote">"%{allowMultiple}"</span>/&gt;</span></pre>
</div>
</div>
<h2><a name="TagSyntax-{{value}}isanObject\!"></a><tt>value</tt> is an Object!</h2>
<p>Most often, the <tt>value</tt> attribute is set automatically, since <tt>name</tt> attribute usually tells the framework which property to call to set the <tt>value</tt>. But, if there is a reason to set the <tt>value</tt> directly, be advised that <tt><strong>value</strong></tt> <strong>is an Object</strong> <strong><em>NOT</em></strong> <strong>a String</strong>.</p>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> Since <tt>value</tt> is not a String, whatever is passed to <tt>value</tt> is evaluated as an expression - <strong>NOT</strong> a String literal.</p>
<div class="code">
<div style="color: red;" class="codeHeader"><strong>Probably wrong!</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:textfield key=<span class="code-quote">"state.label"</span> name=<span class="code-quote">"state"</span> value=<span class="code-quote">"CA"</span>/&gt;</span></pre>
</div>
</div>
<p>If a <tt>textfield</tt> is passed the value attribute <tt>"CA"</tt>, the framework will look for a property named <tt>getCa</tt>.
Generally, this is not what we mean. What we mean to do is pass a
literal String. In the expression language, literals are placed within
quotes</p>
<div class="code">
<div class="codeHeader"><strong>Passing a literal value the right way</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:textfield key=<span class="code-quote">"state.label"</span> name=<span class="code-quote">"state"</span> value=<span class="code-quote">"%{'CA'}"</span> /&gt;</span></pre>
</div>
</div>
<p>Another approach would be to use the idiom <tt>value="'CA'"</tt>, but, in this case, using the expression notation is recommended.</p>
<p>Boiled down, the tag attributes are evaluated using three rules.</p>
<ol>
    <li>All <em>String</em> attribute types are <em>parsed</em> for the "%{ ... }" notation.</li>
    <li>All <em>non-String</em> attribute  types are <strong>not</strong> parsed, but evaluated directly as an expression</li>
    <li>The exception to rule #2 is that if the <em>non-String</em> attribute uses the escape notion "{%{}", the notation is ignored as redundant, and the content evaluated.</li>
</ol>
<h2><a name="TagSyntax-ExpressionLanguageNotations"></a>Expression Language Notations</h2>
<table class="confluenceTable">
    <tbody>
        <tr>
            <td class="confluenceTd">
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">&lt;p&gt;Username: ${user.username}&lt;/p&gt;</pre>
            </div>
            </div>
            </td>
            <td class="confluenceTd"> A JavaBean object in a standard context in Freemarker, Velocity, or JSTL EL (Not OGNL). </td>
        </tr>
        <tr>
            <td class="confluenceTd">
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">&lt;s:textfield name=<span class="code-quote">"username"</span>/&gt;</pre>
            </div>
            </div>
            </td>
            <td class="confluenceTd"> A username property on the Value Stack. </td>
        </tr>
        <tr>
            <td class="confluenceTd">
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">&lt;s:url id=<span class="code-quote">"es"</span> action=<span class="code-quote">"Hello"</span>&gt;<br>  &lt;s:param name=<span class="code-quote">"request_locale"</span>&gt;<br>    es<br>  &lt;/s:param&gt;<br>&lt;/s:url&gt;<br>&lt;s:a href=<span class="code-quote">"%{es}"</span>&gt;Espanol&lt;/s:a&gt;</pre>
            </div>
            </div>
            </td>
            <td class="confluenceTd">  Another way to refer to a property placed on the Value Stack. </td>
        </tr>
        <tr>
            <td class="confluenceTd">
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">&lt;s:property<br>  name=<span class="code-quote">"#session.user.username"</span> /&gt;</pre>
            </div>
            </div>
            </td>
            <td class="confluenceTd"> The username property of the User object in the Session context. </td>
        </tr>
        <tr>
            <td class="confluenceTd">
            <div class="code">
            <div class="codeContent">
            <pre class="code-java">&lt;s:select<br>  label=<span class="code-quote">"FooBar"</span> name=<span class="code-quote">"foo"</span><br>  list="#{'username':'trillian',<br>    'username':'zaphod'}" /&gt;</pre>
            </div>
            </div>
            </td>
            <td class="confluenceTd">  A static Map, as in put("username","trillian").</td>
        </tr>
    </tbody>
</table>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 15:30 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 FAQ[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114061.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 06:01:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114061.html</guid><description><![CDATA[<span style="font-weight: bold; color: red;">1,怎样显示用字节数组提供的动态或静态图片</span><span style="color: red;">：</span><br>o display an image represented as an array of bytes
<ul>
    <li>Reference an Action for the image src attribute</li>
</ul>
&nbsp;&nbsp;&nbsp; <span style="background-color: #2000ff;">关系到提供image源属性的Action</span><br>
<ul>
    <li>Provide a helper method on the Action to return an array of bytes</li>
</ul>
<span style="background-color: #2000ff;">&nbsp;&nbsp;&nbsp; 在Action中提供一个返回字节数组的方法</span><br>
<ul>
    <li>Provide a Result Type that renders the array to the response</li>
</ul>
&nbsp;&nbsp;&nbsp; <span style="background-color: #2000ff;">提供一个渲染字节数组为图片的Result类型</span><br>
<h2><a name="Howcanwedisplaydynamicorstaticimagesthatcanbeprovidedasanarrayofbytes-ReferenceanAction"></a>
<div class="code">
<div class="codeHeader"><strong>MyAction.jsp</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;img src=<span class="code-quote">"/myWebAppContext/myAction.do"</span> /&gt;</span></pre>
</div>
</div>
</h2>
<h2><a name="Howcanwedisplaydynamicorstaticimagesthatcanbeprovidedasanarrayofbytes-ProvideHelperMethods"></a>Provide Helper Methods</h2>
<div class="code">
<div class="codeHeader"><strong>MyAction.java</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyAction <span class="code-keyword">extends</span> ActionSupport {<br>  <span class="code-keyword">public</span> <span class="code-object">String</span> doDefault() {<br>    <span class="code-keyword">return</span> <span class="code-quote">"myImageResult"</span>;<br>  }<br><br>  <span class="code-keyword">public</span> <span class="code-object">byte</span>[] getMyImageInBytes() { .... }<br><br>  <span class="code-keyword">public</span> <span class="code-object">String</span> getMyContentType() { ... }<br>  <span class="code-keyword">public</span> <span class="code-object">String</span> getMyContentDisposition() { ... }<br>  <span class="code-keyword">public</span> <span class="code-object">int</span> getMyContentLength() { .... }<br>  <span class="code-keyword">public</span> <span class="code-object">int</span> getMyBufferSize() { ... }<br><br>}</pre>
</div>
</div>
<h2><a name="Howcanwedisplaydynamicorstaticimagesthatcanbeprovidedasanarrayofbytes-ProvideaCustomResultType"></a>Provide a Custom Result Type</h2>
<div class="code">
<div class="codeHeader"><strong>struts.xml</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;struts&gt;</span><br><br>    ...<br>    <span class="code-tag">&lt;result-types&gt;</span><br>        <span class="code-tag">&lt;result-type name=<span class="code-quote">"myBytesResult"</span> class=<span class="code-quote">"MyBytesResult"</span> /&gt;</span><br>    <span class="code-tag">&lt;/result-types&gt;</span><br>    ...<br>    <span class="code-tag">&lt;action name=<span class="code-quote">"myAction"</span> class=<span class="code-quote">"MyAction"</span>&gt;</span><br>        <span class="code-tag">&lt;result name=<span class="code-quote">"myImageResult"</span> type=<span class="code-quote">"myBytesResult"</span>&gt;</span><br>            <span class="code-tag">&lt;param name=<span class="code-quote">"contentType"</span>&gt;</span>${myContentType}<span class="code-tag">&lt;/param&gt;</span><br>            <span class="code-tag">&lt;param name=<span class="code-quote">"contentDisposition"</span>&gt;</span>${myContentDisposition}<span class="code-tag">&lt;/param&gt;</span><br>            <span class="code-tag">&lt;param name=<span class="code-quote">"contentLength"</span>&gt;</span>${myContentLength}<span class="code-tag">&lt;/param&gt;</span><br>            <span class="code-tag">&lt;param name=<span class="code-quote">"bufferSize"</span>&gt;</span>${myBufferSize}<span class="code-tag">&lt;/param&gt;</span><br>        <span class="code-tag">&lt;result&gt;</span><br>    <span class="code-tag">&lt;/action&gt;</span><br>    ...<br><br><span class="code-tag">&lt;/struts&gt;</span></pre>
</div>
</div>
<div class="code">
<div class="codeHeader"><strong>MyBytesResult.java</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyBytesResult <span class="code-keyword">implements</span> Result {<br><br>	<span class="code-keyword">public</span> void execute(ActionInvocation invocation) <span class="code-keyword">throws</span> Exception {<br><br>		MyAction action = (MyAction) invocation.getAction();<br>		HttpServletResponse response = ServletActionContext.getResponse();<br><br>                response.setContentType(action.getContentType());<br>		response.setContentLength(action.getContentLength());<br><br>		response.getOutputStream().write(action.getImageInBytes());<br>		response.getOutputStream().flush();<br>	}<br><br>}</pre>
</div>
</div>
<br><br><span style="font-weight: bold; color: red;">2，怎样测试Struts2的web应用</span><br>
<div class="pagecontent">
<div class="wiki-content">
<p>First,
push as much business and data access logic as possible out of the
Action class and into a POJO facade that the Action can call. In this
way, you can test all that outside of the Action. The MailReader is a
fair example of this, although the data access API is quirky and could
be streamlined.</p>
<p><span style="background-color: #12037c;">首先，把业务和数据访问逻辑分离出去，并且放到能够被Action调用的POJO facade里。这样，你可以在Action的外面测试这部分内容。</span><br></p>
<p>After that, what's really left to test is the UI. For UI tests, a very good choice is <span class="nobr"><a href="http://www.openqa.org/selenium/" title="Visit page outside confluence" rel="nofollow">Selenium<sup><img src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span>.</p>
<p><span style="background-color: #12037c;">之后，需要测试UI，对于UI测试，Selenium是个非常好的选择。</span><br></p>
<p>The Selenium IDE (a FireFox plugin) includes a recorder to help jump
start the tests, and then you can go back and edit the tests, and also
add test that can't be easily recorded. (Like is a control disabled or
text not present.)</p>
<p>The best part is that the initial tests can be recorded in HTML and
the convert to real Java code. The Java code can then be run as part of
a standard JUnit test (if the Selenium proxy server is running in the
background).</p>
<p><span style="background-color: #040c84;">最好的部分是，初始化测试在Html能被录制下来，并且转化成真正的Java代码。Java代码能够作为标准的JUnit来测试（只要Selenium代理服务器在后台运行）</span><br></p>
</div>
</div>
<br><span style="color: red; font-weight: bold;">3，怎样测试Action？</span><br>
<div class="pagecontent">
<div class="wiki-content">
<p>The
Struts 2 Action doesn't expose HTTP in its signature. When access to
HTTP resources is needed, references to these resources can be injected
at runtime, but, to the Action, the servlet resources appear as
ordinary Maps. When running tests outside of the framework, the test
scaffolding can create and set a Map with whatever objects are needed
by the test.</p>
<p><span style="background-color: #040c84;">Struts2 Action在签名上不依赖预HTTP。当访问需要的HTTP是，这些资源在运行时能构被注入。Action，servlet资源看上区就像通用的Maps。当在Framework外部测试时，测试平台会建立所有需要的任何对象的映射。</span><br> </p>
<p>There are several approaches to unit testing Struts 2-based applications, whether using <span class="nobr"><a href="http://junit.org/" title="Visit page outside confluence" rel="nofollow">JUnit<sup><img src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span> or <span class="nobr"><a href="http://testng.org/" title="Visit page outside confluence" rel="nofollow">TestNG<sup><img src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span>.
Two popular techniques are direct Action invocation and testing
interceptors and result-types independently. We will demonstrate both
approaches using JUnit 3.</p>
<p><span style="background-color: #040c84;">两个流行的技术是独立地测试直接的Action调用和interceptor和Result-Type。</span><br></p>
<h2><a name="HowcanwetestActions-DirectActionInvocation"></a>Direct Action Invocation</h2>
<p>The simplest approach is to instantiate your Actions, call the appropriate setters, then invoke <tt>execute</tt>. Calling the Action directly allows you to bypass all the complicated container setup.</p>
<p><span style="background-color: #040c84;">最简单的手段是实例化Action，调用相关的Setter，然后调用excute。调用Action直接允许你绕过复杂的容器启动过程。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Taken from Petsoar</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">package</span> org.petsoar.actions.inventory;<br><br><span class="code-keyword">import</span> com.mockobjects.constraint.IsEqual;<br><span class="code-keyword">import</span> com.mockobjects.dynamic.C;<br><span class="code-keyword">import</span> com.mockobjects.dynamic.Mock;<br><span class="code-keyword">import</span> com.opensymphony.xwork.Action;<br><span class="code-keyword">import</span> junit.framework.TestCase;<br><span class="code-keyword">import</span> org.petsoar.pets.Pet;<br><span class="code-keyword">import</span> org.petsoar.pets.PetStore;<br><br><span class="code-keyword">public</span> class TestViewPet <span class="code-keyword">extends</span> TestCase {<br>    <span class="code-keyword">private</span> Mock mockPetStore;<br>    <span class="code-keyword">private</span> ViewPet action;<br><br>    <span class="code-keyword">protected</span> void setUp() <span class="code-keyword">throws</span> Exception {<br>        mockPetStore = <span class="code-keyword">new</span> Mock(PetStore.class);<br>        PetStore petStore = (PetStore) mockPetStore.proxy();<br><br>        action = <span class="code-keyword">new</span> ViewPet();<br>        action.setPetStore(petStore);<br>    }<br><br>    <span class="code-keyword">public</span> void testViewPet() <span class="code-keyword">throws</span> Exception {<br>        Pet existingPet = <span class="code-keyword">new</span> Pet();<br>        existingPet.setName(<span class="code-quote">"harry"</span>);<br>        existingPet.setId(1);<br><br>        Pet expectedPet = <span class="code-keyword">new</span> Pet();<br>        expectedPet.setName(<span class="code-quote">"harry"</span>);<br>        expectedPet.setId(1);<br><br>        mockPetStore.expectAndReturn(<span class="code-quote">"getPet"</span>, C.args(<span class="code-keyword">new</span> IsEqual(<span class="code-keyword">new</span> <span class="code-object">Long</span>(1))), existingPet);<br>        action.setId(1);<br><br>        <span class="code-object">String</span> result = action.execute();<br><br>        assertEquals(Action.SUCCESS, result);<br>        assertEquals(expectedPet, existingPet);<br>        mockPetStore.verify();<br>    }<br><br>    <span class="code-keyword">public</span> void testViewPetNoId() <span class="code-keyword">throws</span> Exception {<br>        mockPetStore.expectAndReturn(<span class="code-quote">"getPet"</span>, C.ANY_ARGS, <span class="code-keyword">null</span>);<br><br>        <span class="code-object">String</span> result = action.execute();<br><br>        assertEquals(Action.ERROR, result);<br>        assertEquals(1, action.getActionErrors().size());<br>        assertEquals(<span class="code-quote">"Invalid pet selected."</span>, action.getActionErrors().iterator().next());<br>        assertNull(action.getPet());<br>        mockPetStore.verify();<br>    }<br><br>    <span class="code-keyword">public</span> void testViewPetInvalidId() <span class="code-keyword">throws</span> Exception {<br>        action.setId(-1);<br>        testViewPetNoId();<br>    }<br>}</pre>
</div>
</div>
<h2><a name="HowcanwetestActions-TestingInterceptorsand/orResultTypes"></a>Testing Interceptors and/or Result Types</h2>
<p>Check out the test suites in XWork and Struts 2. These suites are
comprehensive and provide a good starting point. Here's an example.</p>
<p><span style="background-color: #040c84;">取出XWork和Struts2的测试套件，这些测试套件是复杂的，并且提供了好的起点。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Test for ParametersInterceptor</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void testDoesNotAllowMethodInvocations() {<br>    Map params = <span class="code-keyword">new</span> HashMap();<br>    params.put(<span class="code-quote">"@java.lang.<span class="code-object">System</span>@exit(1).dummy"</span>, <span class="code-quote">"dumb value"</span>);<br><br>    HashMap extraContext = <span class="code-keyword">new</span> HashMap();<br>    extraContext.put(ActionContext.PARAMETERS, params);<br><br>    <span class="code-keyword">try</span> {<br>        ActionProxy proxy = ActionProxyFactory.getFactory().<br>               createActionProxy("", MockConfigurationProvider.MODEL_DRIVEN_PARAM_TEST, extraContext);<br>        assertEquals(Action.SUCCESS, proxy.execute());<br><br>        ModelDrivenAction action = (ModelDrivenAction) proxy.getAction();<br>        TestBean model = (TestBean) action.getModel();<br><br>        <span class="code-object">String</span> property = <span class="code-object">System</span>.getProperty(<span class="code-quote">"action.security.test"</span>);<br>        assertNull(property);<br>    } <span class="code-keyword">catch</span> (Exception e) {<br>        e.printStackTrace();<br>        fail();<br>    }<br>}</pre>
</div>
</div>
<p><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/lightbulb_on.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16">
The framework also provides built-in support for JUnit 3.8 via an
abstract StrutsTestCase, which provides common Struts variables and
setup code.</p>
<p><span style="background-color: #040c84;">框架也提供了一个抽象的StrutsTestCase，支持JUnit3.8，这个类提供了常用的Struts变量和启动代码。</span><br> </p>
</div>
</div>
<br><span style="font-weight: bold; color: red;">4，怎样上传文件？</span><br>
<div class="pagecontent">
<div class="wiki-content">
<p>You can obtain the MultipartRequestWrapper from the ServletActionContext or by utilizing the <tt>fileUpload</tt> interceptor. The <tt>fileUpload</tt> interceptor is preferred.</p>
<h2><a name="Howdoweuploadfiles-AsktheServletActionContext"></a>Ask the ServletActionContext</h2>
<div class="code">
<div class="codeContent">
<pre class="code-java">MultipartRequestWrapper multipartRequest = ((MultipartRequestWrapper)ServletActionContext.getRequest())</pre>
</div>
</div>
<p>The MultipartRequestWrapper provideds access methods such as <tt>getFiles</tt>, <tt>getFile</tt>, <tt>getContentType</tt>, <tt>hasErrors</tt>, <tt>getErrors</tt>, and so forth, so that you can process the file uploaded.</p>
<h2><a name="Howdoweuploadfiles-UtilizethefileUploadInterceptor"></a>Utilize the fileUpload Interceptor</h2>
<p><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/star_yellow.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> _Preferred_</p>
<ul>
    <li>Ensure that {{fileUpload }} Interceptor is included in the Action's stack.
    <ul>
        <li><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> <em>The default stack already includes {{fileUpload }}.</em></li>
    </ul>
    </li>
    <li>Ensure that the HTML form sets the <tt><span style="font-weight: bold;">enctype</span></tt> and specifies on or more <span style="font-weight: bold;">file</span> type inputs.</li>
</ul>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;form name=<span class="code-quote">"myForm"</span> enctype=<span class="code-quote">"multipart/form-data"</span>&gt;</span><br>     <span class="code-tag">&lt;input type=<span class="code-quote">"file"</span> name=<span class="code-quote">"myDoc"</span> value=<span class="code-quote">"Browse ..."</span> /&gt;</span><br>     <span class="code-tag">&lt;input type=<span class="code-quote">"submit"</span> /&gt;</span><br>  <span class="code-tag">&lt;/form&gt;</span></pre>
</div>
</div>
<ul>
    <li>Ensure that the Action provides one or more fileUpload
    mutator methods, with names that correspond to name of the file type
    input.</li>
</ul>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void setMyDoc(File myDoc)<br><span class="code-keyword">public</span> void setMyDocContentType(<span class="code-object">String</span> contentType)<br><span class="code-keyword">public</span> void setMyDocFileName(<span class="code-object">String</span> filename)</pre>
</div>
</div>
<ul>
    <li>The Action may also provide the corresponding accessor methods.</li>
</ul>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> File getMyDoc()<br><span class="code-keyword">public</span> ContentType getMyDocContentType()<br><span class="code-keyword">public</span> <span class="code-object">String</span> getMyDocFileName()</pre>
</div>
</div>
<h3><a name="Howdoweuploadfiles-Handlingmultiplefiles"></a>Handling multiple files</h3>
<p>When multiple files are uploaded by a form, the files are represented by an array.</p>
<p><span style="background-color: #100084;">可以在同一个Form上传多个文件哦，厉害了</span><br></p>
<p>Given:</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;form name=<span class="code-quote">"myForm"</span> enctype=<span class="code-quote">"multipart/form-data"</span>&gt;</span><br>      <span class="code-tag">&lt;input type=<span class="code-quote">"file"</span> name=<span class="code-quote">"myDoc"</span> value=<span class="code-quote">"Browse File A ..."</span> /&gt;</span><br>      <span class="code-tag">&lt;input type=<span class="code-quote">"file"</span> name=<span class="code-quote">"myDoc"</span> value=<span class="code-quote">"Browse File B ..."</span> /&gt;</span><br>      <span class="code-tag">&lt;input type=<span class="code-quote">"file"</span> name=<span class="code-quote">"myDoc"</span> value=<span class="code-quote">"Browse File C ..."</span> /&gt;</span><br>      <span class="code-tag">&lt;input type=<span class="code-quote">"submit"</span> /&gt;</span><br>   <span class="code-tag">&lt;/form&gt;</span></pre>
</div>
</div>
<p>The Action class can define file handling methods that accept an array.</p>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void setMyDoc(File[] myDocs)<br><span class="code-keyword">public</span> void setMyDocContentType(<span class="code-object">String</span>[] contentTypes)<br><span class="code-keyword">public</span> void setMyDocFileName(<span class="code-object">String</span>[] fileNames)</pre>
</div>
</div>
<p>The uploaded files can be handled by iterating through the appropriate array.</p>
<h3><a name="Howdoweuploadfiles-ExtraInformation"></a>Extra Information</h3>
<table class="confluenceTable">
    <tbody>
        <tr>
            <th class="confluenceTh"> Property </th>
            <th class="confluenceTh"> Default </th>
        </tr>
        <tr>
            <td class="confluenceTd"> struts.multipart.parser </td>
            <td class="confluenceTd"> Commons FileUpload </td>
        </tr>
        <tr>
            <td class="confluenceTd"> struts.multipart.saveDir </td>
            <td class="confluenceTd"> <tt>javax.servlet.context.tempdir</tt> as defined by container </td>
        </tr>
        <tr>
            <td class="confluenceTd"> struts.multipart.maxSize </td>
            <td class="confluenceTd"> Approximately 2M </td>
        </tr>
    </tbody>
</table>
<p>@see struts.properties<br>
@see org.apache.struts2.dispatcher.FilterDispatcher#doFilter(SerlvetRequest, ServletRepsonse, FilterChain)<br>
@see org.apache.struts2.dispatcher.DispatcherUtil#wrapRequest(HttpServletRequest, SerlvetContext)<br>
@see org.apache.struts2.dispatcher.multipart.MultipartRequestWrapper<br>
@see org.apache.struts2.interceptor.FileUploadInterceptor</p>
</div>
</div>
<br><span style="color: red; font-weight: bold;">5，怎样处理配置中Result的参数？</span><br>
<div class="pagecontent">
<div class="wiki-content">
<p>Sometimes
there is a need to redirect from one action to another, but you do not
know the exact url or the destination url requires parameters that are
only known in runtime.</p>
<p><span style="background-color: #080f84;">有时，需要重定向到另外一个Action，但是你不知道确切的url或者目标url需要的运行时才知道的参数。</span><br> </p>
<p>Struts 2 gives you easy to use solution for that problem.</p>
<h2><a name="Parametersinconfigurationresults-Parametersinactionresultdefinitions"></a>Parameters in action result definitions</h2>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;struts&gt;</span><br>....<br>   <span class="code-tag">&lt;package name=<span class="code-quote">"somePackage"</span> namespace=<span class="code-quote">"/myNamespace"</span> extends=<span class="code-quote">"struts-default"</span>&gt;</span><br>      <span class="code-tag">&lt;action name=<span class="code-quote">"myAction"</span> class=<span class="code-quote">"com.project.MyAction"</span>&gt;</span><br>         <span class="code-tag">&lt;result name=<span class="code-quote">"success"</span> type=<span class="code-quote">"redirect-action"</span>&gt;</span>otherAction?id=${id}<span class="code-tag">&lt;/result&gt;</span><br>         <span class="code-tag">&lt;result name=<span class="code-quote">"back"</span> type=<span class="code-quote">"redirect"</span>&gt;</span>${redirectURL}<span class="code-tag">&lt;/result&gt;</span><br>      <span class="code-tag">&lt;/action&gt;</span><br><br>      <span class="code-tag">&lt;action name=<span class="code-quote">"otherAction"</span> class=<span class="code-quote">"com.project.MyOtherAction"</span>&gt;</span><br>         ...<br>      <span class="code-tag">&lt;/action&gt;</span>      <br>   <span class="code-tag">&lt;/package&gt;</span><br>....<br><span class="code-tag">&lt;/struts&gt;</span></pre>
</div>
</div>
<p>The only requirement is to declare the necessary properties in your action, in this case <tt>com.project.MyAction</tt> should define properties <tt>id</tt> and <tt>redirectURL</tt> with standard accessor methods.</p>
<p><span style="background-color: #080f84;">仅仅需要在Action里声明需要的属性，本例中：com.project.MyAction 应该定义redirectURL和get函数。</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyAction <span class="code-keyword">extends</span> ActionSupport {<br>   <span class="code-keyword">private</span> <span class="code-object">int</span> id;<br>   <span class="code-keyword">private</span> <span class="code-object">String</span> redirectURL;<br>   ...<br><br><br>   <span class="code-keyword">public</span> <span class="code-object">String</span> execute() {<br>       ...<br>      <span class="code-keyword">if</span> (someCondition) {<br>         <span class="code-keyword">this</span>.redirectURL = <span class="code-quote">"/the/target/page.action"</span>;<br>         <span class="code-keyword">return</span> <span class="code-quote">"back"</span>;<br>      }<br><br>      <span class="code-keyword">this</span>.id = 123;<br>      <span class="code-keyword">return</span> SUCCESS; <br>   }<br><br>   <span class="code-keyword">public</span> <span class="code-object">int</span> getId() { <span class="code-keyword">return</span> <span class="code-keyword">this</span>.id; }<br>   <span class="code-keyword">public</span> void setId(<span class="code-object">int</span> id) { <span class="code-keyword">this</span>.id = id; }<br>   <span class="code-keyword">public</span> <span class="code-object">String</span> getRedirectURL() { <span class="code-keyword">return</span> <span class="code-keyword">this</span>.redirectURL; }<br>   <span class="code-keyword">public</span> void setRedirectURL(<span class="code-object">String</span> redirectURL) { <span class="code-keyword">this</span>.redirectURL= redirectURL; }<br>   ...<br>}</pre>
</div>
</div>
<p>In the above code if it returns <tt>SUCCESS</tt> then the browser will be forwarded to<br>
<strong><tt>/&lt;app-prefix&gt;/myNamespace/otherAction.action?id=123</tt></strong></p>
</div>
</div>
<br style="font-weight: bold; color: red;"><span style="font-weight: bold; color: red;">6，怎样访问Action中的参数？</span><br>
<div class="pagecontent">
<div class="wiki-content">
<p>You can obtain the request parameters by asking the ActionContext or
implementing ParameterAware. Implementing ParameterAware is preferred.</p>
<p><span style="background-color: #00088e;">你可以通过访问ActionContext或者实现ParameterAware获取请求参数。实现ParameterAware是首选的。</span><br></p>
<h2><a name="HowcanweaccessrequestparameterspassedintoanAction-AsktheActionContext"></a>Ask the ActionContext</h2>
<p>The request parameters are available on the ActionContext instance, which is made available via ThreadLocal.</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">Map parameters = ActionContext.getContext().getParameters();</pre>
</div>
</div>
<h2><a name="HowcanweaccessrequestparameterspassedintoanAction-ImplementParameterAware"></a>Implement ParameterAware</h2>
<p><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/star_yellow.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> <em>Preferred</em></p>
<ul>
    <li>Ensure that <tt>servlet-config</tt> Interceptor is included in the Action's stack.
    <ul>
        <li><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> <em>The default stack already includes</em> <tt><em>servlet-config</em></tt><em>.</em></li>
    </ul>
    </li>
    <li>Edit the Action so that it implements the ParameterAware interface.
    <ul>
        <li>The ParameterAware interface expects a <tt>setParameters</tt> method. You may wish to include a companion <tt>getParameters</tt> method.</li>
    </ul>
    </li>
    <li>At runtime, call <tt>getParameters</tt> to obtain a Map representing the request parameters.</li>
</ul>
<div class="code">
<div class="codeContent">
<pre class="code-java">Map parameters = <span class="code-keyword">this</span>.getParameters();</pre>
</div>
</div>
<table class="infoMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>When the <tt>servlet-config</tt> Interceptor sees that an Action implements ParameterAware, it passes a Map of the request parameters to the Action's <tt>setParameters</tt> method.</td>
        </tr>
    </tbody>
</table>
<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>
            <p>To unit test a ParameterAware Action, create your own Map with the pertinent request parameters and call <tt>setParameters</tt> as part of the test's <tt>setUp</tt> method.</p>
            </td>
        </tr>
    </tbody>
</table>
<p>@see <a href="http://struts.apache.org/2.x/docs/struts-defaultxml.html" title="struts-default.xml">struts-default.xml</a><br>
@see org.apache.struts.action2.interceptor.ParameterAware<br>
@see org.apache.struts.action2.interceptor.<a href="http://struts.apache.org/2.x/docs/servlet-config-interceptor.html" title="Servlet Config Interceptor">Servlet Config Interceptor</a></p>
</div>
</div>
<span style="color: red; font-weight: bold;">7，怎样访问JAAS？</span><br>
<div class="pagecontent">
<div class="wiki-content">
<p>You can obtain the UserPrincipal and other security details by going
through the request or implementing PrincipalAware. Implementing
PrincipalAware is preferred.</p>
<h2><a name="HowdoIobtainsecuritydetails(JAAS)-GoThroughtheRequest"></a>Go Through the Request</h2>
<p>First obtain the HttpServletRequest and then obtain the security Principal.</p>
<div style="color: red;" class="code">
<div class="codeContent">
<pre class="code-java">HttpServletRequest request = ServletActionContext.getRequest();<br><span class="code-object">String</span> authType = request.getAuthType();         <span class="code-comment">// http or https<br></span><span class="code-object">String</span> user = request.getRemoteUser();           <span class="code-comment">// the user principal (in string)<br></span>Principalprincipal = request.getUserPrincipal(); <span class="code-comment">// get a Principal object<br></span>bool isAuth = request.isUserInRole(<span class="code-quote">"patrick"</span>);</pre>
</div>
</div>
<h2><a name="HowdoIobtainsecuritydetails(JAAS)-ImplementPrincipalAware"></a>Implement PrincipalAware</h2>
<p><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/star_yellow.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> <em>Preferred</em></p>
<ul>
    <li>Ensure that <tt>servlet-config</tt> Interceptor is included in the Action's stack.
    <ul>
        <li><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> <em>The default stack already includes</em> <tt><em>servlet-config</em></tt><em>.</em></li>
    </ul>
    </li>
    <li>Edit the Action so that it implements the PrincipalAware interface.
    <ul>
        <li>The PrincipalAware interface expects a <tt>setPrincipalProxy(PrincipalProxy)</tt> method. You may wish to include a companion <tt>getPrincipalProxy</tt> method.</li>
    </ul>
    </li>
    <li>At runtime, use the PrincipalProxy reference to invoke methods such as <tt>isUserInRole</tt>, <tt>getUserPrincipal()</tt>, <tt>getRemoteUser()</tt>, <tt>isRequestSecure()</tt>, and so forth.</li>
</ul>
<p>@see org.apache.struts.action2.interceptor.PrincipalProxy<br>
@see org.apache.struts.action2.interceptor.PrincipalAware<br>
@see org.apache.struts.action2.interceptor.ServletConfigInterceptor</p>
</div>
</div>
<br><span style="color: red; font-weight: bold;">8，怎样访问JSTL？</span><br>
<table class="infoMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">About JSTL</strong><br>The <span class="nobr"><a href="http://java.sun.com/products/jsp/jstl/" title="Visit page outside confluence" rel="nofollow">JavaServer Pages Standard Tag Library<sup><img src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span>
            (JSTL) encapsulates as simple tags the core functionality common to
            many Web applications. JSTL has support for common, structural tasks
            such as iteration and conditionals, tags for manipulating XML
            documents, internationalization tags, and SQL tags.</td>
        </tr>
    </tbody>
</table>
<p><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16">
JSTL integration is built into the framework - there are no steps
required to enable it. Simply refer to your JSTL expressions just as
you would with a normal SAF JSP tag, such as the property tag.</p>
<p><span style="background-color: #00088e;">JSTL被整合到框架里面，不需要做任何工作。GOOD！</span><br></p>
<hr>
<table class="infoMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">Javadoc: (org.apache.struts.action2.dispatcher.StrutsRequestWrapper)</strong><br>
            <p>All Struts requests are wrapped with this class, which provides simple JSTL accessibility. This is because JSTL
            works with request attributes, so this class delegates to the value stack except for a few cases where required to
            prevent infinite loops. Namely, we don't let any attribute name with "#" in it delegate out to the value stack, as it
            could potentially cause an infinite loop. For example, an infinite loop would take place if you called:
            request.getAttribute("#attr.foo").</p>
            </td>
        </tr>
    </tbody>
</table>
<br><br><br><br><br><br><br>       <img src ="http://www.blogjava.net/nobody_am/aggbug/114061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 14:01 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 写Interceptor [笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114058.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 05:46:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114058.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>See the <a  href="file:///F:/Doc/Struts2/docs/interceptors.html" title="Interceptors">Interceptors</a> page for an overview of how interceptors work.</p>
<h3><a name="WritingInterceptors-Interceptorinterface"></a>Interceptor interface</h3>
<p>Interceptors must implement the com.opensymphony.xwork2.interceptor.Interceptor interface.</p>
<div class="code">
<div class="codeHeader"><strong>Interceptor.java</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-keyword">interface</span> Interceptor <span class="code-keyword">extends</span> Serializable {<br><br>    void destroy();<br><br>    void init();<br><br>    <span class="code-object">String</span> intercept(ActionInvocation invocation) <span class="code-keyword">throws</span> Exception;<br>}</pre>
</div>
</div>
<p>The <em>init</em> method is called the after interceptor is instantiated and before calling <em>intercept</em>. This is the place to allocate any resources used by the interceptor.</p>
<p>The <em>intercept</em> method is where the interceptor code is written. Just like an action method, <em>intercept</em> returns a result used by Struts to forward the request to another web resource. Calling <em>invoke</em>
on the parameter of type ActionInvocation will execute the action (if
this is the last interceptor on the stack) or another interceptor.</p>
<p>Overwrite <em>destroy</em> to release resources.</p>
<h3><a name="WritingInterceptors-AbstractInterceptor"></a>AbstractInterceptor</h3>
<p>The AbstractInterceptor class provides an empty implementation of <em>init</em> and <em>destroy</em>, and can be used if these methods are not going to be implemented.</p>
<h3><a name="WritingInterceptors-Mapping"></a>Mapping</h3>
<p>TODO</p>
<h3><a name="WritingInterceptors-Example"></a>Example</h3>
<p>Assuming there is an action of type "MyAction", with a setDate(Date)
method, this simple interceptor will set the date of the action to the
current date:</p>
<div class="code">
<div class="codeHeader"><strong>Interceptor Example</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">import</span> com.opensymphony.xwork2.ActionInvocation;<br><span class="code-keyword">import</span> com.opensymphony.xwork2.interceptor.AbstractInterceptor;<br><br><span class="code-keyword">public</span> class SimpleInterceptor <span class="code-keyword">extends</span> AbstractInterceptor {<br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> intercept(ActionInvocation invocation) <span class="code-keyword">throws</span> Exception {<br>       MyAction action = (MyAction)invocation.getAction();<br>       action.setDate(<span class="code-keyword">new</span> Date());<br>       <span class="code-keyword">return</span> action.invoke();<br>    }<br>}</pre>
</div>
</div>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114058.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 13:46 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114058.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 Interceptor [笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114057.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 05:43:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114057.html</guid><description><![CDATA[<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <tbody>
        <tr>
            <td valign="top"><br></td>
            <td>The default Interceptor stack is designed to serve the needs of most applications. Most applications will <strong>not</strong> need to add Interceptors or change the Interceptor stack.<br><br><span style="background-color: #091190;">默认的Interceptor栈被设计符合大多应用的需要，大部分的应用不需要添加Interceptors或改变Interceptor栈。</span><br></td>
        </tr>
    </tbody>
</table>
<p>Many Actions share common concerns. Some Actions need input
validated. Other Actions may need a file upload to be pre-processed.
Another Action might need protection from a double submit. Many Actions
need drop-down lists and other controls pre-populated before the page
displays.</p>
<p><span style="background-color: #091190;">很多Action共享通用的装置。一些Action需要输入验证，其他Action可能需要文件上传被预处理。另外一些Action可能需要防止两次提交。很多Action需要在页面显示之前，dropdownlist和其他控件被预前渲染。</span><br></p>
<p>The Struts Action Framework makes it easy to share solutions to
these concerns using an "Interceptor" strategy. When you request a
resource that maps to an "action", the framework invokes the Action
object. But, before the Action is executed, the invocation can be
intercepted by another object. After the Action executes, the
invocation could be intercepted again. Unsurprisingly, we call these
objects "Interceptors."</p>
<p><span style="background-color: #091190;">Interceptor在一个Action前后工作。</span><br></p>
<h2><a name="Interceptors-UnderstandingInterceptors"></a>Understanding Interceptors </h2>
<p>Interceptors can execute code before and after an Action is invoked.
Most of the framework's core functionality is implemented as
Interceptors. Features like double-submit guards, type conversion,
object population, validation, file upload, page preparation, and more,
are all implemented with the help of Interceptors. Each and every
Interceptor is pluggable, so you can decide exactly which features an
Action needs to support.</p>
<p>Interceptors can be configured on a per-action basis. Your own
custom Interceptors can be mixed-and-matched with the Interceptors
bundled with the framework. Interceptors "set the stage" for the Action
classes, doing much of the "heavy lifting" before the Action executes.</p>
<table style="width: 162px; height: 58px;" class="confluenceTable">
    <tbody>
        <tr>
            <th class="confluenceTh"> ion Lifecyle </th>
        </tr>
        <tr>
            <td class="confluenceTd"> <img alt=""  src="file:///F:/Doc/Struts2/docs/interceptors.data/overview.png"><img alt=""  src="file:///F:/Doc/Struts2/docs/interceptors.data/overview.png"> Action Lifecyle
            <img  src="file:///F:/Doc/Struts2/docs/interceptors.data/overview.png" align="absmiddle" border="0"> </td>
        </tr>
    </tbody>
</table>
<p>In some cases, an Interceptor might keep an Action from firing,
because of a double-submit or because validation failed. Interceptors
can also change the state of an Action before it executes.</p>
<p>The Interceptors are defined in a stack that specifies the execution
order. In some cases, the order of the Interceptors on the stack can be
very important.</p>
<h2><a name="Interceptors-ConfiguringInterceptors"></a>Configuring Interceptors</h2>
<div class="code">
<div class="codeHeader"><strong>struts.xml</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;package name=<span class="code-quote">"default"</span> extends=<span class="code-quote">"struts-default"</span>&gt;</span><br>   <span class="code-tag">&lt;interceptors&gt;</span><br>       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"timer"</span> class=<span class="code-quote">".."</span>/&gt;</span><br>       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"logger"</span> class=<span class="code-quote">".."</span>/&gt;</span><br>   <span class="code-tag">&lt;/interceptors&gt;</span><br><br>   &lt;action name=<span class="code-quote">"login"</span><br>      class=<span class="code-quote">"tutorial.Login"</span>&gt;<br>        <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"timer"</span>/&gt;</span><br>        <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"logger"</span>/&gt;</span><br>         <span class="code-tag">&lt;result name=<span class="code-quote">"input"</span>&gt;</span>login.jsp<span class="code-tag">&lt;/result&gt;</span><br>         &lt;result name=<span class="code-quote">"success"</span><br>            type=<span class="code-quote">"redirect-action"</span>&gt;/secure/home<span class="code-tag">&lt;/result&gt;</span><br>   <span class="code-tag">&lt;/action&gt;</span><br><span class="code-tag">&lt;/package&gt;</span></pre>
</div>
</div>
<h2><a name="Interceptors-StackingInterceptors"></a>Stacking Interceptors</h2>
<p>With most web applications, we find ourselves wanting to apply the
same set of Interceptors over and over again. Rather than reiterate the
same list of Interceptors, we can bundle these Interceptors together
using an Interceptor Stack.</p>
<div class="code">
<div class="codeHeader"><strong>struts.xml</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;package name=<span class="code-quote">"default"</span> extends=<span class="code-quote">"struts-default"</span>&gt;</span><br>   <span class="code-tag">&lt;interceptors&gt;</span><br>        <span class="code-tag">&lt;interceptor name=<span class="code-quote">"timer"</span> class=<span class="code-quote">".."</span>/&gt;</span><br>        <span class="code-tag">&lt;interceptor name=<span class="code-quote">"logger"</span> class=<span class="code-quote">".."</span>/&gt;</span><br>        <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"myStack"</span>&gt;</span><br>           <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"timer"</span>/&gt;</span><br>           <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"logger"</span>/&gt;</span><br>        <span class="code-tag">&lt;/interceptor-stack&gt;</span><br>    <span class="code-tag">&lt;/interceptors&gt;</span><br><br>&lt;action name=<span class="code-quote">"login"</span><br>     class=<span class="code-quote">"tutuorial.Login"</span>&gt;<br>         <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"myStack"</span>/&gt;</span><br>         <span class="code-tag">&lt;result name=<span class="code-quote">"input"</span>&gt;</span>login.jsp<span class="code-tag">&lt;/result&gt;</span><br>         &lt;result name=<span class="code-quote">"success"</span><br>             type=<span class="code-quote">"redirect-action"</span>&gt;/secure/home<span class="code-tag">&lt;/result&gt;</span><br><span class="code-tag">&lt;/action&gt;</span><br><span class="code-tag">&lt;/package&gt;</span></pre>
</div>
</div>
<p>Looking inside <tt>struts-default.xml</tt>, we can see how it's done.</p>
<h3><a name="Interceptors-TheDefaultConfiguration"></a>The Default Configuration</h3>
<div class="code">
<div class="codeHeader"><strong>struts-default.xml</strong></div>
<div class="codeContent">
<pre class="code-xml">&lt;!DOCTYPE struts PUBLIC<br>    <span class="code-quote">"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"</span><br>    <span class="code-quote">"http://struts.apache.org/dtds/struts-2.0.dtd"</span>&gt;<br><br><span class="code-tag"><span class="code-comment">&lt;!-- // START SNIPPET: struts-default --&gt;</span></span><br><span class="code-tag">&lt;struts&gt;</span><br>    <span class="code-tag">&lt;package name=<span class="code-quote">"struts-default"</span>&gt;</span><br>        <span class="code-tag">&lt;result-types&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"chain"</span> class=<span class="code-quote">"com.opensymphony.xwork.ActionChainResult"</span>/&gt;</span><br>            &lt;result-type name=<span class="code-quote">"dispatcher"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.ServletDispatcherResult"</span><br>                         default=<span class="code-quote">"true"</span>/&gt;<br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"freemarker"</span> class=<span class="code-quote">"org.apache.struts2.views.freemarker.FreemarkerResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"httpheader"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.HttpHeaderResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"jasper"</span> class=<span class="code-quote">"org.apache.struts2.views.jasperreports.JasperReportsResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"redirect"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.ServletRedirectResult"</span>/&gt;</span><br>            &lt;result-type name=<span class="code-quote">"redirect-action"</span><br>                         class=<span class="code-quote">"org.apache.struts2.dispatcher.ServletActionRedirectResult"</span>/&gt;<br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"stream"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.StreamResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"velocity"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.VelocityResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"xslt"</span> class=<span class="code-quote">"org.apache.struts2.views.xslt.XSLTResult"</span>/&gt;</span><br>        <span class="code-tag">&lt;/result-types&gt;</span><br><br>        <span class="code-tag">&lt;interceptors&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"alias"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.AliasInterceptor"</span>/&gt;</span><br>            &lt;interceptor name=<span class="code-quote">"autowiring"</span><br>                         class=<span class="code-quote">"com.opensymphony.xwork.spring.interceptor.ActionAutowiringInterceptor"</span>/&gt;<br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"chain"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.ChainingInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"component"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.component.ComponentInterceptor"</span>/&gt;</span><br>            &lt;interceptor name=<span class="code-quote">"conversionError"</span><br>                         class=<span class="code-quote">"org.apache.struts2.interceptor.WebWorkConversionErrorInterceptor"</span>/&gt;<br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"external-ref"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.ExternalReferencesInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"execAndWait"</span> class=<span class="code-quote">"corg.apache.struts2.interceptor.ExecuteAndWaitInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"exception"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"fileUpload"</span> class=<span class="code-quote">"com.opensymphony.webwork.interceptor.FileUploadInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"i18n"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.I18nInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"logger"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.LoggingInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"model-driven"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"params"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.ParametersInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"prepare"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.PrepareInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"static-params"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.StaticParametersInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"servlet-config"</span> class=<span class="code-quote">"org.apache.struts.action2.interceptor.ServletConfigInterceptor"</span>/&gt;</span><br>            &lt;interceptor name=<span class="code-quote">"sessionAutowiring"</span><br>                         class=<span class="code-quote">"org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"</span>/&gt;<br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"timer"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.TimerInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"token"</span> class=<span class="code-quote">"com.opensymphony.webwork.interceptor.TokenInterceptor"</span>/&gt;</span><br>            &lt;interceptor name=<span class="code-quote">"token-session"</span><br>                         class=<span class="code-quote">"com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"</span>/&gt;<br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"validation"</span> class=<span class="code-quote">"com.opensymphony.xwork.validator.ValidationInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"workflow"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"</span>/&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Basic stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"basicStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"exception"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"servlet-config"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"prepare"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"static-params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"conversionError"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample validation and workflow stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"validationWorkflowStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"validation"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"workflow"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample file upload stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"fileUploadStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"fileUpload"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample model-driven stack  --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"modelDrivenStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"model-driven"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample action chaining stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"chainStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"chain"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample i18n stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"chainStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"i18n"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            &lt;!-- Sample execute and wait stack.<br>                 Note: execAndWait should always be the *last* interceptor. --&gt;<br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"executeAndWaitStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"execAndWait"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            &lt;!-- A complete stack with all the common interceptors in place.<br>                 Generally, this stack should be the one you use, though it<br>                 may process additional stuff you don't need, which could<br>                 lead to some performance problems. Also, the ordering can be<br>                 switched around (ex: if you wish to have your components<br>                 before prepare() is called, you'd need to move the component<br>                 interceptor up --&gt;<br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"defaultStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"exception"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"alias"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"prepare"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"servlet-config"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"i18n"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"chain"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"model-driven"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"fileUpload"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"static-params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"conversionError"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"validation"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"workflow"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            &lt;!-- The completeStack is here for backwards compatibility for<br>                 applications that still refer to the defaultStack by the<br>                 old name --&gt;<br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"completeStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"defaultStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br>        <span class="code-tag">&lt;/interceptors&gt;</span><br><br>        <span class="code-tag">&lt;default-interceptor-ref name=<span class="code-quote">"defaultStack"</span>/&gt;</span><br>    <span class="code-tag">&lt;/package&gt;</span><br><span class="code-tag">&lt;/struts&gt;</span><br><span class="code-tag"><span class="code-comment">&lt;!-- // END SNIPPET: struts-default --&gt;</span></span></pre>
</div>
</div>
<p>Since the <tt>struts-default.xml</tt> is included in the
application's configuration by default, all of the predefined
interceptors and stacks are available "out of the box".</p>
<h2><a name="Interceptors-FrameworkInterceptors"></a>Framework Interceptors</h2>
<p>Interceptor classes are also defined using a key-value pair
specified in the Struts configuration file. The names specified below
come specified in <a  href="file:///F:/Doc/Struts2/docs/struts-defaultxml.html" title="struts-default.xml">struts-default.xml</a>. If you extend the <tt>struts-default</tt>
package, then you can use the names below. Otherwise, they must be
defined in your package with a name-class pair specified in the
&lt;interceptors&gt; tag.</p>
<table class="confluenceTable">
    <tbody>
        <tr>
            <th class="confluenceTh"> Interceptor </th>
            <th class="confluenceTh"> Name </th>
            <th class="confluenceTh"> Description </th>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/alias-interceptor.html" title="Alias Interceptor">Alias Interceptor</a> </td>
            <td class="confluenceTd"> alias </td>
            <td class="confluenceTd"> Converts similar parameters that may be named differently between requests. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/chaining-interceptor.html" title="Chaining Interceptor">Chaining Interceptor</a> </td>
            <td class="confluenceTd"> chain </td>
            <td class="confluenceTd"> Makes the previous Action's properties
            available to the current Action. Commonly used together with &lt;result
            type="chain"&gt; (in the previous Action). </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/checkbox-interceptor.html" title="Checkbox Interceptor">Checkbox Interceptor</a> </td>
            <td class="confluenceTd"> checkbox </td>
            <td class="confluenceTd"> Adds automatic checkbox handling code that
            detect an unchecked checkbox and add it as a parameter with a default
            (usually 'false') value. Uses a specially named hidden field to detect
            unsubmitted checkboxes. The default unchecked value is overridable for
            non-boolean value'd checkboxes. Minor source formatting and cleaned out
            an empty directory. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/conversion-error-interceptor.html" title="Conversion Error Interceptor">Conversion Error Interceptor</a> </td>
            <td class="confluenceTd"> conversionError </td>
            <td class="confluenceTd"> Adds conversion errors from the ActionContext to the Action's field errors </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/create-session-interceptor.html" title="Create Session Interceptor">Create Session Interceptor</a> </td>
            <td class="confluenceTd"> createSession </td>
            <td class="confluenceTd"> Create an HttpSession automatically, useful
            with certain Interceptors that require a HttpSession to work properly
            (like the TokenInterceptor) </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/debugginginterceptor.html" title="DebuggingInterceptor">DebuggingInterceptor</a> </td>
            <td class="confluenceTd"> debugging </td>
            <td class="confluenceTd"> Provides several different debugging screens to provide insight into the data behind the page. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/execute-and-wait-interceptor.html" title="Execute and Wait Interceptor">Execute and Wait Interceptor</a> </td>
            <td class="confluenceTd"> execAndWait </td>
            <td class="confluenceTd"> Executes the Action in the background and then sends the user off to an intermediate waiting page. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/exception-interceptor.html" title="Exception Interceptor">Exception Interceptor</a> </td>
            <td class="confluenceTd"> exception </td>
            <td class="confluenceTd"> Maps exceptions to a result. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/file-upload-interceptor.html" title="File Upload Interceptor">File Upload Interceptor</a> </td>
            <td class="confluenceTd"> fileUpload </td>
            <td class="confluenceTd"> An Interceptor that adds easy access to file upload support. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/i18n-interceptor.html" title="I18n Interceptor">I18n Interceptor</a> </td>
            <td class="confluenceTd"> i18n </td>
            <td class="confluenceTd"> Remembers the locale selected for a user's session. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/logger-interceptor.html" title="Logger Interceptor">Logger Interceptor</a> </td>
            <td class="confluenceTd"> logger </td>
            <td class="confluenceTd"> Outputs the name of the Action. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/message-store-interceptor.html" title="Message Store Interceptor">Message Store Interceptor</a> </td>
            <td class="confluenceTd"> store </td>
            <td class="confluenceTd"> Store and retrieve action messages / errors / field errors for action that implements ValidationAware interface into session. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/model-driven-interceptor.html" title="Model Driven Interceptor">Model Driven Interceptor</a> </td>
            <td class="confluenceTd"> model-driven </td>
            <td class="confluenceTd"> If the Action implements ModelDriven, pushes the <tt>getModel</tt> Result onto the Value Stack. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/scoped-model-driven-interceptor.html" title="Scoped Model Driven Interceptor">Scoped Model Driven Interceptor</a> </td>
            <td class="confluenceTd"> scoped-model-driven </td>
            <td class="confluenceTd"> If the Action implements ScopedModelDriven,
            the interceptor retrieves and stores the model from a scope and sets it
            on the action calling <tt>setModel</tt>. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/parameters-interceptor.html" title="Parameters Interceptor">Parameters Interceptor</a> </td>
            <td class="confluenceTd"> params </td>
            <td class="confluenceTd"> Sets the request parameters onto the Action. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/prepare-interceptor.html" title="Prepare Interceptor">Prepare Interceptor</a> </td>
            <td class="confluenceTd"> prepare </td>
            <td class="confluenceTd"> If the Action implements Preparable, calls its <tt>prepare</tt> method. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/scope-interceptor.html" title="Scope Interceptor">Scope Interceptor</a> </td>
            <td class="confluenceTd"> scope </td>
            <td class="confluenceTd"> Simple mechanism for storing Action state in the session or application scope. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/servlet-config-interceptor.html" title="Servlet Config Interceptor">Servlet Config Interceptor</a> </td>
            <td class="confluenceTd"> servlet-config </td>
            <td class="confluenceTd"> Provide access to Maps representing HttpServletRequest and HttpServletResponse. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/static-parameters-interceptor.html" title="Static Parameters Interceptor">Static Parameters Interceptor</a> </td>
            <td class="confluenceTd"> static-params </td>
            <td class="confluenceTd"> Sets the <tt>struts.xml</tt> defined parameters onto the action. These are the &lt;param&gt; tags that are direct children of the &lt;action&gt; tag. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/roles-interceptor.html" title="Roles Interceptor">Roles Interceptor</a> </td>
            <td class="confluenceTd"> roles </td>
            <td class="confluenceTd"> Action will only be executed if the user has the correct JAAS role. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/timer-interceptor.html" title="Timer Interceptor">Timer Interceptor</a> </td>
            <td class="confluenceTd"> timer </td>
            <td class="confluenceTd"> Outputs how long the Action takes to execute (including nested Interceptors and View) </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/token-interceptor.html" title="Token Interceptor">Token Interceptor</a> </td>
            <td class="confluenceTd"> token </td>
            <td class="confluenceTd"> Checks for valid token presence in Action, prevents duplicate form submission. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/token-session-interceptor.html" title="Token Session Interceptor">Token Session Interceptor</a> </td>
            <td class="confluenceTd"> token-session </td>
            <td class="confluenceTd"> Same as Token Interceptor, but stores the submitted data in session when handed an invalid token </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/validation-interceptor.html" title="Validation Interceptor">Validation Interceptor</a> </td>
            <td class="confluenceTd"> validation </td>
            <td class="confluenceTd"> Performs validation using the validators defined in <em>action</em>-validation.xml </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/workflow-interceptor.html" title="Workflow Interceptor">Workflow Interceptor</a> </td>
            <td class="confluenceTd"> workflow </td>
            <td class="confluenceTd"> Calls the <tt>validate</tt> method in your Action class. If Action errors are created then it returns the <tt>INPUT</tt> view. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/parameter-filter-interceptor.html" title="Parameter Filter Interceptor">Parameter Filter Interceptor</a> </td>
            <td class="confluenceTd"> N/A </td>
            <td class="confluenceTd"> Removes parameters from the list of those available to Actions </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/profiling-interceptor.html" title="Profiling Interceptor">Profiling Interceptor</a> </td>
            <td class="confluenceTd"> profiling </td>
            <td class="confluenceTd"> Activate profiling through parameter </td>
        </tr>
    </tbody>
</table>
<h3><a name="Interceptors-MethodFiltering"></a>Method Filtering</h3>
<p>An abstract <code>Interceptor</code> that is applied to selectively according
to specified included/excluded method lists.</p>
<p>Setable parameters are as follows:</p>
<ul>
    <li>excludeMethods - methods name to be excluded</li>
    <li>includeMethods - methods name to be included</li>
</ul>
<p><strong>NOTE:</strong> If method name are available in both includeMethods and
excludeMethods, it will still be considered as an included method. In short
includeMethods takes precedence over excludeMethods.</p>
<p>Interceptors that extends this capability would be :-</p>
<ul>
    <li>TokenInterceptor</li>
    <li>TokenSessionStoreInterceptor</li>
    <li>DefaultWorkflowInterceptor</li>
    <li>ValidationInterceptor</li>
</ul>
<h3><a name="Interceptors-InterceptorParameterOverriding"></a>Interceptor Parameter Overriding</h3>
<p>Interceptor's parameter could be overriden through the following ways :-</p>
<p><strong>Method 1:</strong>
</p>
<pre>&lt;action name="myAction" class="myActionClass"&gt;<br>  &lt;interceptor-ref name="exception"/&gt;<br>    &lt;interceptor-ref name="alias"/&gt;<br>    &lt;interceptor-ref name="params"/&gt;<br>    &lt;interceptor-ref name="servlet-config"/&gt;<br>    &lt;interceptor-ref name="prepare"/&gt;<br>    &lt;interceptor-ref name="i18n"/&gt;<br>    &lt;interceptor-ref name="chain"/&gt;<br>    &lt;interceptor-ref name="model-driven"/&gt;<br>    &lt;interceptor-ref name="fileUpload"/&gt;<br>    &lt;interceptor-ref name="static-params"/&gt;<br>    &lt;interceptor-ref name="params"/&gt;<br>    &lt;interceptor-ref name="conversionError"/&gt;<br>    &lt;interceptor-ref name="validation"&gt;<br>      &lt;param name="excludeMethods"&gt;myValidationExcudeMethod&lt;/param&gt;<br>    &lt;/interceptor-ref&gt;<br>    &lt;interceptor-ref name="workflow"&gt;<br>      &lt;param name="excludeMethods"&gt;myWorkflowExcludeMethod&lt;/param&gt;<br>    &lt;/interceptor-ref&gt;<br>&lt;/action&gt;<br></pre>
<p><strong>Method 2:</strong>
</p>
<pre>&lt;action name="myAction" class="myActionClass"&gt;<br>  &lt;interceptor-ref name="defaultStack"&gt;<br>    &lt;param name="validation.excludeMethods"&gt;myValidationExcludeMethod&lt;/param&gt;<br>    &lt;param name="workflow.excludeMethods"&gt;myWorkflowExcludeMethod&lt;/param&gt;<br>  &lt;/interceptor-ref&gt;<br>&lt;/action&gt;<br></pre>
<p>In the first method, the whole default stack is copied and the parameter then
changed accordingly.</p>
<p>In the second method, the <interceptor-ref _u002e_..=""> refer to an existing
interceptor-stack, namely default-stack in this example, and override the validator
and workflow interceptor excludeMethods typically in this case. Note that in the
 tag, the name attribute contains a dot (.) the word before the dot(.)
specifies the interceptor name whose parameter is to be overriden and the word after
the dot (.) specifies the parameter itself. Essetially it is as follows :-</interceptor-ref></p>
<pre>   &lt;interceptor-name&gt;.&lt;parameter-name&gt;<br></pre>
<p><strong>Note</strong> also that in this case the <interceptor-ref _u002e_..=""> name attribute
is used to indicate an interceptor stack which makes sense as if it is refering
to the interceptor itself it would be just using Method 1 describe above.</interceptor-ref></p>
<h3><a name="Interceptors-OrderofInterceptorExecution"></a>Order of Interceptor Execution</h3>
<p>Interceptors provide an excellent means to wrap before/after processing. The concept reduces code duplication (think AOP).</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;interceptor-stack name=<span class="code-quote">"xaStack"</span>&gt;<br>  &lt;interceptor-ref name=<span class="code-quote">"thisWillRunFirstInterceptor"</span>/&gt;<br>  &lt;interceptor-ref name=<span class="code-quote">"thisWillRunNextInterceptor"</span>/&gt;<br>  &lt;interceptor-ref name=<span class="code-quote">"followedByThisInterceptor"</span>/&gt;<br>  &lt;interceptor-ref name=<span class="code-quote">"thisWillRunLastInterceptor"</span>/&gt;<br>&lt;/interceptor-stack&gt;</pre>
</div>
</div>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> Note that some Interceptors will interrupt the stack/chain/flow ... so the order is very important.</p>
<p>Interceptors implementing <tt>com.opensymphony.xwork.interceptor.PreResultListener</tt> will run after the Action executes but before the Result executes.</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">thisWillRunFirstInterceptor<br>  thisWillRunNextInterceptor<br>    followedByThisInterceptor<br>      thisWillRunLastInterceptor<br>        MyAction1<br>        MyAction2 (chain)<br>        MyPreResultListener<br>        MyResult (result)<br>      thisWillRunLastInterceptor<br>    followedByThisInterceptor<br>  thisWillRunNextInterceptor<br>thisWillRunFirstInterceptor</pre>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 13:43 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 Type Conversion[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114053.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 05:26:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114053.html</guid><description><![CDATA[<p>Routine type conversion in the framework is transparent. Generally,
all you need to do is ensure that HTML inputs have names that can be
used in <a  href="file:///F:/Doc/Struts2/docs/ognl.html" title="OGNL">OGNL</a> expressions. (HTML inputs are form elements and other GET/POST parameters.)</p>
<p><span style="background-color: #140488;">常规转换在框架里是透明的，通常，所有你需要做的就是保证HTML inputs有名字，使得这些名字能在OGNL表达式中使用。</span><br></p>
<h2><a name="TypeConversion-ASimpleExample"></a>A Simple Example</h2>
<p>Type conversion is great for situations where you need to turn a String in to a more complex object. Because the web
is type-agnostic (everything is a string in HTTP), WebWork's type conversion features are very useful. For instance,
if you were prompting a user to enter in coordinates in the form of a string (such as "3, 22"), you could have
WebWork do the conversion both from String to Point and from Point to String.</p>
<p><span style="background-color: #140488;">在你需要转换String到复杂对象的情况下，类型转换式非常重要的。因为web是一个不懂类型的东西，Webwork类型的转换是非常有用的。例如，你让用户输入一个string（例如：&#8220;3,22&#8221;）,你能让WebWork做从String到Point，以及Point到String的转换。</span><br></p>
<p> Using this "point" example, if your action (or another compound object in which you are setting properties on)
has a corresponding ClassName-conversion.properties file, WebWork will use the configured type converters for
conversion to and from strings. So turning "3, 22" in to new Point(3, 22) is done by merely adding the following
entry to <strong>ClassName-conversion.properties</strong> (Note that the PointConverter should impl the ognl.TypeConverter
interface):</p>
<p><strong>point = com.acme.PointConverter</strong></p>
<p> Your type converter should be sure to check what class type it is being requested to convert. Because it is used
for both to and from strings, you will need to split the conversion method in to two parts: one that turns Strings in
to Points, and one that turns Points in to Strings.</p>
<p> After this is done, you can now reference your point (using &lt;ww:property value="post"/&gt; in JSP or ${point}
in FreeMarker) and it will be printed as "3, 22" again. As such, if you submit this back to an action, it will be
converted back to a Point once again.</p>
<p> In some situations you may wish to apply a type converter globally. This can be done by editing the file
<strong>xwork-conversion.properties</strong> in the root of your class path (typically WEB-INF/classes) and providing a
property in the form of the class name of the object you wish to convert on the left hand side and the class name of
the type converter on the right hand side. For example, providing a type converter for all Point objects would mean
adding the following entry:</p>
<p><strong>com.acme.Point = com.acme.PointConverter</strong></p>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>
            <p>Type conversion should not be used as a substitute for i18n. It is not recommended to use this feature to print out
            properly formatted dates. Rather, you should use the i18n features of WebWork (and consult the JavaDocs for JDK's
            MessageFormat object) to see how a properly formatted date should be displayed.</p>
            </td>
        </tr>
    </tbody>
</table>
<p>The framework ships with a base helper class that simplifies converting to and from Strings, <tt>org.apache.struts.action2.util.StrutsTypeConverter</tt>. The helper class makes it easy to write type converters that handle converting objects to Strings as well as from Strings.</p>
<p>From the JavaDocs:</p>
<p>Base class for type converters used in Struts. This class provides two abstract methods that are used to convert
both to and from strings &#8211; the critical functionality that is core to Struts's type coversion system.</p>
<p> Type converters do not have to use this class. It is merely a helper base class, although it is recommended that
you use this class as it provides the common type conversion contract required for all web-based type conversion.</p>
<p> There's a hook (fall back method) called <code>performFallbackConversion</code> of which
could be used to perform some fallback conversion if <code>convertValue</code> method of this
failed. By default it just ask its super class (Ognl's DefaultTypeConverter) to do the conversion.</p>
<p> To allow the framework to recognize that a conversion error has occurred, throw an XWorkException or
preferable a TypeConversionException.</p>
<h2><a name="TypeConversion-BuiltinTypeConversionSupport"></a>Built in Type Conversion Support</h2>
<p>
XWork will automatically handle the most common type conversion for you. This includes support for converting to
and from Strings for each of the following:
</p>
<p>
</p>
<ul>
    <p>
    </p>
    <li>String</li>
    <p>
    </p>
    <li>boolean / Boolean</li>
    <p>
    </p>
    <li>char / Character</li>
    <p>
    </p>
    <li>int / Integer, float / Float, long / Long, double / Double</li>
    <p>
    </p>
    <li>dates - uses the SHORT format for the Locale associated with the current request</li>
    <p>
    </p>
    <li>arrays - assuming the individual strings can be coverted to the individual items</li>
    <p>
    </p>
    <li>collections - if not object type can be determined, it is assumed to be a String and a new ArrayList is
    created</li>
    <p>
    </p>
</ul>
<p>
</p>
<p> Note that with arrays the type conversion will defer to the type of the array elements and try to convert each
item individually. As with any other type conversion, if the conversion can't be performed the standard type
conversion error reporting is used to indicate a problem occured while processing the type conversion.
</p>
<h2><a name="TypeConversion-RelationshiptoParameterNames"></a>Relationship to Parameter Names</h2>
<p>The best way to take advantage of the framework's type conversion is
to utilize complete objects (ideally your domain objects directly).
There is no need to capture form values using intermediate Strings and
primitives and then convert those values to full objects in an Action
method.</p>
<p>Here are some tips for leveraging the framework's type conversion capabilties:</p>
<ul>
    <li>Use complex OGNL expressions - the framework will automatically take care of creating the actual objects for you.</li>
    <li>Use
    JavaBeans! The framework can only create objects if the objects obey
    the JavaBean specification and provide no-arg constructions, as well as
    getters and setters where appropriate.</li>
    <li>Remember that <em>person.name</em> will call <strong>getPerson().setName()</strong>, but if in order for the framework to create the Person object for you, a <tt>setPerson</tt> must also exist.</li>
    <li>For lists and maps, use index notation, such as <em>people[0].name</em> or <em>friends['patrick'].name</em>. Often these HTML form elements are being rendered inside a loop. For <a  href="file:///F:/Doc/Struts2/docs/jsp-tags.html" title="JSP Tags">JSP Tags</a>, use the iterator tag's status attribute. For <a  href="file:///F:/Doc/Struts2/docs/freemarker-tags.html" title="FreeMarker Tags">FreeMarker Tags</a>, use the special property ${foo_index}[].</li>
    <li>For multiple select boxes, it isn't possible to use index notation to name each individual item. Instead, name your element <em>people.name</em>
    and the framework will understand that it should create a new Person
    object for each selected item and set its name accordingly.</li>
</ul>
<h2><a name="TypeConversion-CreatingaTypeConverter"></a>Creating a Type Converter</h2>
<p>To create a type converter one would need to extends StrutsTypeConverter.</p>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyConverter <span class="code-keyword">extends</span> StrutsTypeConverter {<br>    <span class="code-keyword">public</span> <span class="code-object">Object</span> convertFromString(Map context, <span class="code-object">String</span>[] values, <span class="code-object">Class</span> toClass) {<br>       .....<br>    }<br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> convertToString(Map context, <span class="code-object">Object</span> o) {<br>       .....<br>    }<br> }</pre>
</div>
</div>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>
            <p> To allow Struts to recognize that a conversion error has occurred,
            the converter class need to throw XWorkException or preferably
            TypeConversionException.</p>
            </td>
        </tr>
    </tbody>
</table>
<h2><a name="TypeConversion-AdvancedTypeConversion"></a>Advanced Type Conversion</h2>
<p>The framework also handles advanced type conversion cases, like null
property handling and converting values in Maps and Collections, and
type conversion error handling.</p>
<h3><a name="TypeConversion-NullPropertyHandling"></a>Null Property Handling</h3>
<p>Null property handling will automatically create objects where null references are found.</p>
<p>Provided that the key #CREATE_NULL_OBJECTS is in the action context with a value of true (this key is set
only during the execution of the com.opensymphony.xwork2.interceptor.ParametersInterceptor), OGNL expressions
that have caused a NullPointerException will be temporarily stopped for evaluation while the system automatically
tries to solve the null references by automatically creating the object.</p>
<p> The following rules are used when handling null references:</p>
<ul>
    <li>If the property is declared <em>exactly</em> as a Collection or List, then an ArrayList shall be
    returned and assigned to the null references.</li>
    <li>If the property is declared as a Map, then a HashMap will be returned and assigned to the null
    references.</li>
    <li>If the null property is a simple bean with a no-arg constructor, it will simply be created using the {@link
    ObjectFactory#buildBean(java.lang.Class, java.util.Map)} method.</li>
</ul>
<p>For example, if a form element has a text field named <strong>person.name</strong> and the expression <em>person</em> evaluates
to null, then this class will be invoked. Because the <em>person</em> expression evaluates to a <em>Person</em> class, a
new Person is created and assigned to the null reference. Finally, the name is set on that object and the overall
effect is that the system automatically created a Person object for you, set it by calling setUsers() and then
finally called getUsers().setName() as you would typically expect.</p>
<h3><a name="TypeConversion-CollectionandMapSupport"></a>Collection and Map Support</h3>
<p>Collection and Map support provides intelligent null handling and type conversion for Java Collections.</p>
<p>The framework supports ways to discover the object type for elements in a collection. The discover is made via an <em>ObjectTypeDeterminer</em>.
A default implementation is provided with the framework. The Javadocs
explain how Map and Collection support is discovered in the <tt>DefaultObjectTypeDeterminer</tt>.</p>
<p>This ObjectTypeDeterminer looks at the <strong>Class-conversion.properties</strong> for entries that indicated what
objects are contained within Maps and Collections. For Collections, such as Lists, the element is specified using the
pattern <strong>Element_xxx</strong>, where xxx is the field name of the collection property in your action or object. For
Maps, both the key and the value may be specified by using the pattern <strong>Key_xxx</strong> and <strong>Element_xxx</strong>,
respectively.</p>
<p> From WebWork 2.1.x, the <strong>Collection_xxx</strong> format is still supported and honored, although it is deprecated
and will be removed eventually.</p>
<p>Additionally, you can create your own custom <tt>ObjectTypeDeterminer</tt> by implementing the <tt>ObjectTypeDeterminer</tt> interface. There is also an optional ObjectTypeDeterminer that utilizes Java 5 generics. See the <a  href="file:///F:/Doc/Struts2/docs/annotations.html" title="Annotations">Annotations</a> page for more information.</p>
<h4><a name="TypeConversion-Indexingacollectionbyapropertyofthatcollection"></a>Indexing a collection by a property of that collection</h4>
<p>It is also possible to obtain a unique element of a collection by
passing the value of a given property of that element. By default, the
property of the element of the collection is determined in <em>Class</em>-conversion.properties using <tt>KeyProperty_xxx=yyy</tt>, where xxx is the property of the bean <em>Class</em> that returns the collection and yyy is the property of the collection element that we want to index on.</p>
<p>For an example, see the following two classes:</p>
<div class="code" style="border-style: solid;">
<div class="codeHeader" style="border-bottom-style: solid;"><strong>MyAction.java</strong></div>
<div class="codeContent">
<pre class="code-java">/**<br> * @<span class="code-keyword">return</span> a Collection of Foo objects<br> */<br><span class="code-keyword">public</span> Collection getFooCollection()<br>{<br>    <span class="code-keyword">return</span> foo;<br>}</pre>
</div>
</div>
<div class="code" style="border-style: solid;">
<div class="codeHeader" style="border-bottom-style: solid;"><strong>Foo.java</strong></div>
<div class="codeContent">
<pre class="code-java">/**<br> * @<span class="code-keyword">return</span> a unique identifier<br> */<br><span class="code-keyword">public</span> <span class="code-object">Long</span> getId()<br>{<br>    <span class="code-keyword">return</span> id;<br>}</pre>
</div>
</div>
<p>To enable type conversion, put the instruction <tt>KeyProperty_fooCollection=id</tt> in the <tt>MyAction-conversion.properties</tt> file. This technique allows use of the idiom <tt>fooCollection(someIdValue)</tt> to obtain the Foo object with value <tt>someIdValue</tt> in the Set <tt>fooCollection</tt>. For example, <tt>fooCollection(22)</tt> would return the Foo object in the <tt>fooCollection</tt> Collection whose <tt>id</tt> property value was 22.</p>
<p>This technique is useful, because it ties a collection element
directly to its unique identifier. You are not forced to use an index.
You can edit the elements of a collection associated to a bean without
any additional coding. For example, parameter name <tt>fooCollection(22).name</tt> and value <tt>Phil</tt> would set name the Foo Object in the <tt>fooCollection</tt> Collection whose <tt>id</tt> property value was 22 to be Phil.</p>
<p>The framework automatically converts the type of the parameter sent in to the type of the key property using type conversion.</p>
<p>Unlike Map and List element properties, if <tt>fooCollection(22)</tt> does not exist, it will not be created. If you would like it created, use the notation <tt>fooCollection.makeNew[index]</tt> where <em>index</em> is an integer 0, 1, and so on. Thus, parameter value pairs <tt>fooCollection.makeNew[0]=Phil</tt> and <tt>fooCollection.makeNew[1]=John</tt> would add two new Foo Objects to <tt>fooCollection --</tt> one with name property value <tt>Phil</tt> and the other with name property value <tt>Bar</tt>. However, in the case of a Set, the <tt>equals</tt> and <tt>hashCode</tt> methods should be defined such that they don't only include the <tt>id</tt> property. Otherwise, one element of the null <tt>id</tt> properties Foos to be removed from the Set.</p>
<h2><a name="TypeConversion-AnadvancedexampleforindexedListsandMaps"></a>An advanced example for indexed Lists and Maps</h2>
<p>Here is the model bean used within the list. The KeyProperty for this bean is the <tt>id</tt> attribute.</p>
<div class="code" style="border-style: solid;">
<div class="codeHeader" style="border-bottom-style: solid;"><strong>MyBean.java</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyBean <span class="code-keyword">implements</span> Serializable {<br><br>    <span class="code-keyword">private</span> <span class="code-object">Long</span> id;<br>    <span class="code-keyword">private</span> <span class="code-object">String</span> name;<br><br>    <span class="code-keyword">public</span> <span class="code-object">Long</span> getId() {<br>        <span class="code-keyword">return</span> id;<br>    }<br><br>    <span class="code-keyword">public</span> void setId(<span class="code-object">Long</span> id) {<br>        <span class="code-keyword">this</span>.id = id;<br>    }<br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> getName() {<br>        <span class="code-keyword">return</span> name;<br>    }<br><br>    <span class="code-keyword">public</span> void setName(<span class="code-object">String</span> name) {<br>        <span class="code-keyword">this</span>.name = name;<br>    }<br><br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> toString() {<br>        <span class="code-keyword">return</span> <span class="code-quote">"MyBean{"</span> +<br>                <span class="code-quote">"id="</span> + id +<br>                <span class="code-quote">", name='"</span> + name + '\'' +<br>                '}';<br>    }<br>}</pre>
</div>
</div>
<p>The Action has a <tt>beanList</tt> attribute initialized with an empty ArrayList.</p>
<div class="code" style="border-style: solid;">
<div class="codeHeader" style="border-bottom-style: solid;"><strong>MyBeanAction.java</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyBeanAction <span class="code-keyword">implements</span> Action {<br><br>    <span class="code-keyword">private</span> List beanList = <span class="code-keyword">new</span> ArrayList();<br>    <span class="code-keyword">private</span> Map beanMap = <span class="code-keyword">new</span> HashMap();<br><br>    <span class="code-keyword">public</span> List getBeanList() {<br>        <span class="code-keyword">return</span> beanList;<br>    }<br><br>    <span class="code-keyword">public</span> void setBeanList(List beanList) {<br>        <span class="code-keyword">this</span>.beanList = beanList;<br>    }<br><br>    <span class="code-keyword">public</span> Map getBeanMap() {<br>        <span class="code-keyword">return</span> beanMap;<br>    }<br><br>    <span class="code-keyword">public</span> void setBeanMap(Map beanMap) {<br>        <span class="code-keyword">this</span>.beanMap = beanMap;<br>    }<br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> execute() <span class="code-keyword">throws</span> Exception {<br>        <span class="code-keyword">return</span> SUCCESS;<br>    }<br>}</pre>
</div>
</div>
<p>These <tt>conversion.properties</tt> tell the TypeConverter to use MyBean instances as elements of the List.</p>
<div class="code" style="border-style: solid;">
<div class="codeHeader" style="border-bottom-style: solid;"><strong>MyBeanAction-conversion.properties</strong></div>
<div class="codeContent">
<pre class="code-java">KeyProperty_beanList=id<br>Element_beanList=MyBean<br>CreateIfNull_beanList=<span class="code-keyword">true</span></pre>
</div>
</div>
<ul>
    <li>When submitting this via a form, the <tt>id</tt> value is used as KeyProperty for the MyBean instances in the beanList.</li>
</ul>
<ul>
    <li>Notice the () notation! Do not use [] notation, which is for Maps only!</li>
</ul>
<ul>
    <li>The value for name will be set to the MyBean instance with this special id.</li>
</ul>
<ul>
    <li>The List does not have null values added for unavailable id values. This approach avoids the risk of OutOfMemoryErrors!</li>
</ul>
<div class="code" style="border-style: solid;">
<div class="codeHeader" style="border-bottom-style: solid;"><strong>MyBeanAction.jsp</strong></div>
<div class="codeContent">
<pre class="code-java">&lt;ww:iterator value=<span class="code-quote">"beanList"</span> id=<span class="code-quote">"bean"</span>&gt;<br>  &lt;ww:textfield name=<span class="code-quote">"beanList(%{bean.id}).name"</span> /&gt;<br>&lt;/ww:iterator&gt;</pre>
</div>
</div>
<h2><a name="TypeConversion-TypeConversionErrorHandling"></a>Type Conversion Error Handling</h2>
<p>Type conversion error handling provides a simple way to distinguish between an input <em>validation</em> problem and an input <em>type conversion</em> problem.</p>
<p>Any error that occurs during type conversion may or may not wish to be reported. For example, reporting that the
input "abc" could not be converted to a number might be important. On the other hand, reporting that an empty string,
"", cannot be converted to a number might not be important - especially in a web environment where it is hard to
distinguish between a user not entering a value vs. entering a blank value.</p>
<p> By default, all conversion errors are reported using the generic i18n key <strong>xwork.default.invalid.fieldvalue</strong>,
which you can override (the default text is <em>Invalid field value for field "xxx"</em>, where xxx is the field name)
in your global i18n resource bundle.</p>
<p>However, sometimes you may wish to override this message on a per-field basis. You can do this by adding an i18n
key associated with just your action (Action.properties) using the pattern <strong>invalid.fieldvalue.xxx</strong>, where xxx
is the field name.</p>
<p>It is important to know that none of these errors are actually reported directly. Rather, they are added to a map
called <em>conversionErrors</em> in the ActionContext. There are several ways this map can then be accessed and the
errors can be reported accordingly.</p>
<p>There are two ways the error reporting can occur:</p>
<ol>
    <li>Globally, using the <a  href="file:///F:/Doc/Struts2/docs/conversion-error-interceptor.html" title="Conversion Error Interceptor">Conversion Error Interceptor</a></li>
    <li>On a per-field basis, using the <a  href="file:///F:/Doc/Struts2/docs/conversion-validator.html" title="conversion validator">conversion validator</a></li>
</ol>
<p>By default, the conversion interceptor is included in <tt><a  href="file:///F:/Doc/Struts2/docs/struts-defaultxml.html" title="struts-default.xml">struts-default.xml</a></tt>
in the default stack. To keep conversion errors from reporting
globally, change the interceptor stack, and add additional validation
rules.</p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 13:26 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 Ajax-base Client Validation[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114051.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 05:16:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114051.html</guid><description><![CDATA[<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <tbody>
        <tr>
            <td valign="top"><br></td>
            <td>This validation mode only works with the <a  href="file:///F:/Doc/Struts2/docs/ajax-theme.html" title="ajax theme">ajax theme</a></td>
        </tr>
    </tbody>
</table>
<p>AJAX-based client side validation improves upon <a  href="file:///F:/Doc/Struts2/docs/pure-javascript-client-side-validation.html" title="Pure JavaScript Client Side Validation">Pure JavaScript Client Side Validation</a> by using a combination of JavaScript, DOM manipulation, and remote server communication via <span class="nobr"><a  href="http://getahead.ltd.uk/dwr" title="Visit page outside confluence" rel="nofollow">DWR<sup><img  src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span>.
Unlike the pure client side implementation, AJAX-based validation
communicates with the server. This means all your validation rules that
worked when submitting a form will still work within the browser.</p>
<p><span style="background-color: #040c84;">AJAX基础上的客户端验证改进了Pure Javascript 客户端验证。它依赖于整合了Javascript，DOM操作，以及通过DWR和原断的server交互。不象纯javascript，AJAX－base的验证与服务器端交互。这意味着提交form后所有验证规则仍然在浏览器里工作。</span><br></p>
<p>The validation occurs on each <strong>onblur</strong> event for each form
element. As each user types in some values and moves to the next form
element, the value (and all other values previously entered) will be
sent to the server for validation. The entire validation stack is run,
including visitor validators and your action's validate() method.</p>
<p><span style="background-color: #040c84;">Validation在每个元素的onblur事件后发生。当用户输入一些值，然后跳到下一个元素是，先输入的值将被送到服务端验证。整个验证栈正在运行，包括visitor validators和你的action的validate()方法。</span><br></p>
<p>If there is an error, like the pure implementation, the HTML and DOM will be updated immediately.</p>
<p>For an example of this, see <a  href="file:///F:/Doc/Struts2/docs/ajax-validation.html" title="AJAX Validation">AJAX Validation</a>.</p>
<h2>Description</h2>
<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>
            <ul>
                <li>Ajax Validation requires DWR servlet being setup, Dojo and the <a  href="file:///F:/Doc/Struts2/docs/ajax-theme.html" title="ajax theme">Ajax theme</a> being used.</li>
            </ul>
            &nbsp;&nbsp;&nbsp;&nbsp; <span style="background-color: #040c84;">Ajax Validation需要建立DWR Servlet，使用Dojo和Ajax主题。</span><br>
            <ul>
                <li>In the Ajax theme, DWR is used for normal validation while Dojo handles everything else (widgets, XHR, browser JS events etc.)</li>
            </ul>
            &nbsp;&nbsp;&nbsp;&nbsp; <span style="background-color: #040c84;">在Ajax 主题里，DWR是用作常规的验证，而Dojo处理其他事情（...）</span><br>
            <ul>
                <li>In order for validation to function properly it is advised to used standard Struts Tags.</li>
            </ul>
            &nbsp;&nbsp;&nbsp;&nbsp; <span style="background-color: #040c84;">为了使验证工作正常进行，建议使用标准的Struts Tags。</span><br>
            </td>
        </tr>
    </tbody>
</table>
<h2><a name="AJAXValidation-SetupDWR"></a>Setup DWR</h2>
<p>DWR could be setup by having the following dwr configuration
(dwr.xml) at /WEB-INF/ directory. If it needs to be in other places,
refer to <span class="nobr"><a  href="http://getahead.ltd.uk/dwr/" title="Visit page outside confluence" rel="nofollow">http://getahead.ltd.uk/dwr/<sup><img  src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span> for more information.</p>
<p><span style="background-color: #040c84;">DWR通过防止drw.xml到/WEB-INF/ 目录来建立。</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml">&lt;!DOCTYPE dwr PUBLIC <br>	<span class="code-quote">"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"</span> <br>	<span class="code-quote">"http://www.getahead.ltd.uk/dwr/dwr10.dtd"</span>&gt;<br><br><span class="code-tag">&lt;dwr&gt;</span><br>    <span class="code-tag">&lt;allow&gt;</span><br>        <span class="code-tag">&lt;create creator=<span class="code-quote">"new"</span> javascript=<span class="code-quote">"validator"</span>&gt;</span><br>            <span class="code-tag">&lt;param name=<span class="code-quote">"class"</span> value=<span class="code-quote">"org.apache.struts2.validators.DWRValidator"</span>/&gt;</span><br>        <span class="code-tag">&lt;/create&gt;</span><br>        <span class="code-tag">&lt;convert converter=<span class="code-quote">"bean"</span> match=<span class="code-quote">"com.opensymphony.xwork2.ValidationAwareSupport"</span>/&gt;</span><br>    <span class="code-tag">&lt;/allow&gt;</span><br><br>    <span class="code-tag">&lt;signatures&gt;</span><br>        &lt;![CDATA[<br>        import java.util.Map;<br>        import org.apache.struts2.validators.DWRValidator;<br><br>        DWRValidator.doPost(String, String, Map<span class="code-tag">&lt;String, String&gt;</span>);<br>        ]]&gt;<br>    <span class="code-tag">&lt;/signatures&gt;</span><br><span class="code-tag">&lt;/dwr&gt;</span></pre>
</div>
</div>
<p>A DWRServlet need to be registered with the web application as well. The following shows a typical web.xml with DWRSerlvet.</p>
<p><span style="background-color: #040c84;">DWRServlet需要注册给web应用，下面展示了如何在web.xml中注册DWRServlet</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;servlet&gt;</span><br>       <span class="code-tag">&lt;servlet-name&gt;</span>dwr<span class="code-tag">&lt;/servlet-name&gt;</span><br>       <span class="code-tag">&lt;servlet-class&gt;</span>uk.ltd.getahead.dwr.DWRServlet<span class="code-tag">&lt;/servlet-class&gt;</span><br>       <span class="code-tag">&lt;init-param&gt;</span><br>           <span class="code-tag">&lt;param-name&gt;</span>debug<span class="code-tag">&lt;/param-name&gt;</span><br>           <span class="code-tag">&lt;param-value&gt;</span>true<span class="code-tag">&lt;/param-value&gt;</span><br>       <span class="code-tag">&lt;/init-param&gt;</span><br>   <span class="code-tag">&lt;/servlet&gt;</span><br><br><span class="code-tag"><span class="code-comment">&lt;!-- JavaServer Faces Servlet Configuration, not used directly --&gt;</span></span><br> 	<span class="code-tag">&lt;servlet&gt;</span><br>   	<span class="code-tag">&lt;servlet-name&gt;</span>faces<span class="code-tag">&lt;/servlet-name&gt;</span><br>    <span class="code-tag">&lt;servlet-class&gt;</span>javax.faces.webapp.FacesServlet<span class="code-tag">&lt;/servlet-class&gt;</span><br>   	<span class="code-tag">&lt;load-on-startup&gt;</span>1<span class="code-tag">&lt;/load-on-startup&gt;</span><br> 	<span class="code-tag">&lt;/servlet&gt;</span><br><br> 	<span class="code-tag"><span class="code-comment">&lt;!-- JavaServer Faces Servlet Mapping, not called directly --&gt;</span></span><br>   	<span class="code-tag">&lt;servlet-mapping&gt;</span><br>       <span class="code-tag">&lt;servlet-name&gt;</span>faces<span class="code-tag">&lt;/servlet-name&gt;</span><br>       <span class="code-tag">&lt;url-pattern&gt;</span>*.action<span class="code-tag">&lt;/url-pattern&gt;</span><br> 	<span class="code-tag">&lt;/servlet-mapping&gt;</span><br><br>   <span class="code-tag">&lt;servlet-mapping&gt;</span><br>       <span class="code-tag">&lt;servlet-name&gt;</span>dwr<span class="code-tag">&lt;/servlet-name&gt;</span><br>       <span class="code-tag">&lt;url-pattern&gt;</span>/dwr/*<span class="code-tag">&lt;/url-pattern&gt;</span><br>   <span class="code-tag">&lt;/servlet-mapping&gt;</span></pre>
</div>
</div>
<h3><a name="AJAXValidation-Step1"></a>Step 1</h3>
<p>Create the jsp page. Note the &lt;ww:head ...&gt; tag is used to set
the theme which will put in necesary dojo sripts etc. See ajax's theme
head.ftl for more information.</p>
<p><span style="background-color: #040c84;">创建jsp页面。注意&lt;s:head...&gt;标签用来获取放置需要dojoscript等的主题。</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;html&gt;</span><br><span class="code-tag">&lt;head&gt;</span><br>    <span class="code-tag">&lt;title&gt;</span>Validation - Basic<span class="code-tag">&lt;/title&gt;</span><br>    <span class="code-tag">&lt;s:head theme=<span class="code-quote">"ajax"</span>/&gt;</span><br><span class="code-tag">&lt;/head&gt;</span><br><br><span class="code-tag">&lt;body&gt;</span><br><br><span class="code-tag">&lt;s:form method=<span class="code-quote">"post"</span> validate=<span class="code-quote">"true"</span> theme=<span class="code-quote">"ajax"</span>&gt;</span><br>    <span class="code-tag">&lt;s:textfield label=<span class="code-quote">"Name"</span> name=<span class="code-quote">"name"</span>/&gt;</span><br>    <span class="code-tag">&lt;s:textfield label=<span class="code-quote">"Age"</span> name=<span class="code-quote">"age"</span>/&gt;</span><br>    <span class="code-tag">&lt;s:textfield label=<span class="code-quote">"Favorite color"</span> name=<span class="code-quote">"answer"</span>/&gt;</span><br>    <span class="code-tag">&lt;s:submit/&gt;</span><br><span class="code-tag">&lt;/s:form&gt;</span><br><br><span class="code-tag">&lt;/body&gt;</span><br><span class="code-tag">&lt;/html&gt;</span></pre>
</div>
</div>
<h3><a name="AJAXValidation-Step2"></a>Step 2</h3>
<p>Create the action class</p>
<div class="code">
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class QuizAction <span class="code-keyword">extends</span> ActionSupport {<br><br>    <span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">long</span> serialVersionUID = -7505437345373234225L;<br><br>    <span class="code-object">String</span> name;<br>    <span class="code-object">int</span> age;<br>    <span class="code-object">String</span> answer;<br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> getName() {<br>        <span class="code-keyword">return</span> name;<br>    }<br><br>    <span class="code-keyword">public</span> void setName(<span class="code-object">String</span> name) {<br>        <span class="code-keyword">this</span>.name = name;<br>    }<br><br>    <span class="code-keyword">public</span> <span class="code-object">int</span> getAge() {<br>        <span class="code-keyword">return</span> age;<br>    }<br><br>    <span class="code-keyword">public</span> void setAge(<span class="code-object">int</span> age) {<br>        <span class="code-keyword">this</span>.age = age;<br>    }<br><br>    <span class="code-keyword">public</span> <span class="code-object">String</span> getAnswer() {<br>        <span class="code-keyword">return</span> answer;<br>    }<br><br>    <span class="code-keyword">public</span> void setAnswer(<span class="code-object">String</span> answer) {<br>        <span class="code-keyword">this</span>.answer = answer;<br>    }<br>}</pre>
</div>
</div>
<h3><a name="AJAXValidation-Step3"></a>Step 3</h3>
<p>Create the validation.xml</p>
An error occurred:
http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction-validation.xml.
The system administrator has been notified.  <img src ="http://www.blogjava.net/nobody_am/aggbug/114051.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 13:16 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114051.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 Pure Javascript Client Validation[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114046.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 04:58:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114046.html</guid><description><![CDATA[<div class="wiki-content">
<p>Pure JavaScript client side validation is the simplest but least feature-rich type of <a  href="file:///F:/Doc/Struts2/docs/client-side-validation.html" title="Client Side Validation">Client Side Validation</a>.
This type of validation uses 100% client-side JavaScript code to try to
validate the values entered by the user. Because the validation logic
is actually repeated in the JavaScript code, it is important to
understand that some values will be considered acceptable by the
JavaScript code but will be marked as unacceptable by the server-side <a  href="file:///F:/Doc/Struts2/docs/validation.html" title="Validation">Validation</a>.</p>
<p>纯Javascript客户端验证是最简单的，但是只功能有限的客户端验证。这种类型的验证用100％的客户端javascript代码验证用户录入的值。因为验证逻辑是javascript代码，所以理解－－一些值javascript代码认为通过了，而服务器端的验证可能不通过－－是非常重要的。<br></p>
<p>Only the following validators are supported:</p>
<ul>
    <li>required validator</li>
    <li>requiredstring validator</li>
    <li>stringlength validator</li>
    <li>regex validator</li>
    <li>email validator</li>
    <li>url validator</li>
    <li>int validator</li>
    <li>double validator</li>
</ul>
<h2><a name="PureJavaScriptClientSideValidation-Errorreporting"></a>Error reporting</h2>
<p>Because client side validation does not talk to the server, the theme (<a  href="file:///F:/Doc/Struts2/docs/xhtml-theme.html" title="xhtml theme">xhtml theme</a> or <a  href="file:///F:/Doc/Struts2/docs/cssxhtml-theme.html" title="css_xhtml theme">css_xhtml theme</a>)
is responsible for properly manipulating the HTML DOM to display the
error message inline. The JavaScript that is responsible for doing this
logic is <tt>validation.js</tt> and can be found in each theme.</p>
<p><span style="background-color: #0f007c;">因为客户端的验证不与服务器端交互，主题（....）负责操纵HTML DOM来显示再现错误消息。负责这个逻辑的javascript是validation.js，能在各自的主题里找到。</span><br></p>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>Errors
            are reported using the default validation message, not the
            internationalized version that the server-side might be aware of. This
            is a known issue. You may want to try the <a  href="file:///F:/Doc/Struts2/docs/ajax-client-side-validation.html" title="AJAX Client Side Validation">AJAX Client Side Validation</a> for messages that are fully internationalized.<br><span style="background-color: #0f007c;">用验证消息显示错误报告不能被国际化。你可能想用Ajax Client Side validation来是消息完全国际化。</span><br></td>
        </tr>
    </tbody>
</table>
<h2><a name="PureJavaScriptClientSideValidation-AdditionalValidatorSupport"></a>Additional Validator Support</h2>
<p>If you wish to add additional validator support beyond those listed, you may override the <a  href="file:///F:/Doc/Struts2/docs/xhtml-theme.html" title="xhtml theme">xhtml theme</a> teamplte <tt>form-close-validate.ftl</tt>. This file contains the JavaScript that tries to validate each user-entered value from within the browswer. The <a  href="file:///F:/Doc/Struts2/docs/cssxhtml-theme.html" title="css_xhtml theme">css_xhtml theme</a> extends the <a  href="file:///F:/Doc/Struts2/docs/xhtml-theme.html" title="xhtml theme">xhtml theme</a> and therefore doesn't have it's own form-close-validate.ftl template.</p>
<p><br></p>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 12:58 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 Validation[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/27/114026.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Fri, 27 Apr 2007 03:30:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/27/114026.html</guid><description><![CDATA[<p>Struts Action 2 relies on a validation framework provided by [XWork]
to enable the application of input validation rules to your Actions
before they are executed. This section only provides the bare minimum
to get you started and focuses on our extension of the XWork validators
to support client-side validation.</p>
<p><span style="background-color: #0e0076;">Struts Action 2 依赖于一个XWork提供的validation框架，它能够在执行Action之前，遵循一些输入验证规则。本节进京提供最小的能够让你开始和关注于对XWork validator扩展来支持客户端的验证。</span><br></p>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>There is also an option for Client Side (Javascript and/or AJAX) based validation, please see <a  href="file:///F:/Doc/Struts2/docs/client-side-validation.html" title="Client Side Validation">Client Side Validation</a> for more information.</td>
        </tr>
    </tbody>
</table>
<h2><a name="Validation-UsingAnnotations"></a>Using Annotations</h2>
<p><a  href="file:///F:/Doc/Struts2/docs/validation-annotation.html" title="Validation Annotation">Annotations</a> can be used as an alternative to XML for validation.</p>
<p><span style="background-color: #0e0076;">Annotations 方式的验证是一个相对于XML更好的选择。</span><br></p>
<h2><a name="Validation-Examples"></a>Examples</h2>
<ol>
    <li><a  href="file:///F:/Doc/Struts2/docs/basic-validation.html" title="Basic Validation">Basic Validation</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/client-validation.html" title="Client Validation">Client Validation</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/ajax-validation.html" title="AJAX Validation">AJAX Validation</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/using-field-validators.html" title="Using Field Validators">Using Field Validators</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/using-non-field-validators.html" title="Using Non Field Validators">Using Non Field Validators</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/using-visitor-field-validator.html" title="Using Visitor Field Validator">Using Visitor Field Validator</a></li>
</ol>
<h2><a name="Validation-BundledValidators"></a>Bundled Validators</h2>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">Note</strong><br>
            <p>When using a Field Validator, Field Validator Syntax is ALWAYS
            preferable than using the Plain Validator Syntax as it facilitates
            grouping of field-validators according to fields. This is very handy
            especially if a field needs to have many field-validators which is
            almost always the case. Examples: <span class="nobr"><a  href="http://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&amp;title=validatortypes&amp;linkCreation=true&amp;fromPageId=14292" title="Create page: validatortypes" class="createlink">validatortypes<sup><img  src="http://cwiki.apache.org/confluence/images/icons/plus.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span></p>
            </td>
        </tr>
    </tbody>
</table>
<ol>
    <li><a  href="file:///F:/Doc/Struts2/docs/required-validator.html" title="required validator">required validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/requiredstring-validator.html" title="requiredstring validator">requiredstring validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/int-validator.html" title="int validator">int validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/date-validator.html" title="date validator">date validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/expression-validator.html" title="expression validator">expression validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/fieldexpression-validator.html" title="fieldexpression validator">fieldexpression validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/email-validator.html" title="email validator">email validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/url-validator.html" title="url validator">url validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/visitor-validator.html" title="visitor validator">visitor validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/conversion-validator.html" title="conversion validator">conversion validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/stringlength-validator.html" title="stringlength validator">stringlength validator</a></li>
    <li><a  href="file:///F:/Doc/Struts2/docs/regex-validator.html" title="regex validator">regex validator</a></li>
</ol>
<h2><a name="Validation-RegisteringValidators"></a>Registering Validators</h2>
<p>Validation rules are handled by validators, which must be registered with
the ValidatorFactory (using the registerValidator method). The simplest way to do so is to add a file name
validators.xml in the root of the classpath (/WEB-INF/classes) that declares
all the validators you intend to use. </p>
<p>This list declares all the validators that comes with the framework.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;validators&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"required"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"requiredstring"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.RequiredStringValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"int"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"double"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"date"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"expression"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.ExpressionValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"fieldexpression"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"email"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.EmailValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"url"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.URLValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"visitor"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"conversion"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"stringlength"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"</span>/&gt;</span><br>    <span class="code-tag">&lt;validator name=<span class="code-quote">"regex"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.validators.RegexFieldValidator"</span>/&gt;</span><br><span class="code-tag">&lt;/validators&gt;</span></pre>
</div>
</div>
<table class="noteMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">Note</strong><br>
            <p>validators.xml if being defined should be available in the classpath. However
            this is not necessary, if no custom validator is needed. Predefined sets of validators
            will automatically be picked up when defined in
            com/opensymphony/xwork2/validator/validators/default.xml packaged in
            in the xwork jar file. See ValidatorFactory static block for details.</p>
            </td>
        </tr>
    </tbody>
</table>
<table class="warningMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/forbidden.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">Warning</strong><br>
            <p>If custom validator is being defined and a validators.xml is created and
            place in the classpath, do remember to copy all the other pre-defined validators
            that is needed into the validators.xml as if not they will not be registered.
            Once a validators.xml is detected in the classpath, the default one
            (com/opensymphony/xwork2/validator/validators/default.xml) will not be loaded.
            It is only loaded when a custom validators.xml cannot be found in the classpath.
            Be careful.</p>
            <p><span style="background-color: #0e0076;">自己的validator.xml和default.xml是二选一。</span><br></p>
            </td>
        </tr>
    </tbody>
</table>
<h2><a name="Validation-TurningonValidation"></a>Turning on Validation</h2>
<p>The default validationWorkflowStack already includes this.<br>
All that is required to enable validation for an Action is to put the
ValidationInterceptor in the interceptor refs of the action (see xwork.xml) like so:</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;interceptor name=<span class="code-quote">"validator"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.ValidationInterceptor"</span>/&gt;</span></pre>
</div>
</div>
<p>Note: The default <strong>validationWorkflowStack</strong> already includes this.</p>
<p>You can turn off validation for a specific method by using the <span style="color: red; font-weight: bold;">@SkipValidation</span> annotation above your action method.</p>
<p><span style="background-color: #0e0076;">你可以关闭对某个方法的验证，使用@SkipValidation annotation在你的action 方法上面。</span><br></p>
<h2><a name="Validation-ValidatorScopes"></a>Validator Scopes</h2>
<p>Field validators, as the name indicate, act on single fields accessible through an action.
A validator, in contrast, is more generic and can do validations in the full action context,
involving more than one field (or even no field at all) in validation rule.
Most validations can be defined on per field basis. This should be preferred over
non-field validation whereever possible, as field validator messages are bound to the
related field and will be presented next to the corresponding input element in the
respecting view.</p>
<p>Non-field validators only add action level messages. Non-field validators
are mostly domain specific and therefore often custom implementations.
The most important standard non-field validator provided by XWork
is ExpressionValidator.</p>
<p><span style="background-color: #0e0076;">上面提到两种Validator， Field Validator和Non-field validator.</span><br></p>
<h3><a name="Validation-Notes"></a>Notes</h3>
<p>Non-field validators takes precedence over field validators
regardless of the order they are defined in *-validation.xml. If a non-field
validator is short-circuited, it will causes its non-field validator to not
being executed. See validation framework documentation for more info.</p>
<h2><a name="Validation-DefiningValidationRules"></a>Defining Validation Rules</h2>
<p>Validation rules can be specified:
</p>
<ol>
    <li> Per Action class: in a file named ActionName-validation.xml</li>
    <li> Per Action alias: in a file named ActionName-alias-validation.xml</li>
    <li> Inheritance hierarchy and interfaces implemented by Action class:
    XWork searches up the inheritance tree of the action to find default
    validations for parent classes of the Action and interfaces implemented</li>
</ol>
Here is an example for SimpleAction-validation.xml:
<div class="code">
<div class="codeContent">
<pre class="code-xml">&lt;!DOCTYPE validators PUBLIC <span class="code-quote">"-//OpenSymphony Group//XWork Validator 1.0.2//EN"</span><br>       <span class="code-quote">"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"</span>&gt;<br><span class="code-tag">&lt;validators&gt;</span><br>  <span class="code-tag">&lt;field name=<span class="code-quote">"bar"</span>&gt;</span><br>      <span class="code-tag">&lt;field-validator type=<span class="code-quote">"required"</span>&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>You must enter a value for bar.<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>      <span class="code-tag">&lt;field-validator type=<span class="code-quote">"int"</span>&gt;</span><br>          <span class="code-tag">&lt;param name=<span class="code-quote">"min"</span>&gt;</span>6<span class="code-tag">&lt;/param&gt;</span><br>          <span class="code-tag">&lt;param name=<span class="code-quote">"max"</span>&gt;</span>10<span class="code-tag">&lt;/param&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>bar must be between ${min} and ${max}, current value is ${bar}.<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;/field&gt;</span><br>  <span class="code-tag">&lt;field name=<span class="code-quote">"bar2"</span>&gt;</span><br>      <span class="code-tag">&lt;field-validator type=<span class="code-quote">"regex"</span>&gt;</span><br>          <span class="code-tag">&lt;param name=<span class="code-quote">"regex"</span>&gt;</span>[0-9],[0-9]<span class="code-tag">&lt;/param&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>The value of bar2 must be in the format <span class="code-quote">"x, y"</span>, where x and y are between 0 and 9<span class="code-tag">&lt;/message&gt;</span><br>     <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;/field&gt;</span><br>  <span class="code-tag">&lt;field name=<span class="code-quote">"date"</span>&gt;</span><br>      <span class="code-tag">&lt;field-validator type=<span class="code-quote">"date"</span>&gt;</span><br>          <span class="code-tag">&lt;param name=<span class="code-quote">"min"</span>&gt;</span>12/22/2002<span class="code-tag">&lt;/param&gt;</span><br>          <span class="code-tag">&lt;param name=<span class="code-quote">"max"</span>&gt;</span>12/25/2002<span class="code-tag">&lt;/param&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>The date must be between 12-22-2002 and 12-25-2002.<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;/field&gt;</span><br>  <span class="code-tag">&lt;field name=<span class="code-quote">"foo"</span>&gt;</span><br>      <span class="code-tag">&lt;field-validator type=<span class="code-quote">"int"</span>&gt;</span><br>          <span class="code-tag">&lt;param name=<span class="code-quote">"min"</span>&gt;</span>0<span class="code-tag">&lt;/param&gt;</span><br>          <span class="code-tag">&lt;param name=<span class="code-quote">"max"</span>&gt;</span>100<span class="code-tag">&lt;/param&gt;</span><br>          <span class="code-tag">&lt;message key=<span class="code-quote">"foo.range"</span>&gt;</span>Could not find foo.range!<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;/field&gt;</span><br>  <span class="code-tag">&lt;validator type=<span class="code-quote">"expression"</span>&gt;</span><br>      <span class="code-tag">&lt;param name=<span class="code-quote">"expression"</span>&gt;</span>foo lt bar <span class="code-tag">&lt;/param&gt;</span><br>      <span class="code-tag">&lt;message&gt;</span>Foo must be greater than Bar. Foo = ${foo}, Bar = ${bar}.<span class="code-tag">&lt;/message&gt;</span><br>  <span class="code-tag">&lt;/validator&gt;</span><br><span class="code-tag">&lt;/validators&gt;</span></pre>
</div>
</div>
<p>Here we can see the configuration of validators for the SimpleAction class.
Validators (and field-validators) must have a <span style="font-weight: bold; color: red;">type</span> attribute, which refers
to a name of an Validator registered with the ValidatorFactory as above.
Validator elements may also have &lt;param&gt; elements with name and value attributes
to set arbitrary parameters into the Validator instance. See below for discussion
of the message element.</p>
<p>Each Validator or Field-Validator element must define one <span style="font-weight: bold; color: red;">message</span> element inside
the validator element body. The message element has 1 attributes, <span style="font-weight: bold; color: red;">key</span> which is not
required. The body of the message tag is taken as the default message which should
be added to the Action if the validator fails.Key gives a message key to look up
in the Action's ResourceBundles using getText() from LocaleAware if the Action
implements that interface (as ActionSupport does). This provides for Localized
messages based on the Locale of the user making the request (or whatever Locale
you've set into the LocaleAware Action). After either retrieving the message from
the ResourceBundle using the Key value, or using the Default message, the current
Validator is pushed onto the ValueStack, then the message is parsed for \${...}
sections which are replaced with the evaluated value of the string between the
\${ and }. This allows you to parameterize your messages with values from the
Validator, the Action, or both.</p>
<p>If the validator fails, the validator is pushed onto the ValueStack and the
message� either the default or the locale-specific one if the key attribute is
defined (and such a message exists)� is parsed for ${...} sections which are
replaced with the evaluated value of the string between the ${ and }. This
allows you to parameterize your messages with values from the validator, the
Action, or both. </p>
<p><strong>NOTE:</strong>Since validation rules are in an XML file, you must make sure
you escape special characters. For example, notice that in the expression
validator rule above we use "&gt;" instead of "&gt;". Consult a resource on XML
for the full list of characters that must be escaped. The most commonly used
characters that must be escaped are: &amp; (use &amp;), &gt; (user &gt;), and &lt; (use &lt;).</p>
<p>Here is an example of a parameterized message:</p>
<p>This will pull the min and max parameters from the IntRangeFieldValidator and
the value of bar from the Action.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml">bar must be between ${min} and ${max}, current value is ${bar}.</pre>
</div>
</div>
<p>Validation rules can be specified:
</p>
<ol>
    <li> Per Action class: in a file named ActionName-validation.xml</li>
    <li> Per Action alias: in a file named ActionName-alias-validation.xml</li>
    <li> Inheritance hierarchy and interfaces implemented by Action class:
    XWork searches up the inheritance tree of the action to find default
    validations for parent classes of the Action and interfaces implemented</li>
</ol>
Here is an example for SimpleAction-validation.xml:
<h2><a name="Validation-ValidatorFlavour"></a>Validator Flavour</h2>
<p>The validators supplied by the Xwork distribution (and any validators you
might write yourself) come in two different flavors:</p>
<ol>
    <li> Plain Validators / Non-Field validators </li>
    <li> FieldValidators </li>
</ol>
<p><span style="font-weight: bold; color: red;">Plain Validators</span><span style="color: red;"> </span>(such as the ExpressionValidator) perform validation checks
that are not inherently tied to a single specified field. When you declare a
plain Validator in your -validation.xml file you do not associate a fieldname
attribute with it. (You should avoid using plain Validators within the
<field-validator> syntax described below.)</field-validator></p>
<p><span style="font-weight: bold; color: red;">FieldValidators</span> (such as the EmailValidator) are designed to perform
validation checks on a single field. They require that you specify a fieldname
attribute in your -validation.xml file. There are two different (but equivalent)
XML syntaxes you can use to declare FieldValidators (see "<validator> vs.
<field-validator> syntax" below).</field-validator></validator></p>
<p>There are two places where the differences between the two validator flavors
are important to keep in mind:</p>
<ol>
    <li> when choosing the xml syntax used for declaring a validator
    (either <validator> or <field-validator>)</field-validator></validator></li>
    <li> when using the short-circuit capability</li>
</ol>
<p><strong>NOTE:</strong>Note that you do not declare what "flavor" of validator you are
using in your -validation.xml file, you just declare the name of the validator
to use and WebWork will know whether it's a "plain Validator" or a "FieldValidator"
by looking at the validation class that the validator's programmer chose
to implement.</p>
<h2><a name="Validation-NonFieldValidatorVsFieldValidator"></a>Non-Field Validator Vs Field-Validator <a name="Validation-validatortypes"></a></h2>
<p>There are two ways you can define validators in your -validation.xml file:</p>
<ol>
    <li> &lt;validator&gt; </li>
    <li> &lt;field-validator&gt; </li>
</ol>
<p>Keep the following in mind when using either syntax:</p>
<p><strong>Non-Field-Validator</strong>
The &lt;validator&gt; element allows you to declare both types of validators
(either a plain Validator a field-specific FieldValidator).</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- Declaring a plain Validator using the &lt;validator&gt;</span> syntax: --&gt;</span><br><br>   <span class="code-tag">&lt;validator type="expression&gt;</span><br>         <span class="code-tag">&lt;param name=<span class="code-quote">"expression"</span>&gt;</span>foo gt bar<span class="code-tag">&lt;/param&gt;</span><br>         <span class="code-tag">&lt;message&gt;</span>foo must be great than bar.<span class="code-tag">&lt;/message&gt;</span><br>   <span class="code-tag">&lt;/validator&gt;</span></pre>
</div>
</div>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- Declaring a field validator using the &lt;validator&gt;</span> syntax; --&gt;</span><br><br>   <span class="code-tag">&lt;validator type=<span class="code-quote">"required"</span>&gt;</span><br>        <span class="code-tag">&lt;param name=<span class="code-quote">"fieldName"</span>&gt;</span>bar<span class="code-tag">&lt;/param&gt;</span><br>        <span class="code-tag">&lt;message&gt;</span>You must enter a value for bar.<span class="code-tag">&lt;/message&gt;</span><br>   &lt;/validator&gt;</pre>
</div>
</div>
<p><strong>field-validator</strong>
The &lt;field-validator&gt; elements are basically the same as the &lt;validator&gt; elements
except that they inherit the fieldName attribute from the enclosing &lt;field&gt; element.
FieldValidators defined within a &lt;field-validator&gt; element will have their fieldName
automatically filled with the value of the parent &lt;field&gt; element's fieldName
attribute. The reason for this structure is to conveniently group the validators
for a particular field under one element, otherwise the fieldName attribute
would have to be repeated, over and over, for each individual &lt;validator&gt;.</p>
<p><strong>HINT:</strong>
It is always better to defined field-validator inside a &lt;field&gt; tag instead of
using a &lt;validator&gt; tag and supplying fieldName as its param as the xml code itself
is clearer (grouping of field is clearer)</p>
<p><strong>NOTE:</strong>
Note that you should only use FieldValidators (not plain Validators) within a
<field-validator> block. A plain Validator inside a &lt;field&gt; will not be
allowed and would generate error when parsing the xml, as it is not allowed in
the defined dtd (xwork-validator-1.0.2.dtd)</field-validator></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml">Declaring a FieldValidator using the <span class="code-tag">&lt;field-validator&gt;</span> syntax:<br><br><span class="code-tag">&lt;field name=<span class="code-quote">"email_address"</span>&gt;</span><br>  <span class="code-tag">&lt;field-validator type=<span class="code-quote">"required"</span>&gt;</span><br>      <span class="code-tag">&lt;message&gt;</span>You cannot leave the email address field empty.<span class="code-tag">&lt;/message&gt;</span><br>  <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;field-validator type=<span class="code-quote">"email"</span>&gt;</span><br>      <span class="code-tag">&lt;message&gt;</span>The email address you entered is not valid.<span class="code-tag">&lt;/message&gt;</span><br>  <span class="code-tag">&lt;/field-validator&gt;</span><br><span class="code-tag">&lt;/field&gt;</span></pre>
</div>
</div>
<p>The choice is yours. It's perfectly legal to only use <validator> elements
without the <field> elements and set the fieldName attribute for each of them.
The following are effectively equal:</field></validator></p>
<p><validator><field><span style="background-color: #0e0076;">有多个选择未必是好事情:)</span><br></field></validator></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;field name=<span class="code-quote">"email_address"</span>&gt;</span><br>  <span class="code-tag">&lt;field-validator type=<span class="code-quote">"required"</span>&gt;</span><br>      <span class="code-tag">&lt;message&gt;</span>You cannot leave the email address field empty.<span class="code-tag">&lt;/message&gt;</span><br>  <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;field-validator type=<span class="code-quote">"email"</span>&gt;</span><br>      <span class="code-tag">&lt;message&gt;</span>The email address you entered is not valid.<span class="code-tag">&lt;/message&gt;</span><br>  <span class="code-tag">&lt;/field-validator&gt;</span><br><span class="code-tag">&lt;/field&gt;</span><br><br><br><span class="code-tag">&lt;validator type=<span class="code-quote">"required"</span>&gt;</span><br>  <span class="code-tag">&lt;param name=<span class="code-quote">"fieldName"</span>&gt;</span>email_address<span class="code-tag">&lt;/param&gt;</span><br>  <span class="code-tag">&lt;message&gt;</span>You cannot leave the email address field empty.<span class="code-tag">&lt;/message&gt;</span><br><span class="code-tag">&lt;/validator&gt;</span><br><span class="code-tag">&lt;validator type=<span class="code-quote">"email"</span>&gt;</span><br>  <span class="code-tag">&lt;param name=<span class="code-quote">"fieldName"</span>&gt;</span>email_address<span class="code-tag">&lt;/param&gt;</span><br>  <span class="code-tag">&lt;message&gt;</span>The email address you entered is not valid.<span class="code-tag">&lt;/message&gt;</span><br><span class="code-tag">&lt;/validator&gt;</span></pre>
</div>
</div>
<h2><a name="Validation-ShortCircuitingValidator"></a>Short-Circuiting Validator</h2>
<p>Beginning with XWork 1.0.1 (bundled with WebWork 2.1), it is possible
to short-circuit a stack of validators. Here is another sample config file
containing validation rules from the Xwork test cases: Notice that some of the
&lt;field-validator&gt; and &lt;validator&gt; elements have the short-circuit
attribute set to true.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml">&lt;!DOCTYPE validators PUBLIC <br>        <span class="code-quote">"-//OpenSymphony Group//XWork Validator 1.0.2//EN"</span> <br>        <span class="code-quote">"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"</span>&gt;<br><span class="code-tag">&lt;validators&gt;</span><br>  <span class="code-tag"><span class="code-comment">&lt;!-- Field Validators for email field --&gt;</span></span><br>  <span class="code-tag">&lt;field name=<span class="code-quote">"email"</span>&gt;</span><br>      <span class="code-tag">&lt;field-validator type=<span class="code-quote">"required"</span> short-circuit=<span class="code-quote">"true"</span>&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>You must enter a value for email.<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>      <span class="code-tag">&lt;field-validator type=<span class="code-quote">"email"</span> short-circuit=<span class="code-quote">"true"</span>&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>Not a valid e-mail.<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;/field&gt;</span><br>  <span class="code-tag"><span class="code-comment">&lt;!-- Field Validators for email2 field --&gt;</span></span><br>  <span class="code-tag">&lt;field name=<span class="code-quote">"email2"</span>&gt;</span><br>     <span class="code-tag">&lt;field-validator type=<span class="code-quote">"required"</span>&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>You must enter a value for email2.<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>     <span class="code-tag">&lt;field-validator type=<span class="code-quote">"email"</span>&gt;</span><br>          <span class="code-tag">&lt;message&gt;</span>Not a valid e-mail2.<span class="code-tag">&lt;/message&gt;</span><br>      <span class="code-tag">&lt;/field-validator&gt;</span><br>  <span class="code-tag">&lt;/field&gt;</span><br>  <span class="code-tag"><span class="code-comment">&lt;!-- Plain Validator 1 --&gt;</span></span><br>  <span class="code-tag">&lt;validator type=<span class="code-quote">"expression"</span>&gt;</span><br>      <span class="code-tag">&lt;param name=<span class="code-quote">"expression"</span>&gt;</span>email.equals(email2)<span class="code-tag">&lt;/param&gt;</span><br>      <span class="code-tag">&lt;message&gt;</span>Email not the same as email2<span class="code-tag">&lt;/message&gt;</span><br>  <span class="code-tag">&lt;/validator&gt;</span><br>  <span class="code-tag"><span class="code-comment">&lt;!-- Plain Validator 2 --&gt;</span></span><br>  <span class="code-tag">&lt;validator type=<span class="code-quote">"expression"</span> short-circuit=<span class="code-quote">"true"</span>&gt;</span><br>      <span class="code-tag">&lt;param name=<span class="code-quote">"expression"</span>&gt;</span>email.startsWith('mark')<span class="code-tag">&lt;/param&gt;</span><br>      <span class="code-tag">&lt;message&gt;</span>Email does not start with mark<span class="code-tag">&lt;/message&gt;</span><br>  <span class="code-tag">&lt;/validator&gt;</span><br><span class="code-tag">&lt;/validators&gt;</span></pre>
</div>
</div>
<p><strong>short-circuiting and Validator flavors</strong></p>
<p>Plain validator takes precedence over field-validator. They get validated
first in the order they are defined and then the field-validator in the order
they are defined. Failure of a particular validator marked as short-circuit
will prevent the evaluation of subsequent validators and an error (action
error or field error depending on the type of validator) will be added to
the ValidationContext of the object being validated.</p>
<p><span style="background-color: #0c0062;">Plain validator 优先级高于field-validator.他们定义的顺序中，先获取plain validator，后获取field-validator.一个标注为short-circuit的validator将避免对接下来validator的评估，并且添加一个error到ValidationContext中。</span><br></p>
<p>In the example above, the actual execution of validator would be as follows:</p>
<ol>
    <li> Plain Validator 1</li>
    <li> Plain Validator 2</li>
    <li> Field Validators for email field</li>
    <li> Field Validators for email2 field</li>
</ol>
<p>Since Field Validator 2 is short-circuited, if its validation failed,
it will causes Field validators for email field and Field validators for email2
field to not be validated as well.</p>
<p><span style="background-color: #0c0062;">既然Field validator 2是短路的，如果验证失败，email 字段会验证，email2字段不会被验证。</span><br></p>
<p><strong>Usefull Information:</strong>
More complecated validation should probably be done in the validate()
method on the action itself (assuming the action implements Validatable
interface which ActionSupport already does).</p>
<p><span style="background-color: #0c0062;">有用信息：更复杂的验证应该在Action类里的validate方法中实现。（假设action实现了validatable接口，这个validatable接口被actionSupport实现）</span><br></p>
<p>
A plain Validator (non FieldValidator) that gets short-circuited will
completely break out of the validation stack no other validators will be
evaluated and plain validator takes precedence over field validator meaning
that they get evaluated in the order they are defined before field validator
gets a chance to be evaludated again according to their order defined.</p>
<p><br>
</p>
<p><strong>Short cuircuiting and validator flavours</strong></p>
<p>A FieldValidator that gets short-circuited will only prevent other
FieldValidators for the same field from being evaluated. Note that this
"same field" behavior applies regardless of whether the <validator> or
<field-validator> syntax was used to declare the validation rule.
By way of example, given this -validation.xml file:</field-validator></validator></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;validator type=<span class="code-quote">"required"</span> short-circuit=<span class="code-quote">"true"</span>&gt;</span><br>  <span class="code-tag">&lt;param name=<span class="code-quote">"fieldName"</span>&gt;</span>bar<span class="code-tag">&lt;/param&gt;</span><br>  <span class="code-tag">&lt;message&gt;</span>You must enter a value for bar.<span class="code-tag">&lt;/message&gt;</span><br><span class="code-tag">&lt;/validator&gt;</span><br><br><span class="code-tag">&lt;validator type=<span class="code-quote">"expression"</span>&gt;</span><br>  <span class="code-tag">&lt;param name=<span class="code-quote">"expression"</span>&gt;</span>foo gt bar<span class="code-tag">&lt;/param&gt;</span><br>  <span class="code-tag">&lt;message&gt;</span>foo must be great than bar.<span class="code-tag">&lt;/message&gt;</span><br><span class="code-tag">&lt;/validator&gt;</span></pre>
</div>
</div>
<p>both validators will be run, even if the "required" validator short-circuits.
"required" validators are FieldValidator's and will not short-circuit the plain
ExpressionValidator because FieldValidators only short-circuit other checks on
that same field. Since the plain Validator is not field specific, it is
not short-circuited.</p>
<p><span style="background-color: #0c0062;">两个validator都在运行，尽管&#8220;required&#8221;validator短路。&#8220;required&#8221;validators 是FieldValidator 不能短路掉plain Expression Validator。因为FieldValidator仅仅能短路掉自己字段的validator。既然palin validator不是field规格的，所以它不会被短路掉。</span><br></p>
<h2><a name="Validation-HowValidatorsofanActionareFound"></a>How Validators of an Action are Found</h2>
<p>As mentioned above, the framework will also search up the inheritance tree
of the action to find default validations for interfaces and parent classes of
the Action. If you are using the short-circuit attribute and relying on
default validators higher up in the inheritance tree, make sure you don't
accidentally short-circuit things higher in the tree that you really want!</p>
<p><span style="background-color: #0c0062;">正如上面提到的，框架将搜索action的继承树，来查为接口和action父类的默认验证。如果你用short-circuit attribute&nbsp; 并且依赖继承树上高层的默认验证，确保你不要意外地短路掉高层继承树里那些你真正想要的东西。 </span><br></p>
<h2><a name="Validation-Resources"></a>Resources </h2>
<p><span class="nobr"><a  href="http://today.java.net/pub/a/today/2006/01/19/webwork-validation.html" title="Visit page outside confluence" rel="nofollow">WebWork Validation<sup><img  src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span></p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/114026.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-27 11:30 <a href="http://www.blogjava.net/nobody_am/news/2007/04/27/114026.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 本地化[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113948.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:58:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113948.html</guid><description><![CDATA[<p>The framework supports internationalization (i18n) in two different places: the <a  href="file:///F:/Doc/Struts2/docs/ui-tags.html" title="UI Tags">UI Tags</a> and the action/field error messages, including the <a  href="file:///F:/Doc/Struts2/docs/validation.html" title="Validation">Validation</a> messages.</p>
<h2><a name="Localization-ResourceBundleSearchOrder"></a>Resource Bundle Search Order</h2>
<p>Resource bundles are searched in the following order:</p>
<p>
</p>
<p>
</p>
<ol>
    <li>ActionClass.properties</li>
    <li>BaseClass.properties (all the way to Object.properties)</li>
    <li>Interface.properties (every interface and sub-interface)</li>
    <li>ModelDriven's model (if implements ModelDriven), for the model object repeat from 1</li>
    <li>package.properties (of the directory where class is located and every parent directory all the way to the root directory)</li>
    <li>search up the i18n message key hierarchy itself</li>
    <li>global resource properties</li>
</ol>
<p>For more, see the LocalizedTextUtil class.</p>
<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">Package hierarchy</strong><br>
            <p>To clarify #5, while traversing the package hierarchy, WW will look for a file package.properties:</p>
            <p>
            com/<br>
            &nbsp; acme/<br>
            &nbsp; &nbsp; package.properties<br>
            &nbsp; &nbsp; actions/<br>
            &nbsp; &nbsp; &nbsp; package.properties<br>
            &nbsp; &nbsp; &nbsp; FooAction.java<br>
            &nbsp; &nbsp; &nbsp; FooAction.properties<br>
            </p>
            <p>
            If FooAction.properties does not exist, com/acme/action/package.properties will be searched for, if
            not found com/acme/package.properties, if not found com/package.properties, etc.
            </p>
            </td>
        </tr>
    </tbody>
</table>
<h2><a name="Localization-Examples"></a>Examples</h2>
<p>There are several ways to access the message resources, including <tt>getText</tt>, the <tt>text</tt> tag, and the <tt>i18n</tt> tag.</p>
<h3><a name="Localization-Using{{getText}}"></a>Using <tt>getText</tt></h3>
<p>To display i18n text, use a call to <tt>getText</tt> in the <a  href="file:///F:/Doc/Struts2/docs/property.html" title="property">property</a> tag, or any other tag, such as the UI tags. (The <tt>getText</tt> technique is especially useful for labels of UI tags.)</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:property value=<span class="code-quote">"getText('some.key')"</span> /&gt;</span></pre>
</div>
</div>
<h3><a name="Localization-Usingthe{{text}}tag"></a>Using the <tt>text</tt> tag</h3>
<p>The <a  href="file:///F:/Doc/Struts2/docs/text.html" title="text">text</a> tag retrieves a message from the default resource bundle.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;-- Fourth Example --&gt;</span><br><span class="code-tag">&lt;s:text name=<span class="code-quote">"some.key"</span> /&gt;</span><br><br><span class="code-tag">&lt;-- Fifth Example --&gt;</span><br><span class="code-tag">&lt;s:text name=<span class="code-quote">"some.invalid.key"</span> &gt;</span><br>   The Default Message That Will Be Displayed<br><span class="code-tag">&lt;/s:text&gt;</span></pre>
</div>
</div>
<h3><a name="Localization-Usingthe{{I18n}}tag"></a>Using the <tt>I18n</tt> tag</h3>
<p>The <a  href="file:///F:/Doc/Struts2/docs/i18n.html" title="i18n">i18n</a>
tag pushes an arbitrary resource bundle on to the value stack. Other
tags within the scope of the i18n tag can display messages from that
resource bundle.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;s:i18n name=<span class="code-quote">"some.package.bundle"</span> &gt;</span><br>     <span class="code-tag">&lt;s:text name=<span class="code-quote">"some.key"</span> /&gt;</span><br><span class="code-tag">&lt;/s:i18n&gt;</span></pre>
</div>
</div>
<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>
            <p>Internationalizing SiteMesh decorators is possible, but there are quirks. See <a  href="file:///F:/Doc/Struts2/S2PLUGINS/sitemesh-plugin.html" title="Sitemesh Plugin">SiteMesh Plugin</a> for more.</p>
            </td>
        </tr>
    </tbody>
</table>
<h2><a name="Localization-I18nInterceptor"></a>I18n Interceptor</h2>
<p>Essentially, the i18n Interceptor pushes a locale into the
ActionContext map upon every request. The framework components that
support localization all utilize the ActionContext locale. See <a  href="file:///F:/Doc/Struts2/docs/i18n-interceptor.html" title="I18n Interceptor">I18n Interceptor</a> for details.</p>
<h2><a name="Localization-GlobalResources(struts.custom.i18n.resources)in{{struts.properties}}"></a>Global Resources (struts.custom.i18n.resources) in <tt>struts.properties</tt></h2>
<p>A global resource bundle could be specified programatically, as well as the locale.
</p>
<h2><a name="Localization-ComparisonwithStruts1"></a>Comparison with Struts 1</h2>
<p>Struts 1 users should be familiar with the application.properties
resource bundle, where you can put all the messages in the application
that are going to be translated. Struts 2, though, splits the resource
bundles per action or model class, and you may end up with duplicated
messages in those resource bundles. A quick fix for that is to create a
file called StrutsActionSupport.properties in org/apache/struts2 and
put it on your classpath. This will only work well if all your actions
subclass StrutsActionSupport.</p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113948.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:58 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113948.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Wildcard Mapping[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113945.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:53:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113945.html</guid><description><![CDATA[<p>As an application grows in size, so will the number of action
mappings. Wildcards can be used to combine similar mappings into one
more generic mapping.</p>
<p>The best way to explain wildcards is to show an example and walk
through how it works. This example modifies a conventional mapping to
use wildcards to match all pages that start with /edit:</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;!-- Generic edit* mapping --&gt;<br>&lt;action<br>    name=<span class="code-quote">"/edit*"</span><br>    class=<span class="code-quote">"org.apache.struts.webapp.example.Edit{1}Action"</span>&gt;<br>    &lt;result<br>        name=<span class="code-quote">"failure"</span><br>        path=<span class="code-quote">"/mainMenu.jsp"</span>/&gt;<br>    &lt;result<br>        path=<span class="code-quote">"/\{1\}.jsp"</span>/&gt;<br>&lt;/action&gt;</pre>
</div>
</div>
<p>The "*" in the path attribute allows the mapping to match the
request URIs /editSubscription, editRegistration, or any other URI that
starts with /edit, however /editSubscription/add would not be matched.
The part of the URI matched by the wildcard will then be substituted
into various attributes of the action mapping and its action results
replacing {1}. For the rest of the request, the framework will see the
action mapping and its action results containing the new values.</p>
<p>Mappings are matched against the request in the order they appear in
the framework's configuration file. If more than one pattern matches
the last one wins, so less specific patterns must appear before more
specific ones. However, if the request URL can be matched against a
path without any wildcards in it, no wildcard matching is performed and
order is not important.</p>
<p>Wildcard patterns can contain one or more of the following special tokens:<br>
* 	Matches zero or more characters excluding the slash ('/') character.<br>
** 	Matches zero or more characters including the slash ('/') character.<br>
\character 	The backslash character is used as an escape sequence. Thus * matches the character asterisk ('*'), and <br clear="all"> matches the character backslash ('<br clear="all">').</p>
<p>In the action mapping and action results, the wildcard-matched
values can be accessed with the token {N} where N is a number from 1 to
9 indicating which wildcard-matched value to substitute. The whole
request URI can be accessed with the {0} token.</p>
<p>Also, the action mapping properties (set using the &lt;set-property
key="foo" value="bar"&gt; syntax) will accept wildcard-matched strings
in their value attribute.</p>
<p>Like the action mapping, the action result properties (set using the
&lt;set-property key="foo" value="bar"&gt; syntax) will accept
wildcard-matched strings in their value attribute.</p>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/lightbulb_on.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> See also <a  href="file:///F:/Doc/Struts2/docs/action-configuration.html#ActionConfiguration-WildcardMethod" title="Wildcard Method on Action Configuration">Wildcard Method</a></p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:53 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: struts-default.xml[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113943.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:48:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113943.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>A base configuration file named <tt>struts-default.xml</tt> is included in the <tt>struts2.jar</tt> file. This file is automatically included into <tt>struts.xml</tt> file to  provide the standard configuration settings without having to copy them. </p>
<table class="tipMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td>To exclude the <tt>struts-default.xml</tt> or to provide your own version, see the <tt>struts.configuration.files</tt> setting in <a  href="file:///F:/Doc/Struts2/docs/strutsproperties.html" title="struts.properties">struts.properties</a>.</td>
        </tr>
    </tbody>
</table>
<p>The contents of struts-default.xml are here:</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span> ?&gt;</span><br><br>&lt;!DOCTYPE struts PUBLIC<br>    <span class="code-quote">"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"</span><br>    <span class="code-quote">"http://struts.apache.org/dtds/struts-2.0.dtd"</span>&gt;<br>    <br><span class="code-tag">&lt;struts&gt;</span><br>	<span class="code-tag">&lt;bean class=<span class="code-quote">"com.opensymphony.xwork2.ObjectFactory"</span> name=<span class="code-quote">"xwork"</span> /&gt;</span><br>	<span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.ObjectFactory"</span> name=<span class="code-quote">"struts"</span> class=<span class="code-quote">"org.apache.struts2.impl.StrutsObjectFactory"</span> /&gt;</span><br>	<br>	<span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.ActionProxyFactory"</span> name=<span class="code-quote">"xwork"</span> class=<span class="code-quote">"com.opensymphony.xwork2.DefaultActionProxyFactory"</span>/&gt;</span><br>	<span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.ActionProxyFactory"</span> name=<span class="code-quote">"struts"</span> class=<span class="code-quote">"org.apache.struts2.impl.StrutsActionProxyFactory"</span>/&gt;</span><br>	<br>	<span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.util.ObjectTypeDeterminer"</span> name=<span class="code-quote">"tiger"</span> class=<span class="code-quote">"com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer"</span>/&gt;</span><br>	<span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.util.ObjectTypeDeterminer"</span> name=<span class="code-quote">"notiger"</span> class=<span class="code-quote">"com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"</span>/&gt;</span><br>	<span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.util.ObjectTypeDeterminer"</span> name=<span class="code-quote">"struts"</span> class=<span class="code-quote">"com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer"</span>/&gt;</span><br>    <br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.ActionMapper"</span> name=<span class="code-quote">"struts"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.DefaultActionMapper"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.ActionMapper"</span> name=<span class="code-quote">"composite"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.CompositeActionMapper"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.ActionMapper"</span> name=<span class="code-quote">"restful"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.RestfulActionMapper"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.ActionMapper"</span> name=<span class="code-quote">"restful2"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.mapper.Restful2ActionMapper"</span> /&gt;</span><br>    <br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.dispatcher.multipart.MultiPartRequest"</span> name=<span class="code-quote">"struts"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest"</span> scope=<span class="code-quote">"default"</span> optional=<span class="code-quote">"true"</span>/&gt;</span><br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.dispatcher.multipart.MultiPartRequest"</span> name=<span class="code-quote">"jakarta"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest"</span> scope=<span class="code-quote">"default"</span> optional=<span class="code-quote">"true"</span> /&gt;</span><br>    <br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.views.TagLibrary"</span> name=<span class="code-quote">"s"</span> class=<span class="code-quote">"org.apache.struts2.views.DefaultTagLibrary"</span> /&gt;</span><br>    <br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.views.freemarker.FreemarkerManager"</span> name=<span class="code-quote">"struts"</span> optional=<span class="code-quote">"true"</span>/&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.views.velocity.VelocityManager"</span> name=<span class="code-quote">"struts"</span> optional=<span class="code-quote">"true"</span> /&gt;</span><br>    <br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.components.template.TemplateEngineManager"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.components.template.TemplateEngine"</span> name=<span class="code-quote">"ftl"</span> class=<span class="code-quote">"org.apache.struts2.components.template.FreemarkerTemplateEngine"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.components.template.TemplateEngine"</span> name=<span class="code-quote">"vm"</span> class=<span class="code-quote">"org.apache.struts2.components.template.VelocityTemplateEngine"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"org.apache.struts2.components.template.TemplateEngine"</span> name=<span class="code-quote">"jsp"</span> class=<span class="code-quote">"org.apache.struts2.components.template.JspTemplateEngine"</span> /&gt;</span><br><br>	<span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.util.XWorkConverter"</span> name=<span class="code-quote">"xwork1"</span> class=<span class="code-quote">"com.opensymphony.xwork2.util.XWorkConverter"</span> /&gt;</span>    <br>    <span class="code-tag">&lt;bean type=<span class="code-quote">"com.opensymphony.xwork2.util.XWorkConverter"</span> name=<span class="code-quote">"struts"</span> class=<span class="code-quote">"com.opensymphony.xwork2.util.AnnotationXWorkConverter"</span> /&gt;</span><br>    <br>    <span class="code-tag"><span class="code-comment">&lt;!--  Only have static injections --&gt;</span></span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"com.opensymphony.xwork2.util.OgnlValueStack"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.dispatcher.Dispatcher"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.components.Include"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.dispatcher.FilterDispatcher"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.views.util.ContextUtil"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.struts2.views.util.UrlHelper"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"com.opensymphony.xwork2.util.XWorkConverter"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>    <span class="code-tag">&lt;bean class=<span class="code-quote">"com.opensymphony.xwork2.ObjectFactory"</span> static=<span class="code-quote">"true"</span> /&gt;</span><br>	<br>    <span class="code-tag">&lt;package name=<span class="code-quote">"struts-default"</span>&gt;</span><br>        <span class="code-tag">&lt;result-types&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"chain"</span> class=<span class="code-quote">"com.opensymphony.xwork2.ActionChainResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"dispatcher"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.ServletDispatcherResult"</span> default=<span class="code-quote">"true"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"freemarker"</span> class=<span class="code-quote">"org.apache.struts2.views.freemarker.FreemarkerResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"httpheader"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.HttpHeaderResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"redirect"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.ServletRedirectResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"redirect-action"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.ServletActionRedirectResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"stream"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.StreamResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"velocity"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.VelocityResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"xslt"</span> class=<span class="code-quote">"org.apache.struts2.views.xslt.XSLTResult"</span>/&gt;</span><br>            <span class="code-tag">&lt;result-type name=<span class="code-quote">"plaintext"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.PlainTextResult"</span> /&gt;</span><br>        <span class="code-tag">&lt;/result-types&gt;</span><br><br>        <span class="code-tag">&lt;interceptors&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"alias"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.AliasInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"autowiring"</span> class=<span class="code-quote">"com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"chain"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ChainingInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"conversionError"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"createSession"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.CreateSessionInterceptor"</span> /&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"debugging"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.debugging.DebuggingInterceptor"</span> /&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"external-ref"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"execAndWait"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"exception"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"fileUpload"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.FileUploadInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"i18n"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.I18nInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"logger"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.LoggingInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"model-driven"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"scoped-model-driven"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ParametersInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"prepare"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.PrepareInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"static-params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"scope"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.ScopeInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"servlet-config"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.ServletConfigInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"sessionAutowiring"</span> class=<span class="code-quote">"org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"timer"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.TimerInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"token"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.TokenInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"token-session"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.TokenSessionStoreInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"validation"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"workflow"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"</span>/&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"store"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.MessageStoreInterceptor"</span> /&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"checkbox"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.CheckboxInterceptor"</span> /&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"profiling"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.ProfilingActivationInterceptor"</span> /&gt;</span><br>            <span class="code-tag">&lt;interceptor name=<span class="code-quote">"roles"</span> class=<span class="code-quote">"org.apache.struts2.interceptor.RolesInterceptor"</span> /&gt;</span><br>            <br>            <span class="code-tag"><span class="code-comment">&lt;!-- Basic stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"basicStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"exception"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"servlet-config"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"prepare"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"checkbox"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"conversionError"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample validation and workflow stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"validationWorkflowStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"validation"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"workflow"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample file upload stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"fileUploadStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"fileUpload"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample model-driven stack  --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"modelDrivenStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"model-driven"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample action chaining stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"chainStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"chain"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            <span class="code-tag"><span class="code-comment">&lt;!-- Sample i18n stack --&gt;</span></span><br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"i18nStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"i18n"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"basicStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            &lt;!-- An example of the params-prepare-params trick. This stack<br>                 is exactly the same as the defaultStack, except that it<br>                 includes one extra interceptor before the prepare interceptor:<br>                 the params interceptor.<br><br>                 This is useful for when you wish to apply parameters directly<br>                 to an object that you wish to load externally (such as a DAO<br>                 or database or service layer), but can't load that object<br>                 until at least the ID parameter has been loaded. By loading<br>                 the parameters twice, you can retrieve the object in the<br>                 prepare() method, allowing the second params interceptor to<br>                 apply the values on the object. --&gt;<br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"paramsPrepareParamsStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"exception"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"alias"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"servlet-config"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"prepare"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"i18n"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"chain"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"model-driven"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"fileUpload"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"checkbox"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"static-params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"conversionError"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"validation"</span>&gt;</span><br>                    <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel<span class="code-tag">&lt;/param&gt;</span><br>                <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"workflow"</span>&gt;</span><br>                    <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel<span class="code-tag">&lt;/param&gt;</span><br>                <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            &lt;!-- A complete stack with all the common interceptors in place.<br>                 Generally, this stack should be the one you use, though it<br>                 may do more than you need. Also, the ordering can be<br>                 switched around (ex: if you wish to have your servlet-related<br>                 objects applied before prepare() is called, you'd need to move<br>                 servlet-config interceptor up.<br><br>                 This stack also excludes from the normal validation and workflow<br>                 the method names input, back, and cancel. These typically are<br>                 associated with requests that should not be validated.<br>                 --&gt;<br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"defaultStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"exception"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"alias"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"servlet-config"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"prepare"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"i18n"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"chain"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"debugging"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"profiling"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"scoped-model-driven"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"model-driven"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"fileUpload"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"checkbox"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"static-params"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"params"</span>&gt;</span><br>                	<span class="code-tag">&lt;param name=<span class="code-quote">"excludeParams"</span>&gt;</span>dojo\..*<span class="code-tag">&lt;/param&gt;</span><br>                <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"conversionError"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"validation"</span>&gt;</span><br>                    <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel,browse<span class="code-tag">&lt;/param&gt;</span><br>                <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"workflow"</span>&gt;</span><br>                    <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel,browse<span class="code-tag">&lt;/param&gt;</span><br>                <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            &lt;!-- The completeStack is here for backwards compatibility for<br>                 applications that still refer to the defaultStack by the<br>                 old name --&gt;<br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"completeStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"defaultStack"</span>/&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><br>            &lt;!-- Sample execute and wait stack.<br>                 Note: execAndWait should always be the *last* interceptor. --&gt;<br>            <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"executeAndWaitStack"</span>&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"execAndWait"</span>&gt;</span><br>                    <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel<span class="code-tag">&lt;/param&gt;</span><br>                <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"defaultStack"</span>/&gt;</span><br>                <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"execAndWait"</span>&gt;</span><br>                    <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel<span class="code-tag">&lt;/param&gt;</span><br>                <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>            <span class="code-tag">&lt;/interceptor-stack&gt;</span><br>            <br>       <span class="code-tag">&lt;/interceptors&gt;</span><br>        <br>        <span class="code-tag">&lt;default-interceptor-ref name=<span class="code-quote">"defaultStack"</span>/&gt;</span><br>    <span class="code-tag">&lt;/package&gt;</span><br><br><span class="code-tag">&lt;/struts&gt;</span></pre>
</div>
</div>
<p>This file defines all of the default bundled results and
interceptors and many interceptor stacks which you can use either as-is
or as a basis for your own application-specific interceptor stacks. <strong>Notice the name of the package is "struts-default"</strong>.</p>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113943.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:48 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113943.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: struts.properties[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113942.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:46:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113942.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> All properties can also be set using <a  href="file:///F:/Doc/Struts2/docs/constant-configuration.html" title="Constant Configuration">Constant Configuration</a> in an XML configuration file.</p>
<p>The framework uses a number of properties that can be changed to fit
your needs. To change any of these properties, specify the property key
and value in an <tt>struts.properties</tt> file. The properties file can be locate anywhere on the classpath, but it is typically found under <tt>/WEB-INF/class</tt></p>
<p>The list of properties can be found in <tt>struts-default.properties</tt> (inside <tt>struts2.jar</tt>).</p>
<div class="panel">
<div class="panelHeader"><strong>struts-default.properties</strong></div>
<div class="panelContent">
<div class="code">
<div class="codeContent">
<pre class="code-none">### Struts default properties<br>###(can be overridden by a struts.properties file in the root of the classpath)<br>###<br><br>### Specifies the Configuration used to configure Struts <br>### one could extend org.apache.struts2.config.Configuration<br>### to build one's customize way of getting the configurations parameters into Struts<br># struts.configuration=org.apache.struts2.config.DefaultConfiguration<br><br>### This can be used to set your default locale and encoding scheme<br><span style="background-color: #ffbf00;"># struts.locale</span>=en_US<br><span style="background-color: #ffbf00;">struts.i18n.encoding</span>=UTF-8<br><br>### if specified, the default object factory can be overridden here<br>### Note: short-hand notation is supported in some cases, such as "spring"<br>###       Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here  <br><span style="background-color: #ffbf00;"># struts.objectFactory</span> = spring<br><br>### specifies the autoWiring logic when using the SpringObjectFactory.<br>### valid values are: name, type, auto, and constructor (name is the default)<br><span style="background-color: #ffbf00;">struts.objectFactory.spring.autoWire</span> = name<br><br>### indicates to the struts-spring integration if Class instances should be cached<br>### this should, until a future Spring release makes it possible, be left as true<br>### unless you know exactly what you are doing!<br>### valid values are: true, false (true is the default)<br><span style="background-color: #ffbf00;">struts.objectFactory.spring.useClassCache</span> = true<br><br>### if specified, the default object type determiner can be overridden here<br>### Note: short-hand notation is supported in some cases, such as "tiger" or "notiger"<br>###       Alternatively, you can provide a com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation name here<br>### Note: if you have the xwork-tiger.jar within your classpath, GenericsObjectTypeDeterminer is used by default<br>###       To disable tiger support use the "notiger" property value here.<br><span style="background-color: #ffbf00;">#struts.objectTypeDeterminer</span> = tiger<br><span style="background-color: #ffbf00;">#struts.objectTypeDeterminer </span>= notiger<br><br>### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data<br><span style="background-color: #ffbf00;"># struts.multipart.parser</span>=cos<br><span style="background-color: #ffbf00;"># struts.multipart.parser</span>=pell<br><span style="background-color: #ffbf00;">struts.multipart.parser</span>=jakarta<br># uses javax.servlet.context.tempdir by default<br><span style="background-color: #ffbf00;">struts.multipart.saveDir</span>=<br><span style="background-color: #ffbf00;">struts.multipart.maxSize</span>=2097152<br><br>### Load custom property files (does not override struts.properties!)<br><span style="background-color: #ffbf00;"># struts.custom.properties</span>=application,org/apache/struts2/extension/custom<br><br>### How request URLs are mapped to and from actions<br><span style="background-color: #ffbf00;">#struts.mapper.class</span>=org.apache.struts2.dispatcher.mapper.DefaultActionMapper<br><br>### Used by the DefaultActionMapper<br>### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do<br><span style="background-color: #ffbf00;">struts.action.extension</span>=action<br><br>### Used by FilterDispatcher<br>### If true then Struts serves static content from inside its jar. <br>### If false then the static content must be available at &lt;context_path&gt;/struts<br><span style="background-color: #ffbf00;">struts.serve.static</span>=true<br><br>### Used by FilterDispatcher<br>### This is good for development where one wants changes to the static content be<br>### fetch on each request. <br>### NOTE: This will only have effect if struts.serve.static=true<br>### If true -&gt; Struts will write out header for static contents such that they will<br>###             be cached by web browsers (using Date, Cache-Content, Pragma, Expires)<br>###             headers).<br>### If false -&gt; Struts will write out header for static contents such that they are<br>###            NOT to be cached by web browser (using Cache-Content, Pragma, Expires<br>###            headers)<br><span style="background-color: #ffbf00;">struts.serve.static.browserCache</span>=true<br><br>### Set this to false if you wish to disable implicit dynamic method invocation<br>### via the URL request. This includes URLs like foo!bar.action, as well as params<br>### like method:bar (but not action:foo). <br>### An alternative to implicit dynamic method invocation is to use wildcard <br>### mappings, such as &lt;action name="*/*" method="{2}" class="actions.{1}"&gt;<br><span style="background-color: #ffbf00;">struts.enable.DynamicMethodInvocation</span> = true<br><br>### Set this to true if you wish to allow slashes in your action names.  If false,<br>### Actions names cannot have slashes, and will be accessible via any directory<br>### prefix.  This is the traditional behavior expected of WebWork applications.<br>### Setting to true is useful when you want to use wildcards and store values<br>### in the URL, to be extracted by wildcard patterns, such as <br>### &lt;action name="*/*" method="{2}" class="actions.{1}"&gt; to match "/foo/edit" or <br>### "/foo/save".<br><span style="background-color: #ffbf00;">struts.enable.SlashesInActionNames </span>= false<br><br>### use alternative syntax that requires %{} in most places<br>### to evaluate expressions for String attributes for tags<br><span style="background-color: #ffbf00;">struts.tag.altSyntax</span>=true<br><br>### when set to true, Struts will act much more friendly for developers. This<br>### includes:<br>### - struts.i18n.reload = true<br>### - struts.configuration.xml.reload = true<br>### - raising various debug or ignorable problems to errors<br>###   For example: normally a request to foo.action?someUnknownField=true should<br>###                be ignored (given that any value can come from the web and it<br>###                should not be trusted). However, during development, it may be<br>###                useful to know when these errors are happening and be told of<br>###                them right away.<br><span style="background-color: #ffbf00;">struts.devMode</span> = false<br><br>### when set to true, resource bundles will be reloaded on _every_ request.<br>### this is good during development, but should never be used in production<br><span style="background-color: #ffbf00;">struts.i18n.reload</span>=false<br><br>### Standard UI theme<br>### Change this to reflect which path should be used for JSP control tag templates by default<br><span style="background-color: #ffbf00;">struts.ui.theme</span>=xhtml<br><span style="background-color: #ffbf00;">struts.ui.templateDir</span>=template<br>#sets the default template type. Either ftl, vm, or jsp<br><span style="background-color: #ffbf00;">struts.ui.templateSuffix</span>=ftl<br><br>### Configuration reloading<br>### This will cause the configuration to reload struts.xml when it is changed<br><span style="background-color: #ffbf00;">struts.configuration.xml.reload</span>=false<br><br>### Location of velocity.properties file.  defaults to velocity.properties<br><span style="background-color: #ffbf00;">struts.velocity.configfile</span> = velocity.properties<br><br>### Comma separated list of VelocityContext classnames to chain to the StrutsVelocityContext<br><span style="background-color: #ffbf00;">struts.velocity.contexts</span> =<br><br>### Location of the velocity toolbox<br><span style="background-color: #ffbf00;">struts.velocity.toolboxlocation</span>=<br><br>### used to build URLs, such as the UrlTag<br><span style="background-color: #ffbf00;">struts.url.http.port</span> = 80<br><span style="background-color: #ffbf00;">struts.url.https.port</span> = 443<br>### possible values are: none, get or all<br><span style="background-color: #ffbf00;">struts.url.includeParams</span> = get<br><br>### Load custom default resource bundles<br># <span style="background-color: #ffbf00;">struts.custom.i18n.resources</span>=testmessages,testmessages2<br><br>### workaround for some app servers that don't handle HttpServletRequest.getParameterMap()<br>### often used for WebLogic, Orion, and OC4J<br><span style="background-color: #ffbf00;">struts.dispatcher.parametersWorkaround</span> = false<br><br>### configure the Freemarker Manager class to be used<br>### Allows user to plug-in customised Freemarker Manager if necessary<br>### MUST extends off org.apache.struts2.views.freemarker.FreemarkerManager<br>#<span style="background-color: #ffbf00;">struts.freemarker.manager.classname</span>=org.apache.struts2.views.freemarker.FreemarkerManager<br><br>### See the StrutsBeanWrapper javadocs for more information<br><span style="background-color: #ffbf00;">struts.freemarker.wrapper.altMap</span>=true<br><br>### configure the XSLTResult class to use stylesheet caching.<br>### Set to true for developers and false for production.<br><span style="background-color: #ffbf00;">struts.xslt.nocache</span>=false<br><br>### A list of configuration files automatically loaded by Struts<br><span style="background-color: #ffbf00;">struts.configuration.files</span>=struts-default.xml,struts-plugin.xml,struts.xml<br><br>### Whether to always select the namespace to be everything before the last slash or not<br><span style="background-color: #ffbf00;">struts.mapper.alwaysSelectFullNamespace</span>=false</pre>
</div>
</div>
</div>
</div>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113942.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:46 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113942.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: web.xml[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113941.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:40:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113941.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>The <tt>web.xml</tt>
web application descriptor file represents the core of the Java web
application, so it is appropriate that it is also part of the core of
the Struts framework. In the <tt>web.xml</tt> file, Struts defines its
FilterDispatcher, the Servlet Filter class that initializes the Struts
framework and handles all requests. This filter can contain
initialization parameters that affect what, if any, additional
configuration files are loaded and how the framework should behave.</p>
<p>In addition to the FilterDispatcher, Struts also provides an
ActionCleanupFilter class that handles special cleanup tasks when other
filters, such as those used by Sitemesh, need access to an initialized
Struts framework.</p>
<h2><a name="web.xml-KeyInitializationParameters"></a>Key Initialization Parameters</h2>
<ul>
    <li><strong>config</strong> - a comma-delimited list of XML configuration files to load.</li>
    <li><strong>actionPackages</strong> - a comma-delimited list of Java packages to scan for Actions.</li>
    <li><strong>configProviders</strong> - a comma-delimited list of Java classes that implement the
    ConfigurationProvider interface that should be used for building the Configuration.</li>
    <li><strong>*</strong> - any other parameters are treated as framework constants.</li>
</ul>
<h2><a name="web.xml-SimpleExample"></a>Simple Example</h2>
<p>Configuring <tt>web.xml</tt> for the framework is a matter of adding a filter and filter-mapping.</p>
<div class="code">
<div class="codeHeader"><strong>FilterDispatcher Example (web.xml)</strong></div>
<div class="codeContent">
<pre class="code-xml">&lt;web-app id=<span class="code-quote">"WebApp_9"</span> version=<span class="code-quote">"2.4"</span> <br>	xmlns=<span class="code-quote">"http://java.sun.com/xml/ns/j2ee"</span> <br>	<span class="code-keyword">xmlns:xsi</span>=<span class="code-quote">"http://www.w3.org/2001/XMLSchema-instance"</span> <br>	xsi:schemaLocation=<span class="code-quote">"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"</span>&gt;<br><br>    <span class="code-tag">&lt;filter&gt;</span><br>        <span class="code-tag">&lt;filter-name&gt;</span>struts<span class="code-tag">&lt;/filter-name&gt;</span><br>        <span class="code-tag">&lt;filter-class&gt;</span>org.apache.struts2.dispatcher.FilterDispatcher<span class="code-tag">&lt;/filter-class&gt;</span><br>        <span class="code-tag">&lt;init-param&gt;</span><br>        	<span class="code-tag">&lt;param-name&gt;</span>actionPackages<span class="code-tag">&lt;/param-name&gt;</span><br>        	<span class="code-tag">&lt;param-value&gt;</span>com.mycompany.myapp.actions<span class="code-tag">&lt;/param-value&gt;</span><br>        <span class="code-tag">&lt;/init-param&gt;</span><br>    <span class="code-tag">&lt;/filter&gt;</span><br><br>    <span class="code-tag">&lt;filter-mapping&gt;</span><br>        <span class="code-tag">&lt;filter-name&gt;</span>struts<span class="code-tag">&lt;/filter-name&gt;</span><br>        <span class="code-tag">&lt;url-pattern&gt;</span>/*<span class="code-tag">&lt;/url-pattern&gt;</span><br>    <span class="code-tag">&lt;/filter-mapping&gt;</span><br><br>    <span class="code-tag"><span class="code-comment">&lt;!-- ... --&gt;</span></span><br><br><span class="code-tag">&lt;/web-app&gt;</span></pre>
</div>
</div>
<h2><a name="web.xml-TaglibExample"></a>Taglib Example </h2>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> Typically, configuring a taglib is neither required nor recommended. The taglib is included in <tt>struts-core.jar</tt>, and the container will discover it automatically.</p>
<p>If, for some reason, a taglib configuration is needed within web.xml, copy <tt>struts2-core/core/src/main/resources/META-INF/struts-tags.tld</tt> to the WEB-INF directory as <tt>struts-tags.tld</tt>. Then, add a <tt>taglib</tt> element to the <tt>web.xml</tt>.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- ... --&gt;</span></span><br>    <span class="code-tag">&lt;/welcome-file-list&gt;</span><br><br>    <span class="code-tag">&lt;taglib&gt;</span><br>       <span class="code-tag">&lt;taglib-uri&gt;</span>/s<span class="code-tag">&lt;/taglib-uri&gt;</span><br>       <span class="code-tag">&lt;taglib-location&gt;</span>/WEB-INF/struts-tags.tld<span class="code-tag">&lt;/taglib-location&gt;</span><br>    <span class="code-tag">&lt;/taglib&gt;</span><br><span class="code-tag">&lt;/web-app&gt;</span></pre>
</div>
</div>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:40 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Configuration files[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113939.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:37:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113939.html</guid><description><![CDATA[<p>From a Struts developer point of view, the one required configuration file used by the framework is <tt>web.xml</tt>.
From here, you have full control over how Struts configures both itself
and your application. By default, Struts will load a set of internal
configuration files to configure itself, then another set to configure
your application, however it is possible to build an entire Struts
application without writing a single configuration file other than <tt>web.xml</tt>.</p>
<p>The table lists the files that you can use to configure the
framework for your application. Some configuration files can be
reloaded dynamically. Dynamic reloading makes interactive development
possible. See <a  href="file:///F:/Doc/Struts2/docs/reloading-configuration.html" title="Reloading configuration">Reloading configuration</a> for more.</p>
<table class="confluenceTable">
    <tbody>
        <tr>
            <th class="confluenceTh"> File </th>
            <th class="confluenceTh"> Optional </th>
            <th class="confluenceTh"> Location (relative to webapp) </th>
            <th class="confluenceTh"> Purpose </th>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/webxml.html" title="web.xml">web.xml</a> </td>
            <td class="confluenceTd"> no </td>
            <td class="confluenceTd"> /WEB-INF/ </td>
            <td class="confluenceTd"> Web deployment descriptor to include all necessary framework components </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/strutsxml.html" title="struts.xml">struts.xml</a> </td>
            <td class="confluenceTd"> yes </td>
            <td class="confluenceTd"> /WEB-INF/classes/ </td>
            <td class="confluenceTd"> Main configuration, contains result/view types, action mappings, interceptors, and so forth <br clear="all"> </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/strutsproperties.html" title="struts.properties">struts.properties</a> </td>
            <td class="confluenceTd"> yes </td>
            <td class="confluenceTd"> /WEB-INF/classes/ </td>
            <td class="confluenceTd"> Framework properties </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/struts-defaultxml.html" title="struts-default.xml">struts-default.xml</a> </td>
            <td class="confluenceTd"> yes </td>
            <td class="confluenceTd"> /WEB-INF/lib/struts2-core.jar </td>
            <td class="confluenceTd"> Default configuration provided by Struts </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/struts-defaultvm.html" title="struts-default.vm">struts-default.vm</a> </td>
            <td class="confluenceTd"> yes </td>
            <td class="confluenceTd"> /WEB-INF/classes/ </td>
            <td class="confluenceTd"> Default macros referenced by <tt>velocity.properties</tt> </td>
        </tr>
        <tr>
            <td class="confluenceTd"> struts-plugin.xml </td>
            <td class="confluenceTd"> yes </td>
            <td class="confluenceTd"> At the root of a plugin JAR</td>
            <td class="confluenceTd"> Optional configuration files for <a  href="file:///F:/Doc/Struts2/docs/plugins.html" title="Plugins">Plugins</a> in the same format as <tt>struts.xml</tt>. </td>
        </tr>
        <tr>
            <td class="confluenceTd"> <a  href="file:///F:/Doc/Struts2/docs/velocityproperties.html" title="velocity.properties">velocity.properties</a> </td>
            <td class="confluenceTd"> yes </td>
            <td class="confluenceTd"> /WEB-INF/classes/ </td>
            <td class="confluenceTd"> Override the default <a  href="file:///F:/Doc/Struts2/docs/velocity.html" title="Velocity">Velocity</a> configuration </td>
        </tr>
    </tbody>
</table>
<h2><a name="ConfigurationFiles-StaticContent"></a>Static Content</h2>
<p>Common static content that is needed by the framework (JavaScript
and CSS files, etc.) is served automatically by the FilterDispatcher
filter. Any request starting with "<tt>/struts/</tt>" denotes that static content is required, and then mapping the value after "<tt>/struts/</tt>" to common packages in the framework and, optionally in the application's class path.</p>
<p>By default, the following packages are searched:</p>
<ul class="alternate" type="square">
    <li>org.apache.struts2.static</li>
    <li>template</li>
</ul>
<p>Additional packages can be specified by providing a comma separated
list to the configuration parameter named "packages" (configured in
web.xml for the FilterDispatcher filter). When specifying additional
static content, you should be careful not to expose sensitive
configuration information (such as the password to a database).</p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113939.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:37 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113939.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Exception Config[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113935.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:31:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113935.html</guid><description><![CDATA[<p>Exception mappings is a powerful feature for dealing with an Action
class that throws an Exception. The core idea is that an Exception
thrown during the Action method can be automatically caught and mapped
to a predefined Result. This declarative strategy is especially useful
for frameworks, like Hibernate and Acegi, that throw RuntimeExceptions.</p>
<p><span style="background-color: #007006;">Exception 映射是一个强大的功能，用来处理Action类抛出一个Exception。核心是一个Exceptio你在Action期间异常被自动抓取，并且映射到预先定义好的结果。这个声明方式的策略对framework相当有用，例如Hibernate和Acegi，他们抛出RuntimeException。</span><br></p>
<p>As with many other parts of the framework, an Interceptor is needed
to activate the exception mapping functionality. Below is a snippet
from <tt>struts-default.xml</tt> which has the exception mapping already activated.</p>
<p><span style="background-color: #007006;">与框架其他部分类似，一个Interceptor用来激活exception mappingfunctionality.下面是struts-default.xml的代码片断，在它里面exception映射已经被激活。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>snippet of struts-default.xml</strong></div>
<div class="codeContent">
<pre class="code-xml">...<br><span class="code-tag">&lt;interceptors&gt;</span><br>    ...<br>    <span class="code-tag">&lt;interceptor name=<span class="code-quote">"exception"</span> class=<span class="code-quote">"com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"</span>/&gt;</span><br>    ...<br><span class="code-tag">&lt;/interceptors&gt;</span><br><br><span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"defaultStack"</span>&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"exception"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"alias"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"servlet-config"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"prepare"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"i18n"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"chain"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"debugging"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"profiling"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"scoped-model-driven"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"model-driven"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"fileUpload"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"checkbox"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"static-params"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"params"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"conversionError"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"validation"</span>&gt;</span><br>        <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel,browse<span class="code-tag">&lt;/param&gt;</span><br>    <span class="code-tag">&lt;/interceptor-ref&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"workflow"</span>&gt;</span><br>        <span class="code-tag">&lt;param name=<span class="code-quote">"excludeMethods"</span>&gt;</span>input,back,cancel,browse<span class="code-tag">&lt;/param&gt;</span><br>    <span class="code-tag">&lt;/interceptor-ref&gt;</span><br><span class="code-tag">&lt;/interceptor-stack&gt;</span><br>...</pre>
</div>
</div>
<p>To use exception mapping, we simply need to map Exceptions to
specific Results. The framework provides two ways to declare an
exception mapping <tt>&lt;exception-mapping/&gt;</tt> - globally or for a specific action mapping. The exception mapping element takes two attributes, <tt>exception</tt> and <tt>result</tt>.</p>
<p><span style="background-color: #007006;">用Exception映射，我们简单地需要映射Exception到特定的结果。框架提供两种方式申明一个Exception映射&lt;exception-mapping&gt;-全局或特定的Action映射。Exception映射元素使用两种属性，exception和result。</span><br></p>
<p>When declaring an exception mapping, the Interceptor will find the
closest class inheritance match between the Exception thrown and the
Exception declared. The Interceptor will examine all declared mappings
applicable to the action mapping, first local and then global mappings.
If a match is found, the Result is processed, just as if it had been
returned by the Action.</p>
<p><span style="background-color: #007006;">当声明一个exception映射，Interceptor将寻找最近的类继承关系来在Exception throw和Exception声明之间匹配。首先找local，然后找全局。如果找到匹配，结果将会被处理，就像它被Action处理返回一样。</span><br></p>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16">
This process follows the same rules as a Result returned from an
Action. It first looks for the Result in the local action mapping, and
if not found, it looks for a global Result.</p>
<p>Below is an example of global and local exception mappings.</p>
<div class="code">
<div class="codeHeader"><strong>snippet from struts.xml</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;struts&gt;</span><br>    <span class="code-tag">&lt;package name=<span class="code-quote">"default"</span>&gt;</span><br>        ...<br>        <span class="code-tag">&lt;global-results&gt;</span><br>            <span class="code-tag">&lt;result name=<span class="code-quote">"login"</span> type=<span class="code-quote">"redirect"</span>&gt;</span>/Login.action<span class="code-tag">&lt;/result&gt;</span><br>            <span class="code-tag">&lt;result name=<span class="code-quote">"Exception"</span>&gt;</span>/Exception.jsp<span class="code-tag">&lt;/result&gt;</span><br>        <span class="code-tag">&lt;/global-results&gt;</span><br><br>        <span class="code-tag">&lt;global-exception-mappings&gt;</span><br>            <span class="code-tag">&lt;exception-mapping exception=<span class="code-quote">"java.sql.SQLException"</span> result=<span class="code-quote">"SQLException"</span>/&gt;</span><br>            <span class="code-tag">&lt;exception-mapping exception=<span class="code-quote">"java.lang.Exception"</span> result=<span class="code-quote">"Exception"</span>/&gt;</span><br>        <span class="code-tag">&lt;/global-exception-mappings&gt;</span><br>        ...<br>        <span class="code-tag">&lt;action name=<span class="code-quote">"DataAccess"</span> class=<span class="code-quote">"com.company.DataAccess"</span>&gt;</span><br>            <span class="code-tag">&lt;exception-mapping exception=<span class="code-quote">"com.company.SecurityException"</span> result=<span class="code-quote">"login"</span>/&gt;</span><br>            <span class="code-tag">&lt;result name=<span class="code-quote">"SQLException"</span> type=<span class="code-quote">"chain"</span>&gt;</span>SQLExceptionAction<span class="code-tag">&lt;/result&gt;</span><br>            <span class="code-tag">&lt;result&gt;</span>/DataAccess.jsp<span class="code-tag">&lt;/result&gt;</span><br>        <span class="code-tag">&lt;/action&gt;</span><br>        ...<br>    <span class="code-tag">&lt;/package&gt;</span><br><span class="code-tag">&lt;/xwork&gt;</span></pre>
</div>
</div>
<p>In the example above, here is what happens based upon each Exception:</p>
<ul>
    <li>A <tt>java.sql.SQLException</tt> will chain to the <tt>SQLExceptionAction</tt> (action mapping not shown)</li>
    <li>A <tt>com.company.SecurityException</tt> will redirect to <tt>Login.action</tt></li>
    <li>Any other exception that extends <tt>java.lang.Exception</tt> will return the <tt>/Exception.jsp</tt> page</li>
</ul>
<h2><a name="ExceptionConfiguration-ExceptionValuesontheValueStack"></a>Exception Values on the ValueStack</h2>
<p>By default, the <tt>ExceptionMappingInterceptor</tt> adds the following values to the Value Stack:</p>
<table class="confluenceTable">
    <tbody>
        <tr>
            <th class="confluenceTh"> exception </th>
            <td class="confluenceTd"> The exception object itself </td>
        </tr>
        <tr>
            <th class="confluenceTh"> exceptionStack </th>
            <td class="confluenceTd"> The value from the stack trace</td>
        </tr>
    </tbody>
</table>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113935.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:31 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113935.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Result Config[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113928.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 15:12:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113928.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>When an <a  href="file:///F:/Doc/Struts2/docs/action.html" title="action">Action</a>
class method completes, it returns a String. The value of the String is
used to select a result element. An action mapping will often have a
set of results representing different possible outcomes. A standard set
of result tokens are defined by the ActionSupport base class.</p>
<p><span style="background-color: #0010ff;">当一个Action类方法完成以后，他返回一个String。这个String值用来选择结果元素。一个Action映射可能有一系列的结果来展示不同的可能输出。有一系列标准的结果令牌被ActionSupport类定义。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Predefined result names</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-object">String</span> SUCCESS = <span class="code-quote">"success"</span>;<br><span class="code-object">String</span> NONE    = <span class="code-quote">"none"</span>;<br><span class="code-object">String</span> ERROR   = <span class="code-quote">"error"</span>;<br><span class="code-object">String</span> INPUT   = <span class="code-quote">"input"</span>;<br><span class="code-object">String</span> LOGIN   = <span class="code-quote">"login"</span>;</pre>
</div>
</div>
<p>Of course, applications can define other result tokens to match specific cases.</p>
<h2><a name="ResultConfiguration-ResultElements"></a>Result Elements</h2>
<p>The result element has two jobs. First, it provides a logical name.
An Action can pass back a token like "success" or "error" without
knowing any other implementation details. Second, the result element
provides a Result Type. Most results simply forward to a server page or
template, but other <a  href="file:///F:/Doc/Struts2/docs/result-types.html" title="Result Types">Result Types</a> can be used to do more interesting things.</p>
<p><span style="background-color: #0010ff;">Result元素有两个任务，第一，提供了一个逻辑名，一个action能返回类似&#8220;success&#8221;或&#8220;error&#8221;，其实并不知道任何其他细节信息。第二，result元素提供了一个Result Type。大多数的result仅仅表明转入一个serverpage或template，但是其他类型的Result Type能被用来做更加有用的事情。</span><br></p>
<h3><a name="ResultConfiguration-IntelligentDefaults"></a>Intelligent Defaults</h3>
<p>A default Result Type can be set as part of the configuration for
each package. If one package extends another, the "child" package can
set its own default result, or inherit one from the parent.</p>
<div class="code">
<div class="codeHeader"><strong>Setting a default Result Type</strong></div>
<div class="codeContent">
<pre class="code-java">&lt;result-types&gt;<br> &lt;result-type name=<span class="code-quote">"dispatcher"</span> class=<span class="code-quote">"org.apache.struts2.dispatcher.ServletDispatcherResult"</span> <br>  <span class="code-keyword">default</span>=<span class="code-quote">"<span class="code-keyword">true</span>"</span>/&gt;<br>&lt;/result-types&gt;</pre>
</div>
</div>
<p>If a <tt>type</tt> attribute is not specified, the framework will use the <tt>dispatcher</tt>. The default Result Type, <tt>dispatcher</tt>,
forwards to another web resource. If the resource is a JavaServer Page,
then the container will render it, using its JSP engine.</p>
<p>Likewise if the <tt>name</tt> attribute is not specified, the framework will give it the name "success".</p>
<p>Using these intelligent defaults, the most often used result types also become the simplest.</p>
<div class="code">
<div class="codeHeader"><strong>Result element without defaults</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;result name=<span class="code-quote">"success"</span> type=<span class="code-quote">"dispatcher"</span>&gt;</span><br>    <span class="code-tag">&lt;param name=<span class="code-quote">"location"</span>&gt;</span>/ThankYou.jsp<span class="code-tag">&lt;/param&gt;</span><br><span class="code-tag">&lt;/result&gt;</span></pre>
</div>
</div>
<div class="code">
<div class="codeHeader"><strong>A Result element using some defaults</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;result&gt;</span><br>    <span class="code-tag">&lt;param name=<span class="code-quote">"location"</span>&gt;</span>/ThankYou.jsp<span class="code-tag">&lt;/param&gt;</span><br><span class="code-tag">&lt;/result&gt;</span></pre>
</div>
</div>
<p>The <tt>param</tt> tag sets a property on the Result object. The most commonly-set property is <tt>location</tt>, which usually specifies the path to a web resources. The <tt>param</tt> attribute is another intelligent default.</p>
<div class="code">
<div class="codeHeader"><strong>Result element using more defaults</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;result&gt;</span>/ThankYou.jsp<span class="code-tag">&lt;/result&gt;</span></pre>
</div>
</div>
<p>Mixing results with intelligent defaults with other results makes it easier to see the "critical path".</p>
<div class="code">
<div class="codeHeader"><strong>Multiple Results</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;action name=<span class="code-quote">"Hello"</span>&gt;</span><br>  <span class="code-tag">&lt;result&gt;</span>/hello/Result.jsp<span class="code-tag">&lt;/result&gt;</span><br>  <span class="code-tag">&lt;result name=<span class="code-quote">"error"</span>&gt;</span>/hello/Error.jsp<span class="code-tag">&lt;/result&gt;</span><br>  <span class="code-tag">&lt;result name=<span class="code-quote">"input"</span>&gt;</span>/hello/Input.jsp<span class="code-tag">&lt;/result&gt;</span><br><span class="code-tag">&lt;/action&gt;</span></pre>
</div>
</div>
<h2><a name="ResultConfiguration-GlobalResults"></a>Global Results</h2>
<p>Most often, results are nested with the action element. But some
results apply to multiple actions. In a secure application, a client
might try to access a page without being authorized, and many actions
may need access to a "logon" result.</p>
<p>If actions need to share results, a set of global results can be
defined for each package. The framework will first look for a local
result nested in the action. If a local match is not found, then the
global results are checked.</p>
<div class="code">
<div class="codeHeader"><strong>Defining global results</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;global-results&gt;</span><br>  <span class="code-tag">&lt;result name=<span class="code-quote">"error"</span>&gt;</span>/Error.jsp<span class="code-tag">&lt;/result&gt;</span><br>  <span class="code-tag">&lt;result name=<span class="code-quote">"invalid.token"</span>&gt;</span>/Error.jsp<span class="code-tag">&lt;/result&gt;</span><br>  <span class="code-tag">&lt;result name=<span class="code-quote">"login"</span> type=<span class="code-quote">"redirect-action"</span>&gt;</span>Logon!input<span class="code-tag">&lt;/result&gt;</span><br><span class="code-tag">&lt;/global-results&gt;</span></pre>
</div>
</div>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/lightbulb_on.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> For more about results, see <a  href="file:///F:/Doc/Struts2/docs/result-types.html" title="Result Types">Result Types</a>.</p>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 23:12 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Action Config[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113924.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 14:58:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113924.html</guid><description><![CDATA[<p>The action mappings are the basic "unit-of-work" in the framework.
Essentially, the action maps an identifier to a handler class. When a
request matches the action's name, the framework uses the mapping to
determine how to process the request.</p>
<p><span style="background-color: #0010ff;">Action映射是框架的最基本的工作单元，本质上，action映射一个id到处理类，当一个请求匹配action名称，框架用映射来决定怎样处理这个请求。</span><br></p>
<h2><a name="ActionConfiguration-ActionMappings"></a>Action Mappings</h2>
<p>The action mapping can specify a set of result types, a set of exception handlers, and an interceptor stack. But, only the <tt>name</tt> attribute is required. The other attributes can also be provided at package scope.</p>
<p>Action映射能够描述N多的result type，n多的Exception handle，和一个interceptor栈，但是，只有name属性是需要的，其他属性也能够在package级别提供。<br></p>
<div class="code">
<div class="codeHeader"><strong>A Logon Action</strong></div>
<div class="codeContent">
<pre class="code-java">&lt;action name=<span class="code-quote">"Logon"</span> class=<span class="code-quote">"tutorial.Logon"</span>&gt;<br>  &lt;result type=<span class="code-quote">"redirect-action"</span>&gt;Menu&lt;/result&gt;<br>  &lt;result name=<span class="code-quote">"input"</span>&gt;/tutorial/Logon.jsp&lt;/result&gt;<br>&lt;/action&gt;</pre>
</div>
</div>
<h2><a name="ActionConfiguration-ActionNames"></a>Action Names</h2>
<p>In a web application, the <tt>name</tt> attribute is matched a part
of the location requested by a browser (or other HTTP client). The
framework will drop the host and application name and the extension,
and match what's in the middle. So, a request for <tt><span class="nobr"><a  href="http://www.planetstruts.org/struts2-mailreader/Welcome.do" title="Visit page outside confluence" rel="nofollow">http://www.planetstruts.org/struts2-mailreader/Welcome.do<sup><img  src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span></tt> will map to the <tt>Welcome</tt> action.</p>
<p><span style="background-color: #0010ff;">在一个Web应用中，name属性匹配来自浏览器的一系列本地请求。框架能够去掉主机和应用名，以及扩展名，来比配中间的那个名称，所以请求.....将映射Welcome Action。</span><br></p>
<p>Within an application, the link to an action is usually generated by
a Struts Tag. The tag can specify the action by name, and the framework
will render the default extension and anything else that is needed.</p>
<p>在一个应用里面，action的link通常有StrutsTag产生，tag能够用名字描述，框架将渲染默认扩展和其他它需要的任何东西。<br></p>
<div class="code">
<div class="codeHeader"><strong>A Hello Form</strong></div>
<div class="codeContent">
<pre class="code-java">&lt;s:form action=<span class="code-quote">"Hello"</span>&gt;<br>    &lt;s:textfield label=<span class="code-quote">"Please enter your name"</span> name=<span class="code-quote">"name"</span>/&gt;<br>    &lt;s:submit/&gt;<br>&lt;/s:form&gt;</pre>
</div>
</div>
<table class="infoMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">Action Names With Slashes</strong><br>
            <p>If your action names have slashes in them (for example, <tt>&lt;action name="admin/home" class="tutorial.Admin"/&gt;</tt>) you need to specifically enable that functionality via the <tt>struts.xml</tt> file by specifying <tt>&lt;constant name="struts.enable.SlashesInActionNames" value="true"/&gt;</tt>. See <span class="nobr"><a  href="https://issues.apache.org/struts/browse/WW-1383" title="Visit page outside confluence" rel="nofollow">JIRA Issue WW-1383<sup><img  src="http://cwiki.apache.org/confluence/images/icons/linkext7.gif" class="rendericon" alt="" align="absmiddle" border="0" height="7" width="7"></sup></a></span> for discussion as there are side effects to setting this property to <tt>true</tt>.</p>
            </td>
        </tr>
    </tbody>
</table>
<h2><a name="ActionConfiguration-ActionMethods"></a>Action Methods</h2>
<p>The default entry method to the handler class is defined by the Action interface.</p>
<p><span style="background-color: #0010ff;">Handler类的默认入口方法被定义在Action 接口里。</span><br></p>
<div class="code">
<div class="codeHeader"><strong>Action interface</strong></div>
<div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-keyword">interface</span> Action {<br>    <span class="code-keyword">public</span> <span class="code-object">String</span> execute() <span class="code-keyword">throws</span> Exception;<br>}</pre>
</div>
</div>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> Implementing the Action interface is optional. If Action is not implemented, the framework will use reflection to look for an <tt>execute</tt> method.</p>
<p><span style="background-color: #0010ff;">实现Action接口是可选的，如果没有实现，框架自动用反射技术来搜寻execute方法。</span><br></p>
<p>Sometimes, developers like to create more than one entry point to an
Action. For example, in the case of of a data-access Action, a
developer might want separate entry-points for <tt>create</tt>, <tt>retrieve</tt>, <tt>update</tt>, and <tt>delete</tt>. A different entry point can be specified by the <tt>method</tt> attribute.</p>
<p><span style="background-color: #0010ff;">有时，在Action里，开发者喜欢创建多于一个入口，例如，在data-access Action案例中，一个developer可能象区分Create，retrieve，update和delete等各种入口点。一个不同的入口点可以被教书在method属性中。</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;action name=<span class="code-quote">"delete"</span> class=<span class="code-quote">"example.CrudAction"</span> method=<span class="code-quote">"delete"</span>&gt;</span></pre>
</div>
</div>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> If there is no <tt>execute</tt> method, and no other method, specified in the configuration, the framework will throw an exception.</p>
<p><br></p>
<h2><a name="ActionConfiguration-WildcardMethod"></a>Wildcard Method</h2>
<p>Many times, a set of action mappings will share a common pattern. For example, all your <tt>edit</tt> actions might start with the word "edit", and call the <tt>edit</tt> method on the Action class. The <tt>delete</tt> actions might use the same pattern, but call the <tt>delete</tt> method instead.</p>
<p><span style="background-color: #0010ff;">很多时候，一系列的action因设将给一个通用模式共用，例如，你的所有edit action可能用&#8220;edit&#8221;开头，调用Action里的ecit方法。Delete Action可能用同样的方式，调用所有delete方法。</span><br> </p>
<p>Rather than code a separate mapping for each action class that uses this pattern, you can write it once as a wildcard mapping.</p>
<p><span style="background-color: #0010ff;">不用为每个action以同样的模式写映射，你可以以疲惫符的方式只写一遍。</span><br> </p>
<p><br>
&lt;action name="*Crud" class="example.Crud" method="{1}"&gt;<br><br></p>
<p>Here, a reference to "editCrud" will call the <tt>edit</tt> method on an instance of the Crud Action class. Likewise, a reference to "deleteCrud" will call the <tt>delete</tt> method instead. </p>
<p>Another common approach is to postfix the method name and set it off
with an exclamation point (aka "bang"), underscore, or other special
character.</p>
<p><span style="background-color: #0010ff;">另一个通用的方式是使用前缀</span><br> </p>
<ul>
    <li>"action=Crud_input"</li>
    <li>"action=Crud_delete"</li>
</ul>
<p>To use a postfix wildcard, just move the asterisk and add an underscore.<br><br>
&lt;action name="Crud_*" class="example.Crud" method="{1}"&gt;<br></p>
<p>From the framework's perspective, a wildcard mapping creates a new
"virtual" mapping with all the same attributes as a conventional,
static mapping. As a result, you can use the expanded wildcard name as
the name of validation, type conversion, and localization files, just
as if it were an Action name (which it is!). </p>
<ul>
    <li><tt>Crud_input-validation.xml</tt></li>
    <li><tt>Crud_delete-conversion.xml</tt></li>
</ul>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/forbidden.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> The postfix "!" notation is also available in WebWork 2, but it is implemented differently. To use the old implementation, set <tt>struts.enable.DynamicMethodInvocation=TRUE</tt> in the <tt>struts.properties</tt> file. To use wildcards instead (preferred), set <tt>struts.enable.DynamicMethodInvocation=FALSE</tt>. </p>
<h2><a name="ActionConfiguration-ActionSupportDefault"></a>ActionSupport Default</h2>
<p>If the class attribute in an action mapping is left blank, the <tt>com.opensymphony.xwork.ActionSupport</tt> class is used as a default.</p>
<p><span style="background-color: #0010ff;">如果不写class属性，com.opensymphony.xwork.actionSupport类默认被使用。</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;action name=<span class="code-quote">"Hello"</span>&gt;<br>   <span class="code-comment">// ...<br></span>&lt;/action&gt;</pre>
</div>
</div>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> The ActionSupport class has <tt>execute</tt> and <tt>input</tt> methods that return "success".</p>
<p><span style="background-color: #0010ff;">ActionSupport类有execute和input方法，并且都返回"success".</span><br></p>
<p>
<img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/information.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> To specify a different class as the default Action, set the&nbsp; package attribute.</p>
<p><span style="background-color: #0010ff;">设置package的attribute，可以指定其他类为默认Action</span><br> </p>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/lightbulb_on.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> For more about using wildcards, see <a  href="file:///F:/Doc/Struts2/docs/wildcard-mappings.html" title="Wildcard Mappings">Wildcard Mappings</a>.</p>
<h2><a name="ActionConfiguration-PostBackDefault"></a>Post-Back Default</h2>
<p>A good practice is to link to actions rather than pages. Linking to
actions encapsulates which server page renders, and ensures that an
Action class can fire before a page renders. </p>
<p>Another common workflow stategy is to first render a page using an alternate method, like <tt>input</tt> and then have it submit back to the default <tt>execute</tt> method. </p>
<p>Using these two strategies together creates an opportunity to use a
"post-back" form that doesn't specify an action. The form simply
submits back to the action that created it.</p>
<span style="background-color: #0010ff;">一个最佳实践是链接一个action而不是page，链接到一个被server page渲染器包装的action，确保页面渲染之前，action类能被渲染。<br>另一个通常的工作流策略是用一个变通的方法渲染页面，例如input，然后使它提交返回到默认的execute方法。<br>把这两中策略结合起来，创建一个条件来使用没有action的&#8220;Post-back&#8221; Form，那个Form简单地返回创建它的他个action。</span><br>
<p>&#160;</p>
<br>
<div class="code">
<div class="codeHeader"><strong>Posting Back</strong></div>
<div class="codeContent">
<pre class="code-java">&lt;s:form&gt;<br>    &lt;s:textfield label=<span class="code-quote">"Please enter your name"</span> name=<span class="code-quote">"name"</span>/&gt;<br>    &lt;s:submit/&gt;<br>&lt;/s:form&gt;</pre>
</div>
</div>
<h2><a name="ActionConfiguration-ActionDefault"></a>Action Default</h2>
<p>Usually, if an action is requested, and the framework can't map the
request to an action name, the result will be the usual "404 - Page not
found" error. But, if you would prefer that an ominbus action handle
any unmatched requests, you can specify a default action. If no other
action matches, the default action is used instead.</p>
<p><span style="background-color: #0010ff;">通常，如果一个action被请求，而fromework不能映射那个请求到一个action名字，结果通常使一个&#8220;404－Page not found &#8221;错误。但是，如果你更热衷于一个能处理任何不匹配请求的万能action，你能描述一个默认的action。如果没有其他action匹配，默认的action被使用。</span><br></p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;package name=<span class="code-quote">"Hello"</span> extends=<span class="code-quote">"action-default"</span>&gt;</span><br><br><span class="code-tag">&lt;default-action-ref name=<span class="code-quote">"UnderConstruction"</span>&gt;</span><br><br><span class="code-tag">&lt;action name=<span class="code-quote">"UnderConstruction"</span>&gt;</span><br>  <span class="code-tag">&lt;result&gt;</span>/UnderConstruction.jsp<span class="code-tag">&lt;/result&gt;</span><br><span class="code-tag">&lt;/action&gt;</span></pre>
</div>
</div>
<p>There are no special requirements for the default action. Each
package can have its own default action, but there should only be one
default action per namespace.</p>
<table class="warningMacro" align="center" border="0" cellpadding="5" cellspacing="8" width="85%">
    <colgroup><col width="24"><col></colgroup>
    <tbody>
        <tr>
            <td valign="top"><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/forbidden.gif" alt="" align="absmiddle" border="0" height="16" width="16"></td>
            <td><strong class="strong">One to a Namespace</strong><br>
            <p>The default action features should be setup so that there is only
            one default action per namespace. If you have multiple packages
            declaring a default action with the same namespace, there is no
            guarantee which action will be the default.</p>
            </td>
        </tr>
    </tbody>
</table>
<h3><a name="ActionConfiguration-WildcardDefault"></a>Wildcard Default </h3>
<p>Using wildcards is another approach to default actions. A wildcard
action at the end of the configuration can be used to catch unmatched
references. </p>
<div class="code">
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;action name=<span class="code-quote">"*"</span> &gt;</span><br>  <span class="code-tag">&lt;result&gt;</span>/{1}.jsp<span class="code-tag">&lt;/result&gt;</span><br><span class="code-tag">&lt;/action&gt;</span></pre>
</div>
</div>
<p>When a new action is needed, just add a stub page.</p>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 22:58 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Interceptor Config[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113920.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 14:14:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113920.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>Interceptors allow you to define code to be executed before and/or
after the execution of an Action method. (The "Filter" pattern.)
Interceptors can be a powerful tool when developing applications. There
are many, many use cases for Interceptors, including validation,
property population, security, logging, and profiling.</p>
<p><span style="background-color: #00088e;">Interceptors 允许你定义代码在Action方法前或后来执行。当发布应用的时候，Interceptor是个强大的工具，它们能被用在很多很多的案例下，包括validation，peroperty population，security，logging，和 profiling。</span><br></p>
<table class="confluenceTable">
    <tbody>
        <tr>
            <th class="confluenceTh"> Validation </th>
            <td class="confluenceTd"> Examine input for correctness </td>
        </tr>
        <tr>
            <th class="confluenceTh"> Property Population </th>
            <td class="confluenceTd"> Transfer and convert input to object properties </td>
        </tr>
        <tr>
            <th class="confluenceTh"> Logging </th>
            <td class="confluenceTd"> Journal details regarding each action </td>
        </tr>
        <tr>
            <th class="confluenceTh"> Profiling </th>
            <td class="confluenceTd"> Time action throughput, looking for performance bottlenecks </td>
        </tr>
    </tbody>
</table>
<p>Interceptors can be chained together to create an Interceptor
"Stack". If an action neeeds to check the client's credentials, log the
action, and time the action, all of these routines, and more, could be
made part of the same Interceptor Stack.</p>
<p>Interceptors are implemented as Java classes, and so each
Interceptor has a unique class name. To make it easier to reference
Interceptors, each class can be registered with the framework and given
a simpler name.</p>
<div class="code">
<div class="codeHeader"><strong>Registering Interceptors</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;interceptors&gt;</span><br>  <span class="code-tag">&lt;interceptor name=<span class="code-quote">"security"</span> class=<span class="code-quote">"com.company.security.SecurityInterceptor"</span>/&gt;</span><br>  <span class="code-tag">&lt;interceptor-stack name=<span class="code-quote">"secureStack"</span>&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"security"</span>/&gt;</span><br>    <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"defaultStack"</span>/&gt;</span><br>  <span class="code-tag">&lt;/interceptor-stack&gt;</span><br><span class="code-tag">&lt;/interceptors&gt;</span></pre>
</div>
</div>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16">
Individual Interceptors and Interceptors Stacks can be "mixed and
matched" in any order when defining an Interceptor Stack. The framework
will invoke each Interceptor on the stack in the order it is defined.</p>
<p>Most applications will define a default Interceptor Stack,</p>
<p><tt>&lt;default-interceptor-ref name="secureStack"/&gt;</tt></p>
<p>but each action can also define it's own local stack.</p>
<div class="code">
<div class="codeHeader"><strong>A local Interceptor Stack</strong></div>
<div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;action name=<span class="code-quote">"VelocityCounter"</span> class=<span class="code-quote">"org.apache.struts2.example.counter.SimpleCounter"</span>&gt;</span><br>   <span class="code-tag">&lt;result name=<span class="code-quote">"success"</span>&gt;</span>...<span class="code-tag">&lt;/result&gt;</span><br>   <span class="code-tag">&lt;interceptor-ref name=<span class="code-quote">"defaultComponentStack"</span>/&gt;</span><br><span class="code-tag">&lt;/action&gt;</span></pre>
</div>
</div>
<p>The default configuration (<tt><a  href="file:///F:/Doc/Struts2/docs/struts-defaultxml.html" title="struts-default.xml">struts-default.xml</a></tt>) sets up a default Interceptor Stack that will work well for most applications.</p>
<p><img  src="http://cwiki.apache.org/confluence/images/icons/emoticons/lightbulb_on.gif" class="emoticon" alt="" align="absmiddle" border="0" height="16" width="16"> For more, see <a  href="file:///F:/Doc/Struts2/docs/interceptors.html" title="Interceptors">Interceptors</a>.</p>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 22:14 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Include Config[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113918.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 14:07:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113918.html</guid><description><![CDATA[<div class="pagecontent">
<div class="wiki-content">
<p>A
popular strategy is "divide and conquer". The framework lets you apply
"divide and conquer" to configuration files using the include element.</p>
<div class="code">
<div class="codeContent">
<pre class="code-xml">&lt;!DOCTYPE struts PUBLIC<br>  <span class="code-quote">"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"</span><br>  <span class="code-quote">"http://struts.apache.org/dtds/struts-2.0.dtd"</span>&gt;<br><span class="code-tag">&lt;struts&gt;</span><br>    <span class="code-tag">&lt;include file=<span class="code-quote">"Home.xml"</span>/&gt;</span><br>    <span class="code-tag">&lt;include file=<span class="code-quote">"Hello.xml"</span>/&gt;</span><br>    <span class="code-tag">&lt;include file=<span class="code-quote">"Simple.xml"</span>/&gt;</span><br>    <span class="code-tag">&lt;include file=<span class="code-quote">"/util/POJO.xml"</span>/&gt;</span><br><span class="code-tag">&lt;/struts&gt;</span></pre>
</div>
</div>
<p>Each included file must be in the same format as <tt>struts.xml</tt>, including the <tt>doctype</tt>. The include files can be placed anywhere on the classpath.</p>
<p>In a large-team environment, the include files can be used to
organize different modules of the application that are being developed
by different team members. </p>
</div>
</div>  <img src ="http://www.blogjava.net/nobody_am/aggbug/113918.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 22:07 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113918.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 configuration: Namespace Config[笔记]</title><link>http://www.blogjava.net/nobody_am/news/2007/04/26/113917.html</link><dc:creator>MingIsMe</dc:creator><author>MingIsMe</author><pubDate>Thu, 26 Apr 2007 14:05:00 GMT</pubDate><guid>http://www.blogjava.net/nobody_am/news/2007/04/26/113917.html</guid><description><![CDATA[<p>The namespace attribute subdivides action configurations into logical modules, each with its own identifying prefix. Namespaces avoid conflicts between action names. Each namespace can have it's own "menu" or "help" action, each with its own implementation. While the prefix appears in the browser URI, the tags are "namespace aware", so the namespace prefix does not need to be embedded in forms and links.</p>
<p><span style="BACKGROUND-COLOR: #0010ff" twffan="done">Namespace属性细分了action配置到逻辑模块，每个都有自己的唯一的前缀，Namespace避免了action之间名称的冲突，每个namespace能有他自己的&#8220;menu&#8221;或&#8220;help&#8221;action，每个有自己的实现。当前缀在浏览器URI中出现时，标签能够用namespace感知，所以namespace前缀不需要嵌套在Form和Link里。<br></span><br></p>
<table class=tipMacro cellSpacing=8 cellPadding=5 width="85%" align=center border=0>
    <colgroup>
    <col width=24>
    <col></colgroup>
    <tbody>
        <tr>
            <td vAlign=top><img height=16 alt="" src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" width=16 align=absMiddle border=0 twffan="done"></td>
            <td>Namespaces are the equivalent of Struts Action 1 modules.</td>
        </tr>
    </tbody>
</table>
<h2>Default Namespace</h2>
<p>The default namespace is <tt>""</tt> - an empty string. The default namespace is used as a "catch-all" namespace. If an action configuration is not found in a specified namespace, the default namespace is also be searched. The local/global strategy allows an application to have global action configurations outside of the action element "extends" hierarchy.</p>
<p>The namespace prefix can be registered with Java declarative security, to ensure only authorized users can access the actions in a given namespace.</p>
<p><span style="BACKGROUND-COLOR: #0010ff" twffan="done">namespace前缀能够被Java申明安全注册，来确保只有授权用户访问给定命名空间的action。</span><br></p>
<h2>Root Namespace</h2>
<p>A root namespace ("/") is also supported. The root is the namespace when a request directly under the context path is received. As with other namespace, it will fall back to the default ("") namespace if a local action is not found.</p>
<h2>Namespace Example</h2>
<div class=code twffan="done">
<div class=codeContent twffan="done">
<pre class=code-xml><span class=code-tag twffan="done">&lt;package name=<span class=code-quote twffan="done">"default"</span>&gt;</span><br>    <span class=code-tag twffan="done">&lt;action name=<span class=code-quote twffan="done">"foo"</span> class="mypackage.simpleAction&gt;</span><br>        <span class=code-tag twffan="done">&lt;result name=<span class=code-quote twffan="done">"success"</span> type=<span class=code-quote twffan="done">"dispatcher"</span>&gt;</span>greeting.jsp<span class=code-tag twffan="done">&lt;/result&gt;</span><br>    <span class=code-tag twffan="done">&lt;/action&gt;</span><br>    <span class=code-tag twffan="done">&lt;action name=<span class=code-quote twffan="done">"bar"</span> class=<span class=code-quote twffan="done">"mypackage.simpleAction"</span>&gt;</span><br>        <span class=code-tag twffan="done">&lt;result name=<span class=code-quote twffan="done">"success"</span> type=<span class=code-quote twffan="done">"dispatcher"</span>&gt;</span>bar1.jsp<span class=code-tag twffan="done">&lt;/result&gt;</span><br>    <span class=code-tag twffan="done">&lt;/action&gt;</span><br><span class=code-tag twffan="done">&lt;/package&gt;</span><br><br><span class=code-tag twffan="done">&lt;package name=<span class=code-quote twffan="done">"mypackage1"</span> namespace=<span class=code-quote twffan="done">"/"</span>&gt;</span><br>    <span class=code-tag twffan="done">&lt;action name=<span class=code-quote twffan="done">"moo"</span> class=<span class=code-quote twffan="done">"mypackage.simpleAction"</span>&gt;</span><br>        <span class=code-tag twffan="done">&lt;result name=<span class=code-quote twffan="done">"success"</span> type=<span class=code-quote twffan="done">"dispatcher"</span>&gt;</span>moo.jsp<span class=code-tag twffan="done">&lt;/result&gt;</span><br>    <span class=code-tag twffan="done">&lt;/action&gt;</span><br><span class=code-tag twffan="done">&lt;/package&gt;</span><br><br><span class=code-tag twffan="done">&lt;package name=<span class=code-quote twffan="done">"mypackage2"</span> namespace=<span class=code-quote twffan="done">"/barspace"</span>&gt;</span><br>    <span class=code-tag twffan="done">&lt;action name=<span class=code-quote twffan="done">"bar"</span> class=<span class=code-quote twffan="done">"mypackage.simpleAction"</span>&gt;</span><br>        <span class=code-tag twffan="done">&lt;result name=<span class=code-quote twffan="done">"success"</span> type=<span class=code-quote twffan="done">"dispatcher"</span>&gt;</span>bar2.jsp<span class=code-tag twffan="done">&lt;/result&gt;</span><br>    <span class=code-tag twffan="done">&lt;/action&gt;</span><br><span class=code-tag twffan="done">&lt;/package&gt;</span></pre>
</div>
</div>
<h2>How the Code Works</h2>
<p>If a request for <tt>/barspace/bar.action</tt> is made, <tt>/barspace</tt> namespace is searched and if it is found the bar action is executed, else it will fall back to the default namespace. In the Namespace Example, the <tt>bar</tt> action does exists in the <tt>barspace</tt> namespace. The <tt>barspace.bar</tt> action will be executed, and if "success" is returned, the request will be forwarded to <tt>bar2.jsp</tt>.</p>
<table class=tipMacro cellSpacing=8 cellPadding=5 width="85%" align=center border=0>
    <colgroup>
    <col width=24>
    <col></colgroup>
    <tbody>
        <tr>
            <td vAlign=top><img height=16 alt="" src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" width=16 align=absMiddle border=0 twffan="done"></td>
            <td><strong class=strong>Falling Back to Foo</strong><br>
            <p>If a request is made to <tt>/barspace/foo.action</tt>, the namespace <tt>/barspace</tt> will be checked for action <tt>foo</tt>. If a local action is not found, the default namespace is checked. In the Namespace Example, there is no action <tt>foo</tt> in the namespace <tt>/barspace</tt>, therefore the default will be checked and <tt>/foo.action</tt> will be executed.</p>
            </td>
        </tr>
    </tbody>
</table>
<p>In the Namespace Example, if a request for <tt>moo.action</tt> is made, the root namespace ('/') is searched for a <tt>moo</tt> action; if a root action is not found, the default namespace is checked. In this case, the <tt>moo</tt> action does exist and will be selected. Upon success, the request would be forwarded to <tt>bar2.jsp</tt>.</p>
<table class=tipMacro cellSpacing=8 cellPadding=5 width="85%" align=center border=0>
    <colgroup>
    <col width=24>
    <col></colgroup>
    <tbody>
        <tr>
            <td vAlign=top><img height=16 alt="" src="http://cwiki.apache.org/confluence/images/icons/emoticons/check.gif" width=16 align=absMiddle border=0 twffan="done"></td>
            <td><strong class=strong>Getting to the Root</strong><br>If a request is made for <tt>/foo.action</tt>, the root <tt>/</tt> namespace will be checked. If <tt>foo</tt> is found, the root action will be selected. Otherwise, the framework will check the default namespace. In the Namespace Example, <tt>foo</tt> action does not exist in the root namespace, so the default namespace is checked, and the default <tt>foo</tt> action is selected.</td>
        </tr>
    </tbody>
</table>
<table class=noteMacro cellSpacing=8 cellPadding=5 width="85%" align=center border=0>
    <colgroup>
    <col width=24>
    <col></colgroup>
    <tbody>
        <tr>
            <td vAlign=top><img height=16 alt="" src="http://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" width=16 align=absMiddle border=0 twffan="done"></td>
            <td><strong class=strong>Namespaces are not a path!</strong><br>
            <p>Namespace are not hierarchical like a file system path. There is one namespace level. For example if the URL <tt>/barspace/myspace/bar.action</tt> is requested, the framework will first look for namespace <tt>/barspace/myspace</tt>. If the action does not exist at <tt>/barspace/myspace</tt>, the search will immediately fall back to the default namespace <tt>""</tt>. The framework will not parse the namespace into a series of "folders". In the Namespace Example, the <tt>bar</tt></p>
            </td>
        </tr>
    </tbody>
</table>
  <img src ="http://www.blogjava.net/nobody_am/aggbug/113917.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nobody_am/" target="_blank">MingIsMe</a> 2007-04-26 22:05 <a href="http://www.blogjava.net/nobody_am/news/2007/04/26/113917.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>