??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲中文字幕无码永久在线,亚洲视频一区二区,亚洲一区二区三区高清视频http://www.tkk7.com/ruoyoux/category/34971.html为梦惌来Qؓ自由而生? 性情若水Q风h_风息水止Q故时而激荡,时又清^…?/description>zh-cnFri, 17 Jul 2009 08:32:32 GMTFri, 17 Jul 2009 08:32:32 GMT60每日一?2009/06/11 Sun GlassFish Enterprise Server 2.1 Reference Manualhttp://www.tkk7.com/ruoyoux/articles/281525.htmlBlog of JoJoBlog of JoJoThu, 11 Jun 2009 09:39:00 GMThttp://www.tkk7.com/ruoyoux/articles/281525.htmlhttp://www.tkk7.com/ruoyoux/comments/281525.htmlhttp://www.tkk7.com/ruoyoux/articles/281525.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/281525.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/281525.htmlstart-node-agent(1)

Name | Synopsis | Description | Options | Operands | Examples | Exit Status | See Also

Name

    start-node-agent– starts a node agent

Synopsis

    start-node-agent [--user user]

    [--passwordfile passwordfile] [--secure={true|false}]

    [ --terse={true|false} ] [ --echo={true|false} ]

    [ --interactive={true|false} ] [ --verbose={true|false} ]

    [ --agentdir nodeagent_path] [--startinstances={true|false}]

    [ --syncinstances={true|false} ] [nodeagent_name]

Description


    Note –

    This command is available only in domains that are configured to support clusters, such as domains that are created with the cluster profile.


    Use the start-node-agent command start a node agent. The command will return control to the user before instances are actually started. The list-instances 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.

    This command is supported in local mode only.

Options

    -u --user

    The authorized domain administration server administrative username.

    --passwordfile

    The --passwordfile option specifies the name of a file containing the password entries in a specific format. The entry for the password must have the AS_ADMIN_ prefix followed by the password name in uppercase letters.

    For example, to specify the domain administration server password, use an entry with the following format: AS_ADMIN_PASSWORD=password, where password is the actual administrator password. Other passwords that can be specified include AS_ADMIN_MAPPEDPASSWORD, AS_ADMIN_USERPASSWORD, and AS_ADMIN_ALIASPASSWORD.

    All remote commands must specify the administration password to authenticate to the domain administration server, either through --passwordfile or asadmin login, or interactively on the command prompt. The asadmin login command can be used only to specify the administration password. For other passwords, that must be specified for remote commands, use the --passwordfile or enter them at the command prompt.

    If you have authenticated to a domain using the asadmin login command, then you need not specify the administration password through the --passwordfile option on subsequent operations to this particular domain. However, this is applicable only to AS_ADMIN_PASSWORD option. You will still need to provide the other passwords, for example, AS_ADMIN_USERPASSWORD, as and when required by individual commands, such as update-file-user.

    For security reasons, passwords specified as an environment variable will not be read by asadmin.

    The default value for AS_ADMIN_MASTERPASSWORD is changeit.

    -s --secure

    If set to true, uses SSL/TLS to communicate with the domain administration server. Default is true.

    -t --terse

    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.

    -e --echo

    Setting to true will echo the command line statement on the standard output. Default is false.

    -I --interactive

    If set to true (default), only the required password options are prompted.

    -h --help

    Displays the help text for the command.

    --verbose

    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.

    --agentdir

    Like a Domain Administration Server (DAS), each node agent resides in a top level directory named agentdir/nodeagent_name. If specified, the path must be accessible in the filesystem. If not specified, defaults to the install_dir/nodeagents directory.

    --startinstances

    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 start-servers-in-startup attribute, located in the domain.xml file.

    --syncinstances

    If set to true, forcibly synchronizes the cache repositories of all server instances with the central repository of the DAS. The synchronization occurs when the node agent is started. Default is false.

Operands

    nodeagent_name

    The name of the node agent to be started.

Examples


    Example 1 Using the start-node-agent command


    asadmin> start-node-agent --user admin 

    --passwordfile passwordfile nodeagent1


    Nodeagent1 started.

    The node agent nodeagent1 is started in the default install_dir/nodeagents directory.


Exit Status

    0

    command executed successfully

    1

    error in executing the command

See Also

Java EE 5  Last Revised 13 Jul 2007

Blog of JoJo 2009-06-11 17:39 发表评论
]]>
每日一?2009/06/10 How GlassFish DAS communicates with Node Agents and Instanceshttp://www.tkk7.com/ruoyoux/articles/281159.htmlBlog of JoJoBlog of JoJoWed, 10 Jun 2009 07:12:00 GMThttp://www.tkk7.com/ruoyoux/articles/281159.htmlhttp://www.tkk7.com/ruoyoux/comments/281159.htmlhttp://www.tkk7.com/ruoyoux/articles/281159.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/281159.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/281159.htmlQuestion: Explain the communication details between Domain Admin Server, node-agents and server instances in Sun's Application Server 8.x and 9.x (GlassFish V2).

Terminology:

DAS: Domain Admin Server (One per domain) -- The process that controls the management of the entire domain.

NA: Node Agent -- Generally, one per box or Solaris container -- The process that controls the life cycle of server instances.

SI: Server Instance --  The real Java EE instances that run user applications in an enterprise.

Answer:

1. Background: The domain.xml controls the configuration. At every node-agent, there are also a few configuration files that are consulted by every NA. See NA section at docs.sun.com for details. Following are the points in time when the communication (for administration/management purpose) happens:

  • DAS communicates with each NA: Only when DAS needs to know NA's running status.
  • DAS communicates with each SI: When DAS needs to know SI's running status and when it needs to cascade the SI MBeans into the DAS's MBenServer.
  • NA communicates with DAS: 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.
  • SI communicates with the DAS: Never, explicitly.

Thus, the communication is mainly driven by DAS. When the domain is created, the administration is configured to use an authentication realm named admin-realm. This realm points to what's called a FileRealm which is nothing but the implementation of a security realm implementation that uses admin-keyfile. If you see the domain's configuration, you'll find this file in config folder of that domain.

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.

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.  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 admin-port (default: 4848) as an option.

After an NA is created, the most natural step is to start that NA. This is done by executing the asadmin start-node-agent 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 --savemasterpassword which should be used with care.

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. 

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 8686) comes into picture.

When the domain is created, it uses the self-signed certificate aliased s1as 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.

The Server Instances are synced with the DAS as part of either:

  1. start-instance, or
  2. start-cluster, or
  3. start-node-agent --syncinstances procedure.

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.

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 startserv script that's located in instance's bin folder.

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.

2. Transport Layer Security:

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  admin-listener (HTTP/S) is started only in the DAS. There is no admin-listener in server instances.

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.

3. Authentication and Credentials:

Please see: http://wiki.glassfish.java.net/attach/GlassFishAdministrationPages/admincreds.html




Blog of JoJo 2009-06-10 15:12 发表评论
]]>
Spring Framework Document Resourceshttp://www.tkk7.com/ruoyoux/articles/232578.htmlBlog of JoJoBlog of JoJoSun, 05 Oct 2008 15:29:00 GMThttp://www.tkk7.com/ruoyoux/articles/232578.htmlhttp://www.tkk7.com/ruoyoux/comments/232578.htmlhttp://www.tkk7.com/ruoyoux/articles/232578.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232578.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232578.html最q开始研ISpring FrameworkQ顺手整理了q䆾文档资源列表?/span>

资源链接?/span>

Spring Framework Documentaion

http://www.springframework.org/documentation.html

Spring中文论坛图书?/span>

http://xglw.51.net/5team/springframework/viewtopic.php?t=31

Spring Reference Documentation

http://www.springframework.org/docs/reference/index.html

or http://www.springframework.org/docs/spring-reference.pdf

作者:Spring 开发组

中文?/span>http://xglw.51.net/5team/springframework/book/spring_referece_inchinese_m2.pdfQ?/span>for M2Q?/span>

译Q?/span>Spring中文论坛译l?/span>

Spring?/span>Document中还提供了:

The Spring Framework - A Lightweight Container by Rod Johnson, Juergen Hoeller

Container Resources vs Local Resources(for transactional data access with the Spring Framework) by Juergen Hoeller

Data Access and Transaction Abstraction with the Spring Framework(featuring Hibernate examples) by Juergen Hoeller

Web MVC with the Spring Framework by Juergen Hoeller

中文版:http://xglw.51.net/5team/springframework/book/webMvcSpring.pdf

译Q?/span>yanger

Q?/span>more…Q?/span>

Introducing the Spring Framework

http://www.theserverside.com/articles/article.tss?l=SpringFramework

作者:Rod Johnson

中文?/span> http://xglw.51.net/5team/springframework/viewtopic.php?t=18

译Q?/span>yanger

Developing a Spring Framework MVC application step-by-step

http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html

作者:Thomas Risberg

Spring Framework Tutorial

http://www.springframework.org/downloads/tutorial.pdf

作者:Isabelle Muszynski

?/span>Spring In Chinese Group?/span>

Q?/span>PPTQ?/span> On Spring by gigix

Q?/span>PPTQ?/span> Spring Introduction for 3.12M2 by yanger

Framework Design

http://qca.cn/frameworkdesign/content.htm

作者:林星

书籍购买链接

Expert One-on-One J2EE Design and Development

Q略Q?/span>

作者:Rod Johnson

中文版:http://www.china-pub.com/computers/common/info.asp?id=14126

Q说明:英文版本w很明,译则评L差)

我眼中的Spring

http://www.blogbus.com/blogbus/blog/diary.php?diaryid=125334

作者:dreamhead

Spring is coming

http://www.blogbus.com/blogbus/blog/diary.php?diaryid=126737

作者:founder_chen



Blog of JoJo 2008-10-05 23:29 发表评论
]]>
Tapestry整合到Spring里去http://www.tkk7.com/ruoyoux/articles/232576.htmlBlog of JoJoBlog of JoJoSun, 05 Oct 2008 15:27:00 GMThttp://www.tkk7.com/ruoyoux/articles/232576.htmlhttp://www.tkk7.com/ruoyoux/comments/232576.htmlhttp://www.tkk7.com/ruoyoux/articles/232576.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232576.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232576.htmlhttp://tech.blogbus.com/logs/139683.html

  在Spring最新的文档里,有关于如何将Tapestry整合到Spring里去的说明,见这?a >http://www.springframework.org/docs/reference/view.html#view-tapestry。Spring中文论坛应该会翻译出来,我就不做重复的工作,只摘要说明一下?/p>

  先看看Tapestry。下图说明了Tapestry是怎么栯取到service的?/p>

  在文档里Q基于Tapestry和Spring的应用被划分成五层,我们只关注前边两层:User Interface Layer和Service Layer。这U划分对于单独用Tapestry的应用也是成立的Q从上图可以看出Q那是对Service Layer的操作。当q行整合之后QUser Interface Layer仍然是由Tapestry提供Q而Service Layer则由Spring接手来提供?/p>

  Service实际上就是BeanQTapestry原本一套取得Service的机ӞgetEngine()->getService()。现在,我们用Spring这些ServiecQ也是Bean理hQ那么,要解决的问题只有一个,如何让Tapestry获得由Spring理h的的ServiceQ?/p>

  在Application Context里我们定义了需要被调用的BeanQ见文档Q,我们l它个名字就userService。那么,在Tapestry的page里,需要蝲入这个contextQ然后取得beanA?/p>

  一个最单的Ҏ是利用Spring的static工具WebApplicationContext在Tapestry page对应的Java class definition里直接蝲入Application Context,q取得userService?/p>

