﻿<?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-jojo's blog－－快乐忧伤都与你同在-文章分类-Programming 相关</title><link>http://www.blogjava.net/ruoyoux/category/34971.html</link><description>为梦想而来，为自由而生。
性情若水，风起水兴，风息水止，故时而激荡，时又清平……</description><language>zh-cn</language><lastBuildDate>Fri, 17 Jul 2009 08:32:32 GMT</lastBuildDate><pubDate>Fri, 17 Jul 2009 08:32:32 GMT</pubDate><ttl>60</ttl><item><title>每日一记 2009/06/11 Sun GlassFish Enterprise Server 2.1 Reference Manual</title><link>http://www.blogjava.net/ruoyoux/articles/281525.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Thu, 11 Jun 2009 09:39:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/281525.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/281525.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/281525.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/281525.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/281525.html</trackback:ping><description><![CDATA[<h2>start-node-agent(1)</h2>
<p align="center">
<a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#NAME">Name</a>
| <a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#Synopsis">Synopsis</a>
| <a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#Description">Description</a>
| <a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#Options">Options</a>
| <a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#Operands">Operands</a>
| <a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#Examples">Examples</a>
| <a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#Exit%20Status">Exit Status</a>
| <a href="http://docs.sun.com/app/docs/doc/820-4332/start-node-agent-1?a=view#See%20Also">See Also</a>
</p>
<h4>Name</h4>
<ul>start-node-agent&#8211; starts a node agent</ul>
    <h4>Synopsis</h4>
    <ul>
        <pre><kbd>start-node-agent</kbd> [<kbd><strong>--user</strong></kbd> <var>user</var>]<br />
        <br />
        [<kbd><strong>--passwordfile</strong></kbd> <var>passwordfile</var>] [<kbd><strong>--secure={true|false}</strong></kbd>] <br />
        <br />
        [<kbd><strong> --terse={true|false} </strong></kbd>] [<kbd><strong> --echo={true|false} </strong></kbd>]<br />
        <br />
        [<kbd><strong> --interactive={true|false} </strong></kbd>] [<kbd><strong> --verbose={true|false} </strong></kbd>] <br />
        <br />
        [<kbd><strong> --agentdir </strong></kbd> <var>nodeagent_path</var>] [<kbd><strong>--startinstances={true|false}</strong></kbd>] <br />
        <br />
        [<kbd><strong> --syncinstances={true|false} </strong></kbd>] [<var>nodeagent_name</var>]</pre>
    </ul>
    <h4>Description</h4>
    <ul><hr />
        <strong>Note &#8211; </strong>
        <p>This command is available only in domains that are configured
        to support clusters, such as domains that are created with the cluster profile.</p>
        <hr />
        <p>Use the <kbd>start-node-agent</kbd> command start a node agent.
        The command will return control to the user before instances are actually
        started. The <kbd>list-instances</kbd> command can be executed to
        see if they have actually started. This command may take a while to execute
        since the node agent may need to create and start a number of server instances.</p>
        <p>This command is supported in local mode only.</p>
    </ul>
    <h4>Options</h4>
    <ul><dl><dt>
        <kbd><strong>-u</strong></kbd> <kbd><strong>--user</strong></kbd>
        </dt><dd>
        <p>The authorized domain administration server administrative
        username.</p>
        </dd><dt>
        <kbd><strong>--passwordfile</strong></kbd>
        </dt><dd>
        <p>The <kbd><strong>--passwordfile</strong></kbd> option
        specifies the name of a file containing the password entries in a specific
        format. The entry for the password must have the <tt>AS_ADMIN_</tt> prefix
        followed by the password name in uppercase letters.</p>
        <p>For example, to specify the domain administration server password, use
        an entry with the following format: <kbd>AS_ADMIN_PASSWORD</kbd>=<var>password</var>, where <var>password</var> is the actual
        administrator password. Other passwords that can be specified include <tt>AS_ADMIN_MAPPEDPASSWORD</tt>, <tt>AS_ADMIN_USERPASSWORD</tt>, and <tt>AS_ADMIN_ALIASPASSWORD</tt>.</p>
        <p>All remote commands must specify the administration password to authenticate
        to the domain administration server, either through <kbd><strong>--passwordfile</strong></kbd> or <kbd>asadmin login</kbd>, or interactively on the command
        prompt. The <kbd>asadmin login</kbd> command can be used only to specify
        the administration password. For other passwords, that must be specified for remote
        commands, use the <kbd><strong>--passwordfile</strong></kbd> or enter
        them at the command prompt. </p>
        <p>If you have authenticated to a domain using the <kbd>asadmin login</kbd> command,
        then you need not specify the administration password through the <kbd><strong>--passwordfile</strong></kbd> option on subsequent operations to
        this particular domain. However, this is applicable only to <kbd>AS_ADMIN_PASSWORD</kbd> option. You will still need to provide the other passwords, for
        example, <tt>AS_ADMIN_USERPASSWORD</tt>, as and when required by
        individual commands, such as <kbd>update-file-user</kbd>.</p>
        <p>For security reasons, passwords specified as an environment variable
        will not be read by <kbd>asadmin</kbd>. </p>
        <p>The default value for <tt>AS_ADMIN_MASTERPASSWORD</tt> is <tt>changeit</tt>.</p>
        </dd><dt>
        <kbd><strong>-s</strong></kbd> <kbd><strong>--secure</strong></kbd>
        </dt><dd>
        <p>If set to true, uses SSL/TLS to communicate with the domain
        administration server. Default is true.</p>
        </dd><dt>
        <kbd><strong>-t</strong></kbd> <kbd><strong>--terse</strong></kbd>
        </dt><dd>
        <p>Indicates that any output data must be very concise, typically
        avoiding human-friendly sentences and favoring well-formatted data for consumption
        by a script. Default is false.</p>
        </dd><dt>
        <kbd><strong>-e</strong></kbd> <kbd><strong>--echo</strong></kbd>
        </dt><dd>
        <p>Setting to true will echo the command line statement on the
        standard output. Default is false.</p>
        </dd><dt>
        <kbd><strong>-I</strong></kbd> <kbd><strong>--interactive</strong></kbd>
        </dt><dd>
        <p>If set to true (default), only the required password options
        are prompted.</p>
        </dd><dt>
        <kbd><strong>-h</strong></kbd> <kbd><strong>--help</strong></kbd>
        </dt><dd>
        <p>Displays the help text for the command.</p>
        </dd><dt>
        <kbd><strong>--verbose</strong></kbd>
        </dt><dd>
        <p>By default this flag is set to false. If set to true, a console
        window is opened for the node agent and for every server instance a node agent
        manages. On Windows, press Ctrl-Break in the console to print a thread dump.
        On UNIX, press CTRL-Backslash in the console to print a thread dump. The node
        agent thread dump goes to its console. The server instance thread dump goes
        to the instance log file.</p>
        </dd><dt>
        <kbd><strong>--agentdir</strong></kbd>
        </dt><dd>
        <p>Like a Domain Administration Server (DAS), each node agent
        resides in a top level directory named <var>agentdir</var>/<var>nodeagent_name</var>. If specified, the path must be accessible in
        the filesystem. If not specified, defaults to the <var>install_dir</var><tt>/nodeagents</tt> directory. </p>
        </dd><dt>
        <kbd><strong>--startinstances</strong></kbd>
        </dt><dd>
        <p>If set to true, all server instances that are not currently
        running are started. If set to false, instances are not started. If the option
        is omitted, it defaults to the value of the node agent's <kbd>start-servers-in-startup</kbd> attribute, located in the <kbd>domain.xml</kbd> file.</p>
        </dd><dt>
        <kbd><strong>--syncinstances</strong></kbd>
        </dt><dd>
        <p>If set to true, forcibly synchronizes the cache repositories
        of <strong>all</strong> server instances with the central repository of
        the DAS. The synchronization occurs when the node agent is started. Default
        is false.</p>
        </dd></dl></ul>
        <h4>Operands</h4>
        <ul><dl><dt>
            <var>nodeagent_name</var>
            </dt><dd>
            <p>The name of the node agent to be started.</p>
            </dd></dl></ul>
            <h4>Examples</h4>
            <ul><hr />
                <h5>Example&nbsp;1  Using the start-node-agent command</h5>
                <br />
                <table border="1" cellpadding="1" width="100%">
                    <tbody>
                        <tr>
                            <td nowrap="1">
                            <br />
                            <pre>asadmin&gt; <strong><kbd>start-node-agent --user admin <br />
                            <br />
                            --passwordfile passwordfile nodeagent1</kbd></strong><br />
                            <br />
                            Nodeagent1 started.</pre>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <p>The node agent <tt>nodeagent1</tt> is started in the default <kbd><var>install_dir</var>/nodeagents</kbd> directory. </p>
                <hr />
            </ul>
            <h4>Exit Status</h4>
            <ul><dl><dt>0</dt><dd>
                <p>command executed successfully</p>
                </dd><dt>1</dt><dd>
                <p>error in executing the command</p>
                </dd></dl></ul>
                <h4>See Also</h4>
                <ul>
                    <p>
                    <a href="http://docs.sun.com/app/docs/doc/820-4332/stop-node-agent-1?a=view">stop-node-agent(1)</a>, <a href="http://docs.sun.com/app/docs/doc/820-4332/delete-node-agent-1?a=view">delete-node-agent(1)</a>, <a href="http://docs.sun.com/app/docs/doc/820-4332/list-node-agents-1?a=view">list-node-agents(1)</a>, <a href="http://docs.sun.com/app/docs/doc/820-4332/create-node-agent-1?a=view">create-node-agent(1)</a>
                    </p>
                </ul>
                Java EE 5&nbsp;&nbsp;Last Revised 13 Jul 2007
<img src ="http://www.blogjava.net/ruoyoux/aggbug/281525.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-06-11 17:39 <a href="http://www.blogjava.net/ruoyoux/articles/281525.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>每日一记 2009/06/10 How GlassFish DAS communicates with Node Agents and Instances</title><link>http://www.blogjava.net/ruoyoux/articles/281159.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Wed, 10 Jun 2009 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/281159.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/281159.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/281159.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/281159.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/281159.html</trackback:ping><description><![CDATA[<p><strong>Question</strong>: Explain the communication details between Domain
Admin Server, node-agents and server instances in Sun's Application
Server 8.x and 9.x (<a href="https://glassfish.dev.java.net/">GlassFish</a> V2).</p>
<p><strong>Terminology</strong>:</p>
<p><font size="2"><strong>DAS</strong>: Domain Admin Server (One per domain) -- The process that controls the management of the entire domain.<br />
</font></p>
<p><font size="2"><strong>NA</strong>: Node Agent -- Generally, one per box or Solaris container -- The process that controls the life cycle of server instances.<br />
</font></p>
<p><font size="2"><strong>SI</strong>: Server Instance --&nbsp; The real Java EE instances that run user applications in an enterprise.</font><br />
</p>
<p><strong>Answer</strong>:</p>
<p><strong>1. Background</strong>:
The domain.xml controls the configuration. At every node-agent, there
are also a few configuration files that are consulted by every NA. See <a href="http://docs.sun.com/app/docs/doc/819-3679/abdkv?a=view">NA section at docs.sun.com</a> for details. Following are the points in time when the communication (for administration/management purpose) happens:</p>
<ul>
    <li><strong>DAS communicates with each NA</strong>: Only when DAS needs to know NA's running status.</li>
    <li><strong>DAS communicates with each SI</strong>: When DAS needs to know SI's running status and when it needs to cascade the SI MBeans into the DAS's MBenServer.<br />
    </li>
    <li><strong>NA communicates with DAS</strong>:
    During initial rendezvous (which may happen during creation of NA),
    synchronization of the NA itself and synchronization of each SI that NA
    is responsible for.</li>
    <li><strong>SI communicates with the DAS</strong>: Never, explicitly.</li>
</ul>
<p>Thus,
the communication is mainly driven by DAS. When the domain is created,
the administration is configured to use an authentication realm named <em>admin-realm</em>.
This realm points to what's called a FileRealm which is nothing but the
implementation of a security realm implementation that uses <em>admin-keyfile</em>. If you see the domain's configuration, you'll find this file in config folder of that domain. </p>
<p>The
communication happens over two channels. One is the HTTP channel and
the other is RMI channel. For this purpose, there is a
SynchronizationServlet and a System JMX Connector (standard in JDK 5)
that is provided. Every DAS and SI, including the NA start a JMX RMI
ConnectorServer that can be optionally configured to use transport
layer security.</p>
<p>Every NA communicates with DAS multiple times,
but the key points are of initial hand-shake and synchronization. The
initial hand-shake is when NA makes DAS aware of its own existence and
DAS correspondingly responds if it has the correct credentials. When
the DAS is configured to have secure access (this is the default in
enterprise profile domain), both the HTTP and JMX/RMI channels use
Transport Layer Security with SSL/v3.&nbsp; Note that during the initial
hand-shake, the DAS knows about NA's existence alone. DAS does not
release the contents of the domain's repository during this phase. This
happens over HTTP channel since creation of node-agent takes the DAS's <strong>admin-port </strong>(default: 4848) as an option.<br />
</p>
<p>After an NA is created, the most natural step is to <em>start</em> that NA. This is done by executing the <strong>asadmin start-node-agent</strong>
command. Since this is the first-time startup of the NA, NA syncs up
with the DAS. Note that startup of NA requires the correct credentials
(admin user name and admin password) to be supplied. The DAS compares
them against its own admin-keyfile and the communication succeeds only
when this succeeds. The NA startup also requires the master password to
be provided on the command line because in order to start, the NA has
to be able to unlock the security store (e.g. keystore.jks) that it
synced from the DAS. Note that master password is never put on the
wire! It has to be provided at the time of both DAS startup and every
NA startup. For advanced use cases, there is an unattended boot
scenario that is handled by using the option <strong>--savemasterpassword</strong> which should be used with care.</p>
<p>The
reason NA needs the master password is also to pass it on to the SI's
it starts (as part of start-instance or start-cluster) so that these
instances are able to unlock the security store to get the primary keys
and certificates.&nbsp;</p>
<p>The NA always communicates with the DAS over
JMX/RMI channel. Thus NA opens an RMI connection to the DAS where DAS
is listening for RMI/JMX Connections. This is where the RMI Registry in
DAS (default port <strong>8686</strong>) comes into picture.<br />
</p>
<p>When the domain is created, it uses the self-signed certificate aliased <strong>s1as</strong>
which is used for internal communication. This certificate is created
anew every time a domain is created. The master password of a domain is
what locks the server's keystore. In enterprise profile domain, NSS is
used to manage the secure store, whereas in cluster profile domain, JKS
manages the secure store. The semantics of the master password are
unchanged in both the cases.</p>
<p>The Server Instances are synced with the DAS as part of either:</p>
<ol>
    <li>start-instance, or</li>
    <li>start-cluster, or</li>
    <li>start-node-agent --syncinstances procedure.</li>
