锁定老帖子 主题:WebWork2.2新特性 系列
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-08-30
CC许可:署名,非商业 (其他用途请联系我) 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中,可以通过 <ww:i18n name="message"> <ww:text name="name"/> </ww:i18n> 来实现简单页面的国际化. 无法在freemarker的简单页面中直接使用. (可以在action的结果页面中使用) 4.WebWork 2.2 Beta (在最后发布的版本中,可能会有变化!!!) 在简单页面Jsp中,可以直接使用ww:text,例如 <ww:text name="name"/> (注意:在webwork.properties中需要包含资源文件 webwork.custom.i18n.resources=message ,如果有多个,就用逗号分割) 在FreeMarker的简单文件中,也可以直接使用ww:text. <@ww.text name="name"/> 当前是在web.xml里面配置了FreeMarker的处理引擎.如: <servlet> <servlet-name>freemarker</servlet-name> <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class> <load-on-startup>10</load-on-startup> </servlet> <servlet-mapping> <servlet-name>freemarker</servlet-name> <url-pattern>*.ftl</url-pattern> </servlet-mapping> 警告:如果你不使用FreeMarker的简单页面,不需要配置这个Servlet,即使使用freemarker的ftl页面来做action的结果页面,也不需要配置这个Servlet,使用webwork的freemarker结果即可,具体请浏览webwork的Result Type的文档. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2005-08-31
其实这个I18nInterceptor很简单,而且实际应用中根据实际需求需要进行变通,所以这个I18nInterceptor并不是很实用,当然还是提供了一定的参考作用的.
首先我们来看一下如何使用这个拦截器. 首先我们需要有一个Action,为了演示,其实最简单的Action就可以,例如 public class I18nIcAction extends ActionSupport { public String execute(); { return SUCCESS; } } 展示的页面例子如下: <%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="webwork" prefix="ww" %> <html> <head> <title>Test I18n Interceptor</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> Choose: <a href="?locale=en">English Page</a> , <a href="?locale=zh_CN">Chinese Page</a> <br><br> Content:<ww:text name="desc"/> </body> </html> 其中我们使用"locale"作为locale的参数名,页面里面有2个选项:英文和中文. 对应的资源文件有2个(或者3个,如果包括缺省一个的话): 英文的I18nIcAction_en.properties内容为: desc=english 中文的I18nIcAction_zh_CN.properties内容为: desc=\u7b80\u4f53\u4e2d\u6587 接下来我们在xwork.xml里面定义我们的action和拦截器: <package name="i18nic" extends="webwork-default" namespace="/i18nic"> <interceptors> <interceptor name="i18n" class="com.opensymphony.xwork.interceptor.I18nInterceptor"> <param name="parameterName">locale</param> <param name="attributeName">ww_locale</param> </interceptor> <interceptor-stack name="i18nStack"> <interceptor-ref name="i18n"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="i18nStack"/> <action name="index" class="com.jscud.ww2test.i18nic.I18nIcAction"> <result name="success" type="dispatcher"> <param name="location">/i18nic/index.jsp</param> </result> </action> </package> 所有的工作都好了,发布并运行访问 /i18nic/index.action,一切和预想的一样. 通过查看I18nInterceptor的源码,我们可以看到这个拦截器的工作原理是这样的: 1.如果参数中指定了locale,那么拦截器分析参数,并把locale保存到session中. 2.在后面的action中,拦截器从session中获取这个locale,并设置action的locale,从而保持用户的设置. 3.在后续页面还可以继续切换locale. 从源码分析结果来看,这样做也会有一些实际的问题: 1.session过期后,用户不知道发生了什么,系统使用缺省的locale. 2.只能影响通过action操作的页面 在实际使用中,我们也要考虑如何解决后面2个问题,例如通过cookie,或者把用户的配置保存在数据库里等,这些实现就要结合实际代码进行实现了,完全可以不需要这个I18nInterceptor就可以实现,当然也很简单. 各取所需,看自己的实际需要吧 |
|
返回顶楼 | |
发表时间:2005-08-31
本文介绍了在WebWork2.2中如何使用客户端校验
WebWork2.2中去掉了原来的JavaScript支持,使用AJAX和DWR进行客户端校验. DWR最新版本为1.0,Webwork里面带的是0.6的版本. 如果使用客户端校验,首先在Web.xml里配置DWR: <servlet> <servlet-name>dwr</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> validators.xml的写法和原来一样,不过就是不能用原来的JavaScript的校验了 <validators> <validator name="required" class="com.opensymphony.xwork.validator.validators.RequiredFieldValidator"/> <validator name="requiredstring" class="com.opensymphony.xwork.validator.validators.RequiredStringValidator"/> <validator name="stringlength" class="com.opensymphony.xwork.validator.validators.StringLengthFieldValidator"/> </validators> 对action的校验规则写法也是和原来一样,例如增加新闻的校验如下: <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd"> <validators> <field name="news.title"> <field-validator type="requiredstring"> <message>请输入标题</message> </field-validator> </field> <field name="news.content"> <field-validator type="requiredstring"> <message>请输入内容</message> </field-validator> </field> </validators> 在页面的Form标签中写上validate="true" (注意使用的是alt syntax语法)表示需要进行客户端校验, 如果不写validate="true"则不需要进行客户端校验,仅进行服务器端校验,这就和DWR无关了,和以前的客户端校验一样. <ww:form action="doAddNews" method="post" name="doAddNews" validate="true"> 还需要在WEB-INF下面增加一个dwr.xml配置DWR,如果使用webwork自带的dwr,格式如下 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 0.4//EN" "http://www.getahead.ltd.uk/dwr/dwr.dtd"> <dwr> <allow> <create creator="new" javascript="validator" class="com.opensymphony.webwork.validators.DWRValidator"/> <convert converter="bean" match="com.opensymphony.xwork.ValidationAwareSupport"/> </allow> </dwr> 如果使用DWR 1.0(用新的版本不知道有没有问题),格式如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd"> <dwr> <allow> <create creator="new" javascript="validator" > <param name="class" value="com.opensymphony.webwork.validators.DWRValidator" /> </create> <convert converter="bean" match="com.opensymphony.xwork.ValidationAwareSupport"/> </allow> </dwr> (注:一定要使用匹配dwr和dwr.xml,否则会报错) 通过查看页面Html源码,我们可以看到页面中包含了/webwork和/dwr的路径,这些路径由Webwork和DWR自动生成文件返回,避免了在每个项目中复制重复的文件. <script src="/ww22test/webwork/validationClient.js"></script> <script src="/ww22test/dwr/interface/validator.js"></script> <script src="/ww22test/dwr/engine.js"></script> <script src="/ww22test/webwork/template/xhtml/validation.js"></script> 其中字段使用onblue来进行调用校验: <input type="text" name="news.title" value="" id="doAddNews_news.title" onblur="validate(this);;"/> 至此,Webwork的客户端校验可以运行了. (实际操作中,DWR的校验可能还会有些问题,等待开发人员来进行修正了) Bug说明:目前发现当表单元素的名字没有.的时候(例如是"name"),DWR校验器工作正常,而如果类似上面的表单元素名字类似news.title,校验器工作不正常. 不知道是DWR的问题还是WebWork的问题,webwork开发人员已经确认是个bug. |
|
返回顶楼 | |
发表时间:2005-08-31
1.ServletDispatcher 被FilterDispatcher替代
ServletDispatcher被标记为deprecated. (FreemarkerServlet和WebWorkVelocityServlet也被标记为deprecated) 新的Web.xml部分配置如下: <filter> <filter-name>webwork</filter-name> <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>webwork</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>com.opensymphony.webwork.lifecycle.LifecycleListener</listener-class> </listener> <servlet> <servlet-name>JspSupportServlet</servlet-name> <servlet-class>com.opensymphony.webwork.views.JspSupportServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> 其中filter代替了过去的ServletDispatcher,也增加了不少功能. 其中的LifecycleListener部分是为了使用XWork的IOC功能而设置的监听器,如果不使用,应该是可以去掉的. 其中的JspSupportServlet是为了支持在Freemarker和Velocity中进行的一些设置,如果去掉这个,一些功能就不能在ftl文件里面使用了,例如webwork的tag支持. 如果想单独使用Freemarker的文件(不通过action),还可以在web.xml配置FreeMarkerServlet,类似 <servlet> <servlet-name>freemarker</servlet-name> <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class> <load-on-startup>10</load-on-startup> </servlet> <servlet-mapping> <servlet-name>freemarker</servlet-name> <url-pattern>*.ftl</url-pattern> </servlet-mapping> 注意:如果仅使用ftl文件作为action的结果页面,使用freemarker结果类型即可,不需要配置FreeMarkerServlet. 如果想使用DWR进行客户端校验,还需要配置: <servlet> <servlet-name>dwr</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> DWR还有一些参数配置,可以根据实际修改. 使用FilterDispatcher还有一些其他影响,具体可以参考Webwork的文档 不能使用jsp:include,ww:include了,可以使用action chaining 或者ww:action标签代替. Velocity中的JSP tag仿真不能用了,仅支持原生的Velocity tag了 当然如果你需要以上的功能,还是依然可以使用ServletDispatcher来配置的,不过这是不推荐的了. 2.默认使用alt syntax语法,当然可以配置 如果用新的方法的话字符串不需要加单引号了,不过要引用变量就要用%{名字}的方式了. 例如原来这样写的语句: Message:<ww:text name="key"/> <br><br> Message:<ww:text name="’name’"/> 开启alt syntax后就要这样写: Message:<ww:text name="%{key}"/> <br><br> Message:<ww:text name="name"/> 根据自己的习惯决定吧.我觉得alt syntax直观,不过有点麻烦,呵呵. 更详细的alt syntax的文档,就要期待webwork team的文档了 |
|
返回顶楼 | |
发表时间:2005-08-31
关于FilterDispatcher,我看了看源代码,补充一点说明:
<filter> <filter-name>webwork</filter-name> <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>webwork</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 注意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 |
|
返回顶楼 | |
发表时间:2005-08-31
引用 指定action的扩展名则挪到了webwork.properties里面: 引用: webwork.action.extension=action 以前也是可以改的,也是在这个属性改,当然如果这里改了,映射那里也要改成对应的才行 JspSupportServlet在FreemarkerManager.java里面用到了,是有用的,如果没有这个,可能无法在ftl里面使用jsp tag和其他一些东西了 我修改了一下上面的文章,增加了说明 |
|
返回顶楼 | |
发表时间:2005-09-01
com/opensymphony/webwork/default.properties是webwork的重要文件,它对webwork的参数进行了配置,其中包含了webwork支持的所有配置,如果你想覆盖其中的配置,只需要建立一个webwork.properties放在你的项目中(一般放在源码目录下,发布时的位置是WEB-INF/classes下).
让我们来看看在webwork 2.2中这个文件发生了什么变化. 1.可以配置webwork.objectFactory # if specified, the default object factory can be overridden here #webwork.objectFactory = com.opensymphony.xwork.spring.SpringObjectFactory 这个ObjectFactory是一个很多地方都用到的类,默认webwork使用的是com.opensymphony.xwork.ObjectFactory,如果你想自己实现一个或者使用Spring的机制,可以配置这个属性.不过在没有更详细的文档出来之前,一定要小心使用. SpringObjectFactory类中主要覆写了ObjectFactory的buildBean,并没有替换其他函数. 2.webwork.mapper.class # extension for actions webwork.mapper.class=com.opensymphony.webwork.dispatcher.mapper.DefaultActionMapper webwork.action.extension=action 可以看到,增加了一行webwork.mapper.class. DefaultActionMapper以及同目录下RestfulActionMapper相当于以前的普通action url路径处理和CoolUriServletDispatcher映射方式处理,在webwork2.2中,如果想使用CoolUriServletDispatcher的方式,在此处修改这个属性为RestfulActionMapper即可. 当然,你可以实现自己的ActionMapper,实现自己的想法,很多人都喜欢自己来处理url,那就自己写一个,不错的想法. 3.webwork.tag.altSyntax=true altSyntax语法默认为打开了,参考前面的文章 4.webwork.i18n.reload # when set to true, resource bundles will be reloaded on _every_ request. # this is good during development, but should never be used in production webwork.i18n.reload=false 如果设置为true,每次资源文件都会被重载,方便调试.发布后一定要记得改为false. 5.webwork.ui.templateSuffix #sets the default template type. Either ftl, vm, or jsp webwork.ui.templateSuffix=ftl Tag模板的默认配置为freemarker的ftl了,以前是vm的. 6.webwork.dispatcher.parametersWorkaround # workaround for some app servers that don't handle HttpServletRequest.getParameterMap(); # often used for WebLogic, Orion, and OC4J webwork.dispatcher.parametersWorkaround = false 这个是为了处理一些web server的非常规的运作行为的,具体我就没试过了. 注意:最后发布的版本可能还会有一些变化,以最后发布的版本为准. |
|
返回顶楼 | |
发表时间:2005-09-01
刚才更新了一下webwork的cvs源代码,发现增加了一个iBATIS的子目录,即支持在webwork的IoC容器里面使用iBATIS了。不过一般来说我们更加倾向于使用Spring。
|
|
返回顶楼 | |
发表时间:2005-09-01
刚刚才更新了hibernate,ibatis
还增加了sitemesh对freemarker的一个filter,不过我还没有看 引用 Log: - complete hibernate support - added ibatis support - added sitemesh support for FM and Velocity webwork的论坛上会同步反应cvs的更新,所以我就看论坛的帖子就能看到更新了什么 用的是jive论坛,对开发的支持很方便啊 |
|
返回顶楼 | |
发表时间:2005-09-02
ParameterNameAware 是XWork中新增的一个接口,是由Bob Lee (crazybob@google.com)提供的,主要的用途是限制Action仅接收一定规则的参数,用来防止无意义的参数或者破坏?不过我想我暂时用不到这个接口,不过还是介绍一下如何使用吧.
首先我们写一个Action,实现ParameterNameAware接口,这个接口只有一个方法,就是public boolean acceptableParameterName(String name). 我们的Action如下: package com.jscud.ww2test.parametername; import com.opensymphony.xwork.ActionSupport; import com.opensymphony.xwork.interceptor.ParameterNameAware; /** * @author scud http://www.jscud.com */ public class ParameterNameTestAction extends ActionSupport implements ParameterNameAware { private String name1; private String name2; private String name3; public String execute(); { return SUCCESS; } /** * 当前参数名是否允许. * @param name 参数名 * @return 是否允许 */ public boolean acceptableParameterName(String name); { if (name.equals("name1"); || name.equals("name2");); { return true; } return false; } public String getName1(); { return name1; } public void setName1(String name1); { this.name1 = name1; } public String getName2(); { return name2; } public void setName2(String name2); { this.name2 = name2; } public String getName3(); { return name3; } public void setName3(String name3); { this.name3 = name3; } } 可以看到,这个Action实现了ParameterNameAware接口,并且设置只接收"name1"和"name2"两个参数,而我们在action有三个用来保存用户输入值的对象:name1,name2和name3. 我们的action定义如下: <package name="parameternametest" extends="webwork-default" namespace="/parametername"> <action name="index" class="com.jscud.ww2test.parametername.ParameterNameTestAction"> <result name="success" type="dispatcher"> <param name="location">/parametername/index.jsp</param> </result> </action> </package> 不需要定义任何额外的拦截器,这个接口是在ParametersInterceptor里检测的. 目标页面如下: <%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="webwork" prefix="ww" %> <html> <head> <title>Test ParamaterName</title> </head> <body> <ww:form name="test" action="index" method="post" namespace="/parametername" > <ww:textfield name="name1" label="Name1" /><br> <ww:textfield name="name2" label="Name2" /><br> <ww:textfield name="name3" label="Name3" /><br> <ww:submit value="Submit" /> </ww:form> <br/> Show Message: <br/> Name1 is:<ww:property value="name1" /><br/> Name2 is:<ww:property value="name2" /><br/> Name3 is:<ww:property value="name3" /><br/> </body> </html> 运行程序,我们可以发现,name3的值没有得到设置,我们在页面中也自然得不到name3的值了. |
|
返回顶楼 | |