WebApplicationContext appContext = WebApplicationContextUtils.getApplicationContext(
        getRequestCycle().getRequestContext().getServlet().getServletContext());
    UserService userService = appContext.getBean("userService");

  不过q种用法和我们用Spring的原意有点违背——这不符合DI模式。应该在page里才军_我们调哪个Service?/p>

  所以,推荐的做法如下?/p>

  W一步,让Tapestry page能够获得ApplicationContextQ但q次不直接由Tapestry page来做Q因为在我们需要访问ApplicationContext的时候,Tapestry page很难拿到ServletContextQ所以我们将其放到Enging里去做。代码如下:

package com.whatever.web.xportal;
...
import ...
...
public class MyEngine extends org.apache.tapestry.engine.BaseEngine {
 
    public static final String APPLICATION_CONTEXT_KEY = "appContext";

    protected void setupForRequest(RequestContext context) {
        super.setupForRequest(context);
    
        // insert ApplicationContext in global, if not there
        Map global = (Map) getGlobal();
        ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);
        if (ac == null) {
            ac = WebApplicationContextUtils.getWebApplicationContext(
                context.getServlet().getServletContext()
            );
            global.put(APPLICATION_CONTEXT_KEY, ac);
        }
    }

  q样把ApplicationContext攑ֈ了global里去Q然后我们指定MyEngine是后边应用里实际使用的的EngineQ?/p>

<application
    name="Whatever xPortal"
    engine-class="com.whatever.web.xportal.MyEngine">
</application>

Q写着写着又像译?#8230;…不爽-_-Q?/p>

  W二步,在Tapestry page里取得BeanQ代码如下:

<property-specification name="userService"
                        type="com.whatever.services.service.user.UserService">
    global.appContext.getBean("userService")
</property-specification>

  W三步,在page对应的Java class definition增加一个abstract讉K者,也就是一个abstract getter
Ҏ。代码如下:

public abstract UserService getUserService();

  当Tapestry实际载入面的时候,会对cL件执行runtime codeҎ以增加定义了的propertiesQƈ上边的abstract getter
Ҏ与新建的fields挂钩h。(瀑布汗^^|||Q?/p>

  okQ这完成了。详l的exampleL文档?/p>

  单ȝ一下。Tapestry与Spring的整合实际上是把原本由Tapestry自己负责的Service LayerQ也是对Service/Bean的调用,交给Spring负责。实际的切入点,则在于上图所C的Engine处?br />



Blog of JoJo 2008-10-05 23:27 发表评论
]]>
Tapestry整合Spring实践http://www.tkk7.com/ruoyoux/articles/232575.htmlBlog of JoJoBlog of JoJoSun, 05 Oct 2008 15:25:00 GMThttp://www.tkk7.com/ruoyoux/articles/232575.htmlhttp://www.tkk7.com/ruoyoux/comments/232575.htmlhttp://www.tkk7.com/ruoyoux/articles/232575.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232575.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232575.htmlhttp://tech.blogbus.com/logs/219144.html

两个月前Q写了一blogQ名为《将Tapestry整合到Spring里去》,是根据文档做了理Z的说明。这阵子l于开始动手做Q由于犯了一个很低的错误,费了很多时_直到周六?#8220;摆^”Q很高兴。网上这斚w的资料非常少Q我把实际操作过E再介绍一下,也算补一下文档的不。事实上Spring|站的文档是l对Spring和Tapestry都有开发经验的人写的,多少有点q于略,不是很方便用?/p>

W一步:写一个Java Bean供后边调用:

package my;//接口
public interface IBean {
 public void amethod();
}

package my;//实现c?br /> public class Bean implements IBean {
 
 public void amethod() {
  //do something;
 }
}

W二步:~写Spring的context config文档applicationContext.xmlQ放在web应用?WEB-INF目录?/p>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"
http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
 <bean id="aBean" class="my.Bean">
 </bean>
</beans>

W三步:先试试直接蝲入Spring Application Context的做法。写一个tapestry面Q这里要求你对tapestry多少有点认识Q,如test.htmlQ在对应的test.java中写入以下代码:

WebApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(getRequestCycle().getRequestContext().getServlet().getServletContext());
IBean bean = appContext.getBean("aBean");
bean.amethod();

q里要说明一下,Spring的帮助文档有炚w误,它用了WebApplicationContextUtils.getApplicationContext()的方法,但实际不存在q个ҎQ应该用WebApplicationContextUtils.getWebApplicationContext()

W四步,改ؓ推荐的做法,在Engine里做上边的getWebApplicationContext()Qƈ其写到tapestry的global对象里边厅R?/p>

public class MyEngine extends BaseEngine {
 public static final String APPLICATION_CONTEXT_KEY = "appContext";
 protected void setupForRequest(RequestContext context) {
  super.setupForRequest(context);
  Map global = (Map) getGlobal();
  ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);
  if (ac == null) { ac = WebApplicationContextUtils.getWebApplicationContext(context.getServlet().getServletContext());
   System.out.println("试" + ac);//你可以看看这一句在什么时候执行,从而了解Engine是什么时候被调用?
   global.put(APPLICATION_CONTEXT_KEY, ac);
  }
 }
}

global是一个MapQ我们在里边增加了一个属性appContextQƈ取到的ApplicationContext放进去,以后Q通过调用global.appContext可以得到contextQƈ用来getBean?/p>

W五步,在tapestry应用的sample.application文档Q文件名与web.xml对应Q里Q指定所使用的EngineQ也是W四步写的内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "
http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">

<application name="Sample Application" 
 engine-class="MyEngine">
 <page name="test" specification-path="test.page"/>
</application>

W六步:在test.html对应的test.page里,加入获取bean的操作,代码如下Q?/p>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "
http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
<page-specification class="test">
  <property-specification name="aBean" type="my.IBean">
   global.appContext.getBean("aBean")
  </property-specification>
</page-specification>

W七步:在test.java里增加一个abstract getterQ?/p>

public abstract IBean getABean();

之后Q就可以在代码里用getABean()的方法获取我们需要的bean了,如:

getABean().amethod();

当然Q不要忘了编辑web.xml文档Q?/p>

<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"
http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
 <display-name>Tapestry Tutorial</display-name>
 <!--Redirect it to the servlet mapping address /h-->
 <filter>
  <filter-name>redirect</filter-name>
  <filter-class>org.apache.tapestry.RedirectFilter</filter-class>
  <init-param>
   <param-name>redirect-path</param-name>
   <param-value>/app</param-value>
  </init-param>
 </filter>

 <filter-mapping>
  <filter-name>redirect</filter-name>
  <url-pattern>/</url-pattern>
 </filter-mapping>
   
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param>
 <servlet>
  <servlet-name>context</servlet-name>
  <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 
 <servlet>
  <servlet-name>sample</servlet-name>
  <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
  <load-on-startup>0</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>sample</servlet-name>
  <url-pattern>/app</url-pattern>
 </servlet-mapping>

 <session-config>
  <session-timeout>15</session-timeout>
 </session-config>
 
 <welcome-file-list>
  <welcome-file>index.htm</welcome-file>
 </welcome-file-list>
 
</web-app>

结Q事实上Q这个过E与我上ơ写的内容大体相|不过l过实践之后Q我可以肯定地说q是走得通的Q如果你配置时出现问题,那可能是在一些其它地方忽略了什么。象我这一ơ就?#8230;…嗯,具体的不说了Q说出来会很不好意思的。如果有人配|时正好看到q篇文档Q希望对你有帮助^_^

Ps其实q一ơ失误的q程也可以写成篇blogQ重点在于期间的心\历程。不q还是算了。这D|间的工作受情l媄响太大了Q如果以后成为管理者,一定要注意下属的情l问题ƈ量予以解决Q而不能认Z需要关注这L事?/p>

又:Blogbus回退时输入数据会丢失Q虽然我知道q是Web应用开发里的难题,不过q是希望能够列入待解决的问题里去-_-



Blog of JoJo 2008-10-05 23:25 发表评论
]]>
Tapestry学习l验http://www.tkk7.com/ruoyoux/articles/232445.htmlBlog of JoJoBlog of JoJoSun, 05 Oct 2008 01:22:00 GMThttp://www.tkk7.com/ruoyoux/articles/232445.htmlhttp://www.tkk7.com/ruoyoux/comments/232445.htmlhttp://www.tkk7.com/ruoyoux/articles/232445.html#Feedback2http://www.tkk7.com/ruoyoux/comments/commentRss/232445.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232445.htmlq段旉在学习Tapestry,有些l验l大家分享一?
主要实例?appfuse,workbench,tapmenu-examples

appfuse应用架构:Tapestry + Spring + Hibernate + decorators
偶现在做了Eclipse?对初学者是非常实用的一个实?!!用MyEclipse导入和加入MySQL可以用?
q个架构应用到权限管?decoratorsq个漆工非常实例,可以按不同的文gq行漆改?做页面开发速度非常?
做web开发中应用到的内容基本上都包含有了.而且完全开源的.可以L修改.
主要的栏目有:权限,漆工,登陆,上传,日志,~存,多语a?账号的添加和修改{等...是学习Tapestry最好的一个实?

下蝲|址:在这儿出?上传p|Q文件大超?2,000 k   l箋上传;
文g大小?0M; q儿上传不了,去问主?(希望版主提供I间)
账号和密码ؓ:tomcat


在这D|间里学习Tapestry的不便之处有几点:
1.在Eclipse更改后要在tomcat的servlet理里重启一下appfuse,不知有没有更好的Ҏ可以不用重启?
2.应用Velocity作servlet模板时不能显CZ?我加入的servlet实例.
3.在accessDecisionManager里能不能实例对目录的权限理.
请大哥们指点一?

tapestry3英文手册:
http://tapestry.apache.org/tapestry3/doc/ComponentReference/index.html
tapestry4英文手册:
http://tapestry.apache.org/tapestry4.1/components/Image.html


appfuse的官方下?
https://appfuse.dev.java.net/servlets/ProjectDocumentList?folderID=4695&expandFolder=4695&folderID=0

appfuse中文学习资料:
http://www.kingbit.com/appfuse/index.php?job=art&articleid=a_20051016_231832


workbench的实例很多地斚w可以下蝲?自己上网找一下就有了.



?以appfuse4.0版ؓ?br style="font-family: " /> Tapestry的讨论QQ?8502111


Blog of JoJo 2008-10-05 09:22 发表评论
]]>
Spring hibernate T5 Maven2 http://www.tkk7.com/ruoyoux/articles/232422.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 16:03:00 GMThttp://www.tkk7.com/ruoyoux/articles/232422.htmlhttp://www.tkk7.com/ruoyoux/comments/232422.htmlhttp://www.tkk7.com/ruoyoux/articles/232422.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232422.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232422.html首先抱歉Q几文章中间的间隔如此之久Q一斚w工作太忙Q一斚w也是自己开始偷懒,闲暇之余Lh说自己需要休息一下,可每ơ总都是休息?br /> 本来q篇文章惌?使用Maven2 的maven2-xdoclet2-plugin 插g怎么配置生成 hibernate ?hbm 文g的,在annotation大行光的时候,我决定省略这一了。(有疑问者,可在此处发消息,^_^Q?br />

