锁定老帖子 主题:WebWork2.2新特性 系列
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-09-02
在xwork中,package的定义中增加了global-exception-mappings,action的定义中增加了exception-mapping,要想使用这2个特性,必须使用xwork-1.1.dtd才行.
DTD中,global-exception-mappings是这样定义的, <!ELEMENT global-exception-mappings (exception-mapping+);> 也就是说如果要使用,就至少包含一个异常映射. exception-mapping的定义如下: <!ELEMENT exception-mapping (#PCDATA|param);*> <!ATTLIST exception-mapping name CDATA #IMPLIED exception CDATA #REQUIRED result CDATA #REQUIRED > 可以看到有3个属性:名称,异常类型,和结果. 经过一番查看,发现xwork-default.xml中还没有定义相关的拦截器,搜索了一下,发现了ExceptionMappingInterceptor,看来它是把异常翻译为相应的结果的. (在最后发行版本中,应该会定义的.目前只好我们自己定义了.) 首先我们虚拟一个程序,假设程序会抛出几种程序,例如Action定义如下: package com.jscud.ww2test.exceptionmap; import com.opensymphony.xwork.ActionSupport; /** * @author scud http://www.jscud.com * */ public class ExpMappingAction extends ActionSupport { private int type; public String execute(); throws NoRightException,NotFoundException { if(type==1); { throw new NoRightException();; } else if(type ==99); { throw new NotFoundException();; } else if(type==60); //其他异常 { throw new IllegalArgumentException();; } return SUCCESS; } public int getType(); { return type; } public void setType(int type); { this.type = type; } } 从Action可以看出,程序至少会抛出3种异常,我们如果使用异常映射,就要考虑到抛出的所有异常. 程序中用到的NoRightException,NotFoundException是为了演示而建立的2个简单异常,无任何特殊代码,继承自Exception. 我们的xwork.xml中的定义如下: <package name="exceptionmapping" extends="webwork-default" namespace="/exceptionmap"> <interceptors> <interceptor name="exceptionmapping" class="com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"/> <interceptor-stack name="myDefaultStack"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="exceptionmapping"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="myDefaultStack"/> <global-results> <result name="noright" type="dispatcher"> <param name="location">/exceptionmap/noright.jsp</param> </result> <result name="exception" type="dispatcher"> <param name="location">/exceptionmap/exception.jsp</param> </result> </global-results> <global-exception-mappings> <exception-mapping name="noright" exception="com.jscud.ww2test.exceptionmap.NoRightException" result="noright"/> <exception-mapping name="exception" exception="java.lang.Exception" result="exception"/> </global-exception-mappings> <action name="index" class="com.jscud.ww2test.exceptionmap.ExpMappingAction"> <exception-mapping name="notfound" exception="com.jscud.ww2test.exceptionmap.NotFoundException" result="notfound"/> <result name="success" type="dispatcher"> <param name="location">/exceptionmap/index.jsp</param> </result> <result name="notfound" type="dispatcher"> <param name="location">/exceptionmap/notfound.jsp</param> </result> </action> </package> 首先定义了一个exceptionmapping拦截器,用来指向ExceptionMappingInterceptor. 然后定义一个拦截器Stack,包含defaultStack和exceptionmapping,注意,exceptionmapping是在Stack的最后面,否则会发生不可预期的结果. 可以看到global-exception-mappings段包含了2个异常映射,一个为NoRight的处理,另外一个为对应java.lang.Exception的映射. 在Action的定义中包含了一个exception-mapping,对应NotFound异常. 没有看到IllegalArgumentException的对应结果?? 拦截器对没有定义的异常会依次找这个异常的父类,一级一级向上查找,例如IllegalArgumentException的最终父节点是Exception,就会转向到Exception对应的结果. 如果一个异常有多个层次关系上的父类,那个关系最近就找谁. 演示页面如下: <%@ page contentType="text/html; CHARSET=utf8" %> <%@ taglib uri="webwork" prefix="ww" %> <html> <head> <title>exception mapping</title> </head> <body> <br> Exception 1: <a href="index.jspa?type=1">Exception 1</a> <br><br> Exception 99: <a href="index.jspa?type=99">Exception 99</a> <br><br> Other Exception: <a href="index.jspa?type=60">Exception 60</a> <br><br> Normal: <a href="index.jspa">No Exception</a> <br><br> </body> </html> notfound.jsp,exception.jsp,noright.jsp是三个最简单的jsp页面,自己编写即可. 运行程序,发现根据异常类型会转向相应的异常页面. 如果你自己的程序中的异常没有在异常映射中得到对应的result,会抛出异常,所以应该定义一个底层Exception的映射. |
|
返回顶楼 | |
发表时间:2005-09-07
WebWork2.2新特性(八)使用FreeMarker的FTL做装饰页面
其实我不善于写作,有些东西仅仅是写下来.还可以提醒自己. 人生"入"梦,各位一定要保重身体. 注意:FreeMarkerPageFilter是2.2beta发布后才加到CVS上的,所以从CVS获取新的代码才能看到这个filter,同目录下还有一个VelocityPageFilter. FreeMarkerPageFilter以及VelocityPageFilter都是Sitemesh页面装饰器中PageFilter的扩展,有了它,可以直接使用FreeMarker的ftl作为装饰页面,可以不在使用SiteMesh带的FreemarkerDecoratorServlet了,而且还可以享受Action中的ValueStack了. 不过我不推荐在装饰页面中使用ValueStack中的值,因为装饰页面对应的Action是不确定的,而且也可能修饰的是一个普通页面,不是一个Action. 我们要有一个Action及其结果页面,或者一个简单的页面,这些不在赘述,自己看自己的了. 首先我们有一个装饰页面,示例如下(main.ftl): <html> <head> <title>JScud Develop:${page.title}</title> ${page.head} </head> <body> ${page.body} <br><br> From: ${base} by <@ww.text name="copyright"/> </body> </html> 我们可以看到,其中的标记都有page前缀,而不是直接使用body,title等,原因是这个FreeMarkerPageFilter只把page放到了FreeMarker的model中,如果你还是想遵循原来的习惯,那么自己继承一下FreeMarkerPageFilter即可,非常简单,然后把body,title,head放到model中即可.不过我觉得现在也挺好,省得变量太短和别的混淆. SiteMesh的decorators.xml示例如下: <?xml version="1.0" encoding="ISO-8859-1"?> <decorators defaultdir="/decorators"> <decorator name="main" page="main.ftl"> <pattern>/*</pattern> </decorator> </decorators> 我们还需要在web.xml中配置过滤器,在这个地方,我走了弯路,因为没有文档,结果没有注意到 ActionContexCleanUp 这个Filter,自己还自作聪明修改了一下FreeMarkerPageFilter,后来才发现ActionContexCleanUp这个Filter的作用,这都是没有仔细看源码(JavaDoc)的后果啊. 在不使用SiteMesh的时候,为了使用WebWork,我们只需要在web.xml配置FilterDispatcher一个过滤器即可,阅读一下FilterDispatcher的JavaDoc和源码,我们可以看到它调用了: finally { ActionContextCleanUp.cleanUp(req);; } 而且JavaDoc中也提到看ActionContextCleanUp的文档,那我们就去看吧(我没看所以...) 在ActionContextCleanUp中,有这样的代码: req.setAttribute(CLEANUP_PRESENT, Boolean.TRUE);; 如果FilterDispatcher检测到这个属性,就不会清除ActionContext中的内容了,而由ActionContextCleanUp后续的代码来清楚,保证了一系列的Filter访问正确的ActionContext. 文档中提到,如果用到SiteMesh的Filter,那么设置顺序是: ActionContextCleanUp filter SiteMesh filter FilterDispatcher 所以最后我们的web.xml应该类似这样: <filter> <filter-name>ActionContextCleanUp</filter-name> <filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class> </filter> <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.webwork.sitemesh.FreeMarkerPageFilter</filter-class> </filter> <filter> <filter-name>webwork</filter-name> <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>ActionContextCleanUp</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>webwork</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 发布程序,运行结果正常.在Action改变Locale,装饰页面也获取了正确的Locale,OK,大功告成...嘿嘿 BTW:如果你使用jsp做装饰页面,使用SiteMesh自己的PageFilter即可,不过也要配置ActionContextCleanUp哦. BTW 2: 其实,我还想写一篇AJAX的,不过总是懒得写那... 文件上传的拦截器有些Bug,而且处理流程必须结合实际才行,所以也不想写了... 后补: ActionContexCleanUp 已经被修正为ActionContextCleanUp |
|
返回顶楼 | |
发表时间:2005-09-07
AJAX支持是Webwork2.2最大的亮点,我支持你写!
|
|
返回顶楼 | |
发表时间:2005-09-14
在WebWork2.2中,还有很多的新特性,底层结构也发生了很大的变化,对AJAX的支持也是一个很大的亮点,对于我们使用WebWork的用户来说都是一个巨大的鼓舞.
期待更多的人加入到webwork的使用,开发,测试,讨论中来,呵呵. 投入越多,获得越多,只有努力争取,我们才能获得更多. 没有讲到的一些新特性: AliasInterceptor ScopeInterceptor FileUploadInterceptor(增强) datepicker multiply submit button SpringObjectFactory ...... ...... 阅读WebWork的源码,你会发现更多 如果你希望我对某个方面进行详细介绍,请联系我 我工作时间无法上msn,请原谅 邮件地址: |
|
返回顶楼 | |
发表时间:2005-11-16
scud 写道 BTW:如果你使用jsp做装饰页面,使用SiteMesh自己的PageFilter即可,不过也要配置ActionContextCleanUp哦. 你好,scud,大作拜读后,发现我昨天才做的sitemesh装饰页面是main.jsp,但是没有配置ActionContextCleanUp,现在页面运行正常,不知道我说得有没有错。:) |
|
返回顶楼 | |
发表时间:2005-11-16
建议阅读一下ActionContextCleanUp和FilterDispatcher的源码
如果是简单页面,可能无所谓,如果你的装饰页面用到webwork的功能,action里面的变量就有用了。 建议加上,等你有需要的时候可能就有用了 :) |
|
返回顶楼 | |