| 
         
     
     | 
     | 
    
  
    | 
    Tapestry入门及进阶一 | 
   
  
     | 
   
  
     | 
   
  
    | 
     作者:未知  来源:月光软件站  加入时间:2005-2-28 月光软件站  | 
   
  
    要Tapestry开发一个Web Application,对一个新手来说有点困难的,Tapestry由于不同于
  以前的Web Presentation Framework,所以不可讳言,学习曲线比较长这是事实。
  我先讲讲一个Web Application的大体结构: 以JBuider9为开发工具,你要先建立一个工程,例如是名称是TapestryExmaple,它的
  workspace是F:\myproject\TapestryExmaple.它下面的子目录和文件有 bak--   这是Jbuider自建的backup目录。 build--  我的ant的工作目录,我的ant会利用这个目录编译打包。 classes-- JBuilder编译时放class的目录 configs-- 我的一些配置文件放置的地方 lib--      我的要用到的库文件放置的目录 context-- 我的Web application的context目录  doc-- 我的文档目录 src--     我的java source的目录 build.properties--ant工作的属性设置文件 build.xml--ant工作的定义文件
  你建立好这个工程以后,你好需要建立Web Application, 点击File-->New-->Web-->Web  Application,因为我们需要在JBuilder里利用Tomcat4.1调试,用Jboss3.x也可以,不过你 要去下载一个插件叫 EntWizard_JBoss3x_JB9_v3-1-5.zip 的插件,JBuiderx提供对JB oss的支持,不过Jbuiderx经常有些莫名其妙的怪毛病,而且比较慢,我是不用的。
  你建立Web Application的时候你要输入Name和Directory两项值,Name比如是 patientrecord,注意你在这里输入的name,会在你将来测试时的URL里出现: 你的URL就可能像这样:http://localhost:8080/patientrecord/app 后面那个app是在web.xml里配置的,下面再说。 你的Web Application的Directory值要跟我们上面预定的一致,就是那个context目录,
  在这里就是F:\myproject\TapestryExmaple\context,这个context目录是web applicatio n 的核心目录,下面要详细的讲讲。
  例如像我的context目录下面有这三个目录 home  -- 我的web applicattion的子模块home的context      下面有子目录  css--放置本子模块用到的css文件             images--放置本子模块用到的image(图标)         文件: Home.html,Register.xml ...                         这些是我字模块中的页面对应的HTML template(模版)       patientrecord--我的web applicattion的子模块patientrecord的context         目录结构跟home子模块相同
  WEB-INF--最核心的目录      下面的子目录和文件有            classes--你的java classes会在这里有一份拷贝       lib--你的工程引用的lib在这里用一份拷贝       patientrecord.application--你的Tapestry核心配置文件       web.xml--web application的核心配置文件
  下面我们来研究一下patientrecord.application和web.xml这两个文件,我的范例文 件如下: web.xml
  <?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>   <display-name>Patient Record System</display-name>   <filter>     <filter-name>redirect</filter-name>     <filter-class>org.apache.tapestry.RedirectFilter</filter-class>   </filter>   <filter-mapping>     <filter-name>redirect</filter-name>     <url-pattern>/</url-pattern>   </filter-mapping>   <servlet>     <servlet-name>patientrecord</servlet-name>     <servlet-class>com.ht.web.PatientRecordServlet</servlet-class>   </servlet>   <servlet-mapping>     <servlet-name>patientrecord</servlet-name>     <url-pattern>/app</url-pattern>   </servlet-mapping>   <session-config>     <session-timeout>15</session-timeout>   </session-config> </web-app>              这个里面属性有 display-name --不重要,只是显示名称 filter和filter-mapping配置--不要动,使用默认配置, servlet配置--这个是很重要的,我的servle name是patientrecord, 对应的class为 com.ht.web.PatientRecordServlet,这是我自己开发的一个类: 这个类看上去很简单:
  package com.ht.web;
  import org.apache.tapestry.ApplicationServlet;
  /**  *  @version $Id: SimpleServlet.java,v 1.9 2002/05/04 12:43:31 hship Exp $  *  @author Howard Lewis Ship  *  */ public class PatientRecordServlet extends ApplicationServlet { }
  你一般就是定义一个类extends org.apache.tapestry.ApplicationServlet就行了 当然,如果你还有什么特别要求,你可对这个类进行强化。 我再来谈谈这个核心类的作用:这其实是个Dispatcher(分发者),它接受外界传来的 http request请求,然后把请求处理后派发给Tapestry Engine处理.
  图例: http://bbs1.nju.edu.cn/file/high-level-component-request.p
  servlet-mapping--这是URL映射的设置,一般设为app
  <session-config>     <session-timeout>15</session-timeout> </session-config> 这段是对HTTP Session的timeout的配置,这里是15分钟。
  下面再来研究一下patientrecord.application文件,这也是一个XML文件: <?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="Patient Record System" engine-class="com.ht.web.PatientRecordEngine">   <property name="org.apache.tapestry.visit-class" value="com.ht.web.VisitorState"/>
    <property name="com.ht.home-page" value="home:Home"/> 	   <!--<property name="com.ht.exception-page" value="home:PaitentRecordException"/>-->  	   <property name="com.ht.security-exception-page" value="home:SecurityExceptionPage"/> 	   <!--Overrided the Home Service to let us to decide which page will be the home page-->   <service name="home" class="com.ht.web.HomeService"/>	      <library id="home" specification-path="/com/ht/home/Home.library"/>   <library id="patientrecord" specification-path="/com/ht/patientrecord/PatientRecord.library"/>			 </application>
  由这个文档我们可以看出 我的application name="Patient Record System" 我的engine-class为com.ht.web.PatientRecordEngine 我的org.apache.tapestry.visit-class为com.ht.web.VisitorState 以上两项是override Tapestry的默认实现
  <property name="com.ht.home-page" value="home:Home"/> 这是我配置我的home-page页指向我的web application的子模块home里Home页
   <!--<property name="com.ht.exception-page" value="home:PaitentRecordException"/>-->  	   <property name="com.ht.security-exception-page" value="home:SecurityExceptionPage"/>
  这两项是我设定出错处理页 其中的com.ht.exception-page是处理普通的org.apache.tapestry.ApplicationException, 现在被注释掉,因为目前在开发阶段,我要察看详细的出错情况,不需处理。 com.ht.security-exception-page是处理java.lang.SecurityException, 因为对于一个需要登录的网站,一个为登录的用户是不可以访问大多数资源, 如果他访问了不可访问的资源,我就抛出SecurityException交给engine处理。
    <!--Overrided the Home Service to let us to decide which page will be the home page-->   <service name="home" class="com.ht.web.HomeService"/> Tapestry engine 可以定义一些service提供服务,我在这里定义一个home service就是 要我自己决定我的home page页,而不是Tapestry的默认配置页。
  <library id="home" specification-path="/com/ht/home/Home.library"/>   <library id="patientrecord" specification-path="/com/ht/patientrecord/PatientRecord.library"/>	
  这两项是说明我的application包含两个library,这其实是一个Web application切分 子模块的手段,比如/com/ht/home/Home.library"/ 对应着我的home子模块, 而/com/ht/patientrecord/PatientRecord.library则对应着我的patientrecord子模块
  下面说说Tapestry engine,例如我的engine实现如下:
  package com.ht.web;
  import java.io.*; import java.net.URLEncoder;
  import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
  import org.apache.tapestry.*; import org.apache.tapestry.engine.BaseEngine; import org.apache.tapestry.engine.IPropertySource; import org.apache.tapestry.request.ResponseOutputStream; import org.apache.commons.lang.StringUtils;
  /**  * @author Hery Tang  *  * Creation Date 2003-9-18  * Version 1.0  */ public class PatientRecordEngine extends BaseEngine {            public static final String HOME_PAGE_NAME = "com.ht.home-page";         public static final String EXCEPTION_PAGE_NAME= "com.ht.exception-page";         public static final String SECURITY_EXCEPTION_PAGE_NAME = "com.ht.security-exception-page";	
          private transient boolean killSession;                  protected void cleanupAfterRequest(IRequestCycle cycle)         {                 super.cleanupAfterRequest(cycle);                 if (killSession)                 {                         try                         {                                 HttpSession session = cycle.getRequestContext().getSession();
                                  if (session != null)                                 {                                         session.invalidate();                                 }                         }                         catch (IllegalStateException ex)                         {                                 // Ignore.                         }                 }         }
          public void logout()         {                 VisitorState visit = (VisitorState) getVisit();
                  if (visit != null)                 {                         visit.setUser(null);                         visit = null;                 }
                  killSession = true;         }
          /**          * This methods read the home page name which defined by the user by using          * propetry com.ht.home-page in application specification          *          * @return The name of home page.          */         public String getHomePageName() {                 return getPropertySource().getPropertyValue(HOME_PAGE_NAME);         }
          /**          * Return the security exception page name. If user does not defined this          * page name, the normal exception page will be return.          * @return The name of the security exception page.          */         public String getSecurityExceptionPageName() {                 String result =                         getPropertySource().getPropertyValue(                                 SECURITY_EXCEPTION_PAGE_NAME);
                  if (StringUtils.isEmpty(result)) {                         result = getExceptionPageName();                 }
                  return result;         }
          /**          * Return the exception page name. If user does not defined this page name,          * the default exception page will be return.          * @return The name of the normal exception page.          */         public String getExceptionPageName() {                          String result =                         getPropertySource().getPropertyValue(EXCEPTION_PAGE_NAME);
                  if (StringUtils.isEmpty(result)) {                         result = super.getExceptionPageName();                 }
                  return result;         }
          /**          * Overide the method to support security Exception.          */         protected void activateExceptionPage(                 IRequestCycle cycle,                 ResponseOutputStream output,                 Throwable cause)                 throws ServletException {                 //Print it to console first                 printExceptions(cause);
                  try {                         String exceptionPageName;
                          Throwable throwable = cause;                         Throwable securityException = null;                         boolean isSecurityException = false;
                          if (throwable                                 instanceof org.apache.tapestry.ApplicationRuntimeException) {                                 ApplicationRuntimeException exception =                                         (ApplicationRuntimeException) throwable;                                 if (exception.getRootCause() instanceof SecurityException) {                                         securityException = exception.getCause();                                         isSecurityException = true;                                 }                         }
                          if (isSecurityException) {                                 exceptionPageName = getSecurityExceptionPageName();                         } else {                                 exceptionPageName = getExceptionPageName();                         }
                          IPage exceptionPage = cycle.getPage(exceptionPageName);                         if (securityException == null) {                                 exceptionPage.setProperty("exception", cause);                         } else {                                 exceptionPage.setProperty("exception", securityException);                         }
                          cycle.activate(exceptionPage);
                          renderResponse(cycle, output);                 } catch (Throwable ex) {                         // Worst case scenario.  The exception page itself is broken, leaving                         // us with no option but to write the cause to the output.                         reportException(                                 Tapestry.getMessage(                                         "AbstractEngine.unable-to-process-client-request"),                                 cause);
                          // Also, write the exception thrown when redendering the exception                         // page, so that can get fixed as well.                         reportException(                                 Tapestry.getMessage(                                         "AbstractEngine.unable-to-present-exception-page"),                                 ex);
                          // And throw the exception.                         throw new ServletException(ex.getMessage(), ex);                 }         }
          private void printExceptions(Throwable throwable) {                 if (throwable == null) {                         return;                 }
                  throwable.printStackTrace();                 printExceptions(throwable.getCause());         }
           }
   public void logout() 说明    一个用户登出,则将一个代表用户状态的VisitorState对象里的状态清空,同时置    killSession标志量为true     protected void cleanupAfterRequest(IRequestCycle cycle)     overrride父类BaseEngine实现,先调用父类实现然后再察看killSession标志量,如果为true,则invalidate session.
    public String getHomePageName()   public String getSecurityExceptionPageName()   public String getExceptionPageName() 都是为了取出我在在patientrecord.application的配置。
  protected void activateExceptionPage(                 IRequestCycle cycle,                 ResponseOutputStream output,                 Throwable cause) override AbstractEngine的是实现,用我自己的方式处理各种Exception.
 
  
 
  | 
   
  
     | 
   
  
     相关文章:相关软件:  | 
   
   
      |