Struts2标签语法

本文翻译自struts2文档,增加了自己的测试部分

测试环境

浏览器是Firefox22.0

tomcat6

标签语法

创建动态输入域

struts2的标签用来显示动态数据。创建一个输入域显示属性值,我们将传递字符串"postalCode"到textfield标签。

<s:textfield name="postalCode"/>

如果在value stack中有一个属性"postalCode",那么它的值将被set到输入域。
当这个输入域提交到框架后,控件的值将被回填到"postalCode"属性中。

The tags are designed to display dynamic data. To create a input field that displays the property "postalCode", we'd pass the String "postalCode" to the textfield tag.

有事,我们希望动态的传递数据给标签。例如,我们希望用一个标签显示输入域的内容,同时我们希望从应用消息资源中获得标签的内容。根据此要求,框架将解释标签属性中的表达式,从而使我们可以在运行时动态的将数据插入到标签属性中。转义表达式就是"%{ ... }"。任何表达式中的文本都将被计算。

Sometimes, we want to pass the dynamic data to a tag. For example, we might want to display a label with the input field, and we might want to obtain the label from the application's messages resources. Accordingly, the framework will parse expressions found in the tag attributes, so that we can merge dynamic data into the tag attributes at runtime. The expression escape sequence is "%{ ... }". Any text embedded in the escape sequence is evalulated as an expression.

使用表达式设置标签值

表达式语言(OGNL)使得我们可以调用方法并计算属性的值。getText()方法由ActionSupport类提供,ActionSupport是大多数Action类的父类。只要Action在(值)栈里,我们就可以通过表达式调用它所有方法,包括getText()。

<s:textfield key="postalCode.label" name="postalCode"/>

The expression language (OGNL) lets us call methods and evaluate properties. The method getText is provided by ActionSupport, which is the base class for most Actions. Since the Action is on the stack, we can call any of its methods from an expression, including getText.

非字符型属性

HTTP协议是基于文本的,但一些标签中包含有非文本类的属性,例如bool或者int类型。为了非字符型属性可以直接使用,框架计算所有非字符型类型作为表达式。在这种情况下,你不需要使用转义标识即"%{ ... }"。 (但是,如果你坚持这么做,框架将会忽略这些内容)

例如jsp页面中输入

  <body>
    <h3>Ognl Test</h3>
    <s:property value="%{50}"/><!-- 这一项中的50是作为字符类型的吗答案是否定的看下面 -->
    </br>
    <s:property value="%{1*2}"/>
    </br>
    <s:property value="50"/><!-- 这一项中的50经过计算吗答案是肯定的而且是被认为整型看下面 -->
    </br>
    <s:property value="1*2"/>
    <br>
    <s:property value="%{true}"/><!-- 这一项中的表达式认为"true"是一个字符串而不是bool类型 -->
    </br>
    <s:if test="%{true}"><!-- 在这里"true"被认为是bool类型进行判断 -->
    test result is true
    </s:if>
    </br>
    <s:if test="true"><!-- 这样也是正确的 -->
    test result is true
    </s:if>
  </body>

得到的结果是

50
2
50
2
true
test result is true
test result is true

The HTTP protocol is text-based, but some tags have non-String attribute types, like bool or int. To make using non-String attributes intuitative, the framework evaulates all non-String attributes as an expression. In this case, you do not need to use the escape notation. (But, if you do anyway , the framework will just strip it off.)

下面的标签中,由于属性multiple 映射到一个bool属性,框架不会把这个值作为字符串使用,这里的值会被作为表达式进行计算并自动转换为一个bool类型。

<s:select key="state.label" name="state" multiple="true"/>

Since the attribute multiple maps to a boolean property, the framework does not interpret the value as a String. The value is evaluated as an expression and automtically converted to a boolean.

由于很容易忘记那些属性时字符型或者非字符型,因此你仍可以使用转义标识,以下两种方式都是正确的。

<s:select key="state.label" name="state" multiple="true"/>
<s:select key="state.label" name="state" multiple="%{true}"/>

而下面的内容则是通过属性来计算表达式的bool值,两种方式都正确

<s:select key="state.label" name="state" multiple="allowMultiple"/>
<s:select key="state.label" name="state" multiple="%{allowMultiple}"/>

Since it's easy to forget which attributes are String and which are non-String, you can still use the escape notation.

值是对象(Value is Object)

在大多数情况下,标签的name属性告诉框架应当填充哪一个属性的值,因此标签的value这个属性是自动填充的。但是,如果需要对value直接设置值,那么请注意value是一个对象而非字符串

因为value不是字符串,无论什么值传递给value都被作为表达式进行计算-而不是字符串的字面值。

下面的例子中,数字都是被作为对象计算后才进行展示的。

<s:property value="%{1*2}"/>

<s:property value="50"/>

 

Most often, the value attribute is set automatically, since name attribute usually tells the framework which property to call to set the value. But, if there is a reason to set the value directly, be advised that value is an Object NOT a String.

