This page last changed on Sep 16, 2004 by vitorsouza.

4.2: 在WebWork中使用Velocity

有两种方法可以利用Velocity作为视图.
  • 使用velocity结果类型绘制velocity模版;
  • web.xml文件中注册WebWorkVelocityServlet以便直接通过浏览器请求绘制Velocity模版.

为使用第二种方式, 必须修改web.xml文件加入WebWorkVelocityServlet的servlet定义及其映射, 如下:
<servlet> 
	<servlet-name>velocity</servlet-name> 
	<servlet-class>com.opensymphony.webwork.views.velocity.WebWorkVelocityServlet</servlet-class> 
	<load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
	<servlet-name>velocity</servlet-name> 
	<url-pattern>*.vm</url-pattern> 
</servlet-mapping>

进一步阅读: xwork.xml

使用velocity结果类型意味着Velocity模版仅能通过活动进行绘制, 换言之, 访问.vm页面将不会进行绘制而直接返回文本内容. 如果你选择这种方式, 推荐你将Velocity文件放在WEB-INF目录下使其不可访问.

使用WebWorkVelocityServlet意味着Velocity模版可以通过对.vm页面的请求进行绘制. 这也意味着需要对模版实现安全检查, 以便用户不能绕过活动(如果这是必需的)直接访问它.

不管你选择哪种方式(你也可以选择同时使用两种方式), 当你编写模版时不仅可以使用全部Velocity的特性, 还可以使用WebWork提供的其他功能. 这里假设你已经熟悉了Velocity, 因此我们仅关注WebWork提供的特性. 如果你不熟悉, 清在继续阅读之前参阅'开始Velocity之旅'.

主要特性是提供了对值栈中对象方便的访问途径, 这里包含了WebWork自动提供的一些内容, 因为你在某些地方会发现它的价值. 这是值栈中包含的部分对象:
  • 当前的HttpServletRequest;
  • 当前的HttpServletResponse;
  • 当前的OgnlValueStack;
  • 一个OgnlTool的实例;
  • 当前活动类的全部属性.

要访问值栈中的数据, 你只须使用适当的Velocity引用:
  • $req = HttpServletRequest;
  • $res = HttpServletResponse;
  • $stack = OgnlValueStack;
  • $ognl = OgnlTool;
  • $name-of-property = property of the current action class.

下面的例子完成了与第三课相同的功能, 但是现在使用Velocity模版做为结果. 需要注意的是<property value="person" />标签被替换成$person引用, 它返回同样的内容: 活动类的一个属性. 本例中我们使用了velocity结果类型方式.

xwork.xml:

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" 
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>
	<!-- Include webwork defaults (from WebWork JAR). -->
	<include file="webwork-default.xml" />
	
	<!-- Configuration for the default package. -->
	<package name="default" extends="webwork-default">
		<!-- Default interceptor stack. --> 
		<default-interceptor-ref name="defaultStack" /> 
		
		<!-- Action: Lesson 4.2: HelloAction using Velocity as result. -->
		<action name="helloVelocity" class="lesson03.HelloAction">
			<result name="error" type="dispatcher">ex01-index.jsp</result>
			<result name="success" type="velocity">ex01-success.vm</result>
		</action>
	</package>
</xwork>

HelloAction.java (与第三课相同):

package lesson03;

import com.opensymphony.xwork.ActionSupport;

public class HelloAction extends ActionSupport {
	String person;
	public String getPerson() {
		return person;
	}
	public void setPerson(String person) {
		this.person = person;
	}
	public String execute() throws Exception {
		if ((person == null) || (person.length() == 0)) return ERROR;
		else return SUCCESS;
	}
}

ex01-index.jsp (与第三课相同):

<html>
<head>
<title>WebWork Tutorial - Lesson 3 - Example 2</title>
</head>

<body>

<p>What's your name?</p>

<form action="hello.action" method="post">
<p><input type="text" name="person" /><input type="submit" /></p>
</form>

</body>
</html>

ex01-success.vm:

<html> 
<head> 
<title>WebWork Tutorial - Lesson 4.2 - Example 1</title> 
</head> 
<body> 

Hello, $person 

</body> 
</html>

试试这个例子!

在Velocity使用WebWork的UI标签:

如你所知, 从JSP转换到Velocity时失去了使用JSP标签的能力. 但WebWork的VelocityServlet提供一个方法: 使用#tag, #bodytag#paramVelocity宏定义(velocimacros). 语法如下:
#tag (name-of-tag list-of-attributes)

– 或 –

#bodytag (name-of-tag list-of-attributes)
	#param (key value)
	#param (key value)
...
#end

让我们回顾4.1.1的表单示例来演示在velocity中使用UI标签的用法:

xwork.xml:

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" 
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>
	<!-- Include webwork defaults (from WebWork JAR). -->
	<include file="webwork-default.xml" />
	
	<!-- Configuration for the default package. -->
	<package name="default" extends="webwork-default">
		<!-- Default interceptor stack. --> 
		<default-interceptor-ref name="defaultStack" /> 
		
		<!-- Actions: Lesson 4.2: FormProcessingAction using Velocity. --> 
		<action name="formProcessingVelocityIndex" class="lesson04_02.FormProcessingIndexAction">
			<result name="success" type="velocity">ex02-index.vm</result>
		</action>
		<action name="formProcessingVelocity" class="lesson04_01_01.FormProcessingAction"> 
			<result name="input" type="velocity">ex02-index.vm</result> 
			<result name="success" type="velocity">ex02-success.vm</result> 
			<interceptor-ref name="validationWorkflowStack" /> 
		</action> 
	</package>