</ol>
<p>For
this synchronization, they use the HTTP layer and communicate with the
SynchronizationServlet that's listening for sync requests. This servlet
is (of course) running in the DAS. </p>
<p>The server instances get the
admin credentials from the node-agent process in a secure manner (using
stdin). This also evident when you try to use the <strong>startserv</strong> script that's located in instance's <em>bin</em> folder.</p>
<p>The
process of DAS communicating with the NA and SI's is identical in that
it communicates with them over RMI/JMX in the other direction.<br />
</p>
<p><strong>2. Transport Layer Security</strong>:</p>
<p>This
is achieved when we enable the security-enabled flag on the
admin-listener and jmx-connector named system on the DAS and server
instances. Note that&nbsp; admin-listener (HTTP/S) is started only in the
DAS. There is no admin-listener in server instances.</p>
<p>It's of
course possible to use another CA-signed certificate for this purpose.
It needs additional configuration after importing those certs in the
store.<br />
</p>
<p><strong>3. Authentication and Credentials</strong>:</p>
<p>Please see: <a href="http://wiki.glassfish.java.net/attach/GlassFishAdministrationPages/admincreds.html">http://wiki.glassfish.java.net/attach/GlassFishAdministrationPages/admincreds.html</a><br />
</p>
<br />
<img src ="http://www.blogjava.net/ruoyoux/aggbug/281159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2009-06-10 15:12 <a href="http://www.blogjava.net/ruoyoux/articles/281159.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Framework Document Resources</title><link>http://www.blogjava.net/ruoyoux/articles/232578.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sun, 05 Oct 2008 15:29:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232578.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232578.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232578.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232578.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232578.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">最近开始研究Spring Framework，顺手整理了这份文档资源列表。</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">资源链接页</span></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Spring Framework Documentaion</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://www.springframework.org/documentation.html"><font face="Times New Roman">http://www.springframework.org/documentation.html</font></a></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Spring</font><span style="font-family: 宋体">中文论坛图书贴</span></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://xglw.51.net/5team/springframework/viewtopic.php?t=31"><font face="Times New Roman">http://xglw.51.net/5team/springframework/viewtopic.php?t=31</font></a></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Spring Reference Documentation</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://www.springframework.org/docs/reference/index.html"><font face="Times New Roman">http://www.springframework.org/docs/reference/index.html</font></a></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">or </font><a href="http://www.springframework.org/docs/spring-reference.pdf"><font face="Times New Roman">http://www.springframework.org/docs/spring-reference.pdf</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：</span><font face="Times New Roman">Spring </font><span style="font-family: 宋体">开发组</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">中文版</span><a href="http://xglw.51.net/5team/springframework/book/spring_referece_inchinese_m2.pdf"><font face="Times New Roman">http://xglw.51.net/5team/springframework/book/spring_referece_inchinese_m2.pdf</font></a><span style="font-family: 宋体">（</span><font face="Times New Roman">for M2</font><span style="font-family: 宋体">）</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">翻译：</span><font face="Times New Roman">Spring</font><span style="font-family: 宋体">中文论坛翻译组</span></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Spring</font><span style="font-family: 宋体">的</span><font face="Times New Roman">Document</font><span style="font-family: 宋体">中还提供了：</span></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">The Spring Framework - A Lightweight Container by Rod Johnson, Juergen Hoeller</font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Container Resources vs Local Resources(for transactional data access with the Spring Framework) by Juergen Hoeller</font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Data Access and Transaction Abstraction with the Spring Framework(featuring Hibernate examples) by Juergen Hoeller</font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Web MVC with the Spring Framework by Juergen Hoeller</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://xglw.51.net/5team/springframework/book/webMvcSpring.pdf"><span style="color: windowtext; font-family: 宋体; text-decoration: none; text-underline: none">中文版：<font face="Times New Roman">http://xglw.51.net/5team/springframework/book/webMvcSpring.pdf</font></a></span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">翻译；</span><font face="Times New Roman">yanger</font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">（</span><font face="Times New Roman">more&#8230;</font><span style="font-family: 宋体">）</span></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Introducing the Spring Framework</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://www.theserverside.com/articles/article.tss?l=SpringFramework"><font face="Times New Roman">http://www.theserverside.com/articles/article.tss?l=SpringFramework</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：</span><font face="Times New Roman">Rod Johnson </font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">中文版</span><font face="Times New Roman"> <a href="http://xglw.51.net/5team/springframework/viewtopic.php?t=18">http://xglw.51.net/5team/springframework/viewtopic.php?t=18</a></font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">翻译：</span><font face="Times New Roman">yanger</font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Developing a Spring Framework MVC application step-by-step</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html"><font face="Times New Roman">http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：</span><font face="Times New Roman">Thomas Risberg</font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Spring Framework Tutorial</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://www.springframework.org/downloads/tutorial.pdf"><font face="Times New Roman">http://www.springframework.org/downloads/tutorial.pdf</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：</span><font face="Times New Roman">Isabelle Muszynski</font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">在</span><a href="http://groups.yahoo.com/group/spring_in_chinese/"><font face="Times New Roman">Spring In Chinese Group</font></a><span style="font-family: 宋体">有</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">（</span><font face="Times New Roman">PPT</font><span style="font-family: 宋体">）</span><font face="Times New Roman"> On Spring by gigix</font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">（</span><font face="Times New Roman">PPT</font><span style="font-family: 宋体">）</span><font face="Times New Roman"> Spring Introduction for 3.12M2 by yanger</font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Framework Design</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://qca.cn/frameworkdesign/content.htm"><font face="Times New Roman">http://qca.cn/frameworkdesign/content.htm</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：林星</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">书籍购买链接</span></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Expert One-on-One J2EE Design and Development</font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">（略）</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：</span><font face="Times New Roman">Rod Johnson</font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">中文版：</span><a href="http://www.china-pub.com/computers/common/info.asp?id=14126"><font face="Times New Roman">http://www.china-pub.com/computers/common/info.asp?id=14126</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">（说明：英文版本身很简明，翻译则评价甚差）</span></p>
<span>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">我眼中的</span><font face="Times New Roman">Spring</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=125334"><font face="Times New Roman">http://www.blogbus.com/blogbus/blog/diary.php?diaryid=125334</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：</span><font face="Times New Roman">dreamhead</font></p>
<p style="margin: 0cm 0cm 0pt"><font face="Times New Roman">Spring is coming</font></p>
<p style="margin: 0cm 0cm 0pt"><a href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=126737"><font face="Times New Roman">http://www.blogbus.com/blogbus/blog/diary.php?diaryid=126737</font></a></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">作者：</span><font face="Times New Roman">founder_chen</font></p>
<p style="margin: 0cm 0cm 0pt"></span></p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232578.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-05 23:29 <a href="http://www.blogjava.net/ruoyoux/articles/232578.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>将Tapestry整合到Spring里去</title><link>http://www.blogjava.net/ruoyoux/articles/232576.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sun, 05 Oct 2008 15:27:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232576.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232576.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232576.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232576.html</trackback:ping><description><![CDATA[<a href="http://tech.blogbus.com/logs/139683.html">http://tech.blogbus.com/logs/139683.html</a><br />
<br />
<p>　　在Spring最新的文档里，有关于如何将Tapestry整合到Spring里去的说明，见这里<a href="http://www.springframework.org/docs/reference/view.html#view-tapestry">http://www.springframework.org/docs/reference/view.html#view-tapestry</a>。Spring中文论坛应该会翻译出来，我就不做重复的工作，只摘要说明一下。</p>
<p>　　先看看Tapestry。下图说明了Tapestry是怎么样获取到service的。</p>
<p><img alt="" src="http://go.6to23.com/nftx/images/tapestry.jpg" onload="javascript:if(this.width />740)this.width=740" align=center border=undefined></p>
<p>　　在文档里，基于Tapestry和Spring的应用被划分成五层，我们只关注前边两层：User Interface Layer和Service Layer。这种划分对于单独使用Tapestry的应用也是成立的，从上图可以看出，那是对Service Layer的操作。当进行整合之后，User Interface Layer仍然是由Tapestry提供，而Service Layer则由Spring接手来提供。</p>
<p>　　Service实际上就是Bean，Tapestry原本一套取得Service的机制：getEngine()-&gt;getService()。现在，我们用Spring将这些Serviec，也就是Bean管理起来，那么，要解决的问题就只有一个，如何让Tapestry获得由Spring管理起来的的Service？</p>
<p>　　在Application Context里我们定义了需要被调用的Bean（见文档），我们给它个名字就userService。那么，在Tapestry的page里，就需要载入这个context，然后取得beanA。</p>
<p>　　一个最简单的方法是利用Spring的static工具WebApplicationContext在Tapestry page对应的Java class definition里直接载入Application Context,并取得userService。</p>
<p>
<table cellpadding="1" width="80%" align="center" bgcolor="#eeeeee" border="1">
    <tbody>
        <tr>
            <td bgcolor="#eeeeee">
            <p align="left">WebApplicationContext appContext = WebApplicationContextUtils.getApplicationContext(<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getRequestCycle().getRequestContext().getServlet().getServletContext());<br />
            &nbsp;&nbsp;&nbsp; UserService userService = appContext.getBean("userService");<br />
            </p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　不过这种用法和我们用Spring的原意有点违背——这不符合DI模式。应该在page里才决定我们调哪个Service。</p>
