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

Beginning Apache Struts - From Novice To Professional (2006)

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

C H A P T E R 8

■ ■ ■

Basic Struts Tags

Struts implements the View component of the MVC design pattern entirely through the use of custom tags (actually, the correct term is custom action, but I think the term custom tag conveys more meaning, and leaves less room for confusion with Struts Actions). These tags are applied to the JSPs that constitute the View component of your webapp. The Struts tags are bundled into five tag libraries:

HTML: The custom tags in the HTML library are essentially in one-to-one relationship to the ordinary HTML <form> tag and its associated input tags, like the various <input> tags. The purpose of this tag library is to enable you to connect your View component to the Controller components described in Chapters 6 and 7. The actual connecting details are described in Chapter 9.

Bean: This library has custom tags primarily for writing text. There are two reasons why you’d use the Bean tags instead of hard-coding text into your JSPs. The first is to enable internationalization, that is, the display of the View component in multiple languages. We’ll show how Struts helps you internationalize your webapps in Chapter 12. The second reason is to avoid using scriptlets to display the contents of objects stored on the request or session objects.

Logic: This library provides tags for conditional processing and looping. You use tags in the Logic library in lieu of using scriptlets. The logic library tags are much easier to use and result in significantly more readable code.

Nested: This library has tags for displaying “nested” properties of a form or object. We’ll describe this in detail in Chapter 10.

Tiles: This library contains tags that allow you to create layouts. You’ll see how to use the Tiles tag library in Chapter 14.

79

80

C H A P T E R 8 B A S I C S T R U T S T A G S

Note Appendix C is a comprehensive reference for all Struts tags.

In this chapter, we’ll only discuss the most frequently used tags from just the HTML and Bean libraries.

Before we go into the details of each of these tags, you first have to understand how a JSP page is processed by Struts.

Page Processing Lifecycle

When Struts is asked for a page, it first replaces all Struts tags on that page with the necessary textual data. The underlying mechanism of this replacement process was described in Chapter 4. Not all Struts tags will show up on the displayed page. Some have preconditions, and will only display if they are satisfied. For example, the <html:errors> tag displays only if there are error messages to be displayed.

For a page that doesn’t contain a form, this tag replacement stage ends that page’s processing lifecycle.

If a page does contain a form, then Struts handles processing of the form data. This happens in essentially two stages, which have been the subject of the previous two chapters: simple validation and the processing of business logic.

The form data is first run through simple validation (on your ActionForm subclass). If this fails, the page is typically redisplayed automatically.

Note Whether simple validations are indeed performed and which, if any, input page is redisplayed are all controlled by the Struts configuration file, to be described in Chapter 9.

Because the page now contains validation errors, any relevant <html:errors> tags on the page will display their error messages.

Once the user corrects and resubmits the form, the data is again validated. As before, if the form still contains errors the page is redisplayed yet again. This cycle of redisplaying the form and validating it continues until the form data is free of simple validation errors.

When this happens, Struts sends the form data for business logic processing (by your Action subclass), and the “next” page is displayed. Note that the “next” page could be an error page or could have error messages in the event of complex validation errors.

Figure 8-1 summarizes these steps.

C H A P T E R 8 B A S I C S T R U T S T A G S

81

To make these ideas more concrete, we’ll continue with the Registration webapp example of the previous chapters. Along the way, we’ll show you how to use the most basic Struts tags from the HTML and Bean libraries. Again, Appendix C is a comprehensive reference for all Struts tags.

Figure 8-1. Typical Struts page processing lifecycle

Evaluation, Replacement, and Sending

When a Struts JSP page is requested, its processing does not involve the main Struts servlet (ActionServlet). Only submissions of form data involve the main servlet. It is this servlet that populates your ActionForm subclass and invokes execute() on your Action subclass.

Of course, Struts classes are involved in a page’s rendering, but these are just the BodyTagSupport and TagSupport classes representing each tag (see Chapter 4). The only state that these classes know about is stored on the server-side HttpServletRequest and HttpSession objects, representing the current request and session, respectively.

As you’ve seen in Chapter 4, BodyTagSupport or TagSupport are responsible for the final rendering of a tag’s visual appearance. Not all Struts tags have a visual appearance, though. Those from the Logic library (discussed in Chapter 10), for example, perform conditional processing to selectively display other tags that do have a visual appearance.

82

C H A P T E R 8 B A S I C S T R U T S T A G S

The processing of a Struts JSP page may be summarized in three steps:

Evaluation: Some Struts tags (from the Logic library) or the <html:errors> tag evaluate themselves to determine if they should indeed be displayed.

Replacement: Data is read from the request or session objects (or global forwards— more on this in Chapter 9) and is pasted into the rendered page. <html:errors>, for example, pastes in the appropriate error message.