q里?T5 QT5.0.6Q??T5.0.6 前几天刚刚释攑և来,一只在?5.0.5 Q?6 的SNAPSHOT版本一直没有关注, 发现 Howard Lewis Ship真的是个喜欢变化的h?/font>参见Q?a >tapestry.apache.org/tapestry5/release-notes.html?/a>

q里列D集成配置以及些常用的lg用法Q有些说教,或者过于简单,也许Ҏ些h比较用户?/p>

1.?span class="hilite2">spring集成

修改 web.xml 中的xml 代码
1<filter> 
2<filter-name>appfilter-name> 
3<filter-class>org.apache.tapestry.TapestryFilterfilter-class> 
4filter> 
为:xml 代码
1<filter> 
2<filter-name>financeReportfilter-name> 
3<filter-class>org.apache.tapestry.spring.TapestrySpringFilterfilter-class> 
4filter> 

2. Select

你可以徏立你?SelectTest.tml文g

xml 代码

1<select t:id="id3" t:name="name3" t:type="select" model="genericSelectModel" encoder="genericValueEncoder" value="someBean"/> 


SelectTest.java 可如?br /> java 代码
 1@Persist 
 2private Customer _someBean; 
 3
 4@Inject 
 5private PropertyAccess propertyAccess; 
 6
 7public Customer getSomeBean() 
 8return _someBean; 
 9}
 
10
11public void setSomeBean(Customer _someBean) 
12this._someBean = _someBean; 
13}
 
14//for Select, 
15public SelectModel getGenericSelectModel() 
16return new GenericSelectionModel(getBeanList(), propertyAccess, "name"); 
17}
 
18
19//for select 
20public ValueEncoder getGenericValueEncoder() 
21return new GenericValueEncoder(getBeanList(), propertyAccess, "id"); 
22}
 
23
24public List getBeanList() 
25_beanList = new ArrayList(); 
26for (int i = 0; i < 10; i++
27Customer c = new Customer(); 
28c.setName("Customer Name" + i); 
29c.setCode("Code" + i); 
30c.setId("" + i); 
31_beanList.add(c); 
32}
 
33return _beanList; 
34}
 
35
36public void setBeanList(List _beanList) 
37this._beanList = _beanList; 
38}
 

GenericValueEncoder 和GenericSelectionModel 的实现方式也比较单,可以参见
wiki.apache.org/tapestry/Tapestry5SelectObject

Blog of JoJo 2008-10-05 00:03 发表评论
]]>
tapestry的第一?/title><link>http://www.tkk7.com/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.tkk7.com/ruoyoux/articles/232419.html</guid><wfw:comment>http://www.tkk7.com/ruoyoux/comments/232419.html</wfw:comment><comments>http://www.tkk7.com/ruoyoux/articles/232419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ruoyoux/comments/commentRss/232419.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ruoyoux/services/trackbacks/232419.html</trackback:ping><description><![CDATA[<span style="font-family: Ҏ姚体">        最权威的书是tapestry In ActionQ但初学者上手困难,另一本很好的是Enjoying Web Development with TapestryQ非常的,由浅入深Q可惜目前无法找全这本书Q?a style="font-family: " >http://www.itpub.net/390564.html</a>有前4章。下定决心写我自q学习W记?br style="font-family: " />   每一个tapestry应用都要有一个Home pageQ当tapestry接收W一个requestӞ׃查找Home.pageQ这是他的d口。因为tapestry的URL对于人可L极?3.1改变这U情?Q如Q?a style="font-family: " href="http://localhost:8080/HelloWorld/app?service=page/Home">http://localhost:8080/HelloWorld/app?service=page/Home</a>Q如果访问具体页面在page后面指定卛_Q如有个AddItem面一定要真实存在AddItem.htmlQ只需/app?service=page/AddItem。就q么个浅昄问题在InAction中居然没有介l,害的我找了两天呀Q最后还是在Enjoying中清楚的写着呀Q真是本好书呀Q?br style="font-family: " /> tomcat5.0.28中把cd攑ֈshared/lib下是不行的,找不c,在Engoying书中是q样用的Q版本是tomcat-5.5.7Q应用程序的路径不在tomcat目录下这样用,有待一试!<br style="font-family: " /> 在页面对应的cL件中Q定义抽象方法,p?page配置文g中定义,告诉tapestry负责理q个属性,例如Q?br style="font-family: " /> public abstract void setDvd(DVD dvd);<br style="font-family: " /> public abstract DVD getDvd();<br style="font-family: " /> <property-specificationname="dvd" type="com.sandcast.examples.tapestry.crud.bo.DVD"/><br style="font-family: " /> 事g驱动Q在cM定义listener必须满q个格式Q?br style="font-family: " /> public void methodName(IRequestCycle cycle) {}<br style="font-family: " /> GlobalcL在框架内可以调用保存在context范围内的Q如果用得到要求自己实现q个c,名字可以L命名Q但要在servletName.application配置文g中定义:<br style="font-family: " /> <property name="org.apache.tapestry.global-class" value="com.sandcast.examples.tapestry.Global"/><br style="font-family: " /> </span> <img src ="http://www.tkk7.com/ruoyoux/aggbug/232419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:52 <a href="http://www.tkk7.com/ruoyoux/articles/232419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tsh Tapestry Spring Hibernate 集成W记http://www.tkk7.com/ruoyoux/articles/232417.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 15:49:00 GMThttp://www.tkk7.com/ruoyoux/articles/232417.htmlhttp://www.tkk7.com/ruoyoux/comments/232417.htmlhttp://www.tkk7.com/ruoyoux/articles/232417.html#Feedback1http://www.tkk7.com/ruoyoux/comments/commentRss/232417.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232417.html参考了|上好多文章Q记不太清了Q在此一q感谢!主要有:
Tapestry整合Spring实践 http://tech.blogbus.com/logs/2004/06/219144.html

1、在eclipse中新建tapestry目Q项目名UtshDemo
2、菜单myEclipse-->Add Spring Capabilities... Q?br />

点击Next> Q注意的一ҎQ没有用myeclipse自带的jar包,而是选择User Libraries自己定义的最新的spring开发包(Ҏ是在Window-->Preferences...-->Java-->Build Path-->User Libraries中定?Qؓ了WEB-INF/lib目录下包含相应jar包,选择拯到目?br />

点击FinishQ完成对spring支持Q有一个不好的是,eclipse会把所有的jar包文件一个个明细的列在项目名下,倍长非常不方便,修改办法Q在目属?->Java Build Path-->Libraries中,把所有的明细jar包全部选中删除Q点击Add Library...-->User Library-->Next> -->N相应的user library-->Finish 卛_

3、修改web.xml如下Q?br /> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
      PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
      "

<web-app>
  <display-name>tshDemo</display-name>

  <filter>
    <filter-name>redirect</filter-name>
    <filter-class>org.apache.tapestry.RedirectFilter</filter-class>
    <init-param>
      <param-name>redirect-path</param-name>
      <param-value>/app</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>redirect</filter-name>
    <url-pattern>/</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

  <servlet>
    <servlet-name>tshDemo</servlet-name>
    <servlet-class>
      org.apache.tapestry.ApplicationServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>tshDemo</servlet-name>
    <url-pattern>/app</url-pattern>
  </servlet-mapping>
</web-app>

4、修改applicationContext.xml如下Q?br /> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "

<beans>
  <description>Spring Quick Start</description>
  <bean id="theAction" class="tsh.demo.service.LowerAction">
    <property name="message">
      <value>HeLLo </value>
    </property>
  </bean>

</beans>

5、新?个包Qtsh.demo.dao 持久层,tsh.demo.service 中间层,tsh.demo.web 表示?br />
6、tapestry支持springQ新建tapestry enginec,如下Q?br /> /*
 * package tsh.demo.web;
 * class tsh.demo.web.EngineWithSpring
 * Created on 2006-1-23, 17:49:43
 */
package tsh.demo.web;

import java.util.Map;

import org.apache.tapestry.engine.BaseEngine;
import org.apache.tapestry.request.RequestContext;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class EngineWithSpring extends BaseEngine {

 private static final long serialVersionUID = 1L;
 public static final String APPLICATION_CONTEXT_KEY = "appContext";
 
 protected void setupForRequest(RequestContext context) {
  super.setupForRequest(context);
  Map global = (Map) getGlobal();
  ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);
  if (ac == null) {
   ac = WebApplicationContextUtils.getWebApplicationContext(context.getServlet().getServletContext());
  }
  System.out.println("试" + ac);//你可以看看这一句在什么时候执行,从而了解Engine是什么时候被调用?
  global.put(APPLICATION_CONTEXT_KEY, ac);
 }
}

7、修改tapestry配置文gtshDemo.applicationQ如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "
<!-- generated by Spindle, http://spindle.sourceforge.net -->

<application name="tshDemo" engine-class="tsh.demo.web.EngineWithSpring">
   
    <description>add a description</description>
   
    <page name="Home" specification-path="Home.page"/>
   
</application>

8、修改Home.page文gQ如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  " <!-- generated by Spindle, http://spindle.sourceforge.net -->

<page-specification class="tsh.demo.web.pages.Home">

    <description>add a description</description>
    <property-specification name="theAction" type="tsh.demo.service.Action" >
     global.appContext.getBean("theAction")
    </property-specification>
    <property-specification name="greeting" type="java.lang.String" />
   
</page-specification>

9、Homec,如下Q?br /> /*
 * package tsh.demo.web.pages;
 * class tsh.demo.web.pages.Home
 * Created on 2006-1-24, 10:51:12
 */
package tsh.demo.web.pages;

import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.event.PageRenderListener;
import org.apache.tapestry.html.BasePage;

import tsh.demo.service.Action;

public abstract class Home extends BasePage implements PageRenderListener {

 public abstract Action getTheAction();
 public abstract void setGreeting(String greeting);
 
 /* (non-Javadoc)
  * @see org.apache.tapestry.event.PageRenderListener#pageBeginRender(org.apache.tapestry.event.PageEvent)
  */
 public void pageBeginRender(PageEvent event) {
  System.out.println(getTheAction().execute("Rod Johnson"));
  setGreeting(getTheAction().execute("Rod Johnson"));
 }
}

10、Home.html文gQ如下:
<html jwcid="@Shell" title="application">
<head></head>
<body>
   <h3>welcome, </h3><h1><span jwcid="@Insert" value="ognl:greeting" /></h1>
</body>
</html>

11、相关spring bean cd下:
/*
 * package tsh.demo.service;
 * class tsh.demo.service.Action
 * Created on 2005-11-23, 16:32:52
 */
package tsh.demo.service;

public interface Action {
 public String execute(String str);
}

/*
 * package tsh.demo.service;
 * class tsh.demo.service.LowerAction
 * Created on 2005-11-23, 16:36:32
 */
package tsh.demo.service;

public class LowerAction implements Action {
  private String message;
  
  public String getMessage() {
  return message;
  }
 
  public void setMessage(String string) {
   message = string;
  }
 
  public String execute(String str) {
    return (getMessage() + str).toLowerCase();
 }

}

/*
 * package tsh.demo.service;
 * class tsh.demo.service.UpperAction
 * Created on 2005-11-23, 16:34:17
 */
package tsh.demo.service;

public class UpperAction implements Action {

  private String message;
  
  public String getMessage() {
  return message;
  }
 
  public void setMessage(String string) {
   message = string;
  }
 
  public String execute(String str) {
   return (getMessage() + str).toUpperCase();
  }

}

