Struts has a lot of different features, and trying to introduce them all at once can confuse and scare off users. After getting frustrated reading various tutorials, I decided to sit down and figure out just how simple a Struts implementation could be while still preserving a proper MVC (model two) architecture.
The Struts HTML and Bean tagsets are wonderful, but they are by no means required to use Struts: while the tutorials and introductions do not advertise this fact, Struts works fine with conventional HTML forms and with basic JSPs. I was able to add Struts support to a simple WebApp using only three *.jar files and no *.tld files:
- commons-beanutils.jar
- commons-collections.jar
- commons-digester.jar
- commons-logging.jar
- struts.jar
So, simply add those to your WEB-INF/lib/ directory, and you have all the library support you'll need for now.
Next, you need to set up WEB-INF/web.xml to use Struts' ActionServlet:
<web-app> <display-name>Minimal Struts Application</display-name> <description>Minimal Struts-based WebApp.</description> <servlet> <servlet-name>MinimalStrutsApp</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>MinimalStrutsApp</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
You also need to add one (that's right, just one) extra configuration file, WEB-INF/struts-config.xml:
<struts-config> <form-beans> <form-bean name="nameBean" type="com.megginson.NameBean"/> </form-beans> <action-mappings> <action path="/foo" type="com.megginson.SubmitAction" input="/index.jsp" name="nameBean" scope="request"> <forward name="success" path="/hello.jsp"/> <forward name="failure" path="/error.jsp"/> </action> </action-mappings> </struts-config>
I created two JSPs. First, index.jsp, which contains a simple HTML form and no special JSP logic at all (it could have been named index.html):
<html> <head> <title>Servlet Test</title> </head> <body> <h1>Servlet Test</h1> <form action="foo.do" type="GET"> <input type="text" name="name"/> <input type="submit" value="Say hi!"/> </form> </body> </html>
The second JSP, hello.jsp, displays the output from the servlet, and uses a bit of ugly embedded Java (yes, a tag library would have been cleaner); again, this is straight-forward, non-Struts stuff:
<html> <head> <title>Hello</title> </head> <body> <h1>Hello</h1> <jsp:useBean id="nameBean" class="com.megginson.NameBean" scope="request"></jsp:useBean> <p>Hello, <%=nameBean.getName()%>!</p> </body> </html>
Finally, I added two simple classes. The first one, com.megginson.Name{{`Bean, extends the Struts Action}}`Form class, and is the bean that holds state information for the request (Struts populates it automatically from the HTML form):
package com.megginson; import java.io.Serializable; import org.apache.struts.action.ActionForm; public class NameBean extends ActionForm implements Serializable { public NameBean () { } public String getName () { return name; } public void setName (String name) { this.name = name; } private String name; }
The second class, com.megginson.Submit{{`Action, is virtually useless in its current state, but is here to show how the architecture works. It extends the Struts Action class, and is invoked by the Struts Action}}`Servlet:
package com.megginson; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class SubmitAction extends Action { public ActionForward execute (ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { NameBean nameBean = (NameBean) form; nameBean.setName(nameBean.getName() + ", esquire"); return mapping.findForward("success"); } }
And that's it: a simple Struts MVC app.