Since value is not a String, whatever is passed to value is evaluated as an expression - NOT a String literal.

如果一个文本域标签的value属性输入一个值"ca",那么框架会寻找属性名称getCa,通常,这种并不是我们想要的,我们希望做的是给文本域的value传入一个字符串值"ca",在表达式语言中,字符的使用时被放到引号中的。

If a textfield is passed the value attribute "ca", the framework will look for a property named getCa. Generally, this is not what we mean. What we mean to do is pass a literal String. In the expression language, literals are placed within quotes

错误的例子

下面的例子官方文档中虽然提示肯能会是错误的,但测试是可以通过的,尽量不要这么做。

<s:textfield key="state.label" name="state" value="ca"/>

正确的用法

<s:textfield key="state.label" name="state" value="%{'ca'}" />

其他方法

下面这种在官方文档中提到,但经测试结果是不正确的

<s:textfield key="state.label" name="state" value="'ca'"/>

似乎下面的写法也是正确的,但官方文档中并未提到,不建议这样做。

<s:textfield key="state.label" name="state" value='ca'/>

以上得到的结果分别如下

image

总结

标签属性在进行计算式使用以下3项原则

1.所有字符串属性的类型使用"%{ ... }"进行转义

2.所有非字符串属性的类型不会被转义,但计算时直接作为表达式的(一部分)

3.第2项的例外是,非字符按属性使用"%{}"进行转义,那么标示符将被忽略掉,而其中的内容会被计算。

例如

<!-- 在这里"true"被认为是bool类型进行判断,也就是转义标示符”%{}”被忽略掉了,但"true"被正确的计算了 -->
<s:if test="%{true}">
    test result is true
</s:if>

请注意关于altSyntax的选项,当标签属性value在进行计算式它可以改变的。参见AltSyntax的内容。

Boiled down, the tag attributes are evaluated using three rules.

  1. All String attribute types are parsed for the "%{ ... }" notation.
  2. All non-String attribute types are not parsed, but evaluated directly as an expression
  3. The exception to rule #2 is that if the non-String attribute uses the escape notion "%{}", the notation is ignored as redundant, and the content evaluated.

Please remember about altSyntax option that can change when value is evaluated as an expression - Alt Syntax

禁用的属性名称

parameters 
application 
session 
struts 
request 
servletRequest 
  1. servletResponse

下面的代码将失效

<s:iterator value="parameters"/>
public class MyAction {
 
    private String[] parameters;
 
    public String[] getParameters() {
        return parameters;
    }
}

表达式语言标识

<p>Username: ${user.username}</p>
JavaBean 对象在Freemarker, Velocity, or JSTL EL (Not OGNL)的标准上下文环境中被调用。(也就是说当页面中的内容使用了isELIgnored="false")时,这一项会当做el表达式计算,而非ognl表达式。
A JavaBean object in a standard context in Freemarker, Velocity, or JSTL EL (Not OGNL).
<s:textfield name="username"/>
在值栈中的username属性被调用
(值得注意的是,在测试过程中,如果将左侧的内容直接写在输入页面中,也就是说希望输入和输出是同一个页面时,会出在输入页面中出现一个值username,这是我们不希望看到的,因此本人还是建议使用转义标示符”%{}”)
A username property on the Value Stack.
<s:url id="es" action="Hello">
  <s:param name="request_locale">
    es
  </s:param>
</s:url>
<s:a href="%{es}">Espanol</s:a>
调用值栈中属性的另一种方法
Another way to refer to a property placed on the Value Stack.
<s:property
  value="#session.user.username" />
The username property of the User object in the Session context.
<s:select
  label="FooBar" name="foo"
  list="#{'username':'trillian',
    'username':'zaphod'}" />
静态的Map对象,作为输入
A static Map, as in put("username","trillian").

测试代码

JSP页面

<%@ page language="java" import="java.util.*"  pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
  </head>
  
  <body>
<s:form action="loginAction" namespace="/login">
    <s:textfield key="user.name" name="user.name" value="user.name"/>
    <s:textfield key="user.name" name="user.name" value="%{#session.user.name}"/>
    <s:submit value="%{'提交'}"></s:submit>
<!-- 下面的${user.name}在提交action前不会出现,但在提交之后会出现,这里的表达式标示符被当做EL表达式计算,如果页面中使用了isELIgnored="true",那么正个表达式被当做一个字符串显示在页面上 -->    
                ${user.name }
</s:form>
  </body>
</html>

Action代码

package login;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class LoginAction extends ActionSupport {
    private User user;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        System.out.println(user.getName());
        System.out.println("hi");
        return "success";
    }    
}

JavaBean代码

package login;
 
public class User {
    private String name="test";
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }    
}
posted @ 2013-07-28 13:37  一杯红茶  阅读(1371)  评论(0编辑  收藏  举报