12、在%CATALINA_HOME%\conf\Catalina\localhost目录下徏tshDemo.xml文gQ如下:
<Context path="/tshDemo" docBase="D:\eclipseWorks\workspace\tshDemo\context"
        debug="0" privileged="true" reloadable="true">
  <Logger className="org.apache.catalina.logger.FileLogger"
             prefix="localhost_Mssql_log." suffix=".txt"
             timestamp="true"/>

    <!-- maxActive: Maximum number of dB connections in pool. Make sure you
         configure your mysqld max_connections large enough to handle
         all of your db connections. Set to 0 for no limit.
         -->

    <!-- maxIdle: Maximum number of idle dB connections to retain in pool.
         Set to -1 for no limit.  See also the DBCP documentation on this
         and the minEvictableIdleTimeMillis configuration parameter.
         -->

    <!-- maxWait: Maximum time to wait for a dB connection to become available
         in ms, in this example 10 seconds. An Exception is thrown if
         this timeout is exceeded.  Set to -1 to wait indefinitely.
         -->

    <!-- username and password: MySQL dB username and password for dB connections  -->

    <!-- driverClassName: Class name for the old mm.mysql JDBC driver is
         org.gjt.mm.mysql.Driver - we recommend using Connector/J though.
         Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.
         -->
   
    <!-- url: The JDBC connection url for connecting to your MySQL dB.
         The autoReconnect=true argument to the url makes sure that the
         mm.mysql JDBC Driver will automatically reconnect if mysqld closed the
         connection.  mysqld by default closes idle connections after 8 hours.
         -->
  <!--Resource name="jdbc/m2Base" auth="Container" type="javax.sql.DataSource"
    maxActive="100" maxIdle="30" maxWait="10000"
    url="jdbc:jtds:sqlserver://im04:1433;DatabaseName=m2Base"
    username="xxxx" password="xxxxxxxxx" driverClassName="net.sourceforge.jtds.jdbc.Driver"
    removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" />

  <Resource name="jdbc/merp" auth="Container" type="javax.sql.DataSource"
    maxActive="100" maxIdle="30" maxWait="10000"
    url="jdbc:jtds:sqlserver://im04:1433;DatabaseName=merp"
    username="xxxxxxx" password="xxxxxxxxx" driverClassName="net.sourceforge.jtds.jdbc.Driver"
    removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" /-->

</Context>


/**
 * Hibernate的集成日后补?br />  **/
66、启动tomcatQ访?a href="http://locahost:8080/tshDemo">http://locahost:8080/tshDemoQ如果页面正常显C,配置成功?/p>

Blog of JoJo 2008-10-04 23:49 发表评论
]]>
20080421 Eclipse hibernate spring Tapestry 1http://www.tkk7.com/ruoyoux/articles/232416.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 15:46:00 GMThttp://www.tkk7.com/ruoyoux/articles/232416.htmlhttp://www.tkk7.com/ruoyoux/comments/232416.htmlhttp://www.tkk7.com/ruoyoux/articles/232416.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232416.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232416.html
http://www.shengfang.org/blog/p/20080421EclipsehibernatespringTapestry1.php

Blog of JoJo 2008-10-04 23:46 发表评论
]]>
Tapestry4+Spring+Hibernate--我的Tapestry4学习l历 http://www.tkk7.com/ruoyoux/articles/232414.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 15:39:00 GMThttp://www.tkk7.com/ruoyoux/articles/232414.htmlhttp://www.tkk7.com/ruoyoux/comments/232414.htmlhttp://www.tkk7.com/ruoyoux/articles/232414.html#Feedback1http://www.tkk7.com/ruoyoux/comments/commentRss/232414.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232414.htmlTapestry4正式版在2006q??日终于发布了。这一天,我等了半q。从beta2试用开始,一直等到beta13,再从rc1{到rc3.
之所以等到正式版出台Q才开始学习历E,是因为在beta2试学3天,一无所P错误千出?br /> 学习?0天,l于入门Q有感Tapestry4资料之少Q写本文Q希望能够有助于后来者,走弯\?br /> Tapestry学习资料,其中多ؓTapestry3的资料,Tapestry4的资料则之,而且T4与T3差异甚大Q有不少地方是不一L?br /> 本文介以L的开发框ӞTapestr4+Sping+Hibernate,eclipse 3.1景?br /> 一QT4学习曲线在java的众多web 框架中以长且陡著Uͼ入门要多长时_
老夫愚钝Q用?0个工作日。估计,年才俊7天就可以了。但若无MTTapestry基础Q?天是不了的?/span>

二,特别提示一Q?br /> 目前最新的Spring官方指南QV1.26)关于Spring+Tapestryl合部分Q只适用于Tapestry3,不必费旉了?br /> Spring+Tapestry4主要参考是Tapestry4Spring.国内的干扁四季豆的相关部分基本上是照搬?br /> 三,T4正式版自带了几个例子QVlib,Workbench,我个人看q不怎么P不是最佛_门例E。对无基者尤其无用。不要浪费太多时间去试图~译通过。非要编译它Q也不要怿其文档所a。我的看法是Q很难自动完成,得多ơ手工干预。其实,不理也Ş?br /> 四,正式版所带的文档比较有h|其水UserGuide,40来个components(For,insert...)介绍应该是必读,值得打印。特别提C:T4文档Ҏ印比较友好,修改print.css卛_Q既省墨Q又可有更好的阅L果?br /> 五,我个人最感谢的是Enjoying Web Development with Tapestry,q本书针对T4q行了更斎ͼ也是T4|站推荐的几本书中的W二本?br /> q本书是我看的材料中最W合初学者友好的教程Q提供前4章免费下载,q且可以下蝲全书代码。我打印了这4章,作ؓ重点教材仔细阅读?br /> 书中的代码,可以L地直接导入到ecipse,大大节省了打字时_而且不象很多|上教程Q代码基本上没有错误Q可以直接编译通过?/span>

六,2006qibm dw上面的资料被Ҏ得很高,我个人看Q没有h|都是重复的大陆货Q不值得一诅R?br /> 不要花太多时间去google,baidu,或者去javaeyeQspringforum之类的站点,把我上面提到的一本书Q几个文档仔l阅读,可以了?br /> 虽然基本上是英文的,但语a都很通俗Q四U水q_该就可以了?br />



Blog of JoJo 2008-10-04 23:39 发表评论
]]>
Tapestry 5http://www.tkk7.com/ruoyoux/articles/232411.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 15:31:00 GMThttp://www.tkk7.com/ruoyoux/articles/232411.htmlhttp://www.tkk7.com/ruoyoux/comments/232411.htmlhttp://www.tkk7.com/ruoyoux/articles/232411.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232411.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232411.html

What is Tapestry?
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.

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.

Tapestry is specifically designed to make creating new components very easy, as this is a routine approach when building applications.

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.

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!

Tapestry is released under the Apache Software Licence 2.0.

Roadmap
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:

5.0 Release Candidate in September 2008
5.0 Final Release shortly thereafter
5.1 development to follow, on a much shorter release schedule
... 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.
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.
Third Party Libraries, Tutorials and Resources
Tapestry 5 has inspired a number of people to create third party libraries, providing a mix of new components and new and improved integrations.

Name Author Description
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.
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.
JumpStart Geoff Callender A "living tutorial" in the form of a base Tapestry application ready to be expanded and customized.
InterLDAP Linagora / Francois Armand LDAP content management system for non tech users.
loom-t5 Chris Scheid Eclipse plugin.
Shams Examples, Components Mohammad H. Shamsi A set of Tapestry 5 Examples, Tutorials, Components, and Documents for beginners.
Tapestry for Nonbelievers Renat Zubairov & Igor Drobiazko Simple introduction to using Tapestry and creating components
T5Components Sven Homburg Ajax-enabled components based on Prototype and Scriptaculous.
tacos-seam Igor Drobiazko Intregrates with JBoss Seam.
tapestry5-acegi Robin Helgelin Integration with the Acegi path-based security framework.
tapestry5-treegrid Gabriel Landais Combination tree navigation and data grid, based on sstree.

New And Of Note
Tapestry now bundles Prototype version 1.6.0.2.
New methods have been added to Node to allow nodes to be moved about or otherwise manipulated.
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.
The new @Local annotation makes it easier to reference services within the same module when injecting.
Most general documentation has been moved from the tapestry-core module up to the project level.
Work has started on a Tapestry Cookbook, showing how to tackle common scenarios.
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).
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.
The Exception Report page now identifies the version of the Tapestry framework, and lists out System properties (including the Java classpath).
The Grid component can now update itself in place, using Ajax, when paging or sorting links are clicked.
Added a zone parameter to the BeanEditForm component, to support Ajax updates.
The @Cached annotation has been added to allowing the caching of method results.
What's changed since Tapestry 4?
Tapestry 5 is an all new code base, written from the ground up to take Java web application development to new levels of productivity.

This new release removes many limitations of Tapestry 4:

Components no longer extend from base classes.
Components classes are no longer abstract. Components are pure, simple POJOs (plain old Java objects).
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.
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.
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.
Adaptive API
A key feature of Tapestry 5 is adaptive API.

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.

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.

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.

For example, you may have a login form and have a method that gets invoked when the form is submitted:

public class Login
{
  @Persist
  @Property
  private String userId;

  @Property
  private String password;

  @Component
  private Form form;

  @Inject
  private LoginAuthenticator authenticator;

  void onValidateForm()
  {
    if (! authenticator.isValidLogin(userId, password))
    {
      form.recordError("Invalid user name or password.");
    }
  }

  Object onSuccess()
  {
    return PostLogin.class;
  }

}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.

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.

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.

Tapestry also saves you effort: the @Property annotation marks a field as readable and writable; Tapestry will provide the accessor methods automatically.

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).

About Snapshots and Releases
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.

Better yet, you can pull down Tapestry modules from the central Maven repository.

The use of Maven has let us move with great speed, providing preview releases and snapshots.

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.

A nightly build process on Tapestry's continuous integration server creates new snapshots emevery night/em.

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.

To access this repository, you may add -DremoteRepositories=http://tapestry.formos.com/maven-snapshot-repository to the command line when running Maven.

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.

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.

Principle 1 -- Static Structure, Dynamic Behavior
Tapestry is designed to be extremely scalable in several dimensions:

Tapestry applications may contain large numbers of pages and many custom components.
Tapestry applications may contain very complex functionality.
Tapestry applications may be created by large, diverse teams.
Tapestry applications can service large numbers of concurrent users.
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

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.

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.

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.

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.

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!

Public vs. Internal
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.

With the clean slate of Tapestry 5, we are being much more ruthless about internal vs. external.

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.

Backwards Compatibility
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.

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.

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.

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.

 



