WebWork2.2新特性(系列)---freemark支持多语言

WebWork2.2新特性(三) 在简单页面中使用ww:text进行国际化
这个特性应该说这是一个副产品.是我最近突然想到这个想法,然后试用webwork 2.2,发现可以做到,而webwork 2.1.7是做不到的.


名词定义
:
简单页面:不通过action访问,直接访问文件的url.例如直接访问的jsp,或者直接访问的ftl.

需求想法:
在一个网站中,有很多页面,其中很多页面仅仅是简单的页面,没有程序处理等.不过为了国际化,这些页面就需要进行i18n的工作.

1.按照正常的想法,应该是每个页面都要写一个action,然后结果定义为这个页面,通过访问action来对页面进行国际化.或者是写一个action,根据参数的不同,转向目标页面.
或者要定义很多action或者很多参数 或者用一个程序带不同的参数来访问. 总之是麻烦,不直观.
2.实现自己的一个tag来装载国际化信息.这样很简单.不过只能用在jsp里. 如果想使用freemarker的话,通过一些简单处理,也可以使用这个功能.
这个思路很简单,可以不依赖任何其他组件.
3.WebWork 2.1.7
如果是在Jsp中,可以通过

代码
  1. <ww:i18n name="message">  
  2.   <ww:text name="name"/>  
  3. </ww:i18n>  
<script type="text/javascript">render_code();</script>
来实现简单页面的国际化. 无法在freemarker的简单页面中直接使用. (可以在action的结果页面中使用)

 

4.WebWork 2.2 Beta (在最后发布的版本中,可能会有变化!!!)

在简单页面Jsp中,可以直接使用ww:text,例如

代码
  1. <ww:text name="name"/>     
<script type="text/javascript">render_code();</script>
( 注意:在webwork.properties中需要包含资源文件 webwork.custom.i18n.resources=message ,如果有多个,就用逗号分割)
在FreeMarker的简单文件中,也可以直接使用ww:text.
代码
  1. <@ww.text name="name"/>   
<script type="text/javascript">render_code();</script>
当前是在web.xml里面配置了FreeMarker的处理引擎.如:
代码
  1. <servlet>  
  2.   <servlet-name>freemarker</servlet-name>  
  3.   <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class>  
  4.   <load-on-startup>10</load-on-startup>  
  5. </servlet>  
  6.   
  7. <servlet-mapping>  
  8.   <servlet-name>freemarker</servlet-name>  
  9.   <url-pattern>*.ftl</url-pattern>  
  10. </servlet-mapping>  
<script type="text/javascript">render_code();</script>
警告:如果你不使用FreeMarker的简单页面,不需要配置这个Servlet,即使使用freemarker的ftl页面来做action的结果页面,也不需要配置这个Servlet,使用webwork的freemarker结果即可,具体请浏览webwork的Result Type的文档.

 

评论    共 15 条 发表评论
scud     2005-08-31 16:05

其实这个I18nInterceptor很简单,而且实际应用中根据实际需求需要进行变通,所以这个I18nInterceptor并不是很实用,当然还是提供了一定的参考作用的.

首先我们来看一下如何使用这个拦截器.

首先我们需要有一个Action,为了演示,其实最简单的Action就可以,例如

代码
  1. public class I18nIcAction extends ActionSupport   
  2. {       
  3.     public String execute()   
  4.     {   
  5.         return SUCCESS;   
  6.     }   
  7. }   
<script type="text/javascript">render_code();</script>
展示的页面例子如下:
代码
  1. <%@ page contentType="text/html; charset=UTF-8" %>  
  2. <%@ taglib uri="webwork" prefix="ww" %>  
  3. <html>  
  4. <head>  
  5.     <title>Test I18n Interceptor</title>  
  6.     <meta http-equiv="pragma" content="no-cache">  
  7.     <meta http-equiv="cache-control" content="no-cache">  
  8.     <meta http-equiv="expires" content="0">  
  9. </head>  
  10.      
  11. <body>  
  12. Choose: <a href="?locale=en">English Page</a> ,   
  13.         <a href="?locale=zh_CN">Chinese Page</a>  
  14. <br><br>  
  15. Content:<ww:text name="desc"/>  
  16. </body>  
  17. </html>  
