Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 36 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
36
Dung lượng
670,51 KB
Nội dung
| +- resources | +- webapp | +- jsp | +- styles | +- WEB-INF | +- decorators +- test +- java | +- com | +- fdar | + apress | +- s2 +- resources The standard directory structure goes like this: the src directory is the root for all code in the project, and within this directory, there is a main directory (for production code) and a test directory. Only the src directory’s contents (after any processing/compiling is per- formed) go into the packaged artifact. ■Note For more detail on the standard directory structure, see the Maven2 documentation at http:// maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout. html. These two directories can contain many other directories, which are aligned with a plug- in or technology. The most common are the java and resource (containing property, XML, and other configuration files) directories—because Maven2 is a build tool for Java—but there are many more. When the AspectJ (AspectJ provides a way to weave additional code for cross- cutting concerns, with logging and transaction management being the commonly used examples, into existing compiled code) plug-in is included, an aspects directory contains the .aj files. The same goes for scripting, where a groovy directory contains the Groovy scripts that are to be executed. (Groovy is a dynamic scripting language with syntax similar to Java that can be executed on the fly or compiled down to byte code.) For a war packaged artifact, the main directory includes a webapp directory that contains the additional information for a WAR file that an EAR or JAR does not need. The Maven2 Configuration File As well as the starter program elements, the archetype will create a Maven2 pom.xml config- uration file that is used to build the project. This file defines the project’s dependencies, the packaging details , and the testing and reporting requirements. The configuration file plays a central role, so let’s take some time to understand its parts. The first part is the header information: CHAPTER 2 ■ GETTING UP AND RUNNING16 9039ch02.qxd 10/29/07 3:35 PM Page 16 <project> <modelVersion>4.0.0</modelVersion> <groupId>com.fdar.apress.s2</groupId> <artifactId>app</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>Struts 2 Starter</name> <url>http://www.myComp.com</url> <description>Struts 2 Starter</description> … </project> The header of the configuration file contains information for the final packaging, and you should see several values that are familiar: the groupId and artifactId have the same values that were provided in the command to create the starter package. Some information will remain constant; the modelVersion will always have a value of 4.0.0 (until a significant Maven2 configuration format revision occurs), which refers to the Maven2 model version. The packaging value for web applications is usually war. If this were a component of a larger application, the value would be jar; and if it were a J2EE application containing web components, EJB components, and other resources, it would be ear. The version value remains constant for the time being but will change over time. As this compo- nent becomes stable or goes into preview or testing phases, it may change. When the compo- nent is released for production use, it should be changed to 1.0. As further development starts, it may be changed to 1.1-SNAPSHOT (for enhancements) or 2.0-SNAPSHOT (for new major features). Three elements—the name, url, and description tags—have a default value that you should change soon after the starter code has been generated. Each provides descriptive information to developers and consumers of the packaged artifact but is not utilized during building or packaging. The next interesting part of the pom.xml file is the dependency section: <project> … <dependencies> <! Junit > <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> CHAPTER 2 ■ GETTING UP AND RUNNING 17 9039ch02.qxd 10/29/07 3:35 PM Page 17 <! Struts 2 > <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.0.9</version> </dependency> … <! Servlet & Jsp > <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> … </dependencies> … </project> This part of the file describes the dependencies in the application, which will be down- loaded from either a local or remote repository. Once downloaded, the dependency will be added to various classpaths to build the project and may be included in the final distribution package that is created (in this case, a WAR file). Each individual dependency includes several of the same tags as in the header: groupId, artifactId, and version. These three tags will become very familiar when working with Maven2 because they form the basis of describing the artifact or plug-in that you want to use. The new element that has been introduced is the scope tag. It describes what the depend- ency is used for, ho w to find the dependency, and when it should be included in the classpath. There are five options for scope: • compile: This is the default scope (the struts2-core artifact uses this scope because no other was provided), and these dependencies are available on all classpaths. Any dependency with compile scope will be packaged with the final ar tifact. • provided: The dependency will be provided by the JDK or the application server at run- time. It is required for compilation but will not be packaged in the application. • runtime: The dependency is not required for compilation but is required to run the application. It will be available only on the runtime classpath and the test classpath. CHAPTER 2 ■ GETTING UP AND RUNNING18 9039ch02.qxd 10/29/07 3:35 PM Page 18 • test: The dependency is only required for testing and will be available on the test class- p ath and the runtime classpath. • system: The dependency is always available (you need to provide the JAR file) and is not retrieved via a repository lookup. The repositories section tells Maven2 the additional repositories that can be used to obtain the dependencies. Each repository has a name and url tag. <project> … <repositories> <repository> <id>Struts 2 Repository</id> <url>http://people.apache.org/builds/struts/2.0.9/m2-staging-repository/</url> </repository> </repositories> … </project> Repositories can be set up for your organization, or they can be remote repositories. The repository defined in the preceding code is the official Apache staging repository. If this section is omitted, the official Maven2 central repository at http://repo1.maven.org/maven2 is used. This repository has been mirrored in many locations; one of the most popular is the Ibiblio mirror, which can be found at http://mirrors.ibiblio.org/pub/mirrors/maven2. The final section in the generated pom.xml configuration file is the build section. This section contains specific information pertaining to the control of the build process, including nondefault configurations and plug-ins (that tie into one of the life cycle phases or can be invoked manually). </project> … <build> <finalName>app</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> CHAPTER 2 ■ GETTING UP AND RUNNING 19 9039ch02.qxd 10/29/07 3:35 PM Page 19 <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.0.1</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> </configuration> </plugin> </plugins> </build> </project> The finalName tag provides an override mechanism for the name of the final artifact produced when building the application. By providing this tag, the final name will now be app.war. Without it, the name would be a combination of the artifactId and the version from the header section, hence app-1.0-SNAPSHOT.war. The generated file has a similar name, but this is not necessary, and the names could have been completely different. Several plug-ins are configured next. The first plug-in configures the compiler for Java 5. The code is a simple template; if you want to know more about the configuration options, the plug-ins documentation can be found at http://maven.apache.org/plugins/maven-compiler- plugin/compile-mojo.html . The next plug-in configures the Jetty servlet container. By configuring a servlet container in the build script, it will have access to the application’s classpaths, it will know which directo- ries are for the application, and it will know which files are to be deployed to run the applica- tion. One configuration parameter is provided—the scanIntervalSeconds parameter—which tells Jetty to check the WAR file periodically and, if it is changed, to reload the web application. By default, the server is bound to port 8080. ■Note More detailed information about the Jetty servlet container and the different configurations for the Jetty Maven2 plug-in can be found at http://www.mortbay.org/maven-plugin/. The Jetty server is started by issuing the mvn jetty:run command. Once started, it will need to be explicitly stopped (via Ctrl+C). As the WAR file is checked for changes periodically, leaving the ser ver running and building your application in another process will reduce the turnaround time from building to testing. Starter Application Features The starter S truts2 web application that was created by the Maven2 artifact includes all the basic elements, as well as common S tr uts2 plug-ins that most w eb applications will use. By examining this simple application, you will get a feel for how all the parts fit together. We will explor e the classes , configuration files, and features as they are encountered from running the star ter application. CHAPTER 2 ■ GETTING UP AND RUNNING20 9039ch02.qxd 10/29/07 3:35 PM Page 20 Two plug-ins are utilized in the starter application: the SiteMesh and Spring Framework p lug-ins. To enable plug-ins, the JAR file for the Struts2 plug-in needs to be included in the application. With Maven2, the following dependencies are added to the pom.xml configuration file in the dependency section. If you use another build technique, you want to ensure that the plug-in JAR files and all dependant SiteMesh and Spring JAR files are located in the /WEB-INF/lib directory of the final WAR file. <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-sitemesh-plugin</artifactId> <version>2.0.9</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-spring-plugin</artifactId> <version>2.0.9</version> </dependency> When building the application with Maven2, the Struts2 plug-in JAR files (as well as any dependent JAR files) are downloaded and included in the final WAR packaging. The web.xml configuration file also has to be modified to enable the plug-ins to work. Spring needs an initialization parameter to determine where the applicationContext.xml configuration file is located, and it needs a listener to allow Struts2 to access Spring’s applica- tion context. <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext*.xml</param-value> </context-param> … <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> SiteMesh needs additional filters to be defined and placed in the processing queue before the Struts2 filters. Here’s what this configuration looks like. <filter> <filter-name>action2-cleanup</filter-name> <filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class> </filter> CHAPTER 2 ■ GETTING UP AND RUNNING 21 9039ch02.qxd 10/29/07 3:35 PM Page 21 <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class> </filter> <filter> <filter-name>action2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>action2-cleanup</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>action2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> The code example shows the Struts2 configuration as well as the SiteMesh configuration. In fact, for a bare minimum configuration, only the single Struts2 filter and filter mapping need to be configured. Getting to the First Scr een After starting the Struts2 starter application with the mvn jetty:run command, you can point your browser to the URL http://localhost:8080/app. This will redirect you to the http:// localhost:8080/app/index.action URL. The struts.xml configuration file determines the mappings from the URL to the action class that is invoked. This file can be found in the src/main/resources directory. The following is the part of the file of interest at the moment for the index action: <struts> <package name="myPackage" extends="struts-default"> <action name="index" class="com.fdar.apress.s2.IndexAction"> <result>/jsp/index.jsp</result> </action> … </package> </struts> The default extension for a Struts2 application is .action. Combine this with the value of the name attr ibute of the action configur ation (along with the w eb application’s context), and y ou get the URL. I f the package tag had a namespace attr ibute , it would be added betw een the w eb context and the action name; but in this case , the attr ibute is not pr o vided. CHAPTER 2 ■ GETTING UP AND RUNNING22 9039ch02.qxd 10/29/07 3:35 PM Page 22 ■Note The package tag also has an extends attribute. This attribute acts similarly to class inheritance in Java, in that one package can extend another package, which in turn allows the extending package to get “something for nothing.” In the case of packages, the extending package gets access to all the configura- tions that are in the parent package. Chapter 3 provides more information on this topic. The class attribute provides the name of the action class that is invoked. For the index action, the class is IndexAction: @Conversion() public class IndexAction extends ActionSupport { private Date now = new Date(System.currentTimeMillis()); @TypeConversion(converter = "com.fdar.apress.s2.DateConverter") public Date getDateNow() { return now; } public String execute() throws Exception { now = new Date(System.currentTimeMillis()); return SUCCESS; } } If you are used to Struts actions, this is going to look a little strange. First, there is a class property now, with a getter getDateNow() that returns the value of the property. Unlike Struts actions, which can be reused between requests (and therefore need to be thread-safe), a new Struts2 action is created for each request. This allows Struts2 to use class properties instead of relying exclusively on method properties. ■Note Usually the JavaBean pattern of a property name of now having a getter of getNow() and setter of setNow() is used. In the IndexAction class, this is not the case. Although it is a little confusing at first, it does illustrate that any class property can be used in a getter or setter. There are some similarities, too. The class extends an ActionSupport class and provides an execute() method, which is called to provide the action’s processing logic. The return value is a String, and constant values are provided by the ActionSupport class. In this case, the SUCCESS constant returns a string value of success. This matches the result tag of the action configura- tion. When no name attribute on the result tag is provided, it is implicitly assigned to a value of success. Similarly, when no type attribute is provided, the result is expected to be a JSP, so the /jsp/index.jsp JSP is rendered to HTML for the user. CHAPTER 2 ■ GETTING UP AND RUNNING 23 9039ch02.qxd 10/29/07 3:35 PM Page 23 ■Note In this section, you will learn the basics of configuring actions. Actions can be configured in many ways, and you will learn about these in Chapter 3. For the time being, we will keep the options limited to focus on how all the elements interact. Figure 2-1 shows the screen that is rendered from the following JSP code. <%@taglib prefix="s" uri="/struts-tags" %> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Index</title> <s:head /> </head> <body> <s:form action="helloWorld"> <s:textfield label="What is your name?" name="name" /> <s:textfield label="What is the date?" name="dateNow" /> <s:submit /> </s:form> </body> </html> Comparing the screen and the code, two questions immediately spring to mind: Where did all the extra user interface text come from? This is provided by SiteMesh. SiteMesh uses the filter that was previously configured to intercept and adds additional HTML to the Struts2 result. The WEB-INF/decorators.xml configuration file provides the information on which URL patterns map to which decorators. In the starter application, you have a single decorator file WEB-INF/decorators/main.jsp. There are three tags of interest: <decorator:title /> inserts the title of the original page into the decorator tem- plate; <decorator:head /> inserts the entire head tags’ contents of the original page into the decorator template; and <decorator:body /> inserts the entire body tags’ contents into the decorators template. As you can see, there is no reference from the original page to the decorator template file because it all happens behind the scenes, providing a loosely coupled option that allows the templates to be modified and reapplied across the entire web application very easily. Where did the date come from? The action did not use the HttpServletRequest, HttpSession, or any other type of object, so how did it get rendered? The answer is that Struts2 is a pull-MVC (Model View Controller) framework. Instead of requiring that all model data be placed in a commonly accessible location, the custom tag libraries are able to access the action that just executed. Hence, the tag that displays the date called the getDateNow() method on the action. The name attribute on the <s:textfield … name="dateNow"/> tag uses the JavaBean specification for finding the correct getter (in this case, the getDateNow() getter). CHAPTER 2 ■ GETTING UP AND RUNNING24 9039ch02.qxd 10/29/07 3:35 PM Page 24 Figure 2-1. The initial screen from the starter application ■Note If you are interested in learning more about the features of SiteMesh, including the different tags and decorator ma pping options, check out the project home page at http://www.opensymphony.com/sitemesh. What should be familiar to y ou is the use of custom JSP tags. Most web application frame- works in Java provide wrappers around various HTML tags, as well as additional tags for logic functions, and Struts2 is no different. On the initial screen there are four tags: • The <s: head /> tag provides a single place for any additional JavaScript libraries needed b y other tags to be specified and loaded. • The <s:form … /> tag is a body tag that encloses the field of the form that is to be sub- mitted. The interesting thing here is that the action attribute is only a name value; there is no extension and no namespace. This is because the form tag will generate these for you, calling the action in the same namespace and adding an .action suffix. • The <s:submit /> a nd <s:textfield … /> tags pr o vide wr appers ar ound the corr espon - ding HTML form field tags. The <s:textfield … /> tag has an additional attribute label that the HTML tag does not; this is used as the text to place in fr ont of the input field. Each S tr uts2 tag that is a for m field has this attr ibute , allo wing the form to be formatted in a table with all the fields aligned. CHAPTER 2 ■ GETTING UP AND RUNNING 25 9039ch02.qxd 10/29/07 3:35 PM Page 25 [...]... dispatcher org .apache. struts2. dispatcher ServletDispatcherResult The default result type renders JSPs chain com.opensymphony.xwork2.ActionChainResult Chains one action to another action freemarker org .apache. struts2. views.freemarker FreemarkerResult Renders Freemarker templates httpheader org .apache. struts2. dispatcher.HttpHeaderResult Returns a configured HTTP header response redirect org .apache. struts2. dispatcher... package, and deploy the projects created to a running servlet container You learned how to install Maven2, what the life cycle phases are, and what types of functions each life cycle phase will perform Using Maven2 and the Struts2 starter archetype, you generated a Struts2 starter web application The different sections of the Maven2 pom.xml configuration file were described for a Struts2 web application,... configured URL redirectAction org .apache. struts2. dispatcher ServletActionRedirectResult Redirects the user to a configured action stream org .apache. struts2. dispatcher.StreamResult Streams raw data back to the browser and is useful for downloadable content and images velocity org .apache. struts2. dispatcher.VelocityResult Renders a Velocity template xslt org .apache. struts2. views.xslt.XSLTResult Renders... return values as constants and enforce that implementing classes provide the default execute() method s Note In the 2. 0 version of WebWork (the framework from which Struts2 evolved), each action is required to implement the Action interface In version 2. 2 of WebWork, and hence Struts2, this restriction was removed and the interface remains as a helper class only The ActionSupport class is more interesting... the Struts2 tags can be found in the online documentation at http://struts Tip apache. org /2. 0. 9/docs/tag-reference.html The biggest difference between the Struts2 tag libraries and other tag libraries is in the architecture Just as Struts2 is an MVC framework, so too are the tag libraries Figure 3-3 shows the classes that make up the pattern and interaction between the elements 49 9039ch03.qxd 50 10 /29 /07... annotate the setter of the action and configure the page that the user is redirected to should there be validation errors Struts2 handles everything else on your behalf 31 9039ch 02. qxd 32 10 /29 /07 3:35 PM Page 32 CHAPTER 2 s GETTING UP AND RUNNING Converting Data Types By default, Struts2 automatically converts many common types between the String value received as a form field value and the object or primitive...9039ch 02. qxd 26 10 /29 /07 3:35 PM Page 26 CHAPTER 2 s GETTING UP AND RUNNING That’s it The only thing left to do is enter a name and click the Submit button Figure 2- 2 shows the result of doing this Figure 2- 2 The results of a successfully submitted form Submitting the Form From the preceding discussion of the... of the Struts2 framework • xwork-conversion.properties: Rather than using annotations, this property file is used to define application-level type converters Summary In this chapter, you learned about the different elements that make up a Struts2 web application and generated a starter web application that you could test in the Jetty servlet container The chapter began by introducing the Maven2 build... framework and which aren’t Usually, all requests for an entire web context or installed application are forwarded to the Struts2 servlet filter, and it makes the decision The Struts2 Servlet Filter When requests are received at the servlet container, they are forwarded to either a servlet or a filter that will handle processing the request In Struts2, a filter is used, and the class for handling the request... trim = true) public void setName(String name) { this.name = name; } public String getName() { return this.name; } public String execute() throws Exception { return SUCCESS; } 27 9039ch 02. qxd 28 10 /29 /07 3:35 PM Page 28 CHAPTER 2 s GETTING UP AND RUNNING This action has a lot more code than the index action but less internal functionality The method that performs the business logic is the execute() method, . > <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> CHAPTER 2 ■ GETTING UP AND RUNNING 17 903 9ch 02 . qxd 10 /29 /07 3:35 PM Page 17 <! Struts 2 > <dependency> <groupId>org .apache. struts</groupId> <artifactId> ;struts2- core</artifactId> <version> ;2. 0. 9</version> </dependency> … <!. are encountered from running the star ter application. CHAPTER 2 ■ GETTING UP AND RUNNING 20 903 9ch 02 . qxd 10 /29 /07 3:35 PM Page 20 Two plug-ins are utilized in the starter application: the SiteMesh. name; but in this case , the attr ibute is not pr o vided. CHAPTER 2 ■ GETTING UP AND RUNNING 22 903 9ch 02 . qxd 10 /29 /07 3:35 PM Page 22 ■Note The package tag also has an extends attribute. This attribute