Blog of JoJo 2008-10-04 23:31 发表评论
]]>
利用Xdoclet 生成spring的配|文?/title><link>http://www.tkk7.com/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.tkk7.com/ruoyoux/articles/232410.html</guid><wfw:comment>http://www.tkk7.com/ruoyoux/comments/232410.html</wfw:comment><comments>http://www.tkk7.com/ruoyoux/articles/232410.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ruoyoux/comments/commentRss/232410.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ruoyoux/services/trackbacks/232410.html</trackback:ping><description><![CDATA[<p><br /> 最q看到xdoclet支持spring的自动生成,参考了一下以前的hibernate的代码,自己做了一个尝试,具体l果如下Q?<br /> 引用: <br /> build.xml </p> <p>代码: <br /> <target name="define-tasks" description="defines custom tasks"> <br />   <taskdef  name="springdoclet"           classname="xdoclet.modules.spring.SpringDocletTask" <br />             classpathref="xdoclet.classpath"/>    </target> <br />     <target name="springMap" depends="define-tasks" description="建立spring ?XML文g"> <br />         <br />             <springdoclet <br />             destdir="${build.dir}" <br />             mergedir="logs" <br />             excludedtags="@version,@author" <br />             addedtags="@xdoclet-generated at ${TODAY}" <br />             force="${xdoclet.force}" > <br />             <fileset dir="src/persistent"/> </p> <p>            <springxml validatexml="true" /> </p> <p>        </springdoclet> <br />     </target>     </p> <p><br /> 说明Qant 自动在你的destdir下生成spring.xml.mergedir参数可以包括你自己额外的bean定义Q格式是<bean></bean>Q文件名字必Mؓspring-beans.xmlQ如果你需要定义datasourceQ就可以攑֜q个文g里?</p> <p>下面是我自己的代码例子:Q我只写了一点简单的Q?<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 />  </p> <p><br />  </p> <img src ="http://www.tkk7.com/ruoyoux/aggbug/232410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:29 <a href="http://www.tkk7.com/ruoyoux/articles/232410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 史上最单的struts+spring+hibernate配置实例http://www.tkk7.com/ruoyoux/articles/232408.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 15:28:00 GMThttp://www.tkk7.com/ruoyoux/articles/232408.htmlhttp://www.tkk7.com/ruoyoux/comments/232408.htmlhttp://www.tkk7.com/ruoyoux/articles/232408.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232408.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232408.html本文不关心必ȝJAR包,q个东东在网上能够找到很多,本文只关心如何配|,才能够让STRUTS SPRING HIBERNATE和MYSQL相关q?

<web.xml>
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp">
<display-name>MVC_BPEL_MODELWeb</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/Hibernate_Context.xml</param-value>
</context-param>
<servlet>
<servlet-name>SpringContextServlet</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>validate</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-nested.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-nested.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-template.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-template.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-tiles.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
</taglib>

</web-app>
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?
<action-servlet.xml>
----------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean name="/User" class="com.yaya.action.UserAction" singleton="false">
<property name="userManager">
<ref bean="userManager" />
</property>
</bean>


</beans>
-------------------------------------------------------------------
<hibernate_context.xml>
--------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<!-- <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
<property name="prefix"><value>/WEB-INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean> -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>

<property name="url">
<value>jdbc:mysql://localhost/pdm</value>
</property>

<property name="username">
<value>root</value>
</property>

<property name="password">
<value></value>
</property>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">

<property name="dataSource">
<ref local="dataSource" />
</property>

<property name="mappingResources">
<list>
<value>hbm_tb/TSysuser.hbm.xml</value>
</list>
</property>

<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">

<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>


<!-- Spring的数据访问异常{换器QData Access Exception TranslatorQ定?-->
<bean id="jdbcExceptionTranslator" class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>

<!-- Hibernate Template定义 -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="jdbcExceptionTranslator">
<ref bean="jdbcExceptionTranslator" />
</property>
</bean>

<!--baseTransactionProxy -->
<bean abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" id="baseTransactionProxy">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>


<bean id="userDao" class="com.yaya.service.dao.hibernate.UserHibernateDao">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>

<bean id="userManagerTarget" class="com.yaya.service.spring.UserManagerImpl">
<property name="userDao">
<ref local="userDao" />
</property>
</bean>

<bean id="userManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>

<property name="target">
<ref local="userManagerTarget" />
</property>

<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>

</beans>
-------------------------------------------------------------------
<struts-config.xml>
-------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

<!-- 数据?-->
<data-sources></data-sources>

<!-- 表单 Bean -->
<form-beans>
<form-bean name="UserActionForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="User" type="com.yaya.actionform.UserActionForm" />
</form-bean>
</form-beans>

<!-- 全局异常 -->
<global-exceptions></global-exceptions>

<!-- 全局转发 -->
<global-forwards></global-forwards>

<!-- 操作映射 -->
<action-mappings>
<action path="/User" type="org.springframework.web.struts.DelegatingActionProxy" name="UserActionForm" scope="request" parameter="method" validate="false">
<forward name="list" path="/userlist.jsp" />
<forward name="edit" path="/userform.jsp" />
</action>

</action-mappings>

<!-- 消息资源 -->
<message-resources parameter="mvc_bpel_modelweb.resources.ApplicationResources" />
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/action-servlet.xml" />
</plug-in>

</struts-config>
------------------------------------------------------------------
UserHibernateDao.java
------------------------------------------------------------------
/*
* 创徏日期 2005-4-7
*
* 更改所生成文g模板?
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
package com.yaya.service.dao.hibernate;

import java.util.List;

import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;

import com.yaya.hb.TSysuser;
import com.yaya.service.dao.IUserDao;
import java.util.List;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

/**
* @author Administrator
*
* 更改所生成cd注释的模板ؓ
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
public class UserHibernateDao extends HibernateDaoSupport implements IUserDao {

private Log log = LogFactory.getLog(UserHibernateDao.class);

/* Q非 JavadocQ?

* @see com.jandar.dao.IUserDAO#getUsers()

*/

public List getUsers() {

return getHibernateTemplate().find("from TSysuser");

}

/* Q非 JavadocQ?

* @see com.jandar.dao.IUserDAO#getUser(java.lang.Long)

*/

public TSysuser getUser(String username) {

// TODO 自动生成Ҏ存根
//String msg = getHibernateTemplate().get(TSysuser.class,username).toString();
TSysuser user = (TSysuser) getHibernateTemplate().get(TSysuser.class,username);
//TSysuser user = (TSysuser) getHibernateTemplate().find("from TSysuser where username = ?",username);
System.out.println(user.getUserdesc());
System.out.println(user.getHeadship());
if (user == null) {
throw new ObjectRetrievalFailureException(TSysuser.class, username);
}
return user;
}

/* Q非 JavadocQ?

* @see com.jandar.dao.IUserDAO#saveUser(com.jandar.model.User)

*/

public void saveUser(TSysuser user) {

log.debug("xxxxxxx");

System.out.println("yyyy");

getHibernateTemplate().saveOrUpdate(user);

if (log.isDebugEnabled()) {

log.debug("username set to " + user.getUsername());

}

}

/* Q非 JavadocQ?

* @see com.jandar.dao.IUserDAO#removeUser(java.lang.Long)

*/

public void removeUser(String username) {

Object user = getHibernateTemplate().load(TSysuser.class, username);

getHibernateTemplate().delete(user);

if (log.isDebugEnabled()) {

log.debug("del user " + username);

}

}

}
-------------------------------------------------------------------
useraction.java
--------------------------------------------------------------------
/*
* 创徏日期 2005-4-11
*
* 更改所生成文g模板?
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
package com.yaya.action;

import java.util.Date;

import org.apache.struts.actions.DispatchAction;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.util.MessageResources;

import com.yaya.hb.TSysuser;
import com.yaya.service.spring.UserManagerImpl;
/**
* @author Administrator
*
* 更改所生成cd注释的模板ؓ
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
public class UserAction extends DispatchAction {

private static Log log = LogFactory.getLog(UserAction.class);
private UserManagerImpl mgr = null;
public void setUserManager(UserManagerImpl userManager) {
this.mgr = userManager;
}

public ActionForward delete(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("entering 'delete' method...");
}
mgr.removeUser(request.getParameter("user.username"));
ActionMessages messages = new ActionMessages();
messages.add(
ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("user.deleted"));
saveMessages(request, messages);
return list(mapping, form, request, response);
}

public ActionForward edit(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("entering 'edit' method...");
}

DynaActionForm userForm = (DynaActionForm) form;
String username = request.getParameter("username");

// null userId indicates an add
if (username != null) {
try
{
TSysuser user = mgr.getUser(username);
if (user == null) {
ActionMessages errors = new ActionMessages();
errors.add(
ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("user.missing"));
saveErrors(request, (ActionErrors) errors);
return mapping.findForward("list");
}
userForm.set("user", user);
request.setAttribute("user",user);
}
catch(Exception e)
{
e.printStackTrace();
}

}
return mapping.findForward("edit");
}

public ActionForward list(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("entering 'list' method...");
}
request.setAttribute("users", mgr.getUsers());
return mapping.findForward("list");
}

public ActionForward save(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("entering 'save' method...");
}

if (isCancelled(request)) {
return list(mapping, form, request, response);
}

// run validation rules on this form
ActionMessages errors = form.validate(mapping, request);

if (!errors.isEmpty()) {
saveErrors(request, (ActionErrors) errors);

return mapping.findForward("edit");
}
DynaActionForm userForm = (DynaActionForm) form;
TSysuser user = (TSysuser) userForm.get("username");

mgr.saveUser(user);

ActionMessages messages = new ActionMessages();
messages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("user.saved", user.getUsername()));
saveMessages((HttpServletRequest) request.getSession(), messages);

return mapping.findForward("users");
}

public ActionForward unspecified(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
return list(mapping, form, request, response);
}

}
-------------------------------------------------------------------
UserMenuActionForm.java
-------------------------------------------------------------------
/*
* 创徏日期 2005-3-28
*
* 更改所生成文g模板?
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
package com.yaya.actionform;

import java.sql.Date;

import org.apache.struts.action.ActionForm;

/**
* @author Administrator
*
* 更改所生成cd注释的模板ؓ
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
public class UserMenuActionForm extends ActionForm {

/** identifier field */
private String username;

/** identifier field */
private String fitemcode;

/** identifier field */
private String itemcode;

/** identifier field */
private String itemdesc;

/** identifier field */
private String itemtype;

/** identifier field */
private Integer itemid;

/** identifier field */
private String lastmodif;

/** identifier field */
private Date lastmdate;

/** identifier field */
private String creadtor;

/** identifier field */
private Date creatdate;

/** identifier field */
private String title;

/** identifier field */
private String url;

/** identifier field */
private String target;

/** identifier field */
private String icon;

/** identifier field */
private String iconopen;

/** identifier field */
private Integer open;


/** identifier field */
private Integer id;

/** identifier field */
private Integer pid;

public String getUsername() {
return this.username;
}

public void setUsername(String username) {
this.username = username;
}

public String getFitemcode() {
return this.fitemcode;
}

public void setFitemcode(String fitemcode) {
this.fitemcode = fitemcode;
}

public String getItemcode() {
return this.itemcode;
}

public void setItemcode(String itemcode) {
this.itemcode = itemcode;
}

public String getItemdesc() {
return this.itemdesc;
}

public void setItemdesc(String itemdesc) {
this.itemdesc = itemdesc;
}

public String getItemtype() {
return this.itemtype;
}

public void setItemtype(String itemtype) {
this.itemtype = itemtype;
}

public Integer getItemid() {
return this.itemid;
}

public void setItemid(Integer itemid) {
this.itemid = itemid;
}

public String getLastmodif() {
return this.lastmodif;
}

public void setLastmodif(String lastmodif) {
this.lastmodif = lastmodif;
}

public Date getLastmdate() {
return this.lastmdate;
}

public void setLastmdate(Date lastmdate) {
this.lastmdate = lastmdate;
}

public String getCreadtor() {
return this.creadtor;
}

public void setCreadtor(String creadtor) {
this.creadtor = creadtor;
}

