欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在Tapestry中使用redirect-after-post模式控制表单提交 博客分类: Tapestry4 Tapestry设计模式ApacheOOAjax 

程序员文章站 2024-02-20 18:13:34
...
Tapestry中表单的提交有很多问题,刷新导致表单的重复提交、臭名昭著的dirty form warning
显示不友好的URL等,这些都可以使用redirect-after-post模式来避免,也就是post表单之后将页面redirect一下,
这样地址栏显示的就是
redirect之后的页面,刷新的也将是这个页面,而且redirect之后的页面一般为Page页面,
可以使用
friendlyUrl来显示友好的url<o:p></o:p>
要使用这个模式,不得不提到一个ILink接口,T4中可接受的listener方法中一个方法签名是这样的:<o:p></o:p>
java 代码
 
  1. public ILink listenerMethod(Parameter parameter); 

这个方法的返回值为ILink,如果T4侦测到是这个返回值的话,将自动redirectILink指定的页面。
而且
ILink可以为纯页面的Link也可以是带有参数的Link。纯页面Link也就是page service生成的link
带参数的
linkexternal service生成的link,具体link的生成代码如下:<o:p></o:p>  

java 代码
 
  1. @InjectObject("engine-service:page")  
  2.   
  3.   public abstract IEngineService getPageService();  
  4.   
  5.        public ILink getPageLink(String pageName) {  
  6.   
  7.            return getPageService().getLink(false, pageName);  
  8.   
  9.   }  
  10.   
  11.   
  12.   
  13.       @InjectObject("engine-service:external")  
  14.   
  15.   public abstract IEngineService getExternalService();  
  16.   
  17.        public ILink getExternalLink(String pageName, Object[] parameters) {  
  18.   
  19.      ExternalServiceParameter esp = new ExternalServiceParameter(pageName,  
  20.   
  21.             parameters);  
  22.   
  23.      return getExternalService().getLink(false, esp);  
  24.   
  25.   }  
<o:p></o:p>

将上述方法放入到你的项目中自定义的MyBasePage(继承TapestryBasePage)中,然后让你的

页面类继承MyBasePage,这样就可以使用上述方法了。<o:p></o:p>

这样在页面提交时可以如下调用
java 代码
 
  1. public ILink onDelete(Long id){  
  2.   
  3.    
  4.   
  5. //your code to delete object  
  6.   
  7.    
  8.   
  9. return getPageLink(getPageName());//删除后重新redirect到本页面  
  10.   
  11. }  
  12.   
  13. 当然如果这个页面带参数,例如catgoryId=1,则代码如下:  
  14.   
  15. public ILink onDelete(Long id){  
  16.   
  17.    
  18.   
  19. //your code to delete object  
  20.   
  21.    
  22.   
  23. return getExternalLink(getPageName(),new Object[]{categoryId});  
  24. //删除后重新redirect到本页面,并带一个参数  
  25.   
  26. }  
上述方式通过继承来实现方法调用,感觉不是很好,我们可以利用Tapestry的易扩展特性来扩展它,
首先想到的就是注释方式来注入,例如我想实现如下注入
java 代码
 
  1. @InjectPageLink(“Home“)  
  2.   
  3. Public abstract ILink getHomeLink();  
  4.   
  5.    
  6.   
  7. @InjectExternalLink(“Category“)  
  8.   
  9. Public abstract ILink getCategoryLink(Long categoryId);  

这样即去掉了页面的继承,也显得比较直接。
首先是定义注释类
java 代码
 
  1. import java.lang.annotation.ElementType;  
  2.   
  3. import java.lang.annotation.Retention;  
  4.   
  5. import java.lang.annotation.RetentionPolicy;  
  6.   
  7. import java.lang.annotation.Target;  
  8.   
  9.    
  10.   
  11. @Target( { ElementType.METHOD })  
  12.   
  13. @Retention(RetentionPolicy.RUNTIME)  
  14.   
  15. public @interface InjectPageLink {  
  16.   
  17.     String value();  
  18.   
  19. }  

<o:p></o:p>

