在GAE里配置STRUTS2

在gae用struts2,不会的会浪费很多时间。我参考以下的文章成功搭好环境。希望对其它人也有帮助。

详细地址:http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google-app-engine-gae/

 

Why i am writing this blog?

I faced lot of problems while creating my first application using Struts 2 on Google App Engine . So i decided to write a blog detailing how developers can create their application on Struts2 by avoiding the problems that i faced while developing my application.

Note

If you want to do FileUpload using struts 2  on google app engine please refer to this post .

Prerequisites for starting Struts2 Application on Google App Engine

Before you start building your sample application on google app engine using struts 2 you will need the following:-

  1. Google App Engine runs on java 5 and above so if necessary, download and install the Java SE Development Kit (JDK) for your platform and for mac users download and install the latest version.
  2. In this example we will be using Eclipse as our ide. So if necessary, download eclipse and google app engine plugin for eclipse .You will also need to download the google  java app engine SDK . For more information you can refer to installing the java SDK for google app engine .
  3. Download the latest release of Struts2 framework .If you want to learn struts 2 a very good reference is struts 2 in action book.Please buy Struts 2 in Action .

Step by Step procedure to create Struts2 application on Google App Engine.

Step 1: Create a new project by clicking the New Web Application Project button in the toolbarnew_app_button .

1

Step 2 : Give the project name say login  as we are going to create a simple login application. Enter package name as com.login and uncheck “Use Google Web Toolkit,” and ensure “Use Google App Engine” is checked and click the finish button.

2

Step3 : When you click the finish button you will get a sample HelloWorld application, which you can run going in the Run menu, select Run As > Web Application.By default application will run at port 8080, you can view the sample application at http://locahost:8080 . For more information on the sample google web application created by the plugin you can refer to Google java app engine documentation .Please keep in mind that intent of this document is not to provide developers the overview of Google App engine for Java .

Step4 : By now you are ready with the google app engine infrastructure and we can move to the next step of creating a login application in Struts 2.

  • for creating a struts 2 application you will need to first add the required dependencies to the login project. The required struts 2 jars are below mentioned and you can find these jars in struts2 package you downloaded inside the lib folder :-
    • commons-fileupload-1.2.1.jar
    • commons-io-1.3.2.jar
    • commons-logging-1.1.jar
    • freemarker-2.3.13.jar
    • ognl-2.6.11.jar
    • struts2-core-2.1.6.jar
    • xwork-2.1.2.jar
  • Add these dependencies in your eclipse java build path.

3

  • Add these dependencies in the war/WEB-INF/lib folder so that these jars gets deployed along with your application.

4

  • As you can see in the above image there are some warnings in the problems view like  “commons-fileupload-1.2.1.jar’ will not be available on the server’s classpath” .To remove these warnings you need to right click on the project and select properties and then go to Google > web application and click the add button and add all the jars and then press ok.

5

  • First step in creating a struts 2 application is configuring the web.xml (deployment descriptor) which is located in WEB-INF folder.You can remove the servlet declaration from web.xml as we will not be needing this.We need to add the FilterDispatcher declaration in web.xml because in struts2 every request goes  pass through FilterDispatcher which will invoke the appropriate action corresponding to the URL mapping.So our web.xml will look like :-