public Date getCreatdate() {
return this.creatdate;
}

public void setCreatdate(Date creatdate) {
this.creatdate = creatdate;
}

public String getTitle() {
return this.title;
}

public void setTitle(String title) {
this.title = title;
}

public String getUrl() {
return this.url;
}

public void setUrl(String url) {
this.url = url;
}

public String getTarget() {
return this.target;
}

public void setTarget(String target) {
this.target = target;
}

public String getIcon() {
return this.icon;
}

public void setIcon(String icon) {
this.icon = icon;
}

public String getIconopen() {
return this.iconopen;
}

public void setIconopen(String iconopen) {
this.iconopen = iconopen;
}

public Integer getOpen() {
return this.open;
}

public void setOpen(Integer open) {
this.open = open;
}
public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public Integer getPid() {
return this.pid;
}

public void setPid(Integer pid) {
this.pid = pid;
}


}
------------------------------------------------------------------
package com.yaya.hb;

import java.io.InputStream;
import java.io.Serializable;
import java.util.Date;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

/** @author Hibernate CodeGenerator */
public class TSysuser implements Serializable {

/** identifier field */
private String username;

/** identifier field */
private String userdesc;

/** identifier field */
private String passwords;

/** identifier field */
private String deptno;

/** identifier field */
private String headship;

/** identifier field */
private String sex;

/** identifier field */
private String tel;

/** identifier field */
private String email;

/** identifier field */
private String url;

/** identifier field */
private String pcall;

/** identifier field */

/** identifier field */
private String userphoto;

/** identifier field */
private Integer facerefutime;

/** identifier field */
private String facelanguage;

/** identifier field */
private String lastmodif;

/** identifier field */
private Date lastmdate;

/** identifier field */
private String creadtor;

/** identifier field */
private Date creatdate;

/** full constructor */
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) {
this.username = username;
this.userdesc = userdesc;
this.passwords = passwords;
this.deptno = deptno;
this.headship = headship;
this.sex = sex;
this.tel = tel;
this.email = email;
this.url = url;
this.pcall = pcall;
this.userphoto = userphoto;
this.facerefutime = facerefutime;
this.facelanguage = facelanguage;
this.lastmodif = lastmodif;
this.lastmdate = lastmdate;
this.creadtor = creadtor;
this.creatdate = creatdate;
}

/** default constructor */
public TSysuser() {
}

public String getUsername() {
return this.username;
}

public void setUsername(String username) {
this.username = username;
}

public String getUserdesc() {
return this.userdesc;
}

public void setUserdesc(String userdesc) {
this.userdesc = userdesc;
}

public String getPasswords() {
return this.passwords;
}

public void setPasswords(String passwords) {
this.passwords = passwords;
}

public String getDeptno() {
return this.deptno;
}

public void setDeptno(String deptno) {
this.deptno = deptno;
}

public String getHeadship() {
return this.headship;
}

public void setHeadship(String headship) {
this.headship = headship;
}

public String getSex() {
return this.sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public String getTel() {
return this.tel;
}

public void setTel(String tel) {
this.tel = tel;
}

public String getEmail() {
return this.email;
}

public void setEmail(String email) {
this.email = email;
}

public String getUrl() {
return this.url;
}

public void setUrl(String url) {
this.url = url;
}

public String getPcall() {
return this.pcall;
}

public void setPcall(String pcall) {
this.pcall = pcall;
}


public String getUserphoto() {
return this.userphoto;
}

public void setUserphoto(String userphoto) {
this.userphoto = userphoto;
}

public Integer getFacerefutime() {
return this.facerefutime;
}

public void setFacerefutime(Integer facerefutime) {
this.facerefutime = facerefutime;
}

public String getFacelanguage() {
return this.facelanguage;
}

public void setFacelanguage(String facelanguage) {
this.facelanguage = facelanguage;
}

public String getLastmodif() {
return this.lastmodif;
}

public void setLastmodif(String lastmodif) {
this.lastmodif = lastmodif;
}

public Date getLastmdate() {
return this.lastmdate;
}

public void setLastmdate(Date lastmdate) {
this.lastmdate = lastmdate;
}

public String getCreadtor() {
return this.creadtor;
}

public void setCreadtor(String creadtor) {
this.creadtor = creadtor;
}

public Date getCreatdate() {
return this.creatdate;
}

public void setCreatdate(Date creatdate) {
this.creatdate = creatdate;
}

public String toString() {
return new ToStringBuilder(this)
.append("username", getUsername())
.append("userdesc", getUserdesc())
.append("passwords", getPasswords())
.append("deptno", getDeptno())
.append("headship", getHeadship())
.append("sex", getSex())
.append("tel", getTel())
.append("email", getEmail())
.append("url", getUrl())
.append("pcall", getPcall())
.append("userphoto", getUserphoto())
.append("facerefutime", getFacerefutime())
.append("facelanguage", getFacelanguage())
.append("lastmodif", getLastmodif())
.append("lastmdate", getLastmdate())
.append("creadtor", getCreadtor())
.append("creatdate", getCreatdate())
.toString();
}

public boolean equals(Object other) {
if ( !(other instanceof TSysuser) ) return false;
TSysuser castOther = (TSysuser) other;
return new EqualsBuilder()
.append(this.getUsername(), castOther.getUsername())
.append(this.getUserdesc(), castOther.getUserdesc())
.append(this.getPasswords(), castOther.getPasswords())
.append(this.getDeptno(), castOther.getDeptno())
.append(this.getHeadship(), castOther.getHeadship())
.append(this.getSex(), castOther.getSex())
.append(this.getTel(), castOther.getTel())
.append(this.getEmail(), castOther.getEmail())
.append(this.getUrl(), castOther.getUrl())
.append(this.getPcall(), castOther.getPcall())
.append(this.getUserphoto(), castOther.getUserphoto())
.append(this.getFacerefutime(), castOther.getFacerefutime())
.append(this.getFacelanguage(), castOther.getFacelanguage())
.append(this.getLastmodif(), castOther.getLastmodif())
.append(this.getLastmdate(), castOther.getLastmdate())
.append(this.getCreadtor(), castOther.getCreadtor())
.append(this.getCreatdate(), castOther.getCreatdate())
.isEquals();
}

public int hashCode() {
return new HashCodeBuilder()
.append(getUsername())
.append(getUserdesc())
.append(getPasswords())
.append(getDeptno())
.append(getHeadship())
.append(getSex())
.append(getTel())
.append(getEmail())
.append(getUrl())
.append(getPcall())
.append(getUserphoto())
.append(getFacerefutime())
.append(getFacelanguage())
.append(getLastmodif())
.append(getLastmdate())
.append(getCreadtor())
.append(getCreatdate())
.toHashCode();
}

}
---------------------------------------------------------------------
/*
* 创徏日期 2005-4-11
*
* 更改所生成文g模板?
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
package com.yaya.service;

import java.util.List;

import com.yaya.hb.TSysuser;
import com.yaya.service.dao.IUserDao;

/**
* @author Administrator
*
* 更改所生成cd注释的模板ؓ
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
public interface IUserManager {
public void setUserDAO(IUserDao dao);
public TSysuser getUser(String username);
public List getUsers();
public TSysuser saveUser(TSysuser user);
public void removeUser(String username);

}
--------------------------------------------------------------------
/*
* 创徏日期 2005-4-7
*
* 更改所生成文g模板?
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
package com.yaya.service.dao;
/**
* @author Administrator
*
* 更改所生成cd注释的模板ؓ
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
public interface IDAO {

}
--------------------------------------------------------------
/*
* 创徏日期 2005-4-11
*
* 更改所生成文g模板?
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
package com.yaya.service.dao;

import java.util.List;

import com.yaya.hb.TSysuser;

/**
* @author Administrator
*
* 更改所生成cd注释的模板ؓ
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
public interface IUserDao extends IDAO {

public List getUsers();
public TSysuser getUser(String username);
public void saveUser(TSysuser user);
public void removeUser(String username);
}
----------------------------------------------------------
/*
* 创徏日期 2005-4-11
*
* 更改所生成文g模板?
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
package com.yaya.service.spring;

import com.yaya.hb.TSysuser;
import com.yaya.service.IUserManager;
import com.yaya.service.dao.IUserDao;

import java.util.List;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;
/**
* @author Administrator
*
* 更改所生成cd注释的模板ؓ
* H口 > 首选项 > Java > 代码生成 > 代码和注?
*/
public class UserManagerImpl implements IUserManager {
private static Log log = LogFactory.getLog(UserManagerImpl.class);

public IUserDao userDao;

/**

* @return q回 userDao?

*/

public void setUserDAO(IUserDao dao) {
this.userDao = dao;
}

public IUserDao getUserDao() {
return userDao;
}
/**

* @param userDao 要设|的 userDao?

*/

public void setUserDao(IUserDao userDao) {

this.userDao = userDao;

}

public TSysuser getUser(String username) {

try
{
TSysuser user = userDao.getUser(username);
return user;
}
catch(Exception e)
{
e.printStackTrace();
}
return userDao.getUser(username);

}

/* Q非 JavadocQ?

* @see com.jandar.service.IUserManager#getUsers()

*/

public List getUsers() {
// TODO 自动生成Ҏ存根
return userDao.getUsers();
}
/* Q非 JavadocQ?

* @see com.jandar.service.IUserManager#saveUser(com.jandar.model.User)

*/

public TSysuser saveUser(TSysuser user) {
// TODO 自动生成Ҏ存根
userDao.saveUser(user);
return user;
}

/* Q非 JavadocQ?

* @see com.jandar.service.IUserManager#removeUser(java.lang.String)

*/
public void removeUser(String username) {
// TODO 自动生成Ҏ存根
userDao.removeUser(username);
}



Blog of JoJo 2008-10-04 23:28 发表评论
]]>
Tapestry+Spring+Hibernate整合工作结http://www.tkk7.com/ruoyoux/articles/232406.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 15:26:00 GMThttp://www.tkk7.com/ruoyoux/articles/232406.htmlhttp://www.tkk7.com/ruoyoux/comments/232406.htmlhttp://www.tkk7.com/ruoyoux/articles/232406.html#Feedback1http://www.tkk7.com/ruoyoux/comments/commentRss/232406.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232406.html
Cyberwing 


FrankSoo是我的项目经理。前D|间公司决定作个新的J2EE二次开发^収ͼ以替换公司原有的开发^台。公司让FrankSoo和我l成q_开发项目组QFrankSoo担Q目l理。现在这个^台整合开发阶D已l结束,q入目应用阶段。下面是我们的整合工作小l,介绍一下我们在工作中遇到的问题Q以及我们选择的解x? 


1、架构的选择 

首先Q我们都同意以我们现有的能力Q没有够的旉和资源自行开发一套完整的q_。在已有的众多开源项目中选择若干优秀的项目进行整合,才可能按时完成项目,辑ֈ目目的?nbsp;

但是在^台项目开始前Q我们对q_的技术架构有各自的构惟뀂FrankSoo原来的构xStruts+Spring+HibernateQ而我的构xTapestry+Hibernate?nbsp;

不过FrankSoo非常openQ在我向他演CZTapestry的经典范例workbenchQ介l了TapestryZlg的编E方式之后,他同意选用Tapestry作ؓ实现Web展现层的框架。我想FrankSoo以前的Struts开发经?painful)也是他做个决定的因素之一?nbsp;