<script type="text/javascript">render_code();</script>
其中我们使用"locale"作为locale的参数名,页面里面有2个选项:英文和中文.

 

对应的资源文件有2个(或者3个,如果包括缺省一个的话):

英文的I18nIcAction_en.properties内容为:
desc=english
中文的I18nIcAction_zh_CN.properties内容为:
desc=/u7b80/u4f53/u4e2d/u6587
接下来我们在xwork.xml里面定义我们的action和拦截器:

代码
  1. <package name="i18nic" extends="webwork-default" namespace="/i18nic">  
  2.     <interceptors>  
  3.         <interceptor name="i18n" class="com.opensymphony.xwork.interceptor.I18nInterceptor">  
  4.             <param name="parameterName">locale</param>  
  5.             <param name="attributeName">ww_locale</param>  
  6.         </interceptor>  
  7.            
  8.         <interceptor-stack name="i18nStack">  
  9.             <interceptor-ref name="i18n"/>  
  10.             <interceptor-ref name="defaultStack"/>  
  11.         </interceptor-stack>  
  12.     </interceptors>  
  13.   
  14.     <default-interceptor-ref name="i18nStack"/>  
  15.   
  16.     <action name="index" class="com.jscud.ww2test.i18nic.I18nIcAction">  
  17.         <result name="success" type="dispatcher">  
  18.             <param name="location">/i18nic/index.jsp</param>  
  19.         </result>  
  20.     </action>  
  21. </package>  
<script type="text/javascript">render_code();</script>
所有的工作都好了,发布并运行访问 /i18nic/index.action,一切和预想的一样.

 

通过查看I18nInterceptor的源码,我们可以看到这个拦截器的工作原理是这样的:
1.如果参数中指定了locale,那么拦截器分析参数,并把locale保存到session中.
2.在后面的action中,拦截器从session中获取这个locale,并设置action的locale,从而保持用户的设置.
3.在后续页面还可以继续切换locale.

从源码分析结果来看,这样做也会有一些实际的问题:
1.session过期后,用户不知道发生了什么,系统使用缺省的locale.
2.只能影响通过action操作的页面

在实际使用中,我们也要考虑如何解决后面2个问题,例如通过cookie,或者把用户的配置保存在数据库里等,这些实现就要结合实际代码进行实现了,完全可以不需要这个I18nInterceptor就可以实现,当然也很简单.

各取所需,看自己的实际需要吧

scud     2005-08-31 16:10

本文介绍了在WebWork2.2中如何使用客户端校验

WebWork2.2中去掉了原来的JavaScript支持,使用AJAX和DWR进行客户端校验.

DWR最新版本为1.0,Webwork里面带的是0.6的版本.

如果使用客户端校验,首先在Web.xml里配置DWR:

代码
  1. <servlet>  
  2.     <servlet-name>dwr</servlet-name>  
  3.     <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>  
  4.     <init-param>  
  5.         <param-name>debug</param-name>  
  6.         <param-value>true</param-value>  
  7.     </init-param>  
  8. </servlet>  
  9.   
  10. <servlet-mapping>  
  11.     <servlet-name>dwr</servlet-name>  
  12.     <url-pattern>/dwr/*</url-pattern>  
  13. </servlet-mapping>  
<script type="text/javascript">render_code();</script>

 

validators.xml的写法和原来一样,不过就是不能用原来的JavaScript的校验了

代码
  1. <validators>       
  2.     <validator name="required"    
  3.         class="com.opensymphony.xwork.validator.validators.RequiredFieldValidator"/>  
  4.            
  5.     <validator name="requiredstring"  
  6.         class="com.opensymphony.xwork.validator.validators.RequiredStringValidator"/>  
  7.   
  8.     <validator name="stringlength"    
  9.         class="com.opensymphony.xwork.validator.validators.StringLengthFieldValidator"/>               
  10. </validators>  
<script type="text/javascript">render_code();</script>

 

对action的校验规则写法也是和原来一样,例如增加新闻的校验如下:

 

代码
  1. <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">  
  2. <validators>  
  3.     <field name="news.title">  
  4.         <field-validator type="requiredstring">  
  5.             <message>请输入标题</message>  
  6.         </field-validator>  
  7.     </field>       
  8.     <field name="news.content">  
  9.         <field-validator type="requiredstring">  
  10.             <message>请输入内容</message>  
  11.         </field-validator>  
  12.     </field>  
  13.        
  14. </validators>      
<script type="text/javascript">render_code();</script>

 

页面的Form标签中写上validate="true" (注意使用的是alt syntax语法)表示需要进行客户端校验,
如果不写validate="true"则不需要进行客户端校验,仅进行服务器端校验,这就和DWR无关了,和以前的客户端校验一样.

代码
  1. <ww:form action="doAddNews" method="post" name="doAddNews" validate="true">   
<script type="text/javascript">render_code();</script>

还需要在WEB-INF下面增加一个dwr.xml配置DWR,如果使用webwork自带的dwr,格式如下
代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 0.4//EN" "http://www.getahead.ltd.uk/dwr/dwr.dtd">  
  3. <dwr>  
  4.     <allow>  
  5.         <create creator="new" javascript="validator" class="com.opensymphony.webwork.validators.DWRValidator"/>  
  6.         <convert converter="bean" match="com.opensymphony.xwork.ValidationAwareSupport"/>  
  7.     </allow>  
  8. </dwr>  
<script type="text/javascript">render_code();</script>

 

如果使用DWR 1.0(用新的版本不知道有没有问题),格式如下:

代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd">  
  3. <dwr>  
  4.     <allow>  
  5.         <create creator="new" javascript="validator" >  
  6.         <param name="class" value="com.opensymphony.webwork.validators.DWRValidator" />  
  7.         </create>  
  8.         <convert converter="bean" match="com.opensymphony.xwork.ValidationAwareSupport"/>  
  9.     </allow>  
  10. </dwr>  
<script type="text/javascript">render_code();</script>
(注:一定要使用匹配dwr和dwr.xml,否则会报错)

 

通过查看页面Html源码,我们可以看到页面中包含了/webwork和/dwr的路径,这些路径由Webwork和DWR自动生成文件返回,避免了在每个项目中复制重复的文件.

代码
  1. <script src="/ww22test/webwork/validationClient.js"></script>  
  2. <script src="/ww22test/dwr/interface/validator.js"></script>  
  3. <script src="/ww22test/dwr/engine.js"></script>  
  4. <script src="/ww22test/webwork/template/xhtml/validation.js"></script>  
<script type="text/javascript">render_code();</script>

 

其中字段使用onblue来进行调用校验:

代码
  1. <input type="text" name="news.title" value="" id="doAddNews_news.title" οnblur="validate(this);"/>   
<script type="text/javascript">render_code();</script>
至此,Webwork的客户端校验可以运行了.

 

(实际操作中,DWR的校验可能还会有些问题,等待开发人员来进行修正了)

Bug说明:目前发现当表单元素的名字没有.的时候(例如是"name"),DWR校验器工作正常,而如果类似上面的表单元素名字类似news.title,校验器工作不正常.

不知道是DWR的问题还是WebWork的问题,webwork开发人员已经确认是个bug.

scud     2005-08-31 16:12

1.ServletDispatcher 被FilterDispatcher替代
ServletDispatcher被标记为deprecated.

(FreemarkerServlet和WebWorkVelocityServlet也被标记为deprecated)

新的Web.xml部分配置如下:

代码
  1. <filter>  
  2.     <filter-name>webwork</filter-name>  
  3.     <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>  
  4. </filter>    
  5. <filter-mapping>  
  6.     <filter-name>webwork</filter-name>  
  7.     <url-pattern>/*</url-pattern>  
  8. </filter-mapping>  
  9.   
  10. <listener>  
  11.     <listener-class>com.opensymphony.webwork.lifecycle.LifecycleListener</listener-class>  
  12. </listener>  
  13.   
  14. <servlet>  
  15.     <servlet-name>JspSupportServlet</servlet-name>  
  16.     <servlet-class>com.opensymphony.webwork.views.JspSupportServlet</servlet-class>  
  17.     <load-on-startup>1</load-on-startup>  
  18. </servlet>    
<script type="text/javascript">render_code();</script>

 

其中filter代替了过去的ServletDispatcher,也增加了不少功能.

其中的LifecycleListener部分是为了使用XWork的IOC功能而设置的监听器,如果不使用,应该是可以去掉的.

其中的JspSupportServlet是为了支持在Freemarker和Velocity中进行的一些设置,如果去掉这个,一些功能就不能在ftl文件里面使用了,例如webwork的tag支持.

如果想单独使用Freemarker的文件(不通过action),还可以在web.xml配置FreeMarkerServlet,类似

代码
  1. <servlet>  
  2.   <servlet-name>freemarker</servlet-name>  
  3.   <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class>  
  4.   <load-on-startup>10</load-on-startup>  
  5. </servlet>  
  6.   
  7. <servlet-mapping>  
  8.   <servlet-name>freemarker</servlet-name>  
  9.   <url-pattern>*.ftl</url-pattern>  
  10. </servlet-mapping>  
<script type="text/javascript">render_code();</script>

 

注意:如果仅使用ftl文件作为action的结果页面,使用freemarker结果类型即可,不需要配置FreeMarkerServlet.

如果想使用DWR进行客户端校验,还需要配置:

代码
  1. <servlet>  
  2.     <servlet-name>dwr</servlet-name>  
  3.     <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>  
  4.     <init-param>  
  5.         <param-name>debug</param-name>  
  6.         <param-value>true</param-value>  
  7.     </init-param>  
  8. </servlet>  
  9.   
  10. <servlet-mapping>  
  11.     <servlet-name>dwr</servlet-name>  
  12.     <url-pattern>/dwr/*</url-pattern>  
  13. </servlet-mapping>  
<script type="text/javascript">render_code();</script>

 

DWR还有一些参数配置,可以根据实际修改.

使用FilterDispatcher还有一些其他影响,具体可以参考Webwork的文档

不能使用jsp:include,ww:include了,可以使用action chaining 或者ww:action标签代替.
Velocity中的JSP tag仿真不能用了,仅支持原生的Velocity tag了

当然如果你需要以上的功能,还是依然可以使用ServletDispatcher来配置的,不过这是不推荐的了.


2.默认使用alt syntax语法,当然可以配置

如果用新的方法的话字符串不需要加单引号了,不过要引用变量就要用%{名字}的方式了.
例如原来这样写的语句:

代码
  1. Message:<ww:text name="key"/>   
  2. <br><br>   
  3. Message:<ww:text name="’name’"/>   
<script type="text/javascript">render_code();</script>
开启alt syntax后就要这样写:
代码
  1. Message:<ww:text name="%{key}"/>   
  2. <br><br>   
  3. Message:<ww:text name="name"/>   
<script type="text/javascript">render_code();</script>
根据自己的习惯决定吧.我觉得alt syntax直观,不过有点麻烦,呵呵.

 

更详细的alt syntax的文档,就要期待webwork team的文档了

robbin     2005-08-31 16:34

关于FilterDispatcher,我看了看源代码,补充一点说明:

 

xml 代码
  1. <filter>  
  2.   <filter-name>webwork</filter-name>                <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>  
  3. </filter>  
  4.     <filter-mapping>  
  5.         <filter-name>webwork</filter-name>  
  6.         <url-pattern>/*</url-pattern>  
  7.     </filter-mapping>   
<script type="text/javascript">render_code();</script>

 

注意url-pattern,以前使用ServletDipatcher的时候,url pattern是*.action,现在改成了/*。这个Filter不但对action拦截,而且对其他类型的url也要拦截。指定action的扩展名则挪到了webwork.properties里面:

引用
webwork.action.extension=action

 

为什么要这么改?是为了支持AJAX,一些特殊的URL,例如 /webwork/...是去请求服务器端内置的dojo JS库,所以url pattern一定要改,并且要区分不同的请求类型,究竟是action,还是/webwork/,还是普通资源,FilterDispachter会根据不同情况执行不同操作。

 

引用
<listener-class>com.opensymphony.webwork.lifecycle.LifecycleListener</listener-class>
</listener>

 

这个设置不是必须的,只有当你用到了webwork的components功能才需要。一般而言,我们总是用spring作为业务层bean的IoC,所以webwork的IoC功能用不上,所以不需要配置。

 

引用
<servlet>
<servlet-name>JspSupportServlet</servlet-name>
<servlet-class>com.opensymphony.webwork.views.JspSupportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

似乎是没用的配置,我没有看出来有什么用处。

 

另外要注意的是,webwork2.2默认使用freemarker作为模版引擎,需要把freemarker的jar放进来。修改引擎也是通过webwork.properties:

引用
#sets the default template type. Either ftl, vm, or jsp
webwork.ui.templateSuffix=ftl

 

scud     2005-08-31 17:22

 

引用

指定action的扩展名则挪到了webwork.properties里面:
引用:
webwork.action.extension=action

 

 

 

以前也是可以改的,也是在这个属性改,当然如果这里改了,映射那里也要改成对应的才行

JspSupportServlet在FreemarkerManager.java里面用到了,是有用的,如果没有这个,可能无法在ftl里面使用jsp tag和其他一些东西了

我修改了一下上面的文章,增加了说明

scud     2005-09-01 14:42

com/opensymphony/webwork/default.properties是webwork的重要文件,它对webwork的参数进行了配置,其中包含了webwork支持的所有配置,如果你想覆盖其中的配置,只需要建立一个webwork.properties放在你的项目中(一般放在源码目录下,发布时的位置是WEB-INF/classes下).

让我们来看看在webwork 2.2中这个文件发生了什么变化.

1.可以配置webwork.objectFactory

 

代码
  1. if specified, the default object factory can be overridden here   
  2. #webwork.objectFactory = com.opensymphony.xwork.spring.SpringObjectFactory   
<script type="text/javascript">render_code();</script>

 

这个ObjectFactory是一个很多地方都用到的类,默认webwork使用的是com.opensymphony.xwork.ObjectFactory,如果你想自己实现一个或者使用Spring的机制,可以配置这个属性.不过在没有更详细的文档出来之前,一定要小心使用.

SpringObjectFactory类中主要覆写了ObjectFactory的buildBean,并没有替换其他函数.

2.webwork.mapper.class

代码
  1. # extension for actions   
  2. webwork.mapper.class=com.opensymphony.webwork.dispatcher.mapper.DefaultActionMapper   
  3. webwork.action.extension=action   
<script type="text/javascript">render_code();</script>

 

可以看到,增加了一行webwork.mapper.class.
DefaultActionMapper以及同目录下RestfulActionMapper相当于以前的普通action url路径处理和CoolUriServletDispatcher映射方式处理,在webwork2.2中,如果想使用CoolUriServletDispatcher的方式,在此处修改这个属性为RestfulActionMapper即可.

当然,你可以实现自己的ActionMapper,实现自己的想法,很多人都喜欢自己来处理url,那就自己写一个,不错的想法.

3.webwork.tag.altSyntax=true
altSyntax语法默认为打开了,参考前面的文章

4.webwork.i18n.reload

代码
  1. # when set to true, resource bundles will be reloaded on _every_ request.   
  2. this is good during development, but should never be used in production   
  3. webwork.i18n.reload=false  
<script type="text/javascript">render_code();</script>

 

如果设置为true,每次资源文件都会被重载,方便调试.发布后一定要记得改为false.

5.webwork.ui.templateSuffix

代码
  1. #sets the default template type. Either ftl, vm, or jsp   
  2. webwork.ui.templateSuffix=ftl   
<script type="text/javascript">render_code();</script>

 

Tag模板的默认配置为freemarker的ftl了,以前是vm的.

6.webwork.dispatcher.parametersWorkaround

代码
  1. # workaround for some app servers that don't handle HttpServletRequest.getParameterMap()   
  2. # often used for WebLogic, Orion, and OC4J   
  3. webwork.dispatcher.parametersWorkaround = false  
<script type="text/javascript">render_code();</script>
这个是为了处理一些web server的非常规的运作行为的,具体我就没试过了.

 

注意:最后发布的版本可能还会有一些变化,以最后发布的版本为准.

robbin     2005-09-01 15:47

刚才更新了一下webwork的cvs源代码,发现增加了一个iBATIS的子目录,即支持在webwork的IoC容器里面使用iBATIS了。不过一般来说我们更加倾向于使用Spring。

scud     2005-09-01 15:55

刚刚才更新了hibernate,ibatis

还增加了sitemesh对freemarker的一个filter,不过我还没有看

 

引用

Log:
- complete hibernate support

 

- added ibatis support

- added sitemesh support for FM and Velocity

 

 

webwork的论坛上会同步反应cvs的更新,所以我就看论坛的帖子就能看到更新了什么

用的是jive论坛,对开发的支持很方便啊

scud     2005-09-02 16:01

ParameterNameAware 是XWork中新增的一个接口,是由Bob Lee (crazybob@google.com)提供的,主要的用途是限制Action仅接收一定规则的参数,用来防止无意义的参数或者破坏?不过我想我暂时用不到这个接口,不过还是介绍一下如何使用吧.

首先我们写一个Action,实现ParameterNameAware接口,这个接口只有一个方法,就是public boolean acceptableParameterName(String name).

我们的Action如下:

 

代码
  1. package com.jscud.ww2test.parametername;   
  2.   
  3. import com.opensymphony.xwork.ActionSupport;   
  4. import com.opensymphony.xwork.interceptor.ParameterNameAware;   
  5.   
  6. /**  
  7.  * @author scud http://www.jscud.com  
  8.  */  
  9. public class ParameterNameTestAction extends ActionSupport implements ParameterNameAware   
  10. {   
  11.     private String name1;   
  12.     private String name2;   
  13.     private String name3;   
  14.   
  15.     public String execute()   
  16.     {   
  17.         return SUCCESS;   
  18.     }   
  19.   
  20.     /**  
  21.      * 当前参数名是否允许.  
  22.      * @param name 参数名  
  23.      * @return 是否允许  
  24.      */  
  25.     public boolean acceptableParameterName(String name)   
  26.     {   
  27.         if (name.equals("name1") || name.equals("name2"))   
  28.         {   
  29.             return true;   
  30.         }   
  31.                    
  32.         return false;   
  33.     }   
  34.   
  35.     public String getName1()   
  36.     {   
  37.         return name1;   
  38.     }   
  39.   
  40.     public void setName1(String name1)   
  41.     {   
  42.         this.name1 = name1;   
  43.     }   
  44.   
  45.     public String getName2()   
  46.     {   
  47.         return name2;   
  48.     }   
  49.   
  50.     public void setName2(String name2)   
  51.     {   
  52.         this.name2 = name2;   
  53.     }   
  54.   
  55.     public String getName3()   
  56.     {   
  57.         return name3;   
  58.     }   
  59.   
  60.     public void setName3(String name3)   
  61.     {   
  62.         this.name3 = name3;   
  63.     }   
  64. }   
  65.   