然后写注释的worker
<o:p></o:p>
java 代码
 
  1. import java.lang.reflect.Method;  
  2.   
  3. import java.lang.reflect.Modifier;  
  4.   
  5.    
  6.   
  7. import org.apache.hivemind.ApplicationRuntimeException;  
  8.   
  9. import org.apache.hivemind.Location;  
  10.   
  11. import org.apache.hivemind.service.BodyBuilder;  
  12.   
  13. import org.apache.hivemind.service.MethodSignature;  
  14.   
  15. import org.apache.tapestry.annotations.AnnotationUtils;  
  16.   
  17. import org.apache.tapestry.annotations.MethodAnnotationEnhancementWorker;  
  18.   
  19. import org.apache.tapestry.engine.ILink;  
  20.   
  21. import org.apache.tapestry.enhance.EnhancementOperation;  
  22.   
  23. import org.apache.tapestry.spec.IComponentSpecification;  
  24.   
  25.    
  26.   
  27. public class InjectPageLinkAnnotationWorker implements  
  28.   
  29.        MethodAnnotationEnhancementWorker {  
  30.   
  31.    
  32.   
  33.     public void performEnhancement(EnhancementOperation op,  
  34.   
  35.            IComponentSpecification spec, Method method, Location location) {  
  36.   
  37.        if (!method.getReturnType().equals(ILink.class))  
  38.   
  39.            throw new ApplicationRuntimeException(  
  40.   
  41.                   "InjectPage annotation must return ILink");  
  42.   
  43.    
  44.   
  45.        InjectPageLink injectPageLink = method  
  46.   
  47.               .getAnnotation(InjectPageLink.class);  
  48.   
  49.    
  50.   
  51.        String pageName = injectPageLink.value();  
  52.   
  53.    
  54.   
  55.        BodyBuilder builder = new BodyBuilder();  
  56.   
  57.    
  58.   
  59.        builder.begin();  
  60.   
  61.        builder  
  62.   
  63.               .addln(  
  64.   
  65.                      "return getPage().getRequestCycle().getInfrastructure().getServiceMap().getService( 
  66.  
  67. org.apache.tapestry.Tapestry.PAGE_SERVICE).getLink(false,\"{0}\");",  
  68.   
  69.                      pageName);  
  70.   
  71.    
  72.   
  73.        builder.end();  
  74.   
  75.    
  76.   
  77.        op.addMethod(Modifier.PUBLIC, new MethodSignature(method), builder  
  78.   
  79.               .toString(), location);  
  80.   
  81.    
  82.   
  83.        if (isGetter(method))  
  84.   
  85.            op.claimReadonlyProperty(AnnotationUtils.getPropertyName(method));  
  86.   
  87.     }  
  88.   
  89.    
  90.   
  91.     boolean isGetter(Method method) {  
  92.   
  93.        return method.getName().startsWith("get")  
  94.   
  95.               && method.getParameterTypes().length == 0;  
  96.   
  97.     }  
  98.   
  99. }  

External
的同样两个类<o:p></o:p>
java 代码
 
  1. import java.lang.annotation.ElementType;  
  2.   
  3. import java.lang.annotation.Retention;  
  4.   
  5. import java.lang.annotation.RetentionPolicy;  
  6.   
  7. import java.lang.annotation.Target;  
  8.   
  9.    
  10.   
  11. @Target( { ElementType.METHOD })  
  12.   
  13. @Retention(RetentionPolicy.RUNTIME)  
  14.   
  15. public @interface InjectExternalLink {  
  16.   
  17.     String value();  
  18.   
  19. }  

<o:p></o:p>