FrankSoo gave me a nice introduction of Spring Framework. Wow, what an amazing framework! IOC, Declarative Transaction Support, Hibernate Session Management, Hibernate DAO Support… These features are just what we need for a middle tire container. 

至于HibernateQ这个最成功的开源ORM目Q我们都投了它一^_^ 

最后我们确定^台的技术架构是Tapestry+Spring+Hibernate. 

2、架构整?nbsp;

最初的q_架构借鉴了一介l如何集成Tapestry与Spring的文章E1Q中提到的架构: 


 

Web层的Tapestry负责数据输入输出, 响应用户事gQ及输入校验的工? 通过讉K预先加蝲的WebApplicationContext(由Spring提供, 包含着所有Service bean)获得Service层的Service Bean, 把业务操作都委托l它? 

Service层的bean则负责use case逻辑, domain相关的逻辑委托ldomain model中的beand? Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和Hibernate Session的管?通过Spring的声明式事务理和与之集成的Hibernate Session理). Service层的另一w要工作是权限和访问控制?nbsp;

Domain model负责表示问题域的数据和domain logic. DAO使用Hibernate持久化数据以及查? 在实现DAO? 我们使用了Spring的Hibernate DAO Support,极大地简化了代码, 很多Ҏ都只用简单的一行完? 有意思的? 最后完成的HibernateDAO的代码量居然比我写的MockDAO的代码少了一半还?nbsp;

q样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开? l合mock和spring的IOC, unit test也是非常Ҏ? 而且后台(Service, domain model and DAO)的代码不依赖于Web容器或是EJB容器的API, UL性非常好, 同样的代码可以在Web app中用也可在普通的Java app中? 只需更换UI? 

按照q个整合的构Ӟ我们实现一个简单的实例Q实C列表分页查询和显C,数据增删改,ZHibernate Criteria Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已l徏好的数据库表l构自动生成Hibernate映射文gQ实体类和DAOQ极大地减少了工作量。我们还对这个小例子q行了压力测试(试时的数据量ؓ10万条记录Q,定q_不存在性能问题?nbsp;

通过q个实例我们把整个架构基本走通一遍,qȝ了用这套架构开发时适用的开发流E和需要做的工作?nbsp;

3、困扰我们的问题 

在实C子和现在的项目应用过E中Q我们发C若干头疼的问题,有的解决了,有的q没有?nbsp;

问题1Q要不要使用DTOQ?nbsp;

在上面的架构中我们ƈ没有明确Service和Web层间的数据传输是如何q行的。我们讨论好久要不要使用DTOQ最后的l论是不用?nbsp;

使用DTO有两个主要的理由Q?、减Web层和Service层间的方法调用,通过一个方法调用就Web需要的数据都传lWeb?、隔domain model和Web层?nbsp;

W一个理由在我们的架构下是不成立的。因为我们的架构是集中式的,Web和Service是在同一个JVM中,它们之间的方法调用是没有EJBq程讉K的巨大消耗的?nbsp;

W二个理p是需要考虑的。如果允许把domain model中的对象传给Web层,那么修改domain modelQ就会媄响到Web层。如果用DTOQ那么domain model实现上的变化׃会媄响到Web。但是大量的变化不是domain model实现上的变化Q而是domain model接口的变化,比如一个domain model的对象上d了一个属性,而这个属性需要用户修改,那么q时候必M改Web层,不管是不是用了DTO。而且使用DTOQ就需要维护着一大堆对象Q或是它们的生成器,q是非常无聊、且Ҏ出错的工作?nbsp;

Zq些考虑Q我们没有用DTOQ而是选择把domain model直接传到Web层。下面是修改后的架构图(呵呵Q修改了别h的图Q?Q)?nbsp;

?: 
 


问题2QEntity like domain model or rich domain model? 

我们使用Middlegen自动生成Hibernate映射文gQEntitycdDAOc? 但是生成的Entity只含有简单的属性和getter, setterҎ。因此我们遇C一个问题:我们的domain modelq要不要包含domain logicQ如果包含,那么和自动生成工具如何结合? 

我们讨论后认Z个rich domain modelq是非常有必要的Q可以减Service中的重复代码Q提高复用性?nbsp;

如何同自动生成结合?使用<meta>标签Q生成抽象基c,我们l承q些自动生成的基c,d业务Ҏ?nbsp;

问题3QModel driven or Data driven? 

采用Model drivenq是Data driven的方式大家有q热烈的讨论。我们主要是受到Rod JohnsonQ?Q的影响Q采用了Data driven的方式。先作数据库设计Q生成库表,然后用Middlegen反向生成Hibernate映射文g和Entity及DAO。但是我们在q入目应用之后发现q种Ҏ有两个问题: 

aQ?nbsp;数据库设计仅说明了系l要理的静态数据,我们q是得作面向对象分析Q以反映pȝ的动态行为。特别是当系l的业务不仅仅是单的CRUD操作Ӟq个问题更严重?nbsp;
bQ?nbsp;数据库设计ؓ了优化性能Q可能会把好几个应该是单独实体的数据攑օ一个实体中。这样如果直接把q种极粗_度实体映射成Entityc,那简直是不可接受的。面向对象的分析设计模型得到的类都是相当l粒度的。这U情况还得作面向对象的分析,明确到底q个_粒度的大表应该映射成那几个l粒度的对象?nbsp;

或许我们应该试试Model drivenQ用AndroMDA生成domain modelQHibernate DAOQHibernate mappingQ数据库表,单的Service和前台的Tapestry面?nbsp;

问题4QHibernate Session生命周期如何理Q?nbsp;

对于Hibernate Session的生命周期我们采用的是Session-per-Transaction模式Q未采用Open Session in View模式?nbsp;虽然Hibernate team认ؓq种Ҏ没什么不好,而且FreeRoller和Atlassian的confluence都用了Open Session In Viewq种模式Q但是我们对它可能生的影响q没有很好的把握Q所以暂时弃|不用?nbsp;如果Web层要讉Klazy load的数? 需要先调用Service的业务方? 以获得数? 

问题5QUse case logic 和domain logic 如何区分Q?nbsp;

Service负责use case logicQdomain model负责domain logic。这L划分看v来很好,实现h很ȝ。如何确定什么是use case logicQ什么是domain logicQTBD. 


问题6QService_度如何定Q?nbsp;

q个问题真是很烦Q原先考虑使用usecase controller的方式,每个usecase对应一个ServiceQ但是发现这样复用性太低,而且好多地方必须复用相同的功?nbsp;

另一U方法是用package level serviceQ每个package作个serviceQ这样倒是可以重用Q但是感觉太MQ不好?nbsp;

现在也没有什么很好的办法Q只好在详细设计时根据具体情늡定需要多个Service了。TBD. 

问题7Q权限如何设定?如何查? 

权限讑֮也是个头疼的问题。我们本x按照use case讑֮权限Q每个用例一个权限。在角色讑֮的时候直接处理的都是业务意义非常明确的权限。但是在权限验证q程中发C问题Q如果在Service的方法中验证权限Q而且q个Ҏ在多个用例中用到Q复用ServiceQ,那么q个Service的方法就需要检查多个权? 如果每个ServiceҎ对应一个权? 那么权限又太l了, 不像use case权限那样代表一个完整的业务. 真的是很ȝ阿!TBD. 



Ok, q些是我们q段工作的结果。希望能l大家一些启发,也希望能得到大家的帮助,帮我们出Z意,谢谢大家?nbsp;



Blog of JoJo 2008-10-04 23:26 发表评论
]]>
Tapestry - Spring Framework reference 2.0.5 参考手册中文版http://www.tkk7.com/ruoyoux/articles/232405.htmlBlog of JoJoBlog of JoJoSat, 04 Oct 2008 15:24:00 GMThttp://www.tkk7.com/ruoyoux/articles/232405.htmlhttp://www.tkk7.com/ruoyoux/comments/232405.htmlhttp://www.tkk7.com/ruoyoux/articles/232405.html#Feedback0http://www.tkk7.com/ruoyoux/comments/commentRss/232405.htmlhttp://www.tkk7.com/ruoyoux/services/trackbacks/232405.html阅读全文