</xwork>

ex02-index.vm:

<html> 
<head> 
<title>WebWork Tutorial - Lesson 4.2 - Example 2</title> 
<style type="text/css"> 
  .errorMessage { color: red; } 
</style>   
</head> 

<body> 

<p>UI Form Tags Example using Velocity:</p> 

#bodytag (Form "action='formProcessingVelocity.action'" "method='post'") 
	#tag (Checkbox "name='checkbox'" "label='A checkbox'" "fieldValue='checkbox_value'") 
	#tag (File "name='file'" "label='A file field'") 
	#tag (Hidden "name='hidden'" "value='hidden_value'") 
	#tag (Label "label='A label'") 
	#tag (Password "name='password'" "label='A password field'") 
	#tag (Radio "name='radio'" "label='Radio buttons'" "list={'One', 'Two', 'Three'}") 
	#tag (Select "name='select'" "label='A select list'" "list={'One', 'Two', 'Three'}" 
		"emptyOption=true") 
	#tag (Textarea "name='textarea'" "label='A text area'" "rows='3'" "cols='40'") 
	#tag (TextField "name='textfield'" "label='A text field'") 
	#tag (Submit "value='Send Form'") 
#end 

</body> 
</html>

ex02-success.vm:

<html> 
<head> 
<title>WebWork Tutorial Lesson 4.2 - Example 2</title> 
</head> 

<body> 

<p>UI Form Tags Example result using Velocity:</p> 

<ul> 
	<li>checkbox: $!checkbox</li> 
	<li>file: $!file</li> 
	<li>hidden: $!hidden</li> 
	<li>password: $!password</li> 
	<li>radio: $!radio</li> 
	<li>select: $!select</li> 
	<li>textarea: $!textarea</li> 
	<li>textfield: $!textfield</li> 
</ul> 

</body> 
</html>

FormProcessingAction.java (与4.1.1相同):

package lesson04_01_01;

import com.opensymphony.xwork.ActionSupport;

public class FormProcessingAction extends ActionSupport {
	private String checkbox;
	private String file;
	private String hidden;
	private String password;
	private String radio;
	private String select;
	private String textarea;
	private String textfield;
	
	public String getCheckbox() { return checkbox; }
	public String getFile() { return file; }
	public String getHidden() { return hidden; }
	public String getPassword() { return password; }
	public String getRadio() { return radio; }
	public String getSelect() { return select; }
	public String getTextarea() { return textarea; }
	public String getTextfield() { return textfield; }
	
	public void setCheckbox(String checkbox) { this.checkbox = checkbox; }
	public void setFile(String file) { this.file = file; }
	public void setHidden(String hidden) { this.hidden = hidden; }
	public void setPassword(String password) { this.password = password; }
	public void setRadio(String radio) { this.radio = radio; }
	public void setSelect(String select) { this.select = select; }
	public void setTextarea(String textarea) { this.textarea = textarea; }
	public void setTextfield(String textfield) { this.textfield = textfield; }
	
	public String execute() throws Exception {
		return SUCCESS;
	}
}

FormProcessingAction-validation.xml (与4.1.1相同):

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 
1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">

<validators>
  <field name="checkbox">
    <field-validator type="requiredstring">
      <message>Please, check the checkbox.</message>
    </field-validator>
  </field>

  <field name="file">
    <field-validator type="requiredstring">
      <message>Please select a file.</message>
    </field-validator>
  </field>

  <field name="password">
    <field-validator type="requiredstring">
      <message>Please type something in the password field.</message>
    </field-validator>
  </field>

  <field name="radio">
    <field-validator type="requiredstring">
      <message>Please select a radio button.</message>
    </field-validator>
  </field>

  <field name="select">
    <field-validator type="requiredstring">
      <message>Please select an option from the list.</message>
    </field-validator>
  </field>

  <field name="textarea">
    <field-validator type="requiredstring">
      <message>Please type something in the text area.</message>
    </field-validator>
  </field>

  <field name="textfield">
    <field-validator type="requiredstring">
      <message>Please type something in the text field.</message>
    </field-validator>
  </field>
</validators>

试试这个例子!

上面的例子没有使用#param标签. 因此, 让我们回顾4.1.1中的另一个例子 - 定制组件:

ex03.vm:

<html> 
<head> 
<title>WebWork Tutorial - Lesson 4.2 - Example 3</title> 
</head> 

<body> 

<p>Custom Component Example:</p> 

<p> 
#bodytag (Component "template=datefield.vm") 
	#param ("label" "Date") 
	#param ("name" "mydatefield") 
	#param ("size" "3") 
#end 
</p> 

</body> 
</html>

/template/xhtml/datefield.vm (与4.1.1相同):

#set ($name = $parameters.get('name')) 
#set ($size = $parameters.get('size')) 
#set ($yearSize = $size * 2) 

$parameters.get('label'): 
<input type="text" name="${name}.day" size="$size" /> / 
<input type="text" name="${name}.month" size="$size" /> / 
<input type="text" name="${name}.year" size="$yearSize" /> (dd/mm/yyyy)

注意, 这次我们没有像使用JSP标签那样将Datemydatefield用单引号框起来.

试试这个例子!


上一课 | 下一课
Document generated by Confluence on Dec 14, 2004 16:36