Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning Apache Struts - From Novice To Professional (2006)

.pdf
Скачиваний:
60
Добавлен:
17.08.2013
Размер:
11.68 Mб
Скачать

438

A P P E N D I X C S T R U T S T A G R E F E R E N C E

Attributes

Only the base-attrs attribute set is applicable.

Examples

The following example shows the use of the <logic:empty> tag to conditionally process the nested <bean:write> tag if MyCollection is empty:

<logic:empty name="MyCollection">

<bean:write name="MyCollection" property = "myproperty[13]" /> </logic:empty>

The next example illustrates the use of the property tag:

<logic:empty name="contact" property="email"> <bean:write name="contact" property="email"/>

</logic:empty>

The <bean:write> is executed only if the getEmail() function returns null, or a zerolength String. You can also use the scope variable to specify a scope under which to look for a bean:

<logic:notEmpty name="MyBean" scope="request"> <bean:write name="MyBean" property = "myproperty" />

</logic:empty>

In the previous example, the <bean:write> is called on the base object if MyBean can be found on the request scope.

Equivalents

You can easily create equivalents for empty and notEmpty using JSTL’s <c:if> or <c:choose>...<c:when>. For example using <c:if>, the previous examples would be

<c:if test="${empty MyCollection}">

<bean:write name="MyCollection" property = "myproperty[13]" /> </c:if>

and

<c:if test="${empty contact.email}">

<bean:write name="contact" property="email"/> </c:if>

A P P E N D I X C S T R U T S T A G R E F E R E N C E

439

You’d have to use JSTL’s implicit objects (requestScope, sessionScope, etc.) to specify a scope:

<c:if test="${ not empty requestScope.MyBean}"> <bean:write name="MyBean" property = "myproperty" />

</c:if>

equal/notEqual

equal checks that the given property (or extended property) is equal to a given value. If so, the body of the equal tag is executed. notEqual is the converse of equal.

Usage Restrictions

The value attribute is required. You must specify one selector attribute (see the start of this section for a definition) as well.

Attributes

Both base-attrs and exprop-attrs are accepted. There is also an additional value attribute, which is a constant value that the property or extended property will be compared to.

Examples

The following example shows the use of the <logic:equal> tag to conditionally process the nested <bean:write> tag if the variable client is equal to the String “Joe”:

<logic:equal name="client" value="Joe"> <bean:write name="client" />

</logic:equal>

The next example illustrates the use of the parameter attribute:

<logic:equal parameter="username" value="Susan"> Hello Susan!

</logic:equal>

The body is executed only if there is a parameter named username on the request URL with the value Susan. If there were more than one such parameter, the first one that occurs on the URL is used.

You can also use the scope variable to specify a scope under which to look for a bean:

<logic:notEqual name="MyBean" property="email" scope="session" value="joey@joey.com">

<bean:write name="MyBean" property = "email" /> </logic:notEqual>

440

A P P E N D I X C S T R U T S T A G R E F E R E N C E

In this example, the <bean:write> is called on the base object if there is a bean on the session scope called MyBean, and its getEmail() function returns a value equal to joey@joey.com. Note that if MyBean is null, or does not have a getEmail() function, an exception is thrown.

Equivalents

You can easily create equivalents for equal and notEqual using JSTL’s <c:if> or <c:choose>...<c:when>. For example using <c:if>, the previous examples would be

<c:if test="${client == 'Joe'}"> <bean:write name="client" />

</c:if>

The next example illustrates the use of the parameter attribute:

<c:if test="${param.username == 'Susan'}"> Hello Susan!

</c:if>

You can also use the scope variable to specify a scope under which to look for a bean:

<c:if test="${sessionScope.MyBean.email != 'joey@joey.com'}"> <bean:write name="MyBean" property = "email" />

</c:if>

Also note that unlike the Struts tags that only admit a constant value, the JSTL equivalents have no such restriction. Here’s an example of comparing a variable against another (this is impossible to implement with the Struts tags because value must be constant—unless of course, you’re willing to use scriptlets):

<c:if test="${cookie.userlogin != MyBean.userlogin}"> <bean:message key = "error.myapp.login" />

</c:if>

forward

This tag causes the page to be forwarded to the specified global forward (see Chapters 9 and 17). This tag has no body. See also <logic:redirect>.

Usage Restrictions

The name attribute is required.

Attributes

The name attribute is the name of the global forward to use.

A P P E N D I X C S T R U T S T A G R E F E R E N C E

441

Note If you wish to forward to a Tiles definition, a hack is to do this from an Action subclass, which is in turn exposed as a global forward.

Examples

Consider the global forwards declared in struts-config.xml:

<global-forwards>

<forward name="login" path="/login.jsp"/> <forward name="logoff" path="/Logoff.do"/>