Blog of JoJo 2008-10-04 23:24 发表评论
]]>
Tapestry Spring Hibernate整合工作结Q{Q?/title><link>http://www.tkk7.com/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.tkk7.com/ruoyoux/articles/232403.html</guid><wfw:comment>http://www.tkk7.com/ruoyoux/comments/232403.html</wfw:comment><comments>http://www.tkk7.com/ruoyoux/articles/232403.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ruoyoux/comments/commentRss/232403.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ruoyoux/services/trackbacks/232403.html</trackback:ping><description><![CDATA[<p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="color: red; font-family: Ҏ姚体">[原文Qhttp://javamen.blogdriver.com/javamen/299858.html]</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">FrankSoo是我的项目经理。前D|间公司决定作个新的J2EE二次开发^収ͼ以替换公司原有的开发^台。公司让FrankSoo和我l成q_开发项目组QFrankSoo担Q目l理。现在这个^台整合开发阶D已l结束,q入目应用阶段。下面是我们的整合工作小l,介绍一下我们在工作中遇到的问题Q以及我们选择的解x? </span></span></span></span></p> <p><br /> <span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">1、架构的选择 </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">首先Q我们都同意以我们现有的能力Q没有够的旉和资源自行开发一套完整的q_。在已有的众多开源项目中选择若干优秀的项目进行整合,才可能按时完成项目,辑ֈ目目的?<br /> 但是在^台项目开始前Q我们对q_的技术架构有各自的构惟뀂FrankSoo原来的构xStruts+Spring+HibernateQ而我的构xTapestry+Hibernate?<br /> 不过FrankSoo非常openQ在我向他演CZTapestry的经典范例workbenchQ介l了TapestryZlg的编E方式之后,他同意选用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… 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: 微Y雅黑"><span style="font-family: Ҏ姚体">至于HibernateQ这个最成功的开源ORM目Q我们都投了它一^_^ <br /> 最后我们确定^台的技术架构是Tapestry+Spring+Hibernate. </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">2、架构整?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">最初的q_架构借鉴了一介l如何集成Tapestry与Spring的文章E1Q中提到的架构: </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">Web层的Tapestry负责数据输入输出, 响应用户事gQ及输入校验的工? 通过讉K预先加蝲的WebApplicationContext(由Spring提供, 包含着所有Service bean)获得Service层的Service Bean, 把业务操作都委托l它? </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">Service层的bean则负责use case逻辑, domain相关的逻辑委托ldomain model中的beand? Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和Hibernate Session的管?通过Spring的声明式事务理和与之集成的Hibernate Session理). Service层的另一w要工作是权限和访问控制?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><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: 微Y雅黑"><span style="font-family: Ҏ姚体">q样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开? l合mock和spring的IOC, unit test也是非常Ҏ? 而且后台(Service, domain model and DAO)的代码不依赖于Web容器或是EJB容器的API, UL性非常好, 同样的代码可以在Web app中用也可在普通的Java app中? 只需更换UI? </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">按照q个整合的构Ӟ我们实现一个简单的实例Q实C列表分页查询和显C,数据增删改,ZHibernate Criteria Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已l徏好的数据库表l构自动生成Hibernate映射文gQ实体类和DAOQ极大地减少了工作量。我们还对这个小例子q行了压力测试(试时的数据量ؓ10万条记录Q,定q_不存在性能问题?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">通过q个实例我们把整个架构基本走通一遍,qȝ了用这套架构开发时适用的开发流E和需要做的工作?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">3、困扰我们的问题 </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">在实C子和现在的项目应用过E中Q我们发C若干头疼的问题,有的解决了,有的q没有?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题1Q要不要使用DTOQ?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">在上面的架构中我们ƈ没有明确Service和Web层间的数据传输是如何q行的。我们讨论好久要不要使用DTOQ最后的l论是不用?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">使用DTO有两个主要的理由Q?、减Web层和Service层间的方法调用,通过一个方法调用就Web需要的数据都传lWeb?、隔domain model和Web层?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">W一个理由在我们的架构下是不成立的。因为我们的架构是集中式的,Web和Service是在同一个JVM中,它们之间的方法调用是没有EJBq程讉K的巨大消耗的?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">W二个理p是需要考虑的。如果允许把domain model中的对象传给Web层,那么修改domain modelQ就会媄响到Web层。如果用DTOQ那么domain model实现上的变化׃会媄响到Web。但是大量的变化不是domain model实现上的变化Q而是domain model接口的变化,比如一个domain model的对象上d了一个属性,而这个属性需要用户修改,那么q时候必M改Web层,不管是不是用了DTO。而且使用DTOQ就需要维护着一大堆对象Q或是它们的生成器,q是非常无聊、且Ҏ出错的工作?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">Zq些考虑Q我们没有用DTOQ而是选择把domain model直接传到Web层。下面是修改后的架构图(呵呵Q修改了别h的图Q?Q)?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题2QEntity 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: 微Y雅黑"><span style="font-family: Ҏ姚体">我们使用Middlegen自动生成Hibernate映射文gQEntitycdDAOc? 但是生成的Entity只含有简单的属性和getter, setterҎ。因此我们遇C一个问题:我们的domain modelq要不要包含domain logicQ如果包含,那么和自动生成工具如何结合? </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">我们讨论后认Z个rich domain modelq是非常有必要的Q可以减Service中的重复代码Q提高复用性?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">如何同自动生成结合?使用<meta>标签Q生成抽象基c,我们l承q些自动生成的基c,d业务Ҏ?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题3QModel driven or Data driven? </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">采用Model drivenq是Data driven的方式大家有q热烈的讨论。我们主要是受到Rod JohnsonQ?Q的影响Q采用了Data driven的方式。先作数据库设计Q生成库表,然后用Middlegen反向生成Hibernate映射文g和Entity及DAO。但是我们在q入目应用之后发现q种Ҏ有两个问题: </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">aQ?数据库设计仅说明了系l要理的静态数据,我们q是得作面向对象分析Q以反映pȝ的动态行为。特别是当系l的业务不仅仅是单的CRUD操作Ӟq个问题更严重?<br /> bQ?数据库设计ؓ了优化性能Q可能会把好几个应该是单独实体的数据攑օ一个实体中。这样如果直接把q种极粗_度实体映射成Entityc,那简直是不可接受的。面向对象的分析设计模型得到的类都是相当l粒度的。这U情况还得作面向对象的分析,明确到底q个_粒度的大表应该映射成那几个l粒度的对象?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">或许我们应该试试Model drivenQ用AndroMDA生成domain modelQHibernate DAOQHibernate mappingQ数据库表,单的Service和前台的Tapestry面?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题4QHibernate Session生命周期如何理Q?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">对于Hibernate Session的生命周期我们采用的是Session-per-Transaction模式Q未采用Open Session in View模式?虽然Hibernate team认ؓq种Ҏ没什么不好,而且FreeRoller和Atlassian的confluence都用了Open Session In Viewq种模式Q但是我们对它可能生的影响q没有很好的把握Q所以暂时弃|不用?如果Web层要讉Klazy load的数? 需要先调用Service的业务方? 以获得数? </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题5QUse case logic 和domain logic 如何区分Q?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">Service负责use case logicQdomain model负责domain logic。这L划分看v来很好,实现h很ȝ。如何确定什么是use case logicQ什么是domain logicQTBD. </span></span></span></span></p> <p><br /> <span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题6QService_度如何定Q?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">q个问题真是很烦Q原先考虑使用usecase controller的方式,每个usecase对应一个ServiceQ但是发现这样复用性太低,而且好多地方必须复用相同的功?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">另一U方法是用package level serviceQ每个package作个serviceQ这样倒是可以重用Q但是感觉太MQ不好?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">现在也没有什么很好的办法Q只好在详细设计时根据具体情늡定需要多个Service了。TBD. </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题7Q权限如何设定?如何查? </span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">权限讑֮也是个头疼的问题。我们本x按照use case讑֮权限Q每个用例一个权限。在角色讑֮的时候直接处理的都是业务意义非常明确的权限。但是在权限验证q程中发C问题Q如果在Service的方法中验证权限Q而且q个Ҏ在多个用例中用到Q复用ServiceQ,那么q个Service的方法就需要检查多个权? 如果每个ServiceҎ对应一个权? 那么权限又太l了, 不像use case权限那样代表一个完整的业务. 真的是很ȝ阿!TBD. <br /> Quake wang:问题1Q要不要使用DTOQ?<br /> No DTO, 直接把domain object传给Tapestry的web层,利用Tapestry提供强大的数据绑定和lg功能很方?</span></span></span></span></p> <p><br /> <span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题2QEntity 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: 微Y雅黑"><span style="font-family: Ҏ姚体">问题3QModel driven or Data driven? <br /> q个Ҏ来说不是什么大问题Q个Z惯而已Q我觉得无论是Model driven或者Data drivenQ对于相同的需求,2者最l的设计应该都是很类似的。我是从2边同时考虑的,一边做ModelQ一边还要考虑数据库的l构Q?再进行相应的调整Q用下来也没有什么问题。没有用代码生成Q?只是用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: 微Y雅黑"><span style="font-family: Ҏ姚体">问题4QHibernate Session生命周期如何理Q?<br /> 目前没有采用open session in viewQ也是和你们一P在Service里面准备好所有需要的对象?</span></span></span></span></p> <p><br /> <span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题5QUse case logic 和domain logic 如何区分Q?<br /> ׃domain model里面没有什么domain logicQ这个问题不存在. </span></span></span></span></p> <p><br /> <span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题6QService_度如何定Q?<br /> ׃domain model里面没有什么domain logicQ所以Service的功能就切得很细Q尽量重用,一个package可能有多个service, 感觉q好Q没有太歅R?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">问题7Q权限如何设定?如何查? <br /> q个也是我没有想好的问题Q?因ؓ不同的需求, 权限讑֮都不一P很难用AOP来做一个通用的aspect. 1. DAO的做法: <br /> 我目前不是给每个domain object都做一个DAO, 而是整个pȝ׃个DAO (PersistenceManager), 里面只有create, update, delete entityq?个方法。另外写一个DAO, 专门做查?(QueryManager), 用hibernate的named query做常用的查询Q?用criteria来做Z用户输入的动态查询。不知道你们的做法是怎么P另外criteria ?named query其实都是hardcodeQobject attribute name改变的时候,q得记得手工M改这些代码,unit test很难覆盖到所有的criteria search ?named query里面的代码,q个是目前感觉不是很方便的地斏V?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">2. Spring ?Tapestry的集?<br /> 目前只是用Spring到service layer而已Q?Tapestry通过GlobalQ扮演Service Locator的角Ԍq个对象来调用,在domain Tapestryq一层还是有很多dirty code, 其实也可以用AOP来解冟뀂如果能够像webwork2那样Q所有的action都可以通过从Spring获得Q即通过Spring获得page <br /> listeners, 那会方便很多Q不qTapestry也有自己的类增强功能Q好像有一定的冲突Q目前没有什么好的想法?</span></span></span></span></p> <p><span style="font-family: Ҏ姚体"><span style="font-family: Ҏ姚体"><span style="font-family: 微Y雅黑"><span style="font-family: Ҏ姚体">Z推荐3个我在项目中使用的工?(都是eclipse plugin)Q?<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.tkk7.com/ruoyoux/aggbug/232403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ruoyoux/" target="_blank">Blog of JoJo</a> 2008-10-04 23:04 <a href="http://www.tkk7.com/ruoyoux/articles/232403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://juytv.com" target="_blank">޾糡ҹ߹ۿ</a>| <a href="http://0827fang.com" target="_blank">þ99ྫƷѹۿ</a>| <a href="http://http99.com" target="_blank">Ƶһ߹ۿ</a>| <a href="http://pohezi.com" target="_blank">޹ۺϾþ</a>| <a href="http://868664.com" target="_blank">һ</a>| <a href="http://720880.com" target="_blank">ŷ˳</a>| <a href="http://my55572.com" target="_blank">һɫëƬ</a>| <a href="http://61255555.com" target="_blank">Ʒһ߹ۿ</a>| <a href="http://77tok.com" target="_blank">һ234վ </a>| <a href="http://cc58866.com" target="_blank">þþþAVۿ</a>| <a href="http://abab14.com" target="_blank">޾Ʒtvþþþþþþþ</a>| <a href="http://www6yg6yg.com" target="_blank">ëƬƵ</a>| <a href="http://szyujiaxing.com" target="_blank">1000Ƶ</a>| <a href="http://426366.com" target="_blank">ɫtvվѿ</a>| <a href="http://apguangyu.com" target="_blank">Ļϵ</a>| <a href="http://xuanzhicity.com" target="_blank">һaƬþëƬ</a>| <a href="http://344zx.com" target="_blank">avպav߹ۿ </a>| <a href="http://wwwkckc.com" target="_blank">99ƷƵƵѹۿ</a>| <a href="http://yqstickers.com" target="_blank">ֻѵAVߵӰ</a>| <a href="http://shbailongma.com" target="_blank">ŷպĸwww777</a>| <a href="http://www65axax.com" target="_blank">91޾Ʒ鶹</a>| <a href="http://qinglou31.com" target="_blank">޹ƷۺϾþþ</a>| <a href="http://yaboxxx125.com" target="_blank">99þþƷ</a>| <a href="http://by8847.com" target="_blank">þˮav뾫Ʒ鶹</a>| <a href="http://yiren2233.com" target="_blank">Ļ߹ۿ</a>| <a href="http://zjlxblog.com" target="_blank">Ļк޴Ƭ</a>| <a href="http://1515m.com" target="_blank">޺rӰ</a>| <a href="http://pufenghotel.com" target="_blank">޹Ʒһþ </a>| <a href="http://www91v.com" target="_blank">һ91</a>| <a href="http://1000hu.com" target="_blank">У԰ɫС˵</a>| <a href="http://shaonvfushi.com" target="_blank">޹ۺ</a>| <a href="http://vc77777.com" target="_blank">ŷպߵӰ</a>| <a href="http://zhidianzh.com" target="_blank">޹ƷۺϾþþ</a>| <a href="http://lebaojj.com" target="_blank">޸mv</a>| <a href="http://wwwhaole10.com" target="_blank">õӰ߹ۿ</a>| <a href="http://116603a.com" target="_blank">˳˳ۺþ</a>| <a href="http://ai-xian.com" target="_blank">ҹþ</a>| <a href="http://yxjcgs.com" target="_blank">Ʒlvɫ</a>| <a href="http://tlyyt.com" target="_blank">˾ƷۺƵ</a>| <a href="http://zuche001.com" target="_blank">޹ۺ</a>| <a href="http://zbsensor.com" target="_blank">߳˾Ʒ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>