<p>　　所以，推荐的做法如下。</p>
<p>　　第一步，让Tapestry page能够获得ApplicationContext，但这次不直接由Tapestry page来做，因为在我们需要访问ApplicationContext的时候，Tapestry page很难拿到ServletContext，所以我们将其放到Enging里去做。代码如下：</p>
<p>
<table cellpadding="1" width="80%" align="center" bgcolor="#eeeeee" border="1">
    <tbody>
        <tr>
            <td>package com.whatever.web.xportal;<br />
            ...<br />
            import ...<br />
            ...<br />
            public class MyEngine extends org.apache.tapestry.engine.BaseEngine {<br />
            &nbsp;<br />
            &nbsp;&nbsp;&nbsp; public static final String APPLICATION_CONTEXT_KEY = "appContext";
            <p>&nbsp;&nbsp;&nbsp; protected void setupForRequest(RequestContext context) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.setupForRequest(context);<br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // insert ApplicationContext in global, if not there<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map global = (Map) getGlobal();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ac == null) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ac = WebApplicationContextUtils.getWebApplicationContext(<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.getServlet().getServletContext()<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global.put(APPLICATION_CONTEXT_KEY, ac);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp; }</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　这样就把ApplicationContext放到了global里去，然后我们指定MyEngine是后边应用里实际使用的的Engine：</p>
<p>
<table cellpadding="1" width="80%" align="center" bgcolor="#eeeeee" border="1">
    <tbody>
        <tr>
            <td bgcolor="#eeeeee">
            <p align="left">&lt;application<br />
            &nbsp;&nbsp;&nbsp; name="Whatever xPortal"<br />
            &nbsp;&nbsp;&nbsp; engine-class="com.whatever.web.xportal.MyEngine"&gt;<br />
            &lt;/application&gt;</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>（写着写着又像翻译了&#8230;&#8230;不爽-_-）</p>
<p>　　第二步，在Tapestry page里取得Bean，代码如下：</p>
<p>
<table cellpadding="1" width="80%" align="center" bgcolor="#eeeeee" border="1">
    <tbody>
        <tr>
            <td bgcolor="#eeeeee">
            <p align="left">&lt;property-specification name="userService"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="com.whatever.services.service.user.UserService"&gt;<br />
            &nbsp;&nbsp;&nbsp; global.appContext.getBean("userService")<br />
            &lt;/property-specification&gt;</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　第三步，在page对应的Java class definition增加一个abstract访问者，也就是一个abstract getter<br />
方法。代码如下：</p>
<p>
<table cellpadding="1" width="80%" align="center" bgcolor="#eeeeee" border="1">
    <tbody>
        <tr>
            <td bgcolor="#eeeeee">
            <p align="left">public abstract UserService getUserService();</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>　　当Tapestry实际载入页面的时候，会对类文件执行runtime code方法以增加定义了的properties，并将上边的abstract getter<br />
方法与新建的fields挂钩起来。（瀑布汗^^|||）</p>
<p>　　ok，这就完成了。详细的example请看文档。</p>
<p>　　简单总结一下。Tapestry与Spring的整合实际上是把原本由Tapestry自己负责的Service Layer，也就是对Service/Bean的调用，交给Spring负责。实际的切入点，则在于上图所示的Engine处。<br />
</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-05 23:27 <a href="http://www.blogjava.net/ruoyoux/articles/232576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry整合Spring实践</title><link>http://www.blogjava.net/ruoyoux/articles/232575.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sun, 05 Oct 2008 15:25:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232575.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232575.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232575.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232575.html</trackback:ping><description><![CDATA[<a href="http://tech.blogbus.com/logs/219144.html">http://tech.blogbus.com/logs/219144.html</a><br />
<br />
<p>两个月前，写了一篇blog，名为《将Tapestry整合到Spring里去》，是根据文档做了理论上的说明。这阵子终于开始动手做，由于犯了一个很低级的错误，浪费了很多时间，直到周六才&#8220;摆平&#8221;，很高兴。网上这方面的资料非常少，我把实际操作过程再介绍一下，也算补一下文档的不足。事实上Spring网站的文档是给对Spring和Tapestry都有开发经验的人写的，多少有点过于简略，不是很方便使用。</p>
<p>第一步：写一个Java Bean供后边调用：</p>
<p><font color="#0000ff">package my;//接口<br />
public interface IBean {<br />
&nbsp;public void amethod();<br />
}</font></p>
<p><font color="#0000ff">package my;//实现类<br />
public class Bean implements IBean {<br />
&nbsp;<br />
&nbsp;public void amethod() {<br />
&nbsp;&nbsp;//do something;<br />
&nbsp;}<br />
}</font></p>
<p>第二步：编写Spring的context config文档applicationContext.xml，放在web应用的/WEB-INF目录下</p>
<p><font color="#0000ff">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"<br />
"</font><a href="http://www.springframework.org/dtd/spring-beans.dtd"><font color="#0000ff">http://www.springframework.org/dtd/spring-beans.dtd</font></a><font color="#0000ff">"&gt;<br />
&lt;beans&gt;<br />
&nbsp;&lt;bean id="aBean" class="my.Bean"&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&lt;/beans&gt;</font></p>
<p>第三步：先试试直接载入Spring Application Context的做法。写一个tapestry页面（这里要求你对tapestry多少有点认识），如test.html，在对应的test.java中写入以下代码：</p>
<p><font color="#0000ff">WebApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(getRequestCycle().getRequestContext().getServlet().getServletContext());<br />
IBean bean = appContext.getBean("aBean");<br />
bean.amethod();</font></p>
<p>这里要说明一下，Spring的帮助文档有点错误，它用了WebApplicationContextUtils.getApplicationContext()的方法，但实际不存在这个方法，应该用<font color="#ff0000">WebApplicationContextUtils.getWebApplicationContext()</font></p>
<p>第四步，改为推荐的做法，在Engine里做上边的getWebApplicationContext()，并将其写到tapestry的global对象里边去。</p>
<p><font color="#0000ff">public class MyEngine extends BaseEngine {<br />
&nbsp;public static final String APPLICATION_CONTEXT_KEY = "appContext";<br />
&nbsp;protected void setupForRequest(RequestContext context) {<br />
&nbsp;&nbsp;super.setupForRequest(context);<br />
&nbsp;&nbsp;Map global = (Map) getGlobal();<br />
&nbsp;&nbsp;ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);<br />
&nbsp;&nbsp;if (ac == null) { ac = WebApplicationContextUtils.getWebApplicationContext(context.getServlet().getServletContext());<br />
&nbsp;&nbsp;&nbsp;System.out.println("测试" + ac);//你可以看看这一句在什么时候执行，从而了解Engine是什么时候被调用的;<br />
&nbsp;&nbsp;&nbsp;global.put(APPLICATION_CONTEXT_KEY, ac);<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}</font></p>
<p>global是一个Map，我们在里边增加了一个属性appContext，并将取到的ApplicationContext放进去，以后，通过调用global.appContext就可以得到context，并用来getBean。</p>
<p>第五步，在tapestry应用的sample.application文档（文件名与web.xml对应）里，指定所使用的Engine，也就是第四步写的内容：</p>
<p><font color="#0000ff">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE application PUBLIC <br />
&nbsp; "-//Apache Software Foundation//Tapestry Specification 3.0//EN" <br />
&nbsp; "</font><a href="http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"><font color="#0000ff">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd</font></a><font color="#0000ff">"&gt;</font></p>
<p><font color="#0000ff">&lt;application name="Sample Application"&nbsp; <br />
&nbsp;engine-class="MyEngine"&gt;<br />
&nbsp;&lt;page name="test" specification-path="test.page"/&gt;<br />
&lt;/application&gt;</font></p>
<p>第六步：在test.html对应的test.page里，加入获取bean的操作，代码如下：</p>
<p><font color="#0000ff">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE page-specification PUBLIC <br />
&nbsp; "-//Apache Software Foundation//Tapestry Specification 3.0//EN" <br />
&nbsp; "</font><a href="http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"><font color="#0000ff">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd</font></a><font color="#0000ff">"&gt;<br />
&lt;page-specification class="test"&gt;<br />
&nbsp; &lt;property-specification name="aBean" type="my.IBean"&gt;<br />
&nbsp; &nbsp;global.appContext.getBean("aBean")<br />
&nbsp; &lt;/property-specification&gt;<br />
&lt;/page-specification&gt;</font></p>
<p>第七步：在test.java里增加一个abstract getter：</p>
<p><font color="#0000ff">public abstract IBean getABean();</font></p>
<p>之后，就可以在代码里用getABean()的方法获取我们需要的bean了，如：</p>
<p><font color="#0000ff">getABean().amethod();</font></p>
<p>当然，不要忘了编辑web.xml文档：</p>
<p><font color="#0000ff">&lt;?xml version="1.0"?&gt;<br />
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd"><font color="#0000ff">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font color="#0000ff">"&gt;<br />
&lt;web-app&gt;<br />
&nbsp;&lt;display-name&gt;Tapestry Tutorial&lt;/display-name&gt; <br />
&nbsp;&lt;!--Redirect it to the servlet mapping address /h--&gt;<br />
&nbsp;&lt;filter&gt;<br />
&nbsp;&nbsp;&lt;filter-name&gt;redirect&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&lt;filter-class&gt;org.apache.tapestry.RedirectFilter&lt;/filter-class&gt;<br />
&nbsp;&nbsp;&lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;param-name&gt;redirect-path&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;param-value&gt;/app&lt;/param-value&gt;<br />
&nbsp;&nbsp;&lt;/init-param&gt;<br />
&nbsp;&lt;/filter&gt;</font></p>
<p><font color="#0000ff">&nbsp;&lt;filter-mapping&gt;<br />
&nbsp;&nbsp;&lt;filter-name&gt;redirect&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&lt;url-pattern&gt;/&lt;/url-pattern&gt;<br />
&nbsp;&lt;/filter-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&lt;context-param&gt;<br />
&nbsp;&nbsp;&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;<br />
&nbsp;&nbsp;&lt;param-value&gt;/WEB-INF/applicationContext.xml&lt;/param-value&gt;<br />
&nbsp;&lt;/context-param&gt;<br />
&nbsp;&lt;servlet&gt;<br />
&nbsp;&nbsp;&lt;servlet-name&gt;context&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt;<br />
&nbsp;&nbsp;&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&nbsp;&lt;/servlet&gt;<br />
&nbsp;<br />
&nbsp;&lt;servlet&gt;<br />
&nbsp;&nbsp;&lt;servlet-name&gt;sample&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&lt;servlet-class&gt;org.apache.tapestry.ApplicationServlet&lt;/servlet-class&gt;<br />
&nbsp;&nbsp;&lt;load-on-startup&gt;0&lt;/load-on-startup&gt;<br />
&nbsp;&lt;/servlet&gt;</font></p>
<p><font color="#0000ff">&nbsp;&lt;servlet-mapping&gt;<br />
&nbsp;&nbsp;&lt;servlet-name&gt;sample&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&lt;url-pattern&gt;/app&lt;/url-pattern&gt;<br />
&nbsp;&lt;/servlet-mapping&gt;</font></p>
<p><font color="#0000ff">&nbsp;&lt;session-config&gt;<br />
&nbsp;&nbsp;&lt;session-timeout&gt;15&lt;/session-timeout&gt;<br />
&nbsp;&lt;/session-config&gt;<br />
&nbsp;<br />
&nbsp;&lt;welcome-file-list&gt;<br />
&nbsp;&nbsp;&lt;welcome-file&gt;index.htm&lt;/welcome-file&gt;<br />
&nbsp;&lt;/welcome-file-list&gt;<br />
&nbsp;<br />
&lt;/web-app&gt;</font></p>
<p>小结：事实上，这个过程与我上次写的内容大体相似，不过经过实践之后，我可以肯定地说这是走得通的，如果你配置时出现问题，那可能是在一些其它地方忽略了什么。象我这一次就是&#8230;&#8230;嗯，具体的不说了，说出来会很不好意思的。如果有人配置时正好看到这篇文档，希望对你有帮助^_^</p>
<p>Ps其实这一次失误的过程也可以写成篇blog，重点在于期间的心路历程。不过还是算了。这段时间的工作受情绪影响太大了，如果以后成为管理者，一定要注意下属的情绪问题并尽量予以解决，而不能认为职场不需要关注这样的事。</p>
<p>又：Blogbus回退时输入数据会丢失，虽然我知道这是Web应用开发里的难题，不过还是希望能够列入待解决的问题里去-_-<br />
</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-05 23:25 <a href="http://www.blogjava.net/ruoyoux/articles/232575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry学习经验</title><link>http://www.blogjava.net/ruoyoux/articles/232445.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sun, 05 Oct 2008 01:22:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232445.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232445.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232445.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232445.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232445.html</trackback:ping><description><![CDATA[<span style="font-family: 方正姚体">这段时间在学习Tapestry,有些经验给大家分享一下.<br style="font-family: " />
主要实例有:appfuse,workbench,tapmenu-examples<br style="font-family: " />
<br style="font-family: " />
appfuse应用架构:Tapestry + Spring + Hibernate + decorators <br style="font-family: " />
偶现在做了Eclipse版,对初学者是非常实用的一个实例!!!用MyEclipse导入和加入MySQL就可以用了.<br style="font-family: " />
这个架构应用到权限管理.decorators这个漆工非常实例,可以按不同的文件进行漆改的.做页面开发速度非常快.<br style="font-family: " />
做web开发中应用到的内容基本上都包含有了.而且完全开源的.可以任意修改.<br style="font-family: " />
主要的栏目有:权限,漆工,登陆,上传,日志,缓存,多语言版,账号的添加和修改等等...是学习Tapestry最好的一个实例.<br style="font-family: " />
<br style="font-family: " />
下载网址:在这儿出现:上传失败：文件大小超出 2,000 k&nbsp;&nbsp; 继续上传;<br style="font-family: " />
文件大小为20M; 这儿上传不了,去问群主要.(希望版主提供空间)<br style="font-family: " />
账号和密码为:tomcat<br style="font-family: " />
<br style="font-family: " />
<br style="font-family: " />
在这段时间里学习Tapestry的不便之处有几点:<br style="font-family: " />
1.在Eclipse更改后要在tomcat的servlet管理里重启一下appfuse,不知有没有更好的方法可以不用重启的.<br style="font-family: " />
2.应用Velocity作servlet模板时不能显示中文.我加入的servlet实例.<br style="font-family: " />
3.在accessDecisionManager里能不能实例对目录的权限管理.<br style="font-family: " />
请大哥们指点一下.<br style="font-family: " />
<br style="font-family: " />
tapestry3英文手册:<br style="font-family: " />
http://tapestry.apache.org/tapestry3/doc/ComponentReference/index.html<br style="font-family: " />
tapestry4英文手册:<br style="font-family: " />
http://tapestry.apache.org/tapestry4.1/components/Image.html<br style="font-family: " />
<br style="font-family: " />
<br style="font-family: " />
appfuse的官方下载:<br style="font-family: " />
https://appfuse.dev.java.net/servlets/ProjectDocumentList?folderID=4695&amp;expandFolder=4695&amp;folderID=0<br style="font-family: " />
<br style="font-family: " />
appfuse中文学习资料:<br style="font-family: " />
http://www.kingbit.com/appfuse/index.php?job=art&amp;articleid=a_20051016_231832<br style="font-family: " />
<br style="font-family: " />
<br style="font-family: " />
workbench的实例很多地方都可以下载的,自己上网找一下就有了.<br style="font-family: " />
<br style="font-family: " />
<br style="font-family: " />
<br style="font-family: " />
注:以appfuse4.0版为主<br style="font-family: " />
Tapestry的讨论QQ群:8502111<br style="font-family: " />
</span>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-05 09:22 <a href="http://www.blogjava.net/ruoyoux/articles/232445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Spring hibernate T5 Maven2 </title><link>http://www.blogjava.net/ruoyoux/articles/232422.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 16:03:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232422.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232422.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232422.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232422.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232422.html</trackback:ping><description><![CDATA[<font face="Tahoma" size="2">首先抱歉，几篇文章中间的间隔如此之久，一方面工作太忙，一方面也是自己开始偷懒，闲暇之余总是偷懒说自己需要休息一下，可每次总都是休息。<br />
本来这篇文章想说说 使用Maven2 的maven2-xdoclet2-plugin 插件怎么配置生成 hibernate 的 hbm 文件的，在annotation大行其道的时候，我决定省略这一篇了。（有疑问者，可在此处发消息，^_^）。<br />
</font>
<p><font face="Tahoma" size="2">这里说 T5 （T5.0.6） 。 T5.0.6 前几天刚刚释放出来，一只在用 5.0.5 ， 6 的SNAPSHOT版本一直没有关注， </font><font face="Tahoma" size="2">发现 Howard Lewis Ship真的是个喜欢变化的人。</font>参见：<a href="http://tapestry.apache.org/tapestry5/release-notes.html"><span class="hilite1">tapestry</span>.apache.org/<span class="hilite1">tapestry</span>5/release-notes.html。</a></p>
<p>这里列举集成配置以及些常用的组件用法，有些说教，或者过于简单，也许对有些人比较用户。</p>
<p>1.与<span class="hilite2">spring</span>集成</p>
修改 web.xml 中的xml 代码<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">filter</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;</span><span style="color: #000000">filter</span><span style="color: #000000">-</span><span style="color: #000000">name</span><span style="color: #000000">&gt;</span><span style="color: #000000">appfilter</span><span style="color: #000000">-</span><span style="color: #000000">name</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;</span><span style="color: #000000">filter</span><span style="color: #000000">-</span><span style="color: #0000ff">class</span><span style="color: #000000">&gt;</span><span style="color: #000000">org.apache.tapestry.TapestryFilterfilter</span><span style="color: #000000">-</span><span style="color: #0000ff">class</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />filter</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span></div>
为：xml 代码<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">filter</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;</span><span style="color: #000000">filter</span><span style="color: #000000">-</span><span style="color: #000000">name</span><span style="color: #000000">&gt;</span><span style="color: #000000">financeReportfilter</span><span style="color: #000000">-</span><span style="color: #000000">name</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;</span><span style="color: #000000">filter</span><span style="color: #000000">-</span><span style="color: #0000ff">class</span><span style="color: #000000">&gt;</span><span style="color: #000000">org.apache.tapestry.spring.TapestrySpringFilterfilter</span><span style="color: #000000">-</span><span style="color: #0000ff">class</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />filter</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span></div>
<br />
2. Select<br />
<br />
<p>你可以建立你的 SelectTest.tml文件 </p>
<p>xml 代码</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">select&nbsp;t:id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">id3</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;t:name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">name3</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;t:type</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">select</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;model</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">genericSelectModel</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;encoder</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">genericValueEncoder</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">someBean</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;</span></div>
<br />
<br />
SelectTest.java 可如下<br />
java 代码<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">&nbsp;1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">@Persist&nbsp;<br />
</span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;Customer&nbsp;_someBean;&nbsp;<br />
</span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />@Inject&nbsp;<br />
</span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;PropertyAccess&nbsp;propertyAccess;&nbsp;<br />
</span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img id="Codehighlighter1_120_142_Open_Image" onclick="this.style.display='none'; Codehighlighter1_120_142_Open_Text.style.display='none'; Codehighlighter1_120_142_Closed_Image.style.display='inline'; Codehighlighter1_120_142_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_120_142_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_120_142_Closed_Text.style.display='none'; Codehighlighter1_120_142_Open_Image.style.display='inline'; Codehighlighter1_120_142_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Customer&nbsp;getSomeBean()&nbsp;</span><span id="Codehighlighter1_120_142_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_120_142_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;_someBean;&nbsp;<br />
</span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">10</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">11</span><span style="color: #000000"><img id="Codehighlighter1_190_222_Open_Image" onclick="this.style.display='none'; Codehighlighter1_190_222_Open_Text.style.display='none'; Codehighlighter1_190_222_Closed_Image.style.display='inline'; Codehighlighter1_190_222_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_190_222_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_190_222_Closed_Text.style.display='none'; Codehighlighter1_190_222_Open_Image.style.display='inline'; Codehighlighter1_190_222_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setSomeBean(Customer&nbsp;_someBean)&nbsp;</span><span id="Codehighlighter1_190_222_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_190_222_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">12</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">this</span><span style="color: #000000">._someBean&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;_someBean;&nbsp;<br />
</span><span style="color: #008080">13</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">14</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">for&nbsp;Select,&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">15</span><span style="color: #008000"><img id="Codehighlighter1_283_360_Open_Image" onclick="this.style.display='none'; Codehighlighter1_283_360_Open_Text.style.display='none'; Codehighlighter1_283_360_Closed_Image.style.display='inline'; Codehighlighter1_283_360_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_283_360_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_283_360_Closed_Text.style.display='none'; Codehighlighter1_283_360_Open_Image.style.display='inline'; Codehighlighter1_283_360_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;SelectModel&nbsp;getGenericSelectModel()&nbsp;</span><span id="Codehighlighter1_283_360_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_283_360_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">16</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GenericSelectionModel(getBeanList(),&nbsp;propertyAccess,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">name</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;<br />
</span><span style="color: #008080">17</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">18</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">19</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">for&nbsp;select&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">20</span><span style="color: #008000"><img id="Codehighlighter1_423_496_Open_Image" onclick="this.style.display='none'; Codehighlighter1_423_496_Open_Text.style.display='none'; Codehighlighter1_423_496_Closed_Image.style.display='inline'; Codehighlighter1_423_496_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_423_496_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_423_496_Closed_Text.style.display='none'; Codehighlighter1_423_496_Open_Image.style.display='inline'; Codehighlighter1_423_496_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;ValueEncoder&nbsp;getGenericValueEncoder()&nbsp;</span><span id="Codehighlighter1_423_496_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_423_496_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">21</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GenericValueEncoder(getBeanList(),&nbsp;propertyAccess,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">id</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;<br />
</span><span style="color: #008080">22</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">23</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">24</span><span style="color: #000000"><img id="Codehighlighter1_526_737_Open_Image" onclick="this.style.display='none'; Codehighlighter1_526_737_Open_Text.style.display='none'; Codehighlighter1_526_737_Closed_Image.style.display='inline'; Codehighlighter1_526_737_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_526_737_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_526_737_Closed_Text.style.display='none'; Codehighlighter1_526_737_Open_Image.style.display='inline'; Codehighlighter1_526_737_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;List&nbsp;getBeanList()&nbsp;</span><span id="Codehighlighter1_526_737_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_526_737_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">25</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />_beanList&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ArrayList();&nbsp;<br />
</span><span style="color: #008080">26</span><span style="color: #000000"><img id="Codehighlighter1_588_715_Open_Image" style="display: inline" onclick="this.style.display='none'; Codehighlighter1_588_715_Open_Text.style.display='none'; Codehighlighter1_588_715_Closed_Image.style.display='inline'; Codehighlighter1_588_715_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_588_715_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_588_715_Closed_Text.style.display='none'; Codehighlighter1_588_715_Open_Image.style.display='inline'; Codehighlighter1_588_715_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_588_715_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_588_715_Open_Text" style="display: inline"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">27</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />Customer&nbsp;c&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Customer();&nbsp;<br />
</span><span style="color: #008080">28</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />c.setName(</span><span style="color: #000000">"</span><span style="color: #000000">Customer&nbsp;Name</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;i);&nbsp;<br />
</span><span style="color: #008080">29</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />c.setCode(</span><span style="color: #000000">"</span><span style="color: #000000">Code</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;i);&nbsp;<br />
</span><span style="color: #008080">30</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />c.setId(</span><span style="color: #000000">""</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;i);&nbsp;<br />
</span><span style="color: #008080">31</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />_beanList.add(c);&nbsp;<br />
</span><span style="color: #008080">32</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">33</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;_beanList;&nbsp;<br />
</span><span style="color: #008080">34</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">35</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">36</span><span style="color: #000000"><img id="Codehighlighter1_781_813_Open_Image" onclick="this.style.display='none'; Codehighlighter1_781_813_Open_Text.style.display='none'; Codehighlighter1_781_813_Closed_Image.style.display='inline'; Codehighlighter1_781_813_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_781_813_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_781_813_Closed_Text.style.display='none'; Codehighlighter1_781_813_Open_Image.style.display='inline'; Codehighlighter1_781_813_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setBeanList(List&nbsp;_beanList)&nbsp;</span><span id="Codehighlighter1_781_813_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_781_813_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">37</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">this</span><span style="color: #000000">._beanList&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;_beanList;&nbsp;<br />
</span><span style="color: #008080">38</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;</span></div>
<br />
GenericValueEncoder 和GenericSelectionModel 的实现方式也比较简单，可以参见<br />
<a href="http://wiki.apache.org/tapestry/Tapestry5SelectObject">wiki.apache.org/<span class="hilite1">tapestry</span>/<span class="hilite1">Tapestry</span>5SelectObject</a>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-05 00:03 <a href="http://www.blogjava.net/ruoyoux/articles/232422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tapestry的第一面</title><link>http://www.blogjava.net/ruoyoux/articles/232419.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:52:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232419.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232419.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232419.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232419.html</trackback:ping><description><![CDATA[<span style="font-family: 方正姚体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最权威的书是tapestry In Action，但初学者上手困难，另一本很好的是Enjoying Web Development with Tapestry，非常的棒，由浅入深，可惜目前无法找全这本书，<a style="font-family: " href="http://www.itpub.net/390564.html">http://www.itpub.net/390564.html</a>有前4章。下定决心写我自己的学习笔记。<br style="font-family: " />
　　每一个tapestry应用都要有一个Home page，当tapestry接收第一个request时，就会查找Home.page，这是他的总入口。因为tapestry的URL对于人可读性极差(3.1将改变这种情况)，如：<a style="font-family: " href="http://localhost:8080/HelloWorld/app?service=page/Home">http://localhost:8080/HelloWorld/app?service=page/Home</a>，如果访问具体页面在page后面指定即可，如有个AddItem页面一定要真实存在AddItem.html，只需/app?service=page/AddItem。就这么个浅显的问题在InAction中居然没有介绍，害的我找了两天呀，最后还是在Enjoying中清楚的写着呀，真是本好书呀！<br style="font-family: " />
tomcat5.0.28中把类包放到shared/lib下是不行的，找不类，在Engoying书中就是这样用的，版本是tomcat-5.5.7！应用程序的路径不在tomcat目录下这样使用，有待一试！<br style="font-family: " />
在页面对应的类文件中，定义抽象方法，就要在.page配置文件中定义，告诉tapestry负责管理这个属性，例如：<br style="font-family: " />
public abstract void setDvd(DVD dvd);<br style="font-family: " />
public abstract DVD getDvd();<br style="font-family: " />
&lt;property-specificationname="dvd" type="com.sandcast.examples.tapestry.crud.bo.DVD"/&gt;<br style="font-family: " />
事件驱动，在类中定义listener必须满足这个格式：<br style="font-family: " />
public void methodName(IRequestCycle cycle) {}<br style="font-family: " />
Global类是在框架内可以调用保存在context范围内的，如果用得到要求自己实现这个类，名字可以任意命名，但要在servletName.application配置文件中定义：<br style="font-family: " />
&lt;property name="org.apache.tapestry.global-class" value="com.sandcast.examples.tapestry.Global"/&gt;<br style="font-family: " />
</span>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:52 <a href="http://www.blogjava.net/ruoyoux/articles/232419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tsh Tapestry Spring Hibernate 集成笔记</title><link>http://www.blogjava.net/ruoyoux/articles/232417.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:49:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232417.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232417.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232417.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232417.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232417.html</trackback:ping><description><![CDATA[<p>参考了网上好多文章，记不太清了，在此一并感谢！主要有：<br />
<span class="title"><strong><font face="Verdana" color="#003366" size="2">Tapestry整合Spring实践 </font></strong></span><a href="http://tech.blogbus.com/logs/2004/06/219144.html">http://tech.blogbus.com/logs/2004/06/219144.html</a><br />
<br />
1、在eclipse中新建tapestry项目，项目名称tshDemo<br />
2、菜单myEclipse--&gt;Add Spring Capabilities... ，<br />
<img height="482" src="http://blog.yesky.com/blog/images/yesky_com/javafoot/20060124144232_323.gif" width="438" border="0"  alt="" /><br />
<br />
点击Next&gt; ，注意的一点是，没有使用myeclipse自带的jar包，而是选择User Libraries自己定义的最新的spring开发包(方法是在Window--&gt;Preferences...--&gt;Java--&gt;Build Path--&gt;User Libraries中定义)，为了使WEB-INF/lib目录下包含相应jar包，选择拷贝到目录<br />
<img height="482" src="http://blog.yesky.com/blog/images/yesky_com/javafoot/20060124144527_245.jpg" width="438" border="0"  alt="" /><br />
<br />
点击Finish，完成对spring支持，有一个不好的是，eclipse会把所有的jar包文件一个个明细的列在项目名下，倍长非常不方便，修改办法，在项目属性--&gt;Java Build Path--&gt;Libraries中，把所有的明细jar包全部选中删除，点击Add Library...--&gt;User Library--&gt;Next&gt; --&gt;勾选相应的user library--&gt;Finish 即可<br />
<br />
3、修改web.xml如下：<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE web-app<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>"&gt;</p>
<p>&lt;web-app&gt;<br />
&nbsp; &lt;display-name&gt;tshDemo&lt;/display-name&gt;</p>
<p>&nbsp; &lt;filter&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;redirect&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-class&gt;org.apache.tapestry.RedirectFilter&lt;/filter-class&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;redirect-path&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;/app&lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br />
&nbsp; &lt;/filter&gt;</p>
<p>&nbsp; &lt;filter-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;redirect&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/&lt;/url-pattern&gt;<br />
&nbsp; &lt;/filter-mapping&gt;</p>
<p>&nbsp; &lt;listener&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;listener-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.web.context.ContextLoaderListener<br />
&nbsp;&nbsp;&nbsp; &lt;/listener-class&gt;<br />
&nbsp; &lt;/listener&gt;</p>
<p>&nbsp; &lt;servlet&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;tshDemo&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.tapestry.ApplicationServlet<br />
&nbsp;&nbsp;&nbsp; &lt;/servlet-class&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&nbsp; &lt;/servlet&gt;<br />
&nbsp; &lt;servlet-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;tshDemo&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/app&lt;/url-pattern&gt;<br />
&nbsp; &lt;/servlet-mapping&gt;<br />
&lt;/web-app&gt;<br />
<br />
4、修改applicationContext.xml如下：<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "<a href="http://www.springframework.org/dtd/spring-beans.dtd">http://www.springframework.org/dtd/spring-beans.dtd</a>"&gt;</p>
<p>&lt;beans&gt;<br />
&nbsp; &lt;description&gt;Spring Quick Start&lt;/description&gt;<br />
&nbsp; &lt;bean id="theAction" class="tsh.demo.service.LowerAction"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="message"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;HeLLo &lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;/bean&gt;</p>
<p>&lt;/beans&gt;<br />
<br />
5、新建3个包，tsh.demo.dao 持久层，tsh.demo.service 中间层，tsh.demo.web 表示层<br />
<br />
6、tapestry支持spring，新建tapestry engine类，如下：<br />
/*<br />
&nbsp;* package tsh.demo.web;<br />
&nbsp;* class tsh.demo.web.EngineWithSpring<br />
&nbsp;* Created on 2006-1-23, 17:49:43<br />
&nbsp;*/<br />
package tsh.demo.web;</p>
<p>import java.util.Map;</p>
<p>import org.apache.tapestry.engine.BaseEngine;<br />
import org.apache.tapestry.request.RequestContext;<br />
import org.springframework.context.ApplicationContext;<br />
import org.springframework.web.context.support.WebApplicationContextUtils;</p>
<p>public class EngineWithSpring extends BaseEngine {</p>
<p>&nbsp;private static final long serialVersionUID = 1L;<br />
&nbsp;public static final String APPLICATION_CONTEXT_KEY = "appContext";<br />
&nbsp;<br />
&nbsp;protected void setupForRequest(RequestContext context) {<br />
&nbsp;&nbsp;super.setupForRequest(context);<br />
&nbsp;&nbsp;Map global = (Map) getGlobal();<br />
&nbsp;&nbsp;ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);<br />
&nbsp;&nbsp;if (ac == null) {<br />
&nbsp;&nbsp;&nbsp;ac = WebApplicationContextUtils.getWebApplicationContext(context.getServlet().getServletContext());<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;System.out.println("测试" + ac);//你可以看看这一句在什么时候执行，从而了解Engine是什么时候被调用的;<br />
&nbsp;&nbsp;global.put(APPLICATION_CONTEXT_KEY, ac);<br />
&nbsp;}<br />
}<br />
<br />
7、修改tapestry配置文件tshDemo.application，如下：<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE application PUBLIC<br />
&nbsp; "-//Apache Software Foundation//Tapestry Specification 3.0//EN"<br />
&nbsp; "<a href="http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd</a>"&gt;<br />
&lt;!-- generated by Spindle, <a href="http://spindle.sourceforge.net/">http://spindle.sourceforge.net</a> --&gt;</p>
<p>&lt;application name="tshDemo" <font color="#ff0000">engine-class="tsh.demo.web.EngineWithSpring"</font>&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;description&gt;add a description&lt;/description&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;page name="Home" specification-path="Home.page"/&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&lt;/application&gt;<br />
<br />
8、修改Home.page文件，如下：<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE page-specification PUBLIC<br />
&nbsp; "-//Apache Software Foundation//Tapestry Specification 3.0//EN"<br />
&nbsp; "<a href="http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd</a>"&gt;<br />
&lt;!-- generated by Spindle, <a href="http://spindle.sourceforge.net/">http://spindle.sourceforge.net</a> --&gt;</p>
<p>&lt;page-specification class="tsh.demo.web.pages.Home"&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;description&gt;add a description&lt;/description&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property-specification name="theAction" type="tsh.demo.service.Action" &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;<font color="#ff0000"><strong>global.appContext.getBean("theAction")</strong></font><br />
&nbsp;&nbsp;&nbsp; &lt;/property-specification&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property-specification name="greeting" type="java.lang.String" /&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&lt;/page-specification&gt;<br />
<br />
9、Home类，如下：<br />
/*<br />
&nbsp;* package tsh.demo.web.pages;<br />
&nbsp;* class tsh.demo.web.pages.Home<br />
&nbsp;* Created on 2006-1-24, 10:51:12<br />
&nbsp;*/<br />
package tsh.demo.web.pages;</p>
<p>import org.apache.tapestry.event.PageEvent;<br />
import org.apache.tapestry.event.PageRenderListener;<br />
import org.apache.tapestry.html.BasePage;</p>
<p>import tsh.demo.service.Action;</p>
<p>public abstract class Home extends BasePage implements PageRenderListener {</p>
<p>&nbsp;public abstract Action getTheAction();<br />
&nbsp;public abstract void setGreeting(String greeting);<br />
&nbsp;<br />
&nbsp;/* (non-Javadoc)<br />
&nbsp; * @see org.apache.tapestry.event.PageRenderListener#pageBeginRender(org.apache.tapestry.event.PageEvent)<br />
&nbsp; */<br />
&nbsp;public void pageBeginRender(PageEvent event) {<br />
&nbsp;&nbsp;System.out.println(getTheAction().execute("Rod Johnson"));<br />
&nbsp;&nbsp;setGreeting(getTheAction().execute("Rod Johnson"));<br />
&nbsp;}<br />
}<br />
<br />
10、Home.html文件，如下：<br />
&lt;html jwcid="@Shell" title="application"&gt;<br />
&lt;head&gt;&lt;/head&gt;<br />
&lt;body&gt;<br />
&nbsp;&nbsp; &lt;h3&gt;welcome, &lt;/h3&gt;&lt;h1&gt;&lt;span jwcid="@Insert" value="ognl:greeting" /&gt;&lt;/h1&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;<br />
<br />
11、相关spring bean 类如下：<br />
/*<br />
&nbsp;* package tsh.demo.service;<br />
&nbsp;* class tsh.demo.service.Action<br />
&nbsp;* Created on 2005-11-23, 16:32:52<br />
&nbsp;*/<br />
package tsh.demo.service;</p>
<p>public interface Action {<br />
&nbsp;public String execute(String str);<br />
}<br />
<br />
/*<br />
&nbsp;* package tsh.demo.service;<br />
&nbsp;* class tsh.demo.service.LowerAction<br />
&nbsp;* Created on 2005-11-23, 16:36:32<br />
&nbsp;*/<br />
package tsh.demo.service;</p>
<p>public class LowerAction implements Action {<br />
&nbsp; private String message; <br />
&nbsp;&nbsp; <br />
&nbsp; public String getMessage() { <br />
&nbsp;&nbsp;return message; <br />
&nbsp; } <br />
&nbsp; <br />
&nbsp; public void setMessage(String string) { <br />
&nbsp;&nbsp; message = string; <br />
&nbsp; } <br />
&nbsp; <br />
&nbsp; public String execute(String str) { <br />
&nbsp;&nbsp;&nbsp; return (getMessage() + str).toLowerCase(); <br />
&nbsp;} </p>
<p>}<br />
<br />
/*<br />
&nbsp;* package tsh.demo.service;<br />
&nbsp;* class tsh.demo.service.UpperAction<br />
&nbsp;* Created on 2005-11-23, 16:34:17<br />
&nbsp;*/<br />
package tsh.demo.service;</p>
<p>public class UpperAction implements Action {</p>
<p>&nbsp; private String message; <br />
&nbsp;&nbsp; <br />
&nbsp; public String getMessage() { <br />
&nbsp;&nbsp;return message; <br />
&nbsp; } <br />
&nbsp; <br />
&nbsp; public void setMessage(String string) { <br />
&nbsp;&nbsp; message = string; <br />
&nbsp; } <br />
&nbsp; <br />
&nbsp; public String execute(String str) { <br />
&nbsp;&nbsp; return (getMessage() + str).toUpperCase(); <br />
&nbsp; } </p>
<p>}<br />
<br />
12、在%CATALINA_HOME%\conf\Catalina\localhost目录下建tshDemo.xml文件，如下：<br />
&lt;Context path="/tshDemo" docBase="D:\eclipseWorks\workspace\tshDemo\context"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; debug="0" privileged="true" reloadable="true"&gt;<br />
&nbsp; &lt;Logger className="org.apache.catalina.logger.FileLogger"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prefix="localhost_Mssql_log." suffix=".txt"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timestamp="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;!-- maxActive: Maximum number of dB connections in pool. Make sure you<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; configure your mysqld max_connections large enough to handle<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; all of your db connections. Set to 0 for no limit.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;!-- maxIdle: Maximum number of idle dB connections to retain in pool.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set to -1 for no limit.&nbsp; See also the DBCP documentation on this<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and the minEvictableIdleTimeMillis configuration parameter.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;!-- maxWait: Maximum time to wait for a dB connection to become available<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in ms, in this example 10 seconds. An Exception is thrown if<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this timeout is exceeded.&nbsp; Set to -1 to wait indefinitely.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;!-- username and password: MySQL dB username and password for dB connections&nbsp; --&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;!-- driverClassName: Class name for the old mm.mysql JDBC driver is<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.gjt.mm.mysql.Driver - we recommend using Connector/J though.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;!-- url: The JDBC connection url for connecting to your MySQL dB.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The autoReconnect=true argument to the url makes sure that the<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mm.mysql JDBC Driver will automatically reconnect if mysqld closed the<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connection.&nbsp; mysqld by default closes idle connections after 8 hours.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp; &lt;!--Resource name="jdbc/m2Base" auth="Container" type="javax.sql.DataSource"<br />
&nbsp;&nbsp;&nbsp; maxActive="100" maxIdle="30" maxWait="10000"<br />
&nbsp;&nbsp;&nbsp; url="jdbc:jtds:sqlserver://im04:1433;DatabaseName=m2Base"<br />
&nbsp;&nbsp;&nbsp; username="xxxx" password="xxxxxxxxx" driverClassName="net.sourceforge.jtds.jdbc.Driver"<br />
&nbsp;&nbsp;&nbsp; removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" /&gt;</p>
<p>&nbsp; &lt;Resource name="jdbc/merp" auth="Container" type="javax.sql.DataSource"<br />
&nbsp;&nbsp;&nbsp; maxActive="100" maxIdle="30" maxWait="10000"<br />
&nbsp;&nbsp;&nbsp; url="jdbc:jtds:sqlserver://im04:1433;DatabaseName=merp"<br />
&nbsp;&nbsp;&nbsp; username="xxxxxxx" password="xxxxxxxxx" driverClassName="net.sourceforge.jtds.jdbc.Driver"<br />
&nbsp;&nbsp;&nbsp; removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" /--&gt;</p>
<p>&lt;/Context&gt;<br />
<br />
<br />
/**<br />
&nbsp;* Hibernate的集成日后补充<br />
&nbsp;**/<br />
66、启动tomcat，访问<a href="http://locahost:8080/tshDemo">http://locahost:8080/tshDemo</a>，如果页面正常显示，配置成功。</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:49 <a href="http://www.blogjava.net/ruoyoux/articles/232417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>20080421 Eclipse hibernate spring Tapestry 1</title><link>http://www.blogjava.net/ruoyoux/articles/232416.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:46:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232416.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232416.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232416.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232416.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232416.html</trackback:ping><description><![CDATA[refer to website here<br />
<br />
<span style="color: red">http://www.shengfang.org/blog/p/20080421EclipsehibernatespringTapestry1.php</span>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:46 <a href="http://www.blogjava.net/ruoyoux/articles/232416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry4+Spring+Hibernate--我的Tapestry4学习经历 </title><link>http://www.blogjava.net/ruoyoux/articles/232414.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:39:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232414.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232414.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232414.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232414.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232414.html</trackback:ping><description><![CDATA[<p><span style="font-family: 方正姚体"><span style="color: #808000">Tapestry4正式版在2006年1月7日终于发布了。这一天，我等了半年。从beta2试用开始，一直等到beta13,再从rc1等到rc3.<br />
之所以等到正式版出台，才开始学习历程，是因为在beta2试学3天，一无所获，错误千出。<br />
学习了10天，终于入门，有感Tapestry4资料之少，写本文，希望能够有助于后来者，少走弯路。<br />
Tapestry学习资料少，其中多为Tapestry3的资料，Tapestry4的资料则少之少，而且T4与T3差异甚大，有不少地方是不一样的。<br />
本文简介以主流的开发框架：Tapestr4+Sping+Hibernate,eclipse 3.1为背景。<br />
一，T4学习曲线在java的众多web 框架中以长且陡著称，入门要多长时间？<br />
老夫愚钝，用了10个工作日。估计，少年才俊7天就可以了。但若无任何TTapestry基础，5天是少不了的。</span></span></p>
<p><span style="font-family: 方正姚体"><span style="color: #808000">二，特别提示一：<br />
目前最新的Spring官方指南（V1.26)关于Spring+Tapestry结合部分，只适用于Tapestry3,不必浪费时间了。<br />
Spring+Tapestry4主要参考是Tapestry4Spring.国内的干扁四季豆的相关部分基本上是照搬。<br />
三，T4正式版自带了几个例子：Vlib,Workbench,我个人看并不怎么样，不是最佳入门例程。对无基础者尤其无用。不要浪费太多时间去试图编译通过。非要编译它，也不要相信其文档所言。我的看法是，很难自动完成，得多次手工干预。其实，不理也罢。<br />
四，正式版所带的文档比较有价值，尤其水UserGuide,40来个components(For,insert...)介绍应该是必读，值得打印。特别提示：T4文档对打印比较友好，修改print.css即可，既省墨，又可有更好的阅读效果。<br />
五，我个人最感谢的是Enjoying Web Development with Tapestry,这本书针对T4进行了更新，也是T4网站推荐的几本书中的第二本。<br />
这本书是我看的材料中最符合初学者友好的教程，提供前4章免费下载，并且可以下载全书代码。我打印了这4章，作为重点教材仔细阅读。<br />
书中的代码，可以轻松地直接导入到ecipse,大大节省了打字时间，而且不象很多网上教程，代码基本上没有错误，可以直接编译通过。</span></span></p>
<p><span style="font-family: 方正姚体"><span style="color: #808000">六，2006年ibm dw上面的资料被吹捧得很高，我个人看，没有价值，都是重复的大陆货，不值得一读。<br />
不要花太多时间去google,baidu,或者去javaeye，springforum之类的站点，把我上面提到的一本书，几个文档仔细阅读，就可以了。<br />
虽然基本上是英文的，但语言都很通俗，四级水平应该就可以了。<br />
</span></span></p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:39 <a href="http://www.blogjava.net/ruoyoux/articles/232414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry 5</title><link>http://www.blogjava.net/ruoyoux/articles/232411.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:31:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232411.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232411.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232411.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232411.html</trackback:ping><description><![CDATA[http://tapestry.apache.org/tapestry5/<br />
<br />
<p>What is Tapestry?<br />
Tapestry is an open-source framework for creating dynamic, robust, highly scalable web applications in Java. Tapestry complements and builds upon the standard Java Servlet API, and so it works in any servlet container or application server.</p>
<p>Tapestry divides a web application into a set of pages, each constructed from components. This provides a consistent structure, allowing the Tapestry framework to assume responsibility for key concerns such as URL construction and dispatch, persistent state storage on the client or on the server, user input validation, localization/internationalization, and exception reporting. Developing Tapestry applications involves creating HTML templates using plain HTML, and combining the templates with small amounts of Java code. In Tapestry, you create your application in terms of objects, and the methods and properties of those objects -- and specifically not in terms of URLs and query parameters. Tapestry brings true object oriented development to Java web applications.</p>
<p>Tapestry is specifically designed to make creating new components very easy, as this is a routine approach when building applications. </p>
<p>Tapestry is architected to scale from tiny, single-page applications all the way up to massive applications consisting of hundreds of individual pages, developed by large, diverse teams. Tapestry easily integrates with any kind of backend, including JEE, HiveMind, Spring and Hibernate.</p>
<p>It's more than what you can do with Tapestry ... it's also how you do it! Tapestry is a vastly productive environment. Java developers love it because they can make Java code changes and see them immediately ... no redeploy, no restart! And it's blazingly fast to boot (even when files change). Designers love it because Tapestry templates are so close to ordinary HTML, without all the cruft and confusion seen in JavaServer Pages. Managers love it because it makes it easy for large teams to work together, and because they know important features (including localization) are baked right in. Once you work in Tapestry there's no going back!</p>
<p>Tapestry is released under the Apache Software Licence 2.0.</p>
<p>Roadmap<br />
Tapestry is, of course, an open-source project, with all the work coming from unpaid volunteers. That being said, our rough timeline is as follows:</p>
<p>5.0 Release Candidate in September 2008 <br />
5.0 Final Release shortly thereafter<br />
5.1 development to follow, on a much shorter release schedule<br />
... but we are all open source developers working on our own time and schedules are hard to pin down. Please be patient. Tapestry 5 is increasingly stable. Further "stable" with Tapestry usually refers to names of interfaces and methods, not to code quality, which is always very, very high.<br />
We are now finally edging towards a release candidate, with most work being documentation, minor bug fixes and modest enhancements. Note that Tapestry team members have been using Tapestry 5 to build production applications, and those experiences are being applied back to the framework to improve its quality: we're finding rough edges and we're smoothing them out.<br />
Third Party Libraries, Tutorials and Resources<br />
Tapestry 5 has inspired a number of people to create third party libraries, providing a mix of new components and new and improved integrations.</p>
<p>Name Author Description <br />
equanda-tapestry5 Joachim Van der Auwera Components useful for building enterprise applications. Includes Accordion, Tabs, Formtraversal. Amongst other things, these focus on easy input of data without the need for a mouse. <br />
Godcode Components Chris Lewis A mixed collection of components providing simple but time-saving functionality, as well as more exotic ones; built on top of the prototype and script.aculo.us javascript libraries. <br />
JumpStart Geoff Callender A "living tutorial" in the form of a base Tapestry application ready to be expanded and customized. <br />
InterLDAP Linagora / Francois Armand LDAP content management system for non tech users. <br />
loom-t5 Chris Scheid Eclipse plugin. <br />
Shams Examples, Components Mohammad H. Shamsi A set of Tapestry 5 Examples, Tutorials, Components, and Documents for beginners. <br />
Tapestry for Nonbelievers Renat Zubairov &amp; Igor Drobiazko Simple introduction to using Tapestry and creating components <br />
T5Components Sven Homburg Ajax-enabled components based on Prototype and Scriptaculous. <br />
tacos-seam Igor Drobiazko Intregrates with JBoss Seam. <br />
tapestry5-acegi Robin Helgelin Integration with the Acegi path-based security framework. <br />
tapestry5-treegrid Gabriel Landais Combination tree navigation and data grid, based on sstree. </p>
<p>New And Of Note<br />
Tapestry now bundles Prototype version 1.6.0.2.<br />
New methods have been added to Node to allow nodes to be moved about or otherwise manipulated.<br />
Application State Objects are now automatically saved back to the session at the end of the request, which ensures that ASO data is properly replicated across at cluster.<br />
The new @Local annotation makes it easier to reference services within the same module when injecting. <br />
Most general documentation has been moved from the tapestry-core module up to the project level.<br />
Work has started on a Tapestry Cookbook, showing how to tackle common scenarios. <br />
Component methods may be marked with the @Log annotation, to enable debug logging of method entry (with parameters) and exit (with return value, or thrown exception).<br />
It is now possible to provide method invocation advice to component methods. This opens up a very powerful Aspect Oriented Programming approach to Tapestry components.<br />
The Exception Report page now identifies the version of the Tapestry framework, and lists out System properties (including the Java classpath).<br />
The Grid component can now update itself in place, using Ajax, when paging or sorting links are clicked.<br />
Added a zone parameter to the BeanEditForm component, to support Ajax updates.<br />
The @Cached annotation has been added to allowing the caching of method results.<br />
What's changed since Tapestry 4?<br />
Tapestry 5 is an all new code base, written from the ground up to take Java web application development to new levels of productivity.</p>
<p>This new release removes many limitations of Tapestry 4:</p>
<p>Components no longer extend from base classes.<br />
Components classes are no longer abstract. Components are pure, simple POJOs (plain old Java objects).<br />
Tapestry no longer uses XML page and component specification files. Information that used to be supplied in such files is now supplied directly in the Java class, using Java annotations and naming conventions.<br />
Changes to Tapestry component templates and classes are now picked up immediately, without any kind of restart. This will even work properly in production, not just during development.<br />
Blazing Speed. The new code base operates considerably faster than Tapestry 4. Critical code paths have been simplified, and the use of reflection has been virtually eliminated. Tapestry 4 was as fast as an equivalent Servlet/JSP application, Tapestry 5 is much faster.<br />
Adaptive API<br />
A key feature of Tapestry 5 is adaptive API.</p>
<p>In traditional Java frameworks, including Tapestry 4, user code is expected to conform to the framework. You create classes that extend from framework-provided base classes, or implement framework-provided interfaces.</p>
<p>This works well until you upgrade to the next release of the framework: with the new features of the upgrade, you will more often than not experience breaks in backwards compatibility. Interfaces or base classes will have changed and your existing code will need to be changed to match.</p>
<p>In Tapestry 5, the framework adapts to your code. You have control over the names of the methods, the parameters they take, and the value that is returned. This is driven by annotations, which tell Tapestry under what circumstances your methods are to be invoked.</p>
<p>For example, you may have a login form and have a method that gets invoked when the form is submitted:</p>
<p>public class Login<br />
{<br />
&nbsp; @Persist<br />
&nbsp; @Property<br />
&nbsp; private String userId;</p>
<p>&nbsp; @Property<br />
&nbsp; private String password;</p>
<p>&nbsp; @Component<br />
&nbsp; private Form form;</p>
<p>&nbsp; @Inject<br />
&nbsp; private LoginAuthenticator authenticator;</p>
<p>&nbsp; void onValidateForm()<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; if (! authenticator.isValidLogin(userId, password))<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; form.recordError("Invalid user name or password.");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }</p>
<p>&nbsp; Object onSuccess()<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; return PostLogin.class;<br />
&nbsp; }</p>
<p>}This short snippet demonstrates a bit about how Tapestry operates. Pages and services within the application are injected with the @Inject annotation. The method names, onValidateForm() and onSuccess(), inform Tapestry about when the method is to be invoked. The two events validateForm and success occur when a form is submitted; "validateForm" is triggered to perform cross-field validations, and "success" is only triggered when there are no validation errors. The onSuccess() method's return value directs Tapestry on what to do next: jump to another page within the application (here identified as the class for the page, but many other options exist). When there are exceptions, the page will be redisplayed to the user.</p>
<p>This also represents a distinct change from Tapestry 4. In earlier versions of Tapestry, the Form component's listener parameter would be bound to the method to invoke, by name. Further, the listener method had to be public. This new approach not only support multiple listeners, but provides an improved separation of view concerns (inside the page's HTML template) and logic concerns, inside the Java class.</p>
<p>In many cases, additional information about the event is available, and can be passed into the method by adding parameters to the method. Again, Tapestry will adapt to your parameters, in whatever order you supply them.</p>
<p>Tapestry also saves you effort: the @Property annotation marks a field as readable and writable; Tapestry will provide the accessor methods automatically.</p>
<p>Finally, Tapestry 5 explicitly separates actions (requests that change things) and rendering (requests that render pages) into two separate requests. Performing an action, such as clicking a link or submitting a form, results in a client side redirect to the new page. This is often called "redirect after post". This helps ensure that URLs in the browser are book-markable ... but also requires that a bit more information be stored in the session between requests (using the @Persist annotation).</p>
<p>About Snapshots and Releases<br />
Tapestry is built using Maven, which makes it really easy to download the source and build it yourself, either the whole project, or just one single module.</p>
<p>Better yet, you can pull down Tapestry modules from the central Maven repository.</p>
<p>The use of Maven has let us move with great speed, providing preview releases and snapshots.</p>
<p>Snapshots are intermediate versions of releases. As I'm writing this, the most recent preview release is 5.0.2 and the current snapshots are for 5.0.3-SNAPSHOT. Maven keys off the -SNAPSHOT suffix and handles the dependency specially. It knows that snapshot releases can change frequently, so it will keep checking (at least once a day, maybe more often) to see if there's an updated version of the snapshot.</p>
<p>A nightly build process on Tapestry's continuous integration server creates new snapshots emevery night/em.</p>
<p>Snapshots don't go in the central Maven repository (that's reserved for full releases). Instead, they go into the Tapestry snapshots repository at http://tapestry.formos.com/maven-snapshot-repository.</p>
<p>To access this repository, you may add -DremoteRepositories=http://tapestry.formos.com/maven-snapshot-repository to the command line when running Maven.</p>
<p>Your best bet is to use the quickstart Maven archetype to create your initial Tapestry project; it generates a full project directory, including a POM that links to the Apache snapshots repository.</p>
<p>Documentation on this site usually refers to the latest snapshot ... that is, it is usually ahead of the last official release. In some cases, it is written as if the snapshot release is stable; if documentation refers to version 5.0.x and that doesn't work, try 5.0.x-SNAPSHOT.</p>
<p>Principle 1 -- Static Structure, Dynamic Behavior<br />
Tapestry is designed to be extremely scalable in several dimensions:</p>
<p>Tapestry applications may contain large numbers of pages and many custom components.<br />
Tapestry applications may contain very complex functionality.<br />
Tapestry applications may be created by large, diverse teams.<br />
Tapestry applications can service large numbers of concurrent users.<br />
One core architecture decision in Tapestry exists to service many of the above goals (and others that are harder to describe). Static Structure, Dynamic Behavior</p>
<p>In Tapestry, the structure of any particular page is static. This is necessary for several reasons, most importantly because Tapestry pages are pooled. Creating a Tapestry page is an involved process, because the page object is simply the root of a large tree of other objects including user provided components, many kinds of structural objects, template objects, and others. Creating a new page instance for each request is simply not scalable.</p>
<p>Instead, Tapestry pools pages. Once created, a page instance will be stored in a pool for that particular type of page, and reused in later requests. An incoming request, the result of a user clicking a link or submitting a form, will be processed by some server within a cluster, and will use some page instance within the page pool. Because page instances are static and uniform across instances and servers, Tapestry can use any available page instance, or create a new one as needed.</p>
<p>Tapestry does not need to store page instances inside the HttpSession. At most, it stores a smattering of persistent field values from the page, but not the entire page instance. This lean use of the HttpSession is key to Tapestry's very high scalability, especially in a clustered configuration.</p>
<p>In some Tapestry-like frameworks, such as Faces and Wicket, the page structure is more dynamic, at the cost of storing much, much more data in the HttpSession.</p>
<p>This static structure is not so limiting as you might think. With different kinds of conditional and looping components, and the ability to "jump out of the flow" and render components in an arbitrary order, you will not find Tapestry to be rigid ... anything but!</p>
<p>Public vs. Internal<br />
An issue plaguing previous versions of Tapestry 4 (and earlier) was the lack of a clear delineator between private, internal APIs and public, external APIs. The fact that your code would extend from base objects but that many of the methods on those base objects were "off limits" further confused the issue. This has been identified as a key factor in the "steep learning curve of Tapestry" meme.</p>
<p>With the clean slate of Tapestry 5, we are being much more ruthless about internal vs. external.</p>
<p>First of all, anything inside the org.apache.tapestry5.internal package is internal. It is part of the implementation of Tapestry. It is the man behind the curtain. You should not ever need to directly use this code. It is a bad idea to do so, because internal code may change from one release to the next without concern for backwards compatibility.</p>
<p>Backwards Compatibility<br />
Tapestry has been plagued by backwards compatibility problems with every major release. Tapestry 5 does not even attempt to be backwards compatible to Tapestry 4. Instead, it lays the ground work for true backwards compatibility going forwards.</p>
<p>Tapestry 5's API is based almost entirely on naming conventions and annotations. You components are just ordinary Java classes; you will annotate fields to allow Tapestry to maintain their state or to allow Tapestry to inject resources, and you will name (or annotate) methods to tell Tapestry under what circumstances a method should be invoked.</p>
<p>Tapestry will adapt to your classes. It will call your methods, passing in values via method parameters. Instead of the rigidness of a fixed interface to implement, Tapestry will simply adapt to your classes, using the hints provided by annotations and simple naming conventions.</p>
<p>Because of this, Tapestry will be able to change internally to a great degree without it affecting any of the application code you write. This should finally crack the backwards compatibility nut, allowing you to have great assurance that you can upgrade to future releases of Tapestry without breaking your existing applications.</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:31 <a href="http://www.blogjava.net/ruoyoux/articles/232411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Xdoclet 生成spring的配置文件</title><link>http://www.blogjava.net/ruoyoux/articles/232410.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:29:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232410.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232410.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232410.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232410.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232410.html</trackback:ping><description><![CDATA[<p><br />
最近看到xdoclet支持spring的自动生成，参考了一下以前的hibernate的代码，自己做了一个尝试，具体结果如下： <br />
引用: <br />
build.xml </p>
<p>代码: <br />
&lt;target name="define-tasks" description="defines custom tasks"&gt; <br />
&nbsp; &lt;taskdef&nbsp; name="springdoclet"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; classname="xdoclet.modules.spring.SpringDocletTask" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; classpathref="xdoclet.classpath"/&gt;&nbsp;&nbsp;&nbsp; &lt;/target&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;target name="springMap" depends="define-tasks" description="建立spring 的 XML文件"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;springdoclet <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; destdir="${build.dir}" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mergedir="logs" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; excludedtags="@version,@author" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addedtags="@xdoclet-generated at ${TODAY}" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; force="${xdoclet.force}" &gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;fileset dir="src/persistent"/&gt; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;springxml validatexml="true" /&gt; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/springdoclet&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;/target&gt;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p><br />
说明：ant 自动在你的destdir下生成spring.xml.mergedir参数可以包括你自己额外的bean定义，格式是&lt;bean&gt;&lt;/bean&gt;，文件名字必须为spring-beans.xml，如果你需要定义datasource，就可以放在这个文件里。 </p>
<p>下面是我自己的代码例子：（我只写了一点简单的） <br />
代码: </p>
<p>package com.entertop.smsplatform.persistent.hibernate; </p>
<p>import com.entertop.smsplatform.business.exception.CannotManipulateMoSequenceException; <br />
import com.entertop.smsplatform.model.Mo; <br />
import com.entertop.smsplatform.persistent.MoDAO; <br />
import net.sf.hibernate.HibernateException; <br />
import net.sf.hibernate.Hibernate; <br />
import net.sf.hibernate.Session; <br />
import org.apache.log4j.Logger; <br />
import org.springframework.orm.hibernate.support.HibernateDaoSupport; <br />
import org.springframework.orm.hibernate.SessionFactoryUtils; </p>
<p>import java.util.List; <br />
import java.util.Properties; </p>
<p>public final class MoDAOHibernate extends HibernateDaoSupport implements MoDAO{ <br />
} <br />
&nbsp;</p>
<p><br />
&nbsp;</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:29 <a href="http://www.blogjava.net/ruoyoux/articles/232410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 史上最简单的struts+spring+hibernate配置实例</title><link>http://www.blogjava.net/ruoyoux/articles/232408.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:28:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232408.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232408.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232408.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232408.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232408.html</trackback:ping><description><![CDATA[<p>本文不关心必须的JAR包，这个东东在网上能够找到很多，本文只关心如何配置，才能够让STRUTS SPRING HIBERNATE和MYSQL相关连。 </p>
<p>&lt;web.xml&gt; <br />
－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ <br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"&gt; <br />
&lt;web-app id="WebApp"&gt; <br />
&lt;display-name&gt;MVC_BPEL_MODELWeb&lt;/display-name&gt; <br />
&lt;context-param&gt; <br />
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt; <br />
&lt;param-value&gt;/WEB-INF/Hibernate_Context.xml&lt;/param-value&gt; <br />
&lt;/context-param&gt; <br />
&lt;servlet&gt; <br />
&lt;servlet-name&gt;SpringContextServlet&lt;/servlet-name&gt; <br />
&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt; <br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt; <br />
&lt;/servlet&gt; <br />
&lt;servlet&gt; <br />
&lt;servlet-name&gt;action&lt;/servlet-name&gt; <br />
&lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;config&lt;/param-name&gt; <br />
&lt;param-value&gt;WEB-INF/struts-config.xml&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;debug&lt;/param-name&gt; <br />
&lt;param-value&gt;2&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;detail&lt;/param-name&gt; <br />
&lt;param-value&gt;2&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;validate&lt;/param-name&gt; <br />
&lt;param-value&gt;true&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;load-on-startup&gt;2&lt;/load-on-startup&gt; <br />
&lt;/servlet&gt; <br />
&lt;servlet-mapping&gt; <br />
&lt;servlet-name&gt;action&lt;/servlet-name&gt; <br />
&lt;url-pattern&gt;*.do&lt;/url-pattern&gt; <br />
&lt;/servlet-mapping&gt; <br />
&lt;welcome-file-list&gt; <br />
&lt;welcome-file&gt;index.html&lt;/welcome-file&gt; <br />
&lt;welcome-file&gt;index.htm&lt;/welcome-file&gt; <br />
&lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt; <br />
&lt;welcome-file&gt;default.html&lt;/welcome-file&gt; <br />
&lt;welcome-file&gt;default.htm&lt;/welcome-file&gt; <br />
&lt;welcome-file&gt;default.jsp&lt;/welcome-file&gt; <br />
&lt;/welcome-file-list&gt; <br />
&lt;taglib&gt; <br />
&lt;taglib-uri&gt;/WEB-INF/struts-bean.tld&lt;/taglib-uri&gt; <br />
&lt;taglib-location&gt;/WEB-INF/struts-bean.tld&lt;/taglib-location&gt; <br />
&lt;/taglib&gt; <br />
&lt;taglib&gt; <br />
&lt;taglib-uri&gt;/WEB-INF/struts-html.tld&lt;/taglib-uri&gt; <br />
&lt;taglib-location&gt;/WEB-INF/struts-html.tld&lt;/taglib-location&gt; <br />
&lt;/taglib&gt; <br />
&lt;taglib&gt; <br />
&lt;taglib-uri&gt;/WEB-INF/struts-logic.tld&lt;/taglib-uri&gt; <br />
&lt;taglib-location&gt;/WEB-INF/struts-logic.tld&lt;/taglib-location&gt; <br />
&lt;/taglib&gt; <br />
&lt;taglib&gt; <br />
&lt;taglib-uri&gt;/WEB-INF/struts-nested.tld&lt;/taglib-uri&gt; <br />
&lt;taglib-location&gt;/WEB-INF/struts-nested.tld&lt;/taglib-location&gt; <br />
&lt;/taglib&gt; <br />
&lt;taglib&gt; <br />
&lt;taglib-uri&gt;/WEB-INF/struts-template.tld&lt;/taglib-uri&gt; <br />
&lt;taglib-location&gt;/WEB-INF/struts-template.tld&lt;/taglib-location&gt; <br />
&lt;/taglib&gt; <br />
&lt;taglib&gt; <br />
&lt;taglib-uri&gt;/WEB-INF/struts-tiles.tld&lt;/taglib-uri&gt; <br />
&lt;taglib-location&gt;/WEB-INF/struts-tiles.tld&lt;/taglib-location&gt; <br />
&lt;/taglib&gt; </p>
<p>&lt;/web-app&gt; <br />
－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ <br />
&lt;action-servlet.xml&gt; <br />
---------------------------------------------------------------------- <br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" <br />
"http://www.springframework.org/dtd/spring-beans.dtd"&gt; </p>
<p>&lt;beans&gt; <br />
&lt;bean name="/User" class="com.yaya.action.UserAction" singleton="false"&gt; <br />
&lt;property name="userManager"&gt; <br />
&lt;ref bean="userManager" /&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p><br />
&lt;/beans&gt; <br />
------------------------------------------------------------------- <br />
&lt;hibernate_context.xml&gt; <br />
-------------------------------------------------------------------- <br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt; </p>
<p>&lt;beans&gt; <br />
&lt;!-- &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; <br />
&lt;property name="viewClass"&gt;&lt;value&gt;org.springframework.web.servlet.view.JstlView&lt;/value&gt;&lt;/property&gt; <br />
&lt;property name="prefix"&gt;&lt;value&gt;/WEB-INF/jsp/&lt;/value&gt;&lt;/property&gt; <br />
&lt;property name="suffix"&gt;&lt;value&gt;.jsp&lt;/value&gt;&lt;/property&gt; <br />
&lt;/bean&gt; --&gt; </p>
<p>&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt; </p>
<p>&lt;property name="driverClassName"&gt; <br />
&lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt; <br />
&lt;/property&gt; </p>
<p>&lt;property name="url"&gt; <br />
&lt;value&gt;jdbc:mysql://localhost/pdm&lt;/value&gt; <br />
&lt;/property&gt; </p>
<p>&lt;property name="username"&gt; <br />
&lt;value&gt;root&lt;/value&gt; <br />
&lt;/property&gt; </p>
<p>&lt;property name="password"&gt; <br />
&lt;value&gt;&lt;/value&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p>&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"&gt; </p>
<p>&lt;property name="dataSource"&gt; <br />
&lt;ref local="dataSource" /&gt; <br />
&lt;/property&gt; </p>
<p>&lt;property name="mappingResources"&gt; <br />
&lt;list&gt; <br />
&lt;value&gt;hbm_tb/TSysuser.hbm.xml&lt;/value&gt; <br />
&lt;/list&gt; <br />
&lt;/property&gt; </p>
<p>&lt;property name="hibernateProperties"&gt; <br />
&lt;props&gt; <br />
&lt;prop key="hibernate.dialect"&gt;net.sf.hibernate.dialect.MySQLDialect&lt;/prop&gt; <br />
&lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt; <br />
&lt;/props&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p>&lt;bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"&gt; </p>
<p>&lt;property name="sessionFactory"&gt; <br />
&lt;ref local="sessionFactory" /&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p><br />
&lt;!-- Spring的数据访问异常转换器（Data Access Exception Translator）定义 --&gt; <br />
&lt;bean id="jdbcExceptionTranslator" class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator"&gt; <br />
&lt;property name="dataSource"&gt; <br />
&lt;ref bean="dataSource" /&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p>&lt;!-- Hibernate Template定义 --&gt; <br />
&lt;bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate"&gt; <br />
&lt;property name="sessionFactory"&gt; <br />
&lt;ref bean="sessionFactory" /&gt; <br />
&lt;/property&gt; <br />
&lt;property name="jdbcExceptionTranslator"&gt; <br />
&lt;ref bean="jdbcExceptionTranslator" /&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p>&lt;!--baseTransactionProxy --&gt; <br />
&lt;bean abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" id="baseTransactionProxy"&gt; <br />
&lt;property name="transactionManager"&gt; <br />
&lt;ref bean="transactionManager" /&gt; <br />
&lt;/property&gt; <br />
&lt;property name="transactionAttributes"&gt; <br />
&lt;props&gt; <br />
&lt;prop key="save*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />
&lt;prop key="update*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />
&lt;prop key="find*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />
&lt;prop key="*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt; <br />
&lt;/props&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p><br />
&lt;bean id="userDao" class="com.yaya.service.dao.hibernate.UserHibernateDao"&gt; <br />
&lt;property name="sessionFactory"&gt; <br />
&lt;ref local="sessionFactory" /&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p>&lt;bean id="userManagerTarget" class="com.yaya.service.spring.UserManagerImpl"&gt; <br />
&lt;property name="userDao"&gt; <br />
&lt;ref local="userDao" /&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p>&lt;bean id="userManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt; <br />
&lt;property name="transactionManager"&gt; <br />
&lt;ref bean="transactionManager" /&gt; <br />
&lt;/property&gt; </p>
<p>&lt;property name="target"&gt; <br />
&lt;ref local="userManagerTarget" /&gt; <br />
&lt;/property&gt; </p>
<p>&lt;property name="proxyTargetClass"&gt; <br />
&lt;value&gt;true&lt;/value&gt; <br />
&lt;/property&gt; <br />
&lt;property name="transactionAttributes"&gt; <br />
&lt;props&gt; <br />
&lt;prop key="save*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt; <br />
&lt;prop key="remove*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt; <br />
&lt;prop key="*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt; <br />
&lt;/props&gt; <br />
&lt;/property&gt; <br />
&lt;/bean&gt; </p>
<p>&lt;/beans&gt; <br />
------------------------------------------------------------------- <br />
&lt;struts-config.xml&gt; <br />
------------------------------------------------------------------- <br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />
&lt;!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" <br />
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt; </p>
<p>&lt;struts-config&gt; </p>
<p>&lt;!-- 数据源 --&gt; <br />
&lt;data-sources&gt;&lt;/data-sources&gt; </p>
<p>&lt;!-- 表单 Bean --&gt; <br />
&lt;form-beans&gt; <br />
&lt;form-bean name="UserActionForm" type="org.apache.struts.validator.DynaValidatorForm"&gt; <br />
&lt;form-property name="User" type="com.yaya.actionform.UserActionForm" /&gt; <br />
&lt;/form-bean&gt; <br />
&lt;/form-beans&gt; </p>
<p>&lt;!-- 全局异常 --&gt; <br />
&lt;global-exceptions&gt;&lt;/global-exceptions&gt; </p>
<p>&lt;!-- 全局转发 --&gt; <br />
&lt;global-forwards&gt;&lt;/global-forwards&gt; </p>
<p>&lt;!-- 操作映射 --&gt; <br />
&lt;action-mappings&gt; <br />
&lt;action path="/User" type="org.springframework.web.struts.DelegatingActionProxy" name="UserActionForm" scope="request" parameter="method" validate="false"&gt; <br />
&lt;forward name="list" path="/userlist.jsp" /&gt; <br />
&lt;forward name="edit" path="/userform.jsp" /&gt; <br />
&lt;/action&gt; </p>
<p>&lt;/action-mappings&gt; </p>
<p>&lt;!-- 消息资源 --&gt; <br />
&lt;message-resources parameter="mvc_bpel_modelweb.resources.ApplicationResources" /&gt; <br />
&lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt; <br />
&lt;set-property property="contextConfigLocation" value="/WEB-INF/action-servlet.xml" /&gt; <br />
&lt;/plug-in&gt; </p>
<p>&lt;/struts-config&gt; <br />
------------------------------------------------------------------ <br />
UserHibernateDao.java <br />
------------------------------------------------------------------ <br />
/* <br />
* 创建日期 2005-4-7 <br />
* <br />
* 更改所生成文件模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
package com.yaya.service.dao.hibernate; </p>
<p>import java.util.List; </p>
<p>import org.springframework.orm.ObjectRetrievalFailureException; <br />
import org.springframework.orm.hibernate.support.HibernateDaoSupport; </p>
<p>import com.yaya.hb.TSysuser; <br />
import com.yaya.service.dao.IUserDao; <br />
import java.util.List; </p>
<p>import org.apache.commons.logging.Log; </p>
<p>import org.apache.commons.logging.LogFactory; </p>
<p>/** <br />
* @author Administrator <br />
* <br />
* 更改所生成类型注释的模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
public class UserHibernateDao extends HibernateDaoSupport implements IUserDao { </p>
<p>private Log log = LogFactory.getLog(UserHibernateDao.class); </p>
<p>/* （非 Javadoc） </p>
<p>* @see com.jandar.dao.IUserDAO#getUsers() </p>
<p>*/ </p>
<p>public List getUsers() { </p>
<p>return getHibernateTemplate().find("from TSysuser"); </p>
<p>} </p>
<p>/* （非 Javadoc） </p>
<p>* @see com.jandar.dao.IUserDAO#getUser(java.lang.Long) </p>
<p>*/ </p>
<p>public TSysuser getUser(String username) { </p>
<p>// TODO 自动生成方法存根 <br />
//String msg = getHibernateTemplate().get(TSysuser.class,username).toString(); <br />
TSysuser user = (TSysuser) getHibernateTemplate().get(TSysuser.class,username); <br />
//TSysuser user = (TSysuser) getHibernateTemplate().find("from TSysuser where username = ?",username); <br />
System.out.println(user.getUserdesc()); <br />
System.out.println(user.getHeadship()); <br />
if (user == null) { <br />
throw new ObjectRetrievalFailureException(TSysuser.class, username); <br />
} <br />
return user; <br />
} </p>
<p>/* （非 Javadoc） </p>
<p>* @see com.jandar.dao.IUserDAO#saveUser(com.jandar.model.User) </p>
<p>*/ </p>
<p>public void saveUser(TSysuser user) { </p>
<p>log.debug("xxxxxxx"); </p>
<p>System.out.println("yyyy"); </p>
<p>getHibernateTemplate().saveOrUpdate(user); </p>
<p>if (log.isDebugEnabled()) { </p>
<p>log.debug("username set to " + user.getUsername()); </p>
<p>} </p>
<p>} </p>
<p>/* （非 Javadoc） </p>
<p>* @see com.jandar.dao.IUserDAO#removeUser(java.lang.Long) </p>
<p>*/ </p>
<p>public void removeUser(String username) { </p>
<p>Object user = getHibernateTemplate().load(TSysuser.class, username); </p>
<p>getHibernateTemplate().delete(user); </p>
<p>if (log.isDebugEnabled()) { </p>
<p>log.debug("del user " + username); </p>
<p>} </p>
<p>} </p>
<p>} <br />
------------------------------------------------------------------- <br />
useraction.java <br />
-------------------------------------------------------------------- <br />
/* <br />
* 创建日期 2005-4-11 <br />
* <br />
* 更改所生成文件模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
package com.yaya.action; </p>
<p>import java.util.Date; </p>
<p>import org.apache.struts.actions.DispatchAction; <br />
import javax.servlet.http.HttpServletRequest; <br />
import javax.servlet.http.HttpServletResponse; </p>
<p>import org.apache.commons.beanutils.ConvertUtils; <br />
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter; <br />
import org.apache.commons.logging.Log; <br />
import org.apache.commons.logging.LogFactory; <br />
import org.apache.struts.action.ActionErrors; <br />
import org.apache.struts.action.ActionForm; <br />
import org.apache.struts.action.ActionForward; <br />
import org.apache.struts.action.ActionMapping; <br />
import org.apache.struts.action.ActionMessage; <br />
import org.apache.struts.action.ActionMessages; <br />
import org.apache.struts.action.DynaActionForm; <br />
import org.apache.struts.util.MessageResources; </p>
<p>import com.yaya.hb.TSysuser; <br />
import com.yaya.service.spring.UserManagerImpl; <br />
/** <br />
* @author Administrator <br />
* <br />
* 更改所生成类型注释的模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
public class UserAction extends DispatchAction { </p>
<p>private static Log log = LogFactory.getLog(UserAction.class); <br />
private UserManagerImpl mgr = null; <br />
public void setUserManager(UserManagerImpl userManager) { <br />
this.mgr = userManager; <br />
} </p>
<p>public ActionForward delete( <br />
ActionMapping mapping, <br />
ActionForm form, <br />
HttpServletRequest request, <br />
HttpServletResponse response) <br />
throws Exception { <br />
if (log.isDebugEnabled()) { <br />
log.debug("entering 'delete' method..."); <br />
} <br />
mgr.removeUser(request.getParameter("user.username")); <br />
ActionMessages messages = new ActionMessages(); <br />
messages.add( <br />
ActionMessages.GLOBAL_MESSAGE, <br />
new ActionMessage("user.deleted")); <br />
saveMessages(request, messages); <br />
return list(mapping, form, request, response); <br />
} </p>
<p>public ActionForward edit( <br />
ActionMapping mapping, <br />
ActionForm form, <br />
HttpServletRequest request, <br />
HttpServletResponse response) <br />
throws Exception { <br />
if (log.isDebugEnabled()) { <br />
log.debug("entering 'edit' method..."); <br />
} </p>
<p>DynaActionForm userForm = (DynaActionForm) form; <br />
String username = request.getParameter("username"); </p>
<p>// null userId indicates an add <br />
if (username != null) { <br />
try <br />
{ <br />
TSysuser user = mgr.getUser(username); <br />
if (user == null) { <br />
ActionMessages errors = new ActionMessages(); <br />
errors.add( <br />
ActionMessages.GLOBAL_MESSAGE, <br />
new ActionMessage("user.missing")); <br />
saveErrors(request, (ActionErrors) errors); <br />
return mapping.findForward("list"); <br />
} <br />
userForm.set("user", user); <br />
request.setAttribute("user",user); <br />
} <br />
catch(Exception e) <br />
{ <br />
e.printStackTrace(); <br />
} </p>
<p>} <br />
return mapping.findForward("edit"); <br />
} </p>
<p>public ActionForward list( <br />
ActionMapping mapping, <br />
ActionForm form, <br />
HttpServletRequest request, <br />
HttpServletResponse response) <br />
throws Exception { <br />
if (log.isDebugEnabled()) { <br />
log.debug("entering 'list' method..."); <br />
} <br />
request.setAttribute("users", mgr.getUsers()); <br />
return mapping.findForward("list"); <br />
} </p>
<p>public ActionForward save( <br />
ActionMapping mapping, <br />
ActionForm form, <br />
HttpServletRequest request, <br />
HttpServletResponse response) <br />
throws Exception { <br />
if (log.isDebugEnabled()) { <br />
log.debug("entering 'save' method..."); <br />
} </p>
<p>if (isCancelled(request)) { <br />
return list(mapping, form, request, response); <br />
} </p>
<p>// run validation rules on this form <br />
ActionMessages errors = form.validate(mapping, request); </p>
<p>if (!errors.isEmpty()) { <br />
saveErrors(request, (ActionErrors) errors); </p>
<p>return mapping.findForward("edit"); <br />
} <br />
DynaActionForm userForm = (DynaActionForm) form; <br />
TSysuser user = (TSysuser) userForm.get("username"); </p>
<p>mgr.saveUser(user); </p>
<p>ActionMessages messages = new ActionMessages(); <br />
messages.add(ActionMessages.GLOBAL_MESSAGE, <br />
new ActionMessage("user.saved", user.getUsername())); <br />
saveMessages((HttpServletRequest) request.getSession(), messages); </p>
<p>return mapping.findForward("users"); <br />
} </p>
<p>public ActionForward unspecified( <br />
ActionMapping mapping, <br />
ActionForm form, <br />
HttpServletRequest request, <br />
HttpServletResponse response) <br />
throws Exception { <br />
return list(mapping, form, request, response); <br />
} </p>
<p>} <br />
------------------------------------------------------------------- <br />
UserMenuActionForm.java <br />
------------------------------------------------------------------- <br />
/* <br />
* 创建日期 2005-3-28 <br />
* <br />
* 更改所生成文件模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
package com.yaya.actionform; </p>
<p>import java.sql.Date; </p>
<p>import org.apache.struts.action.ActionForm; </p>
<p>/** <br />
* @author Administrator <br />
* <br />
* 更改所生成类型注释的模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
public class UserMenuActionForm extends ActionForm { </p>
<p>/** identifier field */ <br />
private String username; </p>
<p>/** identifier field */ <br />
private String fitemcode; </p>
<p>/** identifier field */ <br />
private String itemcode; </p>
<p>/** identifier field */ <br />
private String itemdesc; </p>
<p>/** identifier field */ <br />
private String itemtype; </p>
<p>/** identifier field */ <br />
private Integer itemid; </p>
<p>/** identifier field */ <br />
private String lastmodif; </p>
<p>/** identifier field */ <br />
private Date lastmdate; </p>
<p>/** identifier field */ <br />
private String creadtor; </p>
<p>/** identifier field */ <br />
private Date creatdate; </p>
<p>/** identifier field */ <br />
private String title; </p>
<p>/** identifier field */ <br />
private String url; </p>
<p>/** identifier field */ <br />
private String target; </p>
<p>/** identifier field */ <br />
private String icon; </p>
<p>/** identifier field */ <br />
private String iconopen; </p>
<p>/** identifier field */ <br />
private Integer open; </p>
<p><br />
/** identifier field */ <br />
private Integer id; </p>
<p>/** identifier field */ <br />
private Integer pid; </p>
<p>public String getUsername() { <br />
return this.username; <br />
} </p>
<p>public void setUsername(String username) { <br />
this.username = username; <br />
} </p>
<p>public String getFitemcode() { <br />
return this.fitemcode; <br />
} </p>
<p>public void setFitemcode(String fitemcode) { <br />
this.fitemcode = fitemcode; <br />
} </p>
<p>public String getItemcode() { <br />
return this.itemcode; <br />
} </p>
<p>public void setItemcode(String itemcode) { <br />
this.itemcode = itemcode; <br />
} </p>
<p>public String getItemdesc() { <br />
return this.itemdesc; <br />
} </p>
<p>public void setItemdesc(String itemdesc) { <br />
this.itemdesc = itemdesc; <br />
} </p>
<p>public String getItemtype() { <br />
return this.itemtype; <br />
} </p>
<p>public void setItemtype(String itemtype) { <br />
this.itemtype = itemtype; <br />
} </p>
<p>public Integer getItemid() { <br />
return this.itemid; <br />
} </p>
<p>public void setItemid(Integer itemid) { <br />
this.itemid = itemid; <br />
} </p>
<p>public String getLastmodif() { <br />
return this.lastmodif; <br />
} </p>
<p>public void setLastmodif(String lastmodif) { <br />
this.lastmodif = lastmodif; <br />
} </p>
<p>public Date getLastmdate() { <br />
return this.lastmdate; <br />
} </p>
<p>public void setLastmdate(Date lastmdate) { <br />
this.lastmdate = lastmdate; <br />
} </p>
<p>public String getCreadtor() { <br />
return this.creadtor; <br />
} </p>
<p>public void setCreadtor(String creadtor) { <br />
this.creadtor = creadtor; <br />
} </p>
<p>public Date getCreatdate() { <br />
return this.creatdate; <br />
} </p>
<p>public void setCreatdate(Date creatdate) { <br />
this.creatdate = creatdate; <br />
} </p>
<p>public String getTitle() { <br />
return this.title; <br />
} </p>
<p>public void setTitle(String title) { <br />
this.title = title; <br />
} </p>
<p>public String getUrl() { <br />
return this.url; <br />
} </p>
<p>public void setUrl(String url) { <br />
this.url = url; <br />
} </p>
<p>public String getTarget() { <br />
return this.target; <br />
} </p>
<p>public void setTarget(String target) { <br />
this.target = target; <br />
} </p>
<p>public String getIcon() { <br />
return this.icon; <br />
} </p>
<p>public void setIcon(String icon) { <br />
this.icon = icon; <br />
} </p>
<p>public String getIconopen() { <br />
return this.iconopen; <br />
} </p>
<p>public void setIconopen(String iconopen) { <br />
this.iconopen = iconopen; <br />
} </p>
<p>public Integer getOpen() { <br />
return this.open; <br />
} </p>
<p>public void setOpen(Integer open) { <br />
this.open = open; <br />
} <br />
public Integer getId() { <br />
return this.id; <br />
} </p>
<p>public void setId(Integer id) { <br />
this.id = id; <br />
} </p>
<p>public Integer getPid() { <br />
return this.pid; <br />
} </p>
<p>public void setPid(Integer pid) { <br />
this.pid = pid; <br />
} </p>
<p><br />
} <br />
------------------------------------------------------------------ <br />
package com.yaya.hb; </p>
<p>import java.io.InputStream; <br />
import java.io.Serializable; <br />
import java.util.Date; <br />
import org.apache.commons.lang.builder.EqualsBuilder; <br />
import org.apache.commons.lang.builder.HashCodeBuilder; <br />
import org.apache.commons.lang.builder.ToStringBuilder; </p>
<p>/** @author Hibernate CodeGenerator */ <br />
public class TSysuser implements Serializable { </p>
<p>/** identifier field */ <br />
private String username; </p>
<p>/** identifier field */ <br />
private String userdesc; </p>
<p>/** identifier field */ <br />
private String passwords; </p>
<p>/** identifier field */ <br />
private String deptno; </p>
<p>/** identifier field */ <br />
private String headship; </p>
<p>/** identifier field */ <br />
private String sex; </p>
<p>/** identifier field */ <br />
private String tel; </p>
<p>/** identifier field */ <br />
private String email; </p>
<p>/** identifier field */ <br />
private String url; </p>
<p>/** identifier field */ <br />
private String pcall; </p>
<p>/** identifier field */ </p>
<p>/** identifier field */ <br />
private String userphoto; </p>
<p>/** identifier field */ <br />
private Integer facerefutime; </p>
<p>/** identifier field */ <br />
private String facelanguage; </p>
<p>/** identifier field */ <br />
private String lastmodif; </p>
<p>/** identifier field */ <br />
private Date lastmdate; </p>
<p>/** identifier field */ <br />
private String creadtor; </p>
<p>/** identifier field */ <br />
private Date creatdate; </p>
<p>/** full constructor */ <br />
public TSysuser(String username, String userdesc, String passwords, String deptno, String headship, String sex, String tel, String email, String url, String pcall, InputStream userimage, String userphoto, Integer facerefutime, String facelanguage, String lastmodif, Date lastmdate, String creadtor, Date creatdate) { <br />
this.username = username; <br />
this.userdesc = userdesc; <br />
this.passwords = passwords; <br />
this.deptno = deptno; <br />
this.headship = headship; <br />
this.sex = sex; <br />
this.tel = tel; <br />
this.email = email; <br />
this.url = url; <br />
this.pcall = pcall; <br />
this.userphoto = userphoto; <br />
this.facerefutime = facerefutime; <br />
this.facelanguage = facelanguage; <br />
this.lastmodif = lastmodif; <br />
this.lastmdate = lastmdate; <br />
this.creadtor = creadtor; <br />
this.creatdate = creatdate; <br />
} </p>
<p>/** default constructor */ <br />
public TSysuser() { <br />
} </p>
<p>public String getUsername() { <br />
return this.username; <br />
} </p>
<p>public void setUsername(String username) { <br />
this.username = username; <br />
} </p>
<p>public String getUserdesc() { <br />
return this.userdesc; <br />
} </p>
<p>public void setUserdesc(String userdesc) { <br />
this.userdesc = userdesc; <br />
} </p>
<p>public String getPasswords() { <br />
return this.passwords; <br />
} </p>
<p>public void setPasswords(String passwords) { <br />
this.passwords = passwords; <br />
} </p>
<p>public String getDeptno() { <br />
return this.deptno; <br />
} </p>
<p>public void setDeptno(String deptno) { <br />
this.deptno = deptno; <br />
} </p>
<p>public String getHeadship() { <br />
return this.headship; <br />
} </p>
<p>public void setHeadship(String headship) { <br />
this.headship = headship; <br />
} </p>
<p>public String getSex() { <br />
return this.sex; <br />
} </p>
<p>public void setSex(String sex) { <br />
this.sex = sex; <br />
} </p>
<p>public String getTel() { <br />
return this.tel; <br />
} </p>
<p>public void setTel(String tel) { <br />
this.tel = tel; <br />
} </p>
<p>public String getEmail() { <br />
return this.email; <br />
} </p>
<p>public void setEmail(String email) { <br />
this.email = email; <br />
} </p>
<p>public String getUrl() { <br />
return this.url; <br />
} </p>
<p>public void setUrl(String url) { <br />
this.url = url; <br />
} </p>
<p>public String getPcall() { <br />
return this.pcall; <br />
} </p>
<p>public void setPcall(String pcall) { <br />
this.pcall = pcall; <br />
} </p>
<p><br />
public String getUserphoto() { <br />
return this.userphoto; <br />
} </p>
<p>public void setUserphoto(String userphoto) { <br />
this.userphoto = userphoto; <br />
} </p>
<p>public Integer getFacerefutime() { <br />
return this.facerefutime; <br />
} </p>
<p>public void setFacerefutime(Integer facerefutime) { <br />
this.facerefutime = facerefutime; <br />
} </p>
<p>public String getFacelanguage() { <br />
return this.facelanguage; <br />
} </p>
<p>public void setFacelanguage(String facelanguage) { <br />
this.facelanguage = facelanguage; <br />
} </p>
<p>public String getLastmodif() { <br />
return this.lastmodif; <br />
} </p>
<p>public void setLastmodif(String lastmodif) { <br />
this.lastmodif = lastmodif; <br />
} </p>
<p>public Date getLastmdate() { <br />
return this.lastmdate; <br />
} </p>
<p>public void setLastmdate(Date lastmdate) { <br />
this.lastmdate = lastmdate; <br />
} </p>
<p>public String getCreadtor() { <br />
return this.creadtor; <br />
} </p>
<p>public void setCreadtor(String creadtor) { <br />
this.creadtor = creadtor; <br />
} </p>
<p>public Date getCreatdate() { <br />
return this.creatdate; <br />
} </p>
<p>public void setCreatdate(Date creatdate) { <br />
this.creatdate = creatdate; <br />
} </p>
<p>public String toString() { <br />
return new ToStringBuilder(this) <br />
.append("username", getUsername()) <br />
.append("userdesc", getUserdesc()) <br />
.append("passwords", getPasswords()) <br />
.append("deptno", getDeptno()) <br />
.append("headship", getHeadship()) <br />
.append("sex", getSex()) <br />
.append("tel", getTel()) <br />
.append("email", getEmail()) <br />
.append("url", getUrl()) <br />
.append("pcall", getPcall()) <br />
.append("userphoto", getUserphoto()) <br />
.append("facerefutime", getFacerefutime()) <br />
.append("facelanguage", getFacelanguage()) <br />
.append("lastmodif", getLastmodif()) <br />
.append("lastmdate", getLastmdate()) <br />
.append("creadtor", getCreadtor()) <br />
.append("creatdate", getCreatdate()) <br />
.toString(); <br />
} </p>
<p>public boolean equals(Object other) { <br />
if ( !(other instanceof TSysuser) ) return false; <br />
TSysuser castOther = (TSysuser) other; <br />
return new EqualsBuilder() <br />
.append(this.getUsername(), castOther.getUsername()) <br />
.append(this.getUserdesc(), castOther.getUserdesc()) <br />
.append(this.getPasswords(), castOther.getPasswords()) <br />
.append(this.getDeptno(), castOther.getDeptno()) <br />
.append(this.getHeadship(), castOther.getHeadship()) <br />
.append(this.getSex(), castOther.getSex()) <br />
.append(this.getTel(), castOther.getTel()) <br />
.append(this.getEmail(), castOther.getEmail()) <br />
.append(this.getUrl(), castOther.getUrl()) <br />
.append(this.getPcall(), castOther.getPcall()) <br />
.append(this.getUserphoto(), castOther.getUserphoto()) <br />
.append(this.getFacerefutime(), castOther.getFacerefutime()) <br />
.append(this.getFacelanguage(), castOther.getFacelanguage()) <br />
.append(this.getLastmodif(), castOther.getLastmodif()) <br />
.append(this.getLastmdate(), castOther.getLastmdate()) <br />
.append(this.getCreadtor(), castOther.getCreadtor()) <br />
.append(this.getCreatdate(), castOther.getCreatdate()) <br />
.isEquals(); <br />
} </p>
<p>public int hashCode() { <br />
return new HashCodeBuilder() <br />
.append(getUsername()) <br />
.append(getUserdesc()) <br />
.append(getPasswords()) <br />
.append(getDeptno()) <br />
.append(getHeadship()) <br />
.append(getSex()) <br />
.append(getTel()) <br />
.append(getEmail()) <br />
.append(getUrl()) <br />
.append(getPcall()) <br />
.append(getUserphoto()) <br />
.append(getFacerefutime()) <br />
.append(getFacelanguage()) <br />
.append(getLastmodif()) <br />
.append(getLastmdate()) <br />
.append(getCreadtor()) <br />
.append(getCreatdate()) <br />
.toHashCode(); <br />
} </p>
<p>} <br />
--------------------------------------------------------------------- <br />
/* <br />
* 创建日期 2005-4-11 <br />
* <br />
* 更改所生成文件模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
package com.yaya.service; </p>
<p>import java.util.List; </p>
<p>import com.yaya.hb.TSysuser; <br />
import com.yaya.service.dao.IUserDao; </p>
<p>/** <br />
* @author Administrator <br />
* <br />
* 更改所生成类型注释的模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
public interface IUserManager { <br />
public void setUserDAO(IUserDao dao); <br />
public TSysuser getUser(String username); <br />
public List getUsers(); <br />
public TSysuser saveUser(TSysuser user); <br />
public void removeUser(String username); </p>
<p>} <br />
-------------------------------------------------------------------- <br />
/* <br />
* 创建日期 2005-4-7 <br />
* <br />
* 更改所生成文件模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
package com.yaya.service.dao; <br />
/** <br />
* @author Administrator <br />
* <br />
* 更改所生成类型注释的模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
public interface IDAO { </p>
<p>} <br />
-------------------------------------------------------------- <br />
/* <br />
* 创建日期 2005-4-11 <br />
* <br />
* 更改所生成文件模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
package com.yaya.service.dao; </p>
<p>import java.util.List; </p>
<p>import com.yaya.hb.TSysuser; </p>
<p>/** <br />
* @author Administrator <br />
* <br />
* 更改所生成类型注释的模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
public interface IUserDao extends IDAO { </p>
<p>public List getUsers(); <br />
public TSysuser getUser(String username); <br />
public void saveUser(TSysuser user); <br />
public void removeUser(String username); <br />
} <br />
---------------------------------------------------------- <br />
/* <br />
* 创建日期 2005-4-11 <br />
* <br />
* 更改所生成文件模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
package com.yaya.service.spring; </p>
<p>import com.yaya.hb.TSysuser; <br />
import com.yaya.service.IUserManager; <br />
import com.yaya.service.dao.IUserDao; </p>
<p>import java.util.List; </p>
<p>import org.apache.commons.logging.Log; </p>
<p>import org.apache.commons.logging.LogFactory; <br />
/** <br />
* @author Administrator <br />
* <br />
* 更改所生成类型注释的模板为 <br />
* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释 <br />
*/ <br />
public class UserManagerImpl implements IUserManager { <br />
private static Log log = LogFactory.getLog(UserManagerImpl.class); </p>
<p>public IUserDao userDao; </p>
<p>/** </p>
<p>* @return 返回 userDao。 </p>
<p>*/ </p>
<p>public void setUserDAO(IUserDao dao) { <br />
this.userDao = dao; <br />
} </p>
<p>public IUserDao getUserDao() { <br />
return userDao; <br />
} <br />
/** </p>
<p>* @param userDao 要设置的 userDao。 </p>
<p>*/ </p>
<p>public void setUserDao(IUserDao userDao) { </p>
<p>this.userDao = userDao; </p>
<p>} </p>
<p>public TSysuser getUser(String username) { </p>
<p>try <br />
{ <br />
TSysuser user = userDao.getUser(username); <br />
return user; <br />
} <br />
catch(Exception e) <br />
{ <br />
e.printStackTrace(); <br />
} <br />
return userDao.getUser(username); </p>
<p>} </p>
<p>/* （非 Javadoc） </p>
<p>* @see com.jandar.service.IUserManager#getUsers() </p>
<p>*/ </p>
<p>public List getUsers() { <br />
// TODO 自动生成方法存根 <br />
return userDao.getUsers(); <br />
} <br />
/* （非 Javadoc） </p>
<p>* @see com.jandar.service.IUserManager#saveUser(com.jandar.model.User) </p>
<p>*/ </p>
<p>public TSysuser saveUser(TSysuser user) { <br />
// TODO 自动生成方法存根 <br />
userDao.saveUser(user); <br />
return user; <br />
} </p>
<p>/* （非 Javadoc） </p>
<p>* @see com.jandar.service.IUserManager#removeUser(java.lang.String) </p>
<p>*/ <br />
public void removeUser(String username) { <br />
// TODO 自动生成方法存根 <br />
userDao.removeUser(username); <br />
} <br />
}&nbsp; <br />
</p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:28 <a href="http://www.blogjava.net/ruoyoux/articles/232408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry+Spring+Hibernate整合工作小结</title><link>http://www.blogjava.net/ruoyoux/articles/232406.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:26:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232406.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232406.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232406.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232406.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232406.html</trackback:ping><description><![CDATA[<br />
<br />
Cyberwing&nbsp;<br />
<br />
<br />
FrankSoo是我的项目经理。前段时间公司决定作个新的J2EE二次开发平台，以替换公司原有的开发平台。公司让FrankSoo和我组成平台开发项目组，FrankSoo担任项目经理。现在这个平台整合开发阶段已经结束，进入项目应用阶段。下面是我们的整合工作小结，介绍一下我们在工作中遇到的问题，以及我们选择的解决方案.&nbsp;<br />
<br />
<br />
1、架构的选择&nbsp;<br />
<br />
首先，我们都同意以我们现有的能力，没有足够的时间和资源自行开发一套完整的平台。在已有的众多开源项目中选择若干优秀的项目进行整合，才可能按时完成项目，达到项目目的。&nbsp;<br />
<br />
但是在平台项目开始前，我们对平台的技术架构有各自的构想。FrankSoo原来的构想是Struts+Spring+Hibernate，而我的构想是Tapestry+Hibernate。&nbsp;<br />
<br />
不过FrankSoo非常open，在我向他演示了Tapestry的经典范例workbench，介绍了Tapestry基于组件的编程方式之后，他同意选用Tapestry作为实现Web展现层的框架。我想FrankSoo以前的Struts开发经验(painful)也是他做出这个决定的因素之一。&nbsp;<br />
<br />
FrankSoo&nbsp;gave&nbsp;me&nbsp;a&nbsp;nice&nbsp;introduction&nbsp;of&nbsp;Spring&nbsp;Framework.&nbsp;Wow,&nbsp;what&nbsp;an&nbsp;amazing&nbsp;framework!&nbsp;IOC,&nbsp;Declarative&nbsp;Transaction&nbsp;Support,&nbsp;Hibernate&nbsp;Session&nbsp;Management,&nbsp;Hibernate&nbsp;DAO&nbsp;Support&#8230;&nbsp;These&nbsp;features&nbsp;are&nbsp;just&nbsp;what&nbsp;we&nbsp;need&nbsp;for&nbsp;a&nbsp;middle&nbsp;tire&nbsp;container.&nbsp;<br />
<br />
至于Hibernate，这个最成功的开源ORM项目，我们都投了它一票^_^&nbsp;<br />
<br />
最后我们确定平台的技术架构是Tapestry+Spring+Hibernate.&nbsp;<br />
<br />
2、架构整合&nbsp;<br />
<br />
最初的平台架构借鉴了一篇介绍如何集成Tapestry与Spring的文章［1］中提到的架构：&nbsp;<br />
<br />
图1&nbsp;<br />
&nbsp;<br />
<br />
Web层的Tapestry负责数据输入输出,&nbsp;响应用户事件，及输入校验的工作,&nbsp;通过访问预先加载的WebApplicationContext(由Spring提供,&nbsp;包含着所有Service&nbsp;bean)获得Service层的Service&nbsp;Bean,&nbsp;把业务操作都委托给它们.&nbsp;<br />
<br />
Service层的bean则负责use&nbsp;case逻辑,&nbsp;domain相关的逻辑委托给domain&nbsp;model中的bean去实现.&nbsp;Service通过DAO完成对domain&nbsp;model的持久化工作.&nbsp;Service负责数据库事务和Hibernate&nbsp;Session的管理(通过Spring的声明式事务管理和与之集成的Hibernate&nbsp;Session管理).&nbsp;Service层的另一项重要工作是权限和访问控制。&nbsp;<br />
<br />
Domain&nbsp;model负责表示问题域的数据和domain&nbsp;logic.&nbsp;DAO使用Hibernate持久化数据以及查询.&nbsp;在实现DAO时,&nbsp;我们使用了Spring的Hibernate&nbsp;DAO&nbsp;Support,极大地简化了代码,&nbsp;很多方法都只用简单的一行完成.&nbsp;有意思的是,&nbsp;最后完成的HibernateDAO的代码量居然比我写的MockDAO的代码少了一半还多&nbsp;<br />
<br />
这样的架构优点很明显,&nbsp;层次清晰,&nbsp;各层的职责也明确,&nbsp;便于分层设计与开发,&nbsp;结合mock和spring的IOC,&nbsp;unit&nbsp;test也是非常容易的.&nbsp;而且后台(Service,&nbsp;domain&nbsp;model&nbsp;and&nbsp;DAO)的代码不依赖于Web容器或是EJB容器的API,&nbsp;移植性非常好,&nbsp;同样的代码可以在Web&nbsp;app中使用也可在普通的Java&nbsp;app中使用,&nbsp;只需更换UI层.&nbsp;<br />
<br />
按照这个整合的构架，我们实现一个简单的实例，实现了列表分页查询和显示，数据增删改，基于Hibernate&nbsp;Criteria&nbsp;Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已经建好的数据库表结构自动生成Hibernate映射文件，实体类和DAO，极大地减少了工作量。我们还对这个小例子进行了压力测试（测试时的数据量为10万条记录），确定平台不存在性能问题。&nbsp;<br />
<br />
通过这个实例我们把整个架构基本走通一遍，并总结了使用这套架构开发时适用的开发流程和需要做的工作。&nbsp;<br />
<br />
3、困扰我们的问题&nbsp;<br />
<br />
在实现例子和现在的项目应用过程中，我们发现了若干头疼的问题，有的解决了，有的还没有。&nbsp;<br />
<br />
问题1：要不要使用DTO？&nbsp;<br />
<br />
在上面的架构中我们并没有明确Service和Web层间的数据传输是如何进行的。我们讨论好久要不要使用DTO，最后的结论是不用。&nbsp;<br />
<br />
使用DTO有两个主要的理由：1、减少Web层和Service层间的方法调用，通过一个方法调用就将Web需要的数据都传给Web。2、隔离domain&nbsp;model和Web层。&nbsp;<br />
<br />
第一个理由在我们的架构下是不成立的。因为我们的架构是集中式的，Web和Service是在同一个JVM中，它们之间的方法调用是没有EJB远程访问的巨大消耗的。&nbsp;<br />
<br />
第二个理由还是需要考虑的。如果允许把domain&nbsp;model中的对象传给Web层，那么修改domain&nbsp;model，就会影响到Web层。如果使用DTO，那么domain&nbsp;model实现上的变化就不会影响到Web。但是大量的变化不是domain&nbsp;model实现上的变化，而是domain&nbsp;model接口的变化，比如一个domain&nbsp;model的对象上添加了一个属性，而这个属性需要用户修改，那么这时候必须修改Web层，不管是不是用了DTO。而且使用DTO，就需要维护着一大堆对象，或是它们的生成器，这是非常无聊、且容易出错的工作。&nbsp;<br />
<br />
基于这些考虑，我们没有使用DTO，而是选择把domain&nbsp;model直接传到Web层。下面是修改后的架构图（呵呵，修改了别人的图［2］）。&nbsp;<br />
<br />
图2:&nbsp;<br />
&nbsp;<br />
<br />
<br />
问题2：Entity&nbsp;like&nbsp;domain&nbsp;model&nbsp;or&nbsp;rich&nbsp;domain&nbsp;model?&nbsp;<br />
<br />
我们使用Middlegen自动生成Hibernate映射文件，Entity类和DAO类,&nbsp;但是生成的Entity只含有简单的属性和getter,&nbsp;setter方法。因此我们遇到了一个问题：我们的domain&nbsp;model还要不要包含domain&nbsp;logic？如果包含，那么和自动生成工具如何结合？&nbsp;<br />
<br />
我们讨论后认为一个rich&nbsp;domain&nbsp;model还是非常有必要的，可以减少Service中的重复代码，提高复用性。&nbsp;<br />
<br />
如何同自动生成结合？使用&lt;meta&gt;标签，生成抽象基类，我们继承这些自动生成的基类，添加业务方法。&nbsp;<br />
<br />
问题3：Model&nbsp;driven&nbsp;or&nbsp;Data&nbsp;driven?&nbsp;<br />
<br />
采用Model&nbsp;driven还是Data&nbsp;driven的方式大家有过热烈的讨论。我们主要是受到Rod&nbsp;Johnson［3］的影响，采用了Data&nbsp;driven的方式。先作数据库设计，生成库表，然后用Middlegen反向生成Hibernate映射文件和Entity及DAO。但是我们在进入项目应用之后发现这种方法有两个问题：&nbsp;<br />
<br />
a）&nbsp;数据库设计仅说明了系统要管理的静态数据，我们还是得作面向对象分析，以反映系统的动态行为。特别是当系统的业务不仅仅是简单的CRUD操作时，这个问题更严重。&nbsp;<br />
b）&nbsp;数据库设计为了优化性能，可能会把好几个应该是单独实体的数据放入一个实体中。这样如果直接把这种极粗粒度实体映射成Entity类，那简直是不可接受的。面向对象的分析设计模型得到的类都是相当细粒度的。这种情况还得作面向对象的分析，明确到底这个粗粒度的大表应该映射成那几个细粒度的对象。&nbsp;<br />
<br />
或许我们应该试试Model&nbsp;driven，用AndroMDA生成domain&nbsp;model，Hibernate&nbsp;DAO，Hibernate&nbsp;mapping，数据库表，简单的Service和前台的Tapestry页面。&nbsp;<br />
<br />
问题4：Hibernate&nbsp;Session生命周期如何管理？&nbsp;<br />
<br />
对于Hibernate&nbsp;Session的生命周期我们采用的是Session-per-Transaction模式，未采用Open&nbsp;Session&nbsp;in&nbsp;View模式。&nbsp;虽然Hibernate&nbsp;team认为这种方法没什么不好，而且FreeRoller和Atlassian的confluence都使用了Open&nbsp;Session&nbsp;In&nbsp;View这种模式，但是我们对它可能产生的影响还没有很好的把握，所以暂时弃置不用。&nbsp;如果Web层要访问lazy&nbsp;load的数据,&nbsp;需要先调用Service的业务方法,&nbsp;以获得数据.&nbsp;<br />
<br />
问题5：Use&nbsp;case&nbsp;logic&nbsp;和domain&nbsp;logic&nbsp;如何区分？&nbsp;<br />
<br />
Service负责use&nbsp;case&nbsp;logic，domain&nbsp;model负责domain&nbsp;logic。这样的划分看起来很好，实现起来就很麻烦。如何确定什么是use&nbsp;case&nbsp;logic，什么是domain&nbsp;logic？TBD.&nbsp;<br />
<br />
<br />
问题6：Service粒度如何确定？&nbsp;<br />
<br />
这个问题真是很烦，原先考虑使用usecase&nbsp;controller的方式，每个usecase对应一个Service，但是发现这样复用性太低，而且好多地方必须复用相同的功能&nbsp;<br />
<br />
另一种方法是用package&nbsp;level&nbsp;service，每个package作个service，这样倒是可以重用，但是感觉太死了，不好。&nbsp;<br />
<br />
现在也没有什么很好的办法，只好在详细设计时根据具体情况确定需要多少个Service了。TBD.&nbsp;<br />
<br />
问题7：权限如何设定？如何检查？&nbsp;<br />
<br />
权限设定也是个头疼的问题。我们本想是按照use&nbsp;case设定权限，每个用例一个权限。在角色设定的时候直接处理的都是业务意义非常明确的权限。但是在权限验证过程中发现了问题：如果在Service的方法中验证权限，而且这个方法在多个用例中用到（复用Service），那么这个Service的方法就需要检查多个权限;&nbsp;如果每个Service方法对应一个权限,&nbsp;那么权限又太细了,&nbsp;不像use&nbsp;case权限那样代表一个完整的业务.&nbsp;真的是很麻烦阿！TBD.&nbsp;<br />
<br />
<br />
<br />
Ok,&nbsp;这些就是我们这段工作的结果。希望能给大家一些启发，也希望能得到大家的帮助，帮我们出出主意，谢谢大家。&nbsp; <br />
<br />
<script type="text/javascript"><!-- google_ad_client="pub-7390275636631344" ; google_ad_width="728;
google_ad_height" = 90; google_ad_format="728x90_as" ; google_ad_type="text_image" ; google_ad_channel="5095444487" ; google_color_border="336699" ; google_color_bg="FFFFFF" ; google_color_link="0000FF" ; google_color_url="008000" ; google_color_text="000000" ;
//--></script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script><script> window.google_render_ad(); </script><iframe name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-7390275636631344&amp;dt=1223133838420&amp;lmt=1200108696&amp;format=728x90_as&amp;output=html&amp;correlator=1223133838399&amp;channel=5095444487&amp;url=http%3A%2F%2Fwww.javaresearch.org%2Farticle%2F25771.htm&amp;color_bg=FFFFFF&amp;color_text=000000&amp;color_link=0000FF&amp;color_url=008000&amp;color_border=336699&amp;ad_type=text_image&amp;ea=off&amp;ref=http%3A%2F%2Fwww.google.cn%2Fsearch%3Fsourceid%3Dnavclient%26hl%3Dzh-CN%26ie%3DUTF-8%26rlz%3D1T4XNLA_zh-CNCN282CN285%26q%3DTapestry%2B%252b%2Bspring%2B&amp;frm=0&amp;cc=318&amp;ga_vid=80252414.1223133838&amp;ga_sid=1223133838&amp;ga_hid=1432045315&amp;ga_fc=true&amp;flash=0&amp;u_h=768&amp;u_w=1024&amp;u_ah=734&amp;u_aw=1024&amp;u_cd=32&amp;u_tz=480&amp;u_java=true" frameborder="0" width="728" scrolling="no" height="90" allowTransparency></iframe>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232406.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:26 <a href="http://www.blogjava.net/ruoyoux/articles/232406.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry - Spring Framework reference 2.0.5 参考手册中文版</title><link>http://www.blogjava.net/ruoyoux/articles/232405.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:24:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232405.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232405.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232405.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232405.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232405.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 15.5. Tapestry摘自 Tapestry 主页... &#8220; Tapestry 是用来创建动态、健壮、高伸缩性 Web 应用的一个 Java 开源框架。 Tapestry 组件构建于标准的Java Servlet API 之上，所以它可以工作在任何 Servlet 容器或者应用服务器之上。 &#8221;尽管 Spring 有自己的 强有力的 Web 层，但是使用 T...&nbsp;&nbsp;<a href='http://www.blogjava.net/ruoyoux/articles/232405.html'>阅读全文</a><img src ="http://www.blogjava.net/ruoyoux/aggbug/232405.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:24 <a href="http://www.blogjava.net/ruoyoux/articles/232405.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry Spring Hibernate整合工作小结（转）</title><link>http://www.blogjava.net/ruoyoux/articles/232403.html</link><dc:creator>Blog of JoJo</dc:creator><author>Blog of JoJo</author><pubDate>Sat, 04 Oct 2008 15:04:00 GMT</pubDate><guid>http://www.blogjava.net/ruoyoux/articles/232403.html</guid><wfw:comment>http://www.blogjava.net/ruoyoux/comments/232403.html</wfw:comment><comments>http://www.blogjava.net/ruoyoux/articles/232403.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ruoyoux/comments/commentRss/232403.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ruoyoux/services/trackbacks/232403.html</trackback:ping><description><![CDATA[<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="color: red; font-family: 方正姚体">[原文：http://javamen.blogdriver.com/javamen/299858.html]</span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">FrankSoo是我的项目经理。前段时间公司决定作个新的J2EE二次开发平台，以替换公司原有的开发平台。公司让FrankSoo和我组成平台开发项目组，FrankSoo担任项目经理。现在这个平台整合开发阶段已经结束，进入项目应用阶段。下面是我们的整合工作小结，介绍一下我们在工作中遇到的问题，以及我们选择的解决方案. </span></span></span></span></p>
<p><br />
<span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">1、架构的选择 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">首先，我们都同意以我们现有的能力，没有足够的时间和资源自行开发一套完整的平台。在已有的众多开源项目中选择若干优秀的项目进行整合，才可能按时完成项目，达到项目目的。 <br />
但是在平台项目开始前，我们对平台的技术架构有各自的构想。FrankSoo原来的构想是Struts+Spring+Hibernate，而我的构想是Tapestry+Hibernate。 <br />
不过FrankSoo非常open，在我向他演示了Tapestry的经典范例workbench，介绍了Tapestry基于组件的编程方式之后，他同意选用Tapestry作为实现Web展现层的框架。我想FrankSoo以前的Struts开发经验(painful)也是他做出这个决定的因素之一。 FrankSoo gave me a nice introduction of Spring Framework. Wow, what an amazing framework! IOC, Declarative Transaction Support, Hibernate Session Management, Hibernate DAO Support&#8230; These features are just what we need for a middle tire container. </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">至于Hibernate，这个最成功的开源ORM项目，我们都投了它一票^_^ <br />
最后我们确定平台的技术架构是Tapestry+Spring+Hibernate. </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">2、架构整合 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">最初的平台架构借鉴了一篇介绍如何集成Tapestry与Spring的文章［1］中提到的架构： </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">Web层的Tapestry负责数据输入输出, 响应用户事件，及输入校验的工作, 通过访问预先加载的WebApplicationContext(由Spring提供, 包含着所有Service bean)获得Service层的Service Bean, 把业务操作都委托给它们. </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">Service层的bean则负责use case逻辑, domain相关的逻辑委托给domain model中的bean去实现. Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和Hibernate Session的管理(通过Spring的声明式事务管理和与之集成的Hibernate Session管理). Service层的另一项重要工作是权限和访问控制。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">Domain model负责表示问题域的数据和domain logic. DAO使用Hibernate持久化数据以及查询. 在实现DAO时, 我们使用了Spring的Hibernate DAO Support,极大地简化了代码, 很多方法都只用简单的一行完成. 有意思的是, 最后完成的HibernateDAO的代码量居然比我写的MockDAO的代码少了一半还多 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">这样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开发, 结合mock和spring的IOC, unit test也是非常容易的. 而且后台(Service, domain model and DAO)的代码不依赖于Web容器或是EJB容器的API, 移植性非常好, 同样的代码可以在Web app中使用也可在普通的Java app中使用, 只需更换UI层. </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">按照这个整合的构架，我们实现一个简单的实例，实现了列表分页查询和显示，数据增删改，基于Hibernate Criteria Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已经建好的数据库表结构自动生成Hibernate映射文件，实体类和DAO，极大地减少了工作量。我们还对这个小例子进行了压力测试（测试时的数据量为10万条记录），确定平台不存在性能问题。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">通过这个实例我们把整个架构基本走通一遍，并总结了使用这套架构开发时适用的开发流程和需要做的工作。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">3、困扰我们的问题 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">在实现例子和现在的项目应用过程中，我们发现了若干头疼的问题，有的解决了，有的还没有。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题1：要不要使用DTO？ </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">在上面的架构中我们并没有明确Service和Web层间的数据传输是如何进行的。我们讨论好久要不要使用DTO，最后的结论是不用。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">使用DTO有两个主要的理由：1、减少Web层和Service层间的方法调用，通过一个方法调用就将Web需要的数据都传给Web。2、隔离domain model和Web层。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">第一个理由在我们的架构下是不成立的。因为我们的架构是集中式的，Web和Service是在同一个JVM中，它们之间的方法调用是没有EJB远程访问的巨大消耗的。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">第二个理由还是需要考虑的。如果允许把domain model中的对象传给Web层，那么修改domain model，就会影响到Web层。如果使用DTO，那么domain model实现上的变化就不会影响到Web。但是大量的变化不是domain model实现上的变化，而是domain model接口的变化，比如一个domain model的对象上添加了一个属性，而这个属性需要用户修改，那么这时候必须修改Web层，不管是不是用了DTO。而且使用DTO，就需要维护着一大堆对象，或是它们的生成器，这是非常无聊、且容易出错的工作。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">基于这些考虑，我们没有使用DTO，而是选择把domain model直接传到Web层。下面是修改后的架构图（呵呵，修改了别人的图［2］）。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题2：Entity like domain model or rich domain model? </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">我们使用Middlegen自动生成Hibernate映射文件，Entity类和DAO类, 但是生成的Entity只含有简单的属性和getter, setter方法。因此我们遇到了一个问题：我们的domain model还要不要包含domain logic？如果包含，那么和自动生成工具如何结合？ </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">我们讨论后认为一个rich domain model还是非常有必要的，可以减少Service中的重复代码，提高复用性。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">如何同自动生成结合？使用&lt;meta&gt;标签，生成抽象基类，我们继承这些自动生成的基类，添加业务方法。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题3：Model driven or Data driven? </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">采用Model driven还是Data driven的方式大家有过热烈的讨论。我们主要是受到Rod Johnson［3］的影响，采用了Data driven的方式。先作数据库设计，生成库表，然后用Middlegen反向生成Hibernate映射文件和Entity及DAO。但是我们在进入项目应用之后发现这种方法有两个问题： </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">a） 数据库设计仅说明了系统要管理的静态数据，我们还是得作面向对象分析，以反映系统的动态行为。特别是当系统的业务不仅仅是简单的CRUD操作时，这个问题更严重。 <br />
b） 数据库设计为了优化性能，可能会把好几个应该是单独实体的数据放入一个实体中。这样如果直接把这种极粗粒度实体映射成Entity类，那简直是不可接受的。面向对象的分析设计模型得到的类都是相当细粒度的。这种情况还得作面向对象的分析，明确到底这个粗粒度的大表应该映射成那几个细粒度的对象。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">或许我们应该试试Model driven，用AndroMDA生成domain model，Hibernate DAO，Hibernate mapping，数据库表，简单的Service和前台的Tapestry页面。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题4：Hibernate Session生命周期如何管理？ </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">对于Hibernate Session的生命周期我们采用的是Session-per-Transaction模式，未采用Open Session in View模式。 虽然Hibernate team认为这种方法没什么不好，而且FreeRoller和Atlassian的confluence都使用了Open Session In View这种模式，但是我们对它可能产生的影响还没有很好的把握，所以暂时弃置不用。 如果Web层要访问lazy load的数据, 需要先调用Service的业务方法, 以获得数据. </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题5：Use case logic 和domain logic 如何区分？ </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">Service负责use case logic，domain model负责domain logic。这样的划分看起来很好，实现起来就很麻烦。如何确定什么是use case logic，什么是domain logic？TBD. </span></span></span></span></p>
<p><br />
<span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题6：Service粒度如何确定？ </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">这个问题真是很烦，原先考虑使用usecase controller的方式，每个usecase对应一个Service，但是发现这样复用性太低，而且好多地方必须复用相同的功能 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">另一种方法是用package level service，每个package作个service，这样倒是可以重用，但是感觉太死了，不好。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">现在也没有什么很好的办法，只好在详细设计时根据具体情况确定需要多少个Service了。TBD. </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题7：权限如何设定？如何检查？ </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">权限设定也是个头疼的问题。我们本想是按照use case设定权限，每个用例一个权限。在角色设定的时候直接处理的都是业务意义非常明确的权限。但是在权限验证过程中发现了问题：如果在Service的方法中验证权限，而且这个方法在多个用例中用到（复用Service），那么这个Service的方法就需要检查多个权限; 如果每个Service方法对应一个权限, 那么权限又太细了, 不像use case权限那样代表一个完整的业务. 真的是很麻烦阿！TBD. <br />
Quake wang:问题1：要不要使用DTO？ <br />
No DTO, 直接把domain object传给Tapestry的web层，利用Tapestry提供强大的数据绑定和组件功能很方便 </span></span></span></span></p>
<p><br />
<span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题2：Entity like domain model or rich domain model? <br />
domain model不包括复杂的domain logic, 只是作为一个data model bean, 再加上一些简单的logic, 比如addChild的同时，设置child的parent此类简单logic. </span></span></span></span></p>
<p><br />
<span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题3：Model driven or Data driven? <br />
这个对我来说不是什么大问题，个人习惯而已，我觉得无论是Model driven或者Data driven，对于相同的需求，2者最终的设计应该都是很类似的。我是从2边同时考虑的，一边做Model，一边还要考虑数据库的结构， 再进行相应的调整，用下来也没有什么问题。没有用代码生成， 只是用Hibernate的Eclipse plugin (Hibernate Synchronizer)来帮我做一些code assist. </span></span></span></span></p>
<p><br />
<span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题4：Hibernate Session生命周期如何管理？ <br />
目前没有采用open session in view，也是和你们一样，在Service里面准备好所有需要的对象。 </span></span></span></span></p>
<p><br />
<span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题5：Use case logic 和domain logic 如何区分？ <br />
由于domain model里面没有什么domain logic，这个问题不存在. </span></span></span></span></p>
<p><br />
<span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题6：Service粒度如何确定？ <br />
由于domain model里面没有什么domain logic，所以Service的功能就切得很细，尽量重用，一个package可能有多个service, 感觉还好，没有太死。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">问题7：权限如何设定？如何检查？ <br />
这个也是我没有想好的问题， 因为不同的需求， 权限设定都不一样，很难用AOP来做一个通用的aspect. 1. DAO的做法： <br />
我目前不是给每个domain object都做一个DAO, 而是整个系统就一个DAO (PersistenceManager), 里面只有create, update, delete entity这3个方法。另外写一个DAO, 专门做查询 (QueryManager), 用hibernate的named query做常用的查询， 用criteria来做基于用户输入的动态查询。不知道你们的做法是怎么样？另外criteria 和 named query其实都是hardcode，object attribute name改变的时候，还得记得手工去修改这些代码，unit test很难覆盖到所有的criteria search 和 named query里面的代码，这个是目前感觉不是很方便的地方。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">2. Spring 和 Tapestry的集成 <br />
目前只是用Spring到service layer而已， Tapestry通过Global（扮演Service Locator的角色）这个对象来调用，在domain Tapestry这一层还是有很多dirty code, 其实也可以用AOP来解决。如果能够像webwork2那样，所有的action都可以通过从Spring获得，即通过Spring获得page <br />
listeners, 那会方便很多，不过Tapestry也有自己的类增强功能，好像有一定的冲突，目前没有什么好的想法。 </span></span></span></span></p>
<p><span style="font-family: 方正姚体"><span style="font-family: 方正姚体"><span style="font-family: 微软雅黑"><span style="font-family: 方正姚体">顺便推荐3个我在项目中使用的工具 (都是eclipse plugin)： <br />
1. http://spindle.sourceforge.net 开发Tapestry的必备 <br />
2. http://springui.sourceforge.net 写Spring application context file的辅助好工具 <br />
3. http://www.binamics.com/hibernatesynch/ Hibernate 开发的辅助好工具。</span></span></span></span></p>
<img src ="http://www.blogjava.net/ruoyoux/aggbug/232403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:04 <a href="http://www.blogjava.net/ruoyoux/articles/232403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>