</global-forwards>

Then, the forward

<logic:forward name="login"/>

would cause the page login.jsp to be displayed. Similarly, the forward

<logic:forward name="logoff"/>

would cause the Logoff.do form handler to be called. You can use this to load a Tiles definition.

Equivalents

None.

greaterEqual/lessEqual/greaterThan/lessThan

greaterEqual is a conditional tag that executes its body if the given property (or extended property) is greater than or equal to the constant value given by the value attribute. The other tags in this group are similarly defined.

Note that if value is not a numeric value, it is interpreted as a String, and a comparison between Strings (using Java’s standard comparisons between Strings) will be performed.

Usage Restrictions

The value attribute is required. You must specify one selector attribute (see the start of this section for a definition) as well.

Attributes

Both base-attrs and exprop-attrs are accepted. There is also an additional value attribute, which is a constant value that the property or extended property will be compared to.

442

A P P E N D I X C S T R U T S T A G R E F E R E N C E

Examples

The example that follows shows the use of the <logic:greaterThan> tag to conditionally process the nested tags (not shown) if the variable hits is greater or equal to 10:

<logic:greaterEqual name="hits" value="10"> //other tags here.

</logic:greaterEqual>

The next example illustrates the use of the cookie attribute:

<logic:greaterThan cookie="logintries" value="3"> <bean:message key= "error.myapp.login.tries-exceeded" />

</logic:greaterThan>

The <bean:message> is executed only if the cookie called logintries is greater than 3.

Equivalents

You can easily create equivalents for these tags using JSTL’s <c:if> or <c:choose>...<c:when>. For example using <c:if>, the previous examples would be

<c:if test="${hits >= 10}"> //other tags here.

</c:if>

The next example illustrates the use of the cookie attribute:

<c:if test="${cookie.logintries > 3}"> //other tags here.

</c:if>

Also note that unlike the Struts tags that only admit a constant value, the JSTL equivalents have no such restriction.

iterate

The <logic:iterate> tag can be used to iterate over Collections, Maps, Enumerations, arrays, or Iterators (referred to as the “iteratable object”). The tags (or static text) nested within an <logic:iterate> are executed into the JSP’s response stream (i.e., written to the final HTML page).

Usage Restrictions

The id attribute is required. You must also specify the iteratable object (using either the name/property attributes or the collection attribute).

A P P E N D I X C S T R U T S T A G R E F E R E N C E

443

Attributes

The iterate tag uses base-attrs to specify the base object that represents the Collection/ Map/Enumeration/array/Iterator to iterate over. Besides these, several other attributes can be used:

collection: The name/property combination only allows you to loop over iteratable objects that may be read as JavaBean properties. This can be quite restrictive.

For example:

<logic:iterate name="MyBean" property="myCollection" ...

implicitly calls the function

MyBean.getMyCollection()

in order to determine the iteratable object. Many Java classes however, do not use the JavaBeans getXXX() convention, so a different approach is needed for them. The solution is to use the collection attribute in combination with a scriptlet:

<logic:iterate collection="<%=MyObject.iterator()%>" ...

id: This is the name given to a single element read from the iteratable object.

indexId: The current index; starts from zero.

length: The maximum number of elements to read from the iteratable object. If not present, all elements are read.

offset: The index of the first element to return from the iteratable object. For example, if the iteratable object is an array [a, b, c], using offset="1" makes the loop read b and c only. Note that the offset is zero based, as it is in Java.

type: The fully qualified classname of the elements read from the iteratable object. If an element doesn’t match this classname, a ClassCastException is thrown.

Examples

Here’s the basic usage:

<logic:iterate name="MyBean" property="myCollection" id="anElement"> <!-- anElement.toString() called -->

<bean:write name="anElement" /> </logic:iterate>

444

A P P E N D I X C S T R U T S T A G R E F E R E N C E

and with the collection attribute:

<logic:iterate collection="<%=MyObject.iterator()%>" id="anElement"> <!-- anElement.toString() called -->

<bean:write name="anElement" /> </logic:iterate>

And using the indexId attribute to display the current iteration number:

<logic:iterate name="MyContacts" id="aContact" indexId="count"> <bean:write name="count" />

<bean:write name="aContact" property="email"/> </logic:iterate>

Equivalents

JSTL’s <c:forEach> is a better replacement for <logic:iterate>. Here are the previous examples using JSTL:

<c:forEach var="anElement" items="${MyBean.myCollection}"> <c:out value="${anElement}"/>

</c:forEach>

There is no “collection” attribute needed for the next example:

<c:forEach var="anElement" items="<%=MyObject.iterator()%>"> <c:out value="${anElement}"/>

</c:forEach>

Lastly, you expose the iteration number this way:

<c:forEach var="aContact" items="${MyContacts}" varStatus="count"> <c:out value="${count}"/>

<c:out value="${aContact.email}"/> </c:forEach>

match/notMatch

match is a conditional tag that executes its body if the given property (or extended property) contains the value attribute as a substring. notMatch is the converse of match.

Usage Restrictions

The value attribute is required. You must specify one selector attribute (see the start of this section for a definition) as well.

A P P E N D I X C S T R U T S T A G R E F E R E N C E

445

Attributes

Both base-attrs and exprop-attrs are accepted, and have their usual meaning. Besides these, there are two additional attributes:

value: A constant substring that the property or extended property will be matched for. For example, if the property or extended property results in the string “Visit Zimbabwe”, then value="im" would cause a match, while value="Zic" would not.

location: The value is either start or end, and specifies where the matching should take place within the source string. If omitted, a match anywhere will succeed.

Examples

Here’s a simple example that looks for an email address with an .sg suffix:

<logic:match name="MyBean" property="email" value=".sg" location="end">

I see you're from Singapore! </logic:match>

Or you could interrogate the HTTP request header:

<logic:notMatch header="user-agent" value="Windows"> Try knoppix now: http://www.knoppix.net

</logic:notMatch>

Equivalents

You can easily create equivalents for these tags using JSTL’s <c:if> (or <c:choose>...<c:when>) in conjunction with JSTL functions. (This is a standard JSTL library of functions. You must declare the JSTL function taglib in order to use it.) For example, using <c:if> the previous examples would be

<c:if test="${fn:endsWith(MyBean.email,'.sg')}"> I see you're from Singapore!

</c:if>

and

<c:if test="${fn:contains(header.user-agent,'Windows')}"> Try knoppix now: http://www.knoppix.net

</c:if>

446

A P P E N D I X C S T R U T S T A G R E F E R E N C E

messagesPresent/messagesNotPresent

messagesPresent is a conditional tag that executes its body if the given message or error message exists on the current request. messagesNotPresent is the converse of messagesPresent.

Note the following terminology:

“Error messages” are ActionMessage instances stored in an ActionMessages/ ActionErrors instance, which in turn is stored under the key Globals.ERROR_KEY in the request.

“Messages” are ActionMessage instances stored in an ActionMessages/ActionErrors instance, which in turn is stored under the key Globals.MESSAGE_KEY in the request.

For example, your ActionForm’s validate() might return an ActionErrors instance that contains one or more ActionMessage instances. These ActionMessage instances are stored by key, as you’ve seen in Chapters 6 and 7. The key is called the “name” of the corresponding error message/message.

Both error messages and messages may be displayed with <html:errors>, or iterated with <html:messages>.

Usage Restrictions

None.

Attributes

There are three attributes: name, property, and message.

Note that the name and property attributes don’t have their usual meaning. Instead, the following checks are made depending on the settings of these attributes:

If no attributes are specified, messagesPresent simply checks if there any error messages in the current request. It executes its body if there are error messages. Setting message="true" causes messagesPresent to check for any messages instead.

If the property attribute is specified, messagesPresent checks if there are any error messages with that name. Again, setting message="true" causes a check for the appropriate message instead.

The name attribute allows you to look for error messages/messages on the request, under a key other than Globals.ERROR_KEY or Globals.MESSAGE_KEY. Note that if you specify the message attribute, the name attribute is ignored.

If the name attribute is specified, then even a String or String array in the request will result in a match.

A P P E N D I X C S T R U T S T A G R E F E R E N C E

447

The various combinations are probably best illustrated with examples.

Examples

The simplest example tests for the presence of error messages:

<logic:messagesPresent >

There are errors on this page! </logic:messagesPresent>

Or you could test for a specific error message:

<logic:messagesPresent property="email"> The email address field has an error!

</logic:messagesPresent>

If your Action posts messages, you can test for these as well:

<logic:messagesNotPresent property="alerts" messages=true "> The are no alerts for you.

</logic:messagesNotPresent>

And you can look for error messages or messages or Strings or String arrays under a specific key on the request:

<logic:messagesPresent name="mywebapp_debug_messages">

The debug message is: <bean:write name="mywebapp_debug_messages"/> </logic:messagesPresent>

Equivalents

None. There are, of course, hacks using scriptlets in combination with JSTL’s <c:if>.

present/notPresent

present checks the request for the presence of an object under the specified property or extended property. If the object is present, the body of the tag is executed. notPresent is the converse of present.

Usage Restrictions

You must specify a selector attribute (see the start of this section for a definition) or user or role.

Attributes

Both base-attrs and exprop-attrs are accepted, and have their usual interpretation. If the property attribute is specified, present checks that the return value is not null.