Sending: The final page is sent to the user.

These three steps are always involved when a Struts JSP page is requested.

The View Component of the Registration Webapp

The View component of the Registration webapp (see Chapter 5) consists of a single page, registration.jsp, which contains a form with three inputs: a textual input for a user ID and two password fields.

The JSP code for this is given in Listing 8-1, and the visual output, as seen by the user, is depicted in Figure 8-2. Take some time to study both before reading further.

Listing 8-1. Registration.jsp

<%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <html:html>

<head>

<title><bean:message key="registration.jsp.title"/></title> </head>

<body>

<h1><bean:message key="registration.jsp.heading"/></h1> <html:form action="Registration.do" focus="userid">

<p>

<bean:message key="registration.jsp.prompt.userid"/> <html:text property="userid" size="20" /> <html:errors property="userid" />

</p><p>

<bean:message key="registration.jsp.prompt.password"/> <html:password property="password" size="20" /> <html:errors property="password" />

C H A P T E R 8 B A S I C S T R U T S T A G S

83

</p><p>

<bean:message key="registration.jsp.prompt.password2"/> <html:password property="password2" size="20" />

</p>

<html:submit>

<bean:message key="registration.jsp.prompt.submit"/> </html:submit>

<html:reset>

<bean:message key="registration.jsp.prompt.reset"/> </html:reset>

</html:form>

</body>

</html:html>

Figure 8-2. registration.jsp as it appears to the user

Declaring and Installing the HTML and Bean Libraries

Listing 8-1 starts with defining the prefixes for the Bean and HTML tag libraries:

<%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %>

84

C H A P T E R 8 B A S I C S T R U T S T A G S

Having written your own custom tags in Lab 4, this should hold no surprises for you. The TLD files and the Java handlers are all bundled in your Struts distribution:

The TLD files should be placed in \WEB-INF\.

Struts comes with a web.xml file that you should use. At the time of this writing, this web.xml file contains the appropriate <taglib> sections declared for your convenience. But you should always check this for yourself, and insert <taglib> sections for the five tag libraries if necessary.

The Java handler classes for these tags are in the various JAR files that comprise the Struts binaries, which you should place in your webapp’s \lib\ directory (see Chapter 2).

Caution Do not place the Struts JAR files in your servlet container’s “shared” or “common” directories. They must not be shared. You must deploy a fresh set in the \lib\ directory of each webapp. Sharing might in some cases cause ClassNotFoundExceptions to be thrown by the servlet container.

Displaying Static Text

The first thing you might notice in Listing 8-1 is that the prompts in Figure 8-2 (like Register New User, etc.) do not appear in the listing. Instead, registration.jsp uses <bean:message> tags to display these. For example, the tag

<bean:message key="registration.jsp.prompt.userid"/>

displays as

Please enter a userid (between 5 to 15 characters)

The <bean:message> tag can be used anywhere to display static text. The key attribute on this tag points to a key-value pair on a resource file Application.properties, just as it did in the case of error messages of Chapters 6 and 7.

Of course, there’s nothing to stop you from hard-coding text in your JSPs, but this would make your app much more difficult to internationalize and maintain.

Note Struts’ simple approach to displaying static text will only you take you so far. If you have lots of static text to display, then using a template engine like FreeMarker or Velocity (both of which I will not cover in this book) will be necessary. Refer to the “Useful Links” section for some web resources.

C H A P T E R 8 B A S I C S T R U T S T A G S

85

The Bean tag library contains other tags besides <bean:message>. Probably the only other tag you’d use is <bean:write>, which allows you to display properties of JavaBean objects. Refer to Appendix C for a description of this tag.

Forms and Form Handlers

Webapps are all about getting user input and processing them. The primary way of doing this with Struts (as with HTML) is through a form.

In Struts, forms are declared within an <html:form> container tag. This is similar to the way you’d declare a form in HTML. The <html:form> element has the action attribute that describes the handler that processes the form data:

<html:form action="Registration.do" ...

In this snippet, the handler is named Registration. A handler is a particular combination of your ActionForm subclass that performs simple validation and your subclass of Action that does business logic. You will see how to declare a handler in the next chapter. For now, you only need to understand that the action attribute points to a handler that you’ve defined.

Handlers traditionally end with the .do prefix, which tells the servlet container that the action is to be handled by Struts. This mapping is done in web.xml, and is shown in Listing 8-2 (which also shows the Struts ActionServlet declaration). These declarations are done for you in the web.xml file that comes with Struts. However, a high-level understanding of the details is useful, so I’ll digress a little to do this.

Note In case it isn’t clear, Listing 8-2 is an excerpt from the web.xml file generously made available by the Apache Software Foundation. The Apache License is available at http://www.apache.org/licenses/ LICENSE-2.0.

