This page last changed on Dec 14, 2004 by casey.

综述

在WebWork中, UI标签包装了常用的HTML控件以便与核心框架紧密集成. 这些标签设计为最小化逻辑代码并将最终HTML绘制工作转交给模版系统. 模版可以组织起来分成不同的主题. UI标签试图覆盖最常见的情景, 还提供了component标签用以创建定制组件. UI标签内部支持显示错误信息.

模版

WebWork使用Velocity模版系统为所有UI标签(jsp和velocity)绘制最终的HTML输出. 全部模版的缺省实现包含在核心发布包中允许用户直接使用WebWork的UI标签. 模版可以单独编辑也可以全部替换, 这允许定制全部HTML输出结果. 另外, 缺省模版可以在很精细的控制级别下对每个标签进行覆盖.

模版存放在发行包webwork-x.x.jar的src/java目录下的template目录中. 要使用定制模版, 可以将template目录复制到应用的根目录或类路径中. Webwork首先从上述两个地方加载模版. 否则, 将从webwork.jar中加载.
/myApp
      /META-INF
      /WEB-INF
      /template

template目录中, 可以找到两个称作主题的模版集合(xhtml和simple). UI标签缺省使用的模版是'xhtml', 除非在UI标签中指定theme属性或在webwork.properties中指定webwork.ui.theme. 你可以修改已有模版或创建自己的模版.

类AbstractUI是其他UI标签的基类. 它提供一组UI组件常用的属性. 类AbstractUI定义了一个抽象方法:
protected abstract String getTemplateName();

类AbstractUI将加载子类指定的或用户使用template属性指定的模版. 下列代码中textfield标签将使用myOwnTextTemplate.vm而不是内建模版text.vm

注意: 你必须创建一个模版文件myOwnTextTemplate.vm并把它保存在xhtml目录中.
<!-- loads /template/xhtml/myOwnTextTemplate.vm -->

<ww:ui textfield label="'mylabel'" name="'myname'" template="'myOwnTextTemplate.vm'" />

否则
<!-- loads default /template/xhtml/text.vm -->
<ww:ui textfield label="'mylabel'" name="'myname'" />

内建模版

每个UI标签的缺省模版如下:
UI标签 缺省模版
checkboxList checkboxlist.vm
checkbox checbox.vm
combobox combobox.vm
component empty.vm
doubleSelect doubleselect.vm
file file.vm
form form.vm(to open)
form-close.vm(to close)
hidden hidden.vm
label label.vm
password password.vm
radio radiomap.vm
select select.vm
submit submit.vm
tabbedpane tabbedpane.vm
textarea textarea.vm
textfield text.vm
token token.vm

访问变量

WebWork使用下列上下文变量创建VelocityContext对象用于全部velocity视图:

  • tag - 标签对象
  • stack - 当前的OgnlValueStack
  • ognl - 工具类OgnlTool
  • req - HttpServletRequest对象
  • res - HttpServletResponse对象
  • webwork - WebWorkUtil实例
  • action - 当前活动
  • parameters - 当前参数表

在模版中可以使用$TAG_NAME访问上述变量(TAG_NAME可以是tag, stack, ognl, req中的一个). 模版文件随后介绍. 一些例子:
注意: 感叹号(!)将输出定义的值, 否则输出""
$!req.requestURI
$!req.method

$!tag.templateDir
$!tag.theme

$!parameters.name
$!parameters

理解Webwork模版系统

看看模版是如何被找到并加载的. AbstractUITag展示了使用字符串构建模版的方法:
protected String buildTemplateName(String myTemplate, String myDefaultTemplate) {
        ...
        return "/" + getTemplateDir() + "/" + getTheme() + "/" + template;
}

缺省情况下textfield标签的返回值为
/template/xhtml/text.vm

Webwork将在使用缺省值之前尝试查找该值. 如果你愿意, 你可以不修改任何值就可以修改内建模版(请自行选择). Webwork将使用下列顺序进行搜索:
  • getTemplateDir()
    • webwork.properties中的webwork.ui.templateDir
    • 否则, 返回"template"
  • getTheme()
    • UI标签的theme属性
    • webwork.properties中的webwork.ui.theme
    • 否则, 返回"xhtml"
  • template
    • UI标签的template属性
    • 否则, 使用缺省指定的模版

模版中使用CSS

缺省模版在输出HTML时使用了几个CSS属性. 这些属性在/template/xhtml目录中的styles.css样式单中. 你可以将该样式单作为你的应用的样板也可以在创建你自己的样式单, 但要记得在JSP或velocity页面中包含该样式单的链接.
styles.css:
.label {font-style:italic; }
.errorLabel {font-style:italic; color:red; }
.errorMessage {font-weight:bold; text-align: center; color:red; }
.checkboxLabel {}
.checkboxErrorLabel {color:red; }
.required {color:red;}
.requiredLabel {font-weight:bold; font-style:italic; }

在你的页面中使用LINK引用该文件(可以使用相对路径或绝对路径):
<link rel ="stylesheet" type="text/css" href="/webwork-example/template/xhtml/styles.css" title="Style">

注意: 现在Webwork在UI标签中增加了新的属性以便更全面的支持HTML的style和class, 可以更灵活的实现外观. 这些属性分别定义为cssStyle和cssClass.

<ui:textfield label="'lebal'" name="'nmae'" cssStyle="'float:left; color:red'" cssClass="'myclass'"   />