01 <? xml version = "1.0" encoding = "utf-8" ?>
02 < web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance "
04      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
05  
07  
08      version = "2.5" >
09      < filter >
10          < filter-name >struts2</ filter-name >
11          < filter-class >org.apache.struts2.dispatcher.FilterDispatcher</ filter-class >
12      </ filter >
13      < filter-mapping >
14          < filter-name >struts2</ filter-name >
15          < url-pattern >/*</ url-pattern >
16      </ filter-mapping >
17      < welcome-file-list >
18          < welcome-file >index.html</ welcome-file >
19      </ welcome-file-list >
20 </ web-app >
  • To start we will be creating a jsp login page using struts 2 tag library and we will call login page from index.html.To call the login page there are two ways first, we can directly call the login.jsp page from link second, we can calling it through struts. We will be taking the second step as this will show you how to configure actions when you dont need to invoke any action.Lets first see how our login page and index.html will look like :-

index.html

01 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
02 < html >
03 < head >
04 < meta http-equiv = "content-type" content = "text/html; charset=UTF-8" >
05 < title >Struts2 on Google App Engine</ title >
06 </ head >
07  
08 < body >
09 < h1 >Struts2 on Google App Engine!</ h1 >
10 < table >
11 < tr >
12 < td colspan = "2" style = "font-weight: bold;" >Available Application:</ td >
13 </ tr >
14 < tr >
15 < td >< a href = "/member/login" />Login</ td >
16 </ tr >
17 </ table >
18 </ body >
19 </ html >

login.jsp

01 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
02   pageEncoding="ISO-8859-1"%>
03 <%@ taglib prefix="s" uri="/struts-tags" %>
04 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd ">
05 < html >
06 < head >
07 < meta http-equiv = "Content-Type" content = "text/html; charset=ISO-8859-1" >
08 < title >Please login</ title >
09 </ head >
10 < body >
11   < s:actionerror />
12   < s:form action = "home" method = "post" >
13   < s:textfield name = "username" label = "UserName" ></ s:textfield >
14   < s:textfield name = "password" label = "Password" ></ s:textfield >
15   < s:submit name = "login" value = "login" ></ s:submit >
16   </ s:form >
17 </ body >
18 </ html >
  • After creating the login.jsp we need to configure this as action in the struts.xml file which you be should put inside source folder parallel to log4j.properties file.We can configure action as mentioned below:-
01 <? xml version = "1.0" encoding = "UTF-8" ?>
02 <!DOCTYPE struts PUBLIC
03 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
05 < struts >
06      < include file = "struts-default.xml" ></ include >
07 < package name = "member" namespace = "/member" extends = "struts-default" >
08          < action name = "login" >
09              < result >/login.jsp</ result >
10          </ action >
11      </ package >
12 </ struts >
  • Now try running this application by right click on project run as > web application and click http://localhost:8080 . You will see index.html and when you click on login you will get this exception :-

SEVERE: Unable to set parameter [location] in result of type    [org.apache.struts2.dispatcher.ServletDispatcherResult]

Caught OgnlException while setting property ‘location’ on type ‘org.apache.struts2.dispatcher.ServletDispatcherResult’. – Class: ognl.OgnlRuntime

File: OgnlRuntime.java

Method: invokeMethod

Line: 508 – ognl/OgnlRuntime.java:508:-1

at com.opensymphony.xwork2.ognl.OgnlUtil.internalSetProperty(OgnlUtil.java:392)

Caused by: java.lang.IllegalAccessException: Method [public void org.apache.struts2.dispatcher.StrutsResultSupport.setLocation(java.lang.String)] cannot be accessed.

at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:508)

at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:812)

at ognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:964)

at ognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:75)

at ognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:131)

at com.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:28)

at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:1656)

at ognl.ASTProperty.setValueBody(ASTProperty.java:101)

at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:177)

at ognl.SimpleNode.setValue(SimpleNode.java:246)

at ognl.Ognl.setValue(Ognl.java:476)

at com.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:192)

at com.opensymphony.xwork2.ognl.OgnlUtil.internalSetProperty(OgnlUtil.java:385)

… 73 more

  • In order to resolve this problem we  need to create an ServletContextListner which will set OGNL security manager to null when the context is initialized.
01 package com.login;
02  
03 import javax.servlet.ServletContextEvent;
04 import javax.servlet.ServletContextListener;
05  
06 import ognl.OgnlRuntime;
07  
08 public class OgnlListener implements ServletContextListener {
09  
10      @Override
11      public void contextDestroyed(ServletContextEvent arg0) {
12          // TODO Auto-generated method stub
13  
14      }
15  
16      @Override
17      public void contextInitialized(ServletContextEvent arg0) {
18          OgnlRuntime.setSecurityManager( null );
19      }
20  
21 }
  • Also we will need to make entry in web.xml file also for OgnlListener
1      < listener >
2      < listener-class >com.login.OgnlListener</ listener-class >
3 </ listener >
  • Now if you run the web application you will see the login page.
  • You need to add this step if you are using Google App Engine 1.2.6 because when you run struts2 application on google app engine 1.2.6 you will get the following error:-

javax.servlet.ServletException: java.lang.NoClassDefFoundError: javax.swing.tree.TreeNode is a restricted class. Please see the Google App Engine developer’s guide for more details.
at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:825)
at org.apache.jasper.runtime.PageContextImpl.access$1100(PageContextImpl.java:64)
at org.apache.jasper.runtime.PageContextImpl$12.run(PageContextImpl.java:745)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:743)
at org.apache.jsp.login_jsp._jspService(login_jsp.java:86)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
at com.google.appengine.tools.development.PrivilegedJspServlet.access$101(PrivilegedJspServlet.java:23)
at com.google.appengine.tools.development.PrivilegedJspServlet$2.run(PrivilegedJspServlet.java:59)
at java.security.AccessController.doPrivileged(Native Method)
at com.google.appengine.tools.development.PrivilegedJspServlet.service(PrivilegedJspServlet.java)

To avoid this error you need to create a new package “freemarker.core” in your source folder and add the following class

001 </span></span>
002  
003 /*
004   * Copyright (c) 2003 The Visigoth Software Society. All rights
005   * reserved.
006   *
007   * Redistribution and use in source and binary forms, with or without
008   * modification, are permitted provided that the following conditions
009   * are met:
010   *
011   * 1. Redistributions of source code must retain the above copyright
012   *    notice, this list of conditions and the following disclaimer.
013   *
014   * 2. Redistributions in binary form must reproduce the above
015 copyright
016   *    notice, this list of conditions and the following disclaimer in
017   *    the documentation and/or other materials provided with the
018   *    distribution.
019   *
020   * 3. The end-user documentation included with the redistribution, if
021   *    any, must include the following acknowledgement:
022   *       "This product includes software developed by the
023   *        Visigoth Software Society (http://www.visigoths.org/ )."
024   *    Alternately, this acknowledgement may appear in the software
025 itself,
026   *    if and wherever such third-party acknowledgements normally
027 appear.
028   *
029   * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names
030 of the
031   *    project contributors may be used to endorse or promote products
032 derived
033   *    from this software without prior written permission. For written
034   *    permission, please contact visigo...@visigoths.org.
035   *
036   * 5. Products derived from this software may not be called
037 "FreeMarker" or "Visigoth"
038   *    nor may "FreeMarker" or "Visigoth" appear in their names
039   *    without prior written permission of the Visigoth Software
040 Society.
041   *
042   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
043   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
044   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
045   * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
046   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
047   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
048   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
049   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
050   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
051   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
052   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
053   * SUCH DAMAGE.
054   *
055 ====================================================================
056   *
057   * This software consists of voluntary contributions made by many
058   * individuals on behalf of the Visigoth Software Society. For more
059   * information on the Visigoth Software Society, please see
061   */
062  
063 package freemarker.core;
064  
065 import java.io.IOException;
066  
067 /**
068   * A TemplateElement representing a block of plain text.
069   *
070   * @version $Id: TextBlock.java,v 1.17 2004/01/06 17:06:42 szegedia Exp $
071   */
072 public final class TextBlock extends TemplateElement {
073   private static final char[] EMPTY_CHAR_ARRAY = new char[0];
074   static final TextBlock EMPTY_BLOCK = new TextBlock(EMPTY_CHAR_ARRAY, false);
075   // We're using char[] instead of String for storing the text block because
076   // Writer.write(String) involves copying the String contents to a char[]
077   // using String.getChars(), and then calling Writer.write(char[]).By
078   // using Writer.write(char[]) directly, we avoid array copying on each
079   // write.
080   private char[] text;
081   private final boolean unparsed;
082  
083   public TextBlock(String text) {
084   this(text, false);
085   }
086  
087   public TextBlock(String text, boolean unparsed) {
088   this(text.toCharArray(), unparsed);
089   }
090  
091   private TextBlock(char[] text, boolean unparsed) {
092   this.text = text;
093   this.unparsed = unparsed;
094   }
095  
096   /**
097   * Simply outputs the text.
098   */
099   public void accept(Environment env) throws IOException {
100   env.getOut().write(text);
101   }
102  
103   public String getCanonicalForm() {
104   String text = new String(this.text);
105   if (unparsed) {
106   return "<#noparse>" + text + "</#noparse>";
107   }
108   return text;
109   }
110  
111   public String getDescription() {
112   String s = new String(text).trim();
113   if (s.length() == 0) {
114   return "whitespace";
115   }
116   if (s.length() > 20) {
117   s = s.substring(0, 20) + "...";
118   s = s.replace('/n', ' ');
119   s = s.replace('/r', ' ');
120   }
121   return "text block (" + s + ")";
122   }
123  
124   TemplateElement postParseCleanup(boolean stripWhitespace) {
125   if (text.length == 0)
126   return this;
127   int openingCharsToStrip = 0, trailingCharsToStrip = 0;
128   boolean deliberateLeftTrim = deliberateLeftTrim();
129   boolean deliberateRightTrim = deliberateRightTrim();
130   if (!stripWhitespace || text.length == 0) {
131   return this;
132   }
133   if (parent.parent == null && previousSibling() == null)
134   return this;
135   if (!deliberateLeftTrim) {
136   trailingCharsToStrip = trailingCharsToStrip();
137   }
138   if (!deliberateRightTrim) {
139   openingCharsToStrip = openingCharsToStrip();
140   }
141   if (openingCharsToStrip == 0 && trailingCharsToStrip == 0) {
142   return this;
143   }
144   this.text = substring(text, openingCharsToStrip, text.length
145   - trailingCharsToStrip);
146   if (openingCharsToStrip > 0) {
147   this.beginLine++;
148   this.beginColumn = 1;
149   }
150   if (trailingCharsToStrip > 0) {
151   this.endColumn = 0;
152   }
153   return this;
154   }
155  
156   /**
157   * Scans forward the nodes on the same line to see whether there is a
158   * deliberate left trim in effect. Returns true if the left trim was
159   * present.
160   */
161   private boolean deliberateLeftTrim() {
162   boolean result = false;
163   for (TemplateElement elem = this.nextTerminalNode(); elem != null
164   && elem.beginLine == this.endLine; elem = elem
165   .nextTerminalNode()) {
166   if (elem instanceof TrimInstruction) {
167   TrimInstruction ti = (TrimInstruction) elem;
168   if (!ti.left && !ti.right) {
169   result = true;
170   }
171   if (ti.left) {
172   result = true;
173   int lastNewLineIndex = lastNewLineIndex();
174   if (lastNewLineIndex >= 0 || beginColumn == 1) {
175   char[] firstPart = substring(text, 0,
176   lastNewLineIndex + 1);
177   char[] lastLine = substring(text, 1 + lastNewLineIndex);
178   if (trim(lastLine).length == 0) {
179   this.text = firstPart;
180   this.endColumn = 0;
181   } else {
182   int i = 0;
183   while (Character.isWhitespace(lastLine[i])) {
184   i++;
185   }
186   char[] printablePart = substring(lastLine, i);
187   this.text = concat(firstPart, printablePart);
188   }
189   }
190   }
191   }
192   }
193   if (result) {
194   }
195   return result;
196   }
197  
198   /**
199   * Checks for the presence of a t or rt directive on the same line. Returns
200   * true if the right trim directive was present.
201   */
202   private boolean deliberateRightTrim() {
203   boolean result = false;
204   for (TemplateElement elem = this.prevTerminalNode(); elem != null
205   && elem.endLine == this.beginLine; elem = elem
206   .prevTerminalNode()) {
207   if (elem instanceof TrimInstruction) {
208   TrimInstruction ti = (TrimInstruction) elem;
209   if (!ti.left && !ti.right) {
210   result = true;
211   }
212   if (ti.right) {
213   result = true;
214   int firstLineIndex = firstNewLineIndex() + 1;
215   if (firstLineIndex == 0) {
216   return false;
217   }
218   if (text.length > firstLineIndex
219   && text[firstLineIndex - 1] == '/r'
220   && text[firstLineIndex] == '/n') {
221   firstLineIndex++;
222   }
223   char[] trailingPart = substring(text, firstLineIndex);
224   char[] openingPart = substring(text, 0, firstLineIndex);
225   if (trim(openingPart).length == 0) {
226   this.text = trailingPart;
227   this.beginLine++;
228   this.beginColumn = 1;
229   } else {
230   int lastNonWS = openingPart.length - 1;
231   while (Character.isWhitespace(text[lastNonWS])) {
232   lastNonWS--;
233   }
234   char[] printablePart = substring(text, 0, lastNonWS + 1);
235   if (trim(trailingPart).length == 0) {
236   // THIS BLOCK IS HEINOUS! THERE MUST BE A BETTER
237   // WAY! REVISIT (JR)
238   boolean trimTrailingPart = true;
239   for (TemplateElement te = this.nextTerminalNode(); te != null
240   && te.beginLine == this.endLine; te = te
241   .nextTerminalNode()) {
242   if (te.heedsOpeningWhitespace()) {
243   trimTrailingPart = false;
244   }
245   if (te instanceof TrimInstruction
246   && ((TrimInstruction) te).left) {
247   trimTrailingPart = true;
248   break;
249   }
250   }
251   if (trimTrailingPart)
252   trailingPart = EMPTY_CHAR_ARRAY;
253   }
254   this.text = concat(printablePart, trailingPart);
255   }
256   }
257   }
258   }
259   return result;
260   }
261  
262   /*
263   * private String leftTrim(String s) { int i =0; while (i<s.length()) { if
264   * (!Character.isWhitespace(s.charAt(i))) break; ++i; } return
265   * s.substring(i); }
266   */
267   private int firstNewLineIndex() {
268   String content = new String(text);
269   int newlineIndex1 = content.indexOf('/n');
270   int newlineIndex2 = content.indexOf('/r');
271   int result = newlineIndex1 >= 0 ? newlineIndex1 : newlineIndex2;
272   if (newlineIndex1 >= 0 && newlineIndex2 >= 0) {
273   result = Math.min(newlineIndex1, newlineIndex2);
274   }
275   return result;
276   }
277  
278   private int lastNewLineIndex() {
279   String content = new String(text);
280   return Math.max(content.lastIndexOf('/r'), content.lastIndexOf('/n'));
281   }
282  
283   /**
284   * figures out how many opening whitespace characters to strip in the
285   * post-parse cleanup phase.
286   */
287   private int openingCharsToStrip() {
288   int newlineIndex = firstNewLineIndex();
289   if (newlineIndex == -1 && beginColumn != 1) {
290   return 0;
291   }
292   ++newlineIndex;
293   if (text.length > newlineIndex) {
294   if (newlineIndex > 0 && text[newlineIndex - 1] == '/r'
295   && text[newlineIndex] == '/n') {
296   ++newlineIndex;
297   }
298   }
299   if (new String(text).substring(0, newlineIndex).trim().length() > 0) {
300   return 0;
301   }
302   // We look at the preceding elements on the line to see if we should
303   // strip the opening newline and any whitespace preceding it.
304   for (TemplateElement elem = this.prevTerminalNode(); elem != null
305   && elem.endLine == this.beginLine; elem = elem
306   .prevTerminalNode()) {
307   if (elem.heedsOpeningWhitespace()) {
308   return 0;
309   }
310   }
311   return newlineIndex;
312   }
313  
314   /**
315   * figures out how many trailing whitespace characters to strip in the
316   * post-parse cleanup phase.
317   */
318   private int trailingCharsToStrip() {
319   String content = new String(text);
320   int lastNewlineIndex = lastNewLineIndex();
321   if (lastNewlineIndex == - 1 && beginColumn != 1 ) {
322   return 0 ;
323   }
324   String substring = content.substring(lastNewlineIndex + 1 );
325   if (substring.trim().length() > 0 ) {
326   return 0 ;
327   }
328   // We look at the elements afterward on the same line to see if we
329   // should strip any whitespace after the last newline
330   for (TemplateElement elem = this .nextTerminalNode(); elem != null
331   && elem.beginLine == this .endLine; elem = elem
332   .nextTerminalNode()) {
333   if (elem.heedsTrailingWhitespace()) {
334   return 0 ;
335   }
336   }
337   return substring.length();
338   }
339  
340   boolean heedsTrailingWhitespace() {
341   if (isIgnorable()) {
342   return false ;
343   }
344   for ( int i = 0 ; i < text.length; i++) {
345   char c = text[i];
346   if (c == '/n' || c == '/r' ) {
347   return false ;
348   }
349   if (!Character.isWhitespace(c)) {
350   return true ;
351   }
352   }
353   return true ;
354   }
355  
356   boolean heedsOpeningWhitespace() {
357   if (isIgnorable()) {
358   return false ;
359   }
360   for ( int i = text.length - 1 ; i >= 0 ; i--) {
361   char c = text[i];
362   if (c == '/n' || c == '/r' ) {
363   return false ;
364   }
365   if (!Character.isWhitespace(c)) {
366   return true ;
367   }
368   }
369   return true ;
370   }
371  
372   boolean isIgnorable() {
373   if (text == null || text.length == 0 ) {
374   return true ;
375   }
376   if (!isWhitespace()) {
377   return false ;
378   }
379   // trick here
380   boolean atTopLevel = true ;
381   TemplateElement prevSibling = previousSibling();
382   TemplateElement nextSibling = nextSibling();
383   return ((prevSibling == null && atTopLevel) || nonOutputtingType(prevSibling))
384   && ((nextSibling == null && atTopLevel) || nonOutputtingType(nextSibling));
385   }
386  
387   private boolean nonOutputtingType(TemplateElement element) {
388   return (element instanceof Macro || element instanceof Assignment
389   || element instanceof AssignmentInstruction
390   || element instanceof PropertySetting
391   || element instanceof LibraryLoad || element instanceof Comment);
392   }
393  
394   private static char [] substring( char [] c, int from, int to) {
395   char [] c2 = new char [to - from];
396   System.arraycopy(c, from, c2, 0 , c2.length);
397   return c2;
398   }
399  
400   private static char [] substring( char [] c, int from) {
401   return substring(c, from, c.length);
402   }
403  
404   private static char [] trim( char [] c) {
405   if (c.length == 0 ) {
406   return c;
407   }
408   return new String(c).trim().toCharArray();
409   }
410  
411   private static char [] concat( char [] c1, char [] c2) {
412   char [] c = new char [c1.length + c2.length];
413   System.arraycopy(c1, 0 , c, 0 , c1.length);
414   System.arraycopy(c2, 0 , c, c1.length, c2.length);
415   return c;
416   }
417  
418   boolean isWhitespace() {
419   return text == null || trim(text).length == 0 ;
420   }
421  
422 }

  • Next step is to create the LoginAction which will be do the business processing of whether usename and password are correct .