Work
java 代码
 
  1. import java.lang.reflect.Method;  
  2.   
  3. import java.lang.reflect.Modifier;  
  4.   
  5.    
  6.   
  7. import org.apache.hivemind.ApplicationRuntimeException;  
  8.   
  9. import org.apache.hivemind.Location;  
  10.   
  11. import org.apache.hivemind.service.BodyBuilder;  
  12.   
  13. import org.apache.hivemind.service.MethodSignature;  
  14.   
  15. import org.apache.tapestry.Tapestry;  
  16.   
  17. import org.apache.tapestry.annotations.AnnotationUtils;  
  18.   
  19. import org.apache.tapestry.annotations.MethodAnnotationEnhancementWorker;  
  20.   
  21. import org.apache.tapestry.engine.ILink;  
  22.   
  23. import org.apache.tapestry.enhance.EnhancementOperation;  
  24.   
  25. import org.apache.tapestry.spec.IComponentSpecification;  
  26.   
  27.    
  28.   
  29. public class InjectExternalLinkAnnotationWorker implements  
  30.   
  31.        MethodAnnotationEnhancementWorker {  
  32.   
  33.    
  34.   
  35.     public void performEnhancement(EnhancementOperation op,  
  36.   
  37.            IComponentSpecification spec, Method method, Location location) {  
  38.   
  39.        if (!method.getReturnType().equals(ILink.class))  
  40.   
  41.            throw new ApplicationRuntimeException(  
  42.   
  43.                   "injectExternalLink annotation must return ILink");  
  44.   
  45.    
  46.   
  47.        InjectExternalLink injectExternalLink = method  
  48.   
  49.               .getAnnotation(InjectExternalLink.class);  
  50.   
  51.    
  52.   
  53.        String pageName = injectExternalLink.value();  
  54.   
  55.    
  56.   
  57.        BodyBuilder builder = new BodyBuilder();  
  58.   
  59.    
  60.   
  61.        builder.begin();  
  62.   
  63.    
  64.   
  65.        Class[] parameterTypes = method.getParameterTypes();  
  66.   
  67.        int paramCount = Tapestry.size(parameterTypes);  
  68.   
  69.    
  70.   
  71.        if (paramCount > 0) {  
  72.   
  73.            if (parameterTypes[0].isArray()) {  
  74.   
  75.               builder  
  76.   
  77.                      .addln(  
  78.   
  79.                             "return getPage().getRequestCycle().getInfrastructure().getServiceMap(). 
  80.  
  81. getService(org.apache.tapestry.Tapestry.EXTERNAL_SERVICE).getLink(false, new org.apache.tapestry.engine.ExternalServiceParameter(\"{0}\",$1));",  
  82.   
  83.                             pageName);  
  84.   
  85. else {  
  86.   
  87.               builder  
  88.   
  89.                      .addln(  
  90.   
  91.                             "java.lang.Object[] params = new java.lang.Object[{0}];",  
  92.   
  93.                             paramCount);  
  94.   
  95.               for (int i = 0; i < paramCount; i++) {  
  96.   
  97.                   builder.add("params[{0}] = ", i);  
  98.   
  99.    
  100.   
  101.                   if (parameterTypes[i].isPrimitive())  
  102.   
  103.                      builder.add("($w) ");  
  104.   
  105.    
  106.   
  107.                   // Parameter $0 is this, so $1 is the first real parameter.  
  108.   
  109.    
  110.   
  111.                   builder.addln("${0};", i + 1);  
  112.   
  113.               }  
  114.   
  115.               builder  
  116.   
  117.                      .addln(  
  118.   
  119.                             "return getPage().getRequestCycle().getInfrastructure().getServiceMap().getService(org.apache.tapestry.Tapestry.EXTERNAL_SERVICE).getLink(false, new org.apache.tapestry.engine.ExternalServiceParameter(\"{0}\",params));",  
  120.   
  121.                             pageName);  
  122.   
  123.            }  
  124.   
  125.        }  
  126.   
  127.    
  128.   
  129.        builder.end();  
  130.   
  131.    
  132.   
  133.        op.addMethod(Modifier.PUBLIC, new MethodSignature(method), builder  
  134.   
  135.               .toString(), location);  
  136.   
  137.    
  138.   
  139.        if (isGetter(method))  
  140.   
  141.            op.claimReadonlyProperty(AnnotationUtils.getPropertyName(method));  
  142.   
  143.     }  
  144.   
  145.    
  146.   
  147.     boolean isGetter(Method method) {  
  148.   
  149.        // We already know the return type is String  
  150.   
  151.    
  152.   
  153.        return method.getName().startsWith("get")  
  154.   
  155.               && method.getParameterTypes().length == 0;  
  156.   
  157.     }  
  158.   
  159. }  
<o:p></o:p>
类写好了,然后就是贡献到Tapestry<o:p></o:p>
xml 代码
 
  1. <module id="your.model.annotation" version="1.0.0" package="your.package.annotations">  
  2.   
  3.      <contribution configuration-id="tapestry.annotation.MethodWorkers">  
  4.   
  5.       <worker annotation="InjectPageLink" object="instance:InjectPageLinkAnnotationWorker"/>  
  6.   
  7.       <worker annotation="InjectExternalLink" object="instance:InjectExternalLinkAnnotationWorker"/>  
  8.   
  9.     <!---->contribution>  
  10.   
  11. <!---->module>  

<o:p></o:p>
好了将你的module放入项目hivemodule.Xml作为子module<o:p></o:p>
Okenjoy it

<o:p></o:p>

<o:p> </o:p>