创建定制组件

对component标签的最初介绍并没有给人深刻的印象. 只能指定一个模版, 使用一些预先定义的属性看起来能力有限. 但该标签为开发者提供了许多好处.

在深入到定制组件之前, 首先明确使用component标签创建定制组件的几个优点. 然后将详细介绍WebWork 2中的两种错误信息以及定制组件如何(显示其中一种)适应. 最后, 将为我们的组件提供一个简单的活动类, jsp文件和模版文件. 结束时, 你将能够把新组件应用到你的应用中.

为什么使用component标签?

  • 不需要开发你自己的标签库
  • 集成对值栈的访问
  • 利用XWork的国际化, 本地化和错误处理能力
  • 使用模版(可编辑文本文件)而不是编译代码可以更快的建立原型
  • 复用并组合已有模版

对错误消息的支持:

在WebWork 2中, 有两类错误消息: 字段错误消息和活动错误消息. 字段错误消息代表某一控件的问题并显示在控件中. 许多标签支持显示这种消息. 另一方面活动错误消息代表活动执行的问题. 在Web应用中很多事物会导致错误, 尤其是在依赖于外部资源的应用中如数据库, 远程Web服务, 或其他在活动执行期间可能不可用的资源. 能否优雅的处理错误并向用户提供有用的消息通常是用户体验好与坏的区别.

当这种错误发生时, 把消息从表单控件中分离出来单独显示更为合适. 下例中, 我们将创建一个可以用列表现活动错误消息的定制组件. 该组件可以用于全部显示这类错误消息的表单中.

下面的活动将处理网站上的广告: 免费的电子证书. 它将尝试发送证书邮件, 但会抛出异常.

活动类:

package example;

import com.opensymphony.xwork.ActionSupport;

public class AddUser extends ActionSupport {

    private String fullname;
    private String email;

    public String execute() throws Exception {
        // we are ignoring field validation in this example

        try {
            MailUtil.sendCertificate(email, fullname);
        } catch (Exception ex) {
            // there was a problem sending the email
            // in a real application, we would also
            // log the exception
            addActionError("We are experiencing a technical problem and have contacted our support staff. " +
                           "Please try again later.");
        }

        if (hasErrors()) {
            return ERROR;
        } else {
            return SUCCESS;
        }
    }

    public String getFullname() {
        return fullname;
    }

    public void setFullname(String fullname) {
        this.fullname = fullname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

}

Jsp页面:

<%@ taglib uri="webwork" prefix="ui" %>

<html>
<head><title>custom component example</title></head>

<!-- don't forget this -->
<link rel ="stylesheet" type="text/css" href="/webwork-example/template/xhtml/styles.css" title="Style">

<body>

<ui:form action="AddUser.action" method="POST">
<table>
    <ui:component template="action-errors.vm" />
    <ui:textfield label="Full Name" name="fullname" />
    <ui:textfield label="Email" name="email" />
    <ui:submit name="submit" value="Send me a free E-Certificate!" />
</table>
</ui:form>

</body>
</html>

HTML输出(提交前):

<html>
<head><title>custom component example</title></head>
<link rel ="stylesheet" type="text/css" href="/webwork-example/template/xhtml/styles.css" title="Style">

<body>

<form  action="AddUser.action" method="POST" />

<table>
    

    <tr>
  <td align="right" valign="top"><span class="label">Full Name:</span></td>
  <td>
<input type="text" name="fullname" value="" />
  </td>
</tr>
    <tr>
  <td align="right" valign="top"><span class="label">Email:</span></td>
  <td>
<input type="text" name="email" value="" />
  </td>
</tr>
    
<tr>
  <td colspan="2">
    <div align="right">
      <input type="submit" name="submit" value="Send me a free E-Certificate!"/>
    </div>
  </td>
</tr>


</table>
</form>

</body>
</html>

下面的模版将循环全部活动错误并显示在列表中.

模版(action-errors.vm)
#set ($actionErrors = $stack.findValue("actionErrors"))

#if ($actionErrors)
<tr>
    <td colspan="2">
        <span class="errorMessage">The following errors occurred:</span>
        <ul>
            #foreach ($actionError in $actionErrors)
            <li><span class="errorMessage">$actionError</span></li>
            #end
        </ul>
    </td>
</tr>
#end

HTML输出(提交之后):

<html>
<head><title>custom component example</title></head>
<link rel ="stylesheet" type="text/css" href="/webwork-example/template/xhtml/styles.css" title="Style">

<body>

<form  action="AddUser.action" method="POST" />

<table>
    
<tr>
    <td colspan="2">
        <span class="errorMessage">The following errors occurred:</span>
        <ul>
            <li class="errorMessage">
                We are experiencing a technical problem and have contacted our 
                support staff. Please try again later.
            </li>
        </ul>
    </td>
</tr>

    <tr>
  <td align="right" valign="top"><span class="label">Full Name:</span></td>
  <td>
<input type="text" name="fullname" value="Sample User" />
  </td>
</tr>
    <tr>
  <td align="right" valign="top"><span class="label">Email:</span></td>
  <td>
<input type="text" name="email" value="user@example.com" />
  </td>
</tr>
    
<tr>
  <td colspan="2">
    <div align="right">
      <input type="submit" name="submit" value="Send me a free E-Certificate!"/>
    </div>
  </td>
</tr>


</table>
</form>

</body>
</html>

Document generated by Confluence on Dec 14, 2004 16:36