<script type="text/javascript">render_code();</script>

 

可以看到,这个Action实现了ParameterNameAware接口,并且设置只接收"name1"和"name2"两个参数,而我们在action有三个用来保存用户输入值的对象:name1,name2和name3.

我们的action定义如下:

代码
  1. <package name="parameternametest" extends="webwork-default" namespace="/parametername">  
  2.     <action name="index" class="com.jscud.ww2test.parametername.ParameterNameTestAction">  
  3.         <result name="success" type="dispatcher">  
  4.             <param name="location">/parametername/index.jsp</param>  
  5.         </result>  
  6.     </action>  
  7. </package>  
<script type="text/javascript">render_code();</script>

 

不需要定义任何额外的拦截器,这个接口是在ParametersInterceptor里检测的.

目标页面如下:

代码
  1. <%@ page contentType="text/html; charset=UTF-8" %>  
  2. <%@ taglib uri="webwork" prefix="ww" %>  
  3. <html>  
  4. <head>  
  5.     <title>Test ParamaterName</title>  
  6. </head>  
  7. <body>  
  8.   
  9. <ww:form name="test" action="index" method="post" namespace="/parametername" >  
  10. <ww:textfield name="name1"  label="Name1" /><br>  
  11. <ww:textfield name="name2"  label="Name2" /><br>  
  12. <ww:textfield name="name3"  label="Name3" /><br>  
  13. <ww:submit value="Submit" />  
  14. </ww:form>  
  15. <br/>  
  16.   
  17. Show Message:   
  18. <br/>  
  19. Name1 is:<ww:property value="name1" /><br/>  
  20. Name2 is:<ww:property value="name2" /><br/>  
  21. Name3 is:<ww:property value="name3" /><br/>  
  22. </body>  
  23. </html>  