Listing 8-2. Struts’ Standard servlet and servlet mapping declarations

<!-- Standard Action Servlet Configuration --> <servlet>

<servlet-name>action</servlet-name> <servlet-class>

org.apache.struts.action.ActionServlet </servlet-class>

<init-param> <param-name>config</param-name>

<param-value>/WEB-INF/struts-config.xml</param-value> </init-param>

<load-on-startup>2</load-on-startup> </servlet>

86

C H A P T E R 8 B A S I C S T R U T S T A G S

<!-- Standard Action Servlet Mapping --> <servlet-mapping>

<servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern>

</servlet-mapping>

Listing 8-2’s <servlet> declaration starts the main Struts servlet class (org.apache. struts.action.ActionServlet) and gives it a reference to the Struts configuration file (struts-config.xml) described later in Chapter 9. This <servlet> declaration is given the name action. The following <servlet-mapping> tag refers to this name, and specifies that any incoming URL with the page extension ending with .do is to be referred to the servlet called action for processing.

Remember that it’s the servlet container (Tomcat, in our case) that reads the web.xml file and performs these instructions. The servlet container is also the one that orchestrates the control flow between the user and Struts, as depicted in Figure 8-1. It knows how to do this from the <servlet> and <servlet-mapping> declarations in Listing 8-2.

The last thing to note concerning the <html:form> tag is the attribute focus="userid". This is a directive telling Struts to autogenerate JavaScript to cause the userid field on the form to grab focus (that is, the cursor appears in this field) when the page loads in the user’s web browser. The details of the generated JavaScript aren’t important, but the fact that Struts does this at all is. As you will see in this book, much of the power of Struts is in little conveniences like this.

Data Input Tags

Struts tags that accept data input must be placed within the <html:form> tag. Listing 8-1 contains four input tags:

<html:text> represents a text field.

<html:password> represents a password field. The text in this field is displayed as asterisks.

<html:submit> represents the submit button.

<html:reset> represents a reset button to clear the form.

There are a number of other input tags (e.g., for radio buttons, lists, and drop-down lists), which are described in detail in Appendix C and in the lab sessions of subsequent chapters. In this chapter, we’ll concentrate on these four input tags only.

The textual field tags <html:text> and <html:password> all have a property attribute that ties them to the field on the form. Each field must correspond to a getXXX() and setXXX() pair on the ActionForm subclass associated with the form handler. Exactly how

C H A P T E R 8 B A S I C S T R U T S T A G S

87

the form handler links the JSP page with an ActionForm subclass is the subject of Chapter 9. For now, simply assume that each <html:form> has input fields corresponding to properties of an ActionForm subclass.

For example, from Listing 8-1, we can deduce that the ActionForm subclass that handles the Registration data must have the functions getUserid() and setUserid(). And it does (refer to Listing 6-1).

The text fields also accept a size attribute to allow you to specify the physical extent of the displayed field. This is just as you would expect for a text input field in HTML. In fact, all the input tags have attributes closely matching their HTML counterparts.

The <html:submit> and <html:reset> tags represent the submit and reset buttons on the form, respectively. The <bean:message> tags enclosed by these tags tells Struts what labels to place on the buttons. Again, this approach allows easy internationalization, and also lends a more uniform look to your webapp.

The reset button calls the reset() function on your ActionForm subclass (see step 4 of Lab 6). If one isn’t defined, the super.reset() function is called, which simply redisplays a blank form.

Displaying Errors

In the previous two chapters, you saw how validation error messages are generated. We’ll now describe how they are displayed.

When a form fails validation (either simple or complex), an ActionErrors or ActionMessages object is created containing the error messages. Both ActionErrors and ActionMessages behave like Java HashMaps. The key of the HashMap corresponds to the property attribute of the <html:errors> tag. The associated value is the error message itself.

However, unlike a HashMap, it’s possible to store more than one error message under the same key. This is obviously useful if there’s more than one error associated with a single field.

When Struts loads a page, it checks if there are ActionErrors or ActionMessages for the page. If there are, it dutifully pastes the error messages in the right <html:errors> tags of the page. Figure 8-3 shows this process in action.

As you can see, only errors whose keys are on both the ActionErrors (and ActionMessages) and the JSP page will be displayed. Every other error message or error tag is ignored.

So, in Figure 8-3, only the error message for the property userid gets displayed. The error message for the property desc is ignored because there’s no corresponding <html:errors> tag. The <html:errors> tag for the property named pwd doesn’t display at all since there are no corresponding error messages for that property on the ActionErrors object.

Tip A useful trick is to leave out the property attribute like so: <html:errors/>. This causes all error messages to be displayed. This is especially useful for debugging.