解惑

解己之惑,解人之惑

分类:ZK

GAE+ ZK没有那么成熟

开始的感觉都还不错,把原来为公司做POC的一个项目拷贝过来修改修改就可以跑了,在本地基本可以用,但是有些问题:

  • 添加修改数据的窗口不能用Modal窗口,错误消息是:Event processing thread is disabled(这个是因为ZK+GAE本来就需要把事件线程disable掉,因为GAE里面不能开线程)
  • 把Modal窗口修改成Popup窗口,本地是好的,但是上传到GWT没有反应也没有报错。

经验也会帮倒忙

本来打算那个Notes-all用Google的全套解决方案的,就是用GWT + Google App Engine,看了下GWT的Sample,发现还是比较麻烦,但是感觉思路和ZK还是很像的,就打算比较下GWT和ZK,结果发现有人说可以把ZK成功发布到Google App Engine,试了下,果然是可以的,有兴趣的可以试试(在ZK网站可以下载zk-gae的sample,基于这个很容易建立自己的工程)。
基于我玩过一段时间的ZK,当然用ZK更方便了。
今天把原来的东西复制过去了,在做国际化的时候,用Eclipse编辑properties文件,里面有中文,不能保存,只能保存ISO-8859-1编码的内容。后来想着应该装个插件,下载了,好使,但是运行起来发现并没有把转码的内容显示为正确的中文,很奇怪。后来怀疑ZK读取properties文件的时候和Java读取国际化文件不一样,把properties文件的编码修改为UTF-8,然后直接用文本编辑器输入中文内容,运行测试,正常!
这个就是一般的国际化处理的经验造成的问题。
最后说一下,对ZK的这个违反Java惯例的方式赞一下,因为我一直对Java的这个需要把properties国际化文件用native2ascii转换的过程很鄙视,不知道谁这么设计的。ZK是以UTF-8读取properties文件的,不做任何转换。

更新:
可以修改Eclipse,让它对properties文件不强制使用ISO-8859-1编码保存:
eclipse –> window –> Preferences –> General –> Content Types –> Text –> 单击 Java Properties File,把底部的Default edcodng从ISO-8859-1改成utf-8,然后update。

ZK国际化的原型

昨天说了ZK的国际化做得不够好,今天稍微试了下,发现昨天提到的方案是可行的,创建一个Initiator,自动的把文本替换为国际化的内容:
<?init class="xxx.I18nBinderInit"?>
<toolbarbutton label="button.add" image="../images/add.png" onClick="userListWindow.onAdd()"/>

这个只是原型,现在可能还不能处理所有的组件类型,可以简单的修改下变成通用的解决方案:
增加一个Property文件,里面添加需要处理的组件类型以及需要处理的属性,然后读取这个配置,如果谁觉得不够可以在classpath中放置一个同名的配置文件进行定制。
源代码:

阅读全文

zk的国际化不够好

官方文档中说国际化很简单,资源文件放在WEB-INF下,文件名固定,都是i3-label.properties,简体中文的就是i3-label_zh_CN.properties。
按照官方文档说的,修改Locale就是:
session.setAttribute(Attributes.PREFERRED_LOCALE,xxxLocale)
但是根本不好使,后来搜索了下,发现需要设置:
Locales.setThreadLocal(xxxLocale)

另外一个问题是页面的刷新是个问题,如果不考虑用户已有的操作,假设用户进入首页没有做什么事情,首先改变Locale,那么刷新比较简单:
Executions.getCurrent().sendRedirect(“”)

国际化在页面中使用也比较丑陋,先是:
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>

<toolbarbutton label="${c:l(‘button.add’)}" image="../images/add.png" onClick="userListWindow.onAdd()"/>
比较理想的应该是像数据绑定一样,能够声明某个东西,然后Label的内容都从资源文件取:
<?init class="xxx.I18nBinderInit"?>
<toolbarbutton label="button.add" image="../images/add.png" onClick="userListWindow.onAdd()"/>

当然,这个功能可能自己也可以自己实现,有时间我会试试。

最后说的一点就是zk的默认中文是繁体中文,比较难受。

createComponents的问题

ZK很好的一个功能就是打开一个zul文件把组件添加到页面上:
Executions.createComponents(“yyy/xxx.zul”, null, params)
但是用这种方式打开的页面有一个奇怪的问题,和直接加载的不同,直接加载的的那些image是写相对路径的,例如:
<toolbarbutton label="Add" image="../images/add.png"/>
如果是用createComponents打开,这个方式不好使,找不到图片,显示一个红叉叉,需要修改成:
<toolbarbutton image="images/add.png"/>

服务器端的分页功能

ZK的分页功能默认是在客户端做的,也就是服务器端返回所有的结果,然后客户端每次显示一页的数据,翻页的时候不提交请求到服务器端重新查询。如果服务器端返回的结果比较多,这种方案就不太好了,要实现服务器端的分页也很简单,在使用Listbox或者grid的时候不要使用mold="paging",而是添加一个Paging组件:
<paging id="groupListboxPaging" pageSize="10"/>
然后给Paging增加事件监听:
        final Paging paging = getPaging(pagingName);
        paging.addEventListener(
            "onPaging", new EventListener()
        {
            public void onEvent(Event event)
            {
                PagingEvent pagingEvent = (PagingEvent) event;
                int pageNumber = pagingEvent.getActivePage();
                int firstRow = pageNumber * paging.getPageSize();
                queryInfos.get(listName).getPageInfo().setFirstRow(firstRow);
                refreshList(listName);
            }
        });
代码中的getPaging和refreshList都是我自定义的方法,getPaging很简单,因为我的这个代码是在自定义的Window类里面的,所以:
    protected Paging getPaging(String pagingName)
    {
        return (Paging) getFellow(pagingName);
    }
而refreshList就比较复杂一些了,根据传入的list的名字查询结果并刷新list:
    public void refreshList(String name)
    {
        try
        {
            getListbox(getListboxName(name)).setModel(new BindingListModelList(list(name), false));
        }
        catch (Throwable t)
        {
            handleException(t);
        }
    }
核心就是拿到Listbox或者Grid然后setModel。

© 2020 解惑

本主题由Anders Noren提供向上 ↑