<script type="text/javascript">render_code();</script>

 

运行程序,我们可以发现,name3的值没有得到设置,我们在页面中也自然得不到name3的值了.

scud     2005-09-02 19:09

在xwork中,package的定义中增加了global-exception-mappings,action的定义中增加了exception-mapping,要想使用这2个特性,必须使用xwork-1.1.dtd才行.

DTD中,global-exception-mappings是这样定义的,

代码
  1. <!ELEMENT global-exception-mappings (exception-mapping+)>   
<script type="text/javascript">render_code();</script>
也就是说如果要使用,就至少包含一个异常映射.

 

exception-mapping的定义如下:

代码
  1. <!ELEMENT exception-mapping (#PCDATA|param)*>   
  2. <!ATTLIST exception-mapping   
  3.     name CDATA #IMPLIED   
  4.     exception CDATA #REQUIRED   
  5.     result CDATA #REQUIRED   
  6. >   
<script type="text/javascript">render_code();</script>
可以看到有3个属性:名称,异常类型,和结果.

 

经过一番查看,发现xwork-default.xml中还没有定义相关的拦截器,搜索了一下,发现了ExceptionMappingInterceptor,看来它是把异常翻译为相应的结果的.
(在最后发行版本中,应该会定义的.目前只好我们自己定义了.)

首先我们虚拟一个程序,假设程序会抛出几种程序,例如Action定义如下:

代码
  1. package com.jscud.ww2test.exceptionmap;   
  2.   
  3. import com.opensymphony.xwork.ActionSupport;   
  4.   
  5. /**  
  6.  * @author scud http://www.jscud.com  
  7.  *  
  8.  */  
  9. public class ExpMappingAction extends ActionSupport   
  10. {   
  11.     private int type;   
  12.   
  13.     public String execute() throws NoRightException,NotFoundException   
  14.     {   
  15.         if(type==1)   
  16.         {   
  17.             throw new NoRightException();   
  18.         }   
  19.         else if(type ==99)   
  20.         {   
  21.             throw new NotFoundException();   
  22.         }   
  23.         else if(type==60//其他异常   
  24.         {   
  25.             throw new IllegalArgumentException();    
  26.         }   
  27.            
  28.         return SUCCESS;   
  29.     }   
  30.        
  31.     public int getType()   
  32.     {   
  33.         return type;   
  34.     }   
  35.        
  36.     public void setType(int type)   
  37.     {   
  38.         this.type = type;   
  39.     }   
  40. }   
<script type="text/javascript">render_code();</script>
从Action可以看出,程序至少会抛出3种异常,我们如果使用异常映射,就要考虑到抛出的所有异常.

 

程序中用到的NoRightException,NotFoundException是为了演示而建立的2个简单异常,无任何特殊代码,继承自Exception.

我们的xwork.xml中的定义如下:

代码
  1. <package name="exceptionmapping" extends="webwork-default" namespace="/exceptionmap">  
  2.   
  3.     <interceptors>  
  4.         <interceptor name="exceptionmapping" class="com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"/>  
  5.            
  6.         <interceptor-stack name="myDefaultStack">  
  7.             <interceptor-ref name="defaultStack"/>  
  8.             <interceptor-ref name="exceptionmapping"/>  
  9.         </interceptor-stack>  
  10.     </interceptors>  
  11.   
  12.     <default-interceptor-ref name="myDefaultStack"/>  
  13.   
  14.     <global-results>  
  15.         <result name="noright" type="dispatcher">  
  16.             <param name="location">/exceptionmap/noright.jsp</param>  
  17.         </result>  
  18.         <result name="exception" type="dispatcher">  
  19.             <param name="location">/exceptionmap/exception.jsp</param>  
  20.         </result>  
  21.     </global-results>  
  22.   
  23.     <global-exception-mappings>  
  24.         <exception-mapping name="noright" exception="com.jscud.ww2test.exceptionmap.NoRightException" result="noright"/>  
  25.         <exception-mapping name="exception" exception="java.lang.Exception" result="exception"/>  
  26.     </global-exception-mappings>  
  27.   
  28.     <action name="index" class="com.jscud.ww2test.exceptionmap.ExpMappingAction">  
  29.         <exception-mapping  name="notfound" exception="com.jscud.ww2test.exceptionmap.NotFoundException" result="notfound"/>  
  30.         <result name="success" type="dispatcher">  
  31.             <param name="location">/exceptionmap/index.jsp</param>  
  32.         </result>  
  33.         <result name="notfound" type="dispatcher">  
  34.             <param name="location">/exceptionmap/notfound.jsp</param>  
  35.         </result>  
  36.     </action>  
  37.        
  38. </package>  
<script type="text/javascript">render_code();</script>
首先定义了一个exceptionmapping拦截器,用来指向ExceptionMappingInterceptor.
然后定义一个拦截器Stack,包含defaultStack和exceptionmapping,注意,exceptionmapping是在Stack的最后面,否则会发生不可预期的结果.

 

可以看到global-exception-mappings段包含了2个异常映射,一个为NoRight的处理,另外一个为对应java.lang.Exception的映射.

在Action的定义中包含了一个exception-mapping,对应NotFound异常.

没有看到IllegalArgumentException的对应结果?? 拦截器对没有定义的异常会依次找这个异常的父类,一级一级向上查找,例如IllegalArgumentException的最终父节点是Exception,就会转向到Exception对应的结果. 如果一个异常有多个层次关系上的父类,那个关系最近就找谁.

演示页面如下:

代码
  1. <%@ page contentType="text/html; CHARSET=utf8" %>  
  2. <%@ taglib uri="webwork" prefix="ww" %>  
  3. <html>  
  4.   <head>  
  5.     <title>exception mapping</title>  
  6.   </head>  
  7. <body>  
  8.   
  9. <br>  
  10. Exception 1:   
  11. <a href="index.jspa?type=1">Exception 1</a>  
  12. <br><br>  
  13.   
  14. Exception 99:   
  15. <a href="index.jspa?type=99">Exception 99</a>  
  16. <br><br>  
  17.   
  18. Other Exception:   
  19.   
  20. <a href="index.jspa?type=60">Exception 60</a>  
  21. <br><br>  
  22.   
  23. Normal:   
  24. <a href="index.jspa">No Exception</a>  
  25. <br><br>  
  26.   
  27. </body>  
  28. </html>  
<script type="text/javascript">render_code();</script>
notfound.jsp,exception.jsp,noright.jsp是三个最简单的jsp页面,自己编写即可.

 

运行程序,发现根据异常类型会转向相应的异常页面.

如果你自己的程序中的异常没有在异常映射中得到对应的result,会抛出异常,所以应该定义一个底层Exception的映射.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值