01 package com.login;
02  
03 import com.opensymphony.xwork2.ActionSupport;
04  
05 public class LoginAction extends ActionSupport {
06  
07      private static final long serialVersionUID = 1L;
08      private String username;
09      private String password;
10  
11      public String login(){
12          if (username.equals( "whyjava" ) && password.equals( "password" )){
13              addActionMessage( "You are successfully logged in." );
14              return SUCCESS;
15          }
16          addActionError( "Username and Password Combination doesnot match." );
17          return INPUT;
18      }
19  
20      public String getUsername() {
21          return username;
22      }
23  
24      public void setUsername(String username) {
25          this .username = username;
26      }
27  
28      public String getPassword() {
29          return password;
30      }
31  
32      public void setPassword(String password) {
33          this .password = password;
34      }
35  
36 }
  • Next we need to modify struts.xml so that we LoginAction is configured.
01 <? xml version = "1.0" encoding = "UTF-8" ?>
02 <!DOCTYPE struts PUBLIC
03 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
05 < struts >
06      < include file = "struts-default.xml" ></ include >
07 < package name = "member" namespace = "/member" extends = "struts-default" >
08          < action name = "login" >
09              < result >/login.jsp</ result >
10          </ action >
11          < action name = "home" method = "login" class = "com.login.LoginAction" >
12              < result >/home.jsp</ result >
13              < result name = "input" >/login.jsp</ result >
14          </ action >
15      </ package >
16 </ struts >
  • finally we need to add one more jsp which is home.jsp which will be called when user is able to successfully login.
01 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
02      pageEncoding="ISO-8859-1"%>
03 <%@ taglib prefix="s" uri="/struts-tags"%>
04 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd ">
05 < html >
06 < head >
07 < meta http-equiv = "Content-Type" content = "text/html; charset=ISO-8859-1" >
08 < title >Home Page</ title >
09 </ head >
10 < body >
11 < s:actionmessage />
12  
13 </ body >
14 </ html >
  • Now try running this application by right click on project run as > web application and click http://localhost:8080 .

index

  • Now click on the login link you will be taken to the login page

login

  • Now enter username as whyjava and password as password you will be an struts 2 action will fire and you will be taken to the home page.

home

I have tried to cover all the steps you will need to start of your first struts 2 project. Hope you all find this post useful.

If you need to start learning struts2 you can read Struts 2 in Action . It is a very good book to get a very good understanding of all the struts 2 concepts.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值