??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
//关于argsQ如果ApplicationMessages.properties 中有Q就取对应的|如果没有Q就用这个args?br />
]]>
<param-name>config</param-name>
<param-value>/WEB-INF/config/struts/struts-config.xml</param-value>
</init-param>
<init-param>
//q里表示所有以account开头的*.do都用下面的配置文gQ而在配置文g?br /> Actionmapping不用加上account?br />
<param-name>config/account</param-name>
<param-value>/WEB-INF/config/struts/struts-config-account.xml</param-value>
</init-param>
<action-mappings>
<action path="/searchAccount" type="com.suzsoft.demo.account.web.AccountAction"
name="AccountForm" scope="request">
<forward name="success" path="/../WEB-INF/jsp/account/searchList.jsp"/>
<forward name="failure" path="/../WEB-INF/jsp/loginSuccess.jsp"/>
</action> //注意..,表示上一层目录,因ؓ(f)已经在account下,所以要回去
用tiles׃需要了Q?/font>
</action-mappings>
三U联下拉菜单实现 | ||
zhangv 原创 (参与分:(x)15623Q专家分Q?020) 发表Q?005-05-28 13:31 版本Q?.0 阅读Q?B>1490? |
三U联下拉菜单实现(xml+js+struts) derekzhangv.at.hotmail.com 好不Ҏ(gu)实现的一个三U联菜?喜欢把复杂的问题单化,所以从|上的一些方法中提取ZU相Ҏ(gu)爽的Ҏ(gu) - jsp面里只多了2行代?(不过多了两个文g) 目是用struts,所以jspZ(其实q个实现应该在Q何情况下都是可以用的,无论asp,php...)生成:"1个form里含2l?U 联菜? 从某省某市某?BR>到某省某市某?BR> 步骤: 1.xml数据?也就是保存省市地名层ơ信? 如果没有q个文g可能需要自己做一?从数据库或者文本里提取一个xml文g出来应该不算难事? 再说q样的文件保存在xml文g里迟早会(x)有用处的. 本例? (city.xml) ========================== <?xml version="1.0" encoding="gb2312"?> <provinces> <province name="吉林" shortname="?> <city name="长春"> <county name="" /> <county name="双阳" /> <county name="农安" /> </city> </province> <province name="北京" shortname="?> <city name=""> <county name="" /> <county name="北京" /> <county name="东城" /> <county name="西城" /> </city> </province> <province name="p" shortname="?> <city name="太原"> <county name="" /> <county name="古交" /> <county name="x" /> <county name="清徐" /> <county name="娄烦" /> </city> <city name="大同"> <county name="" /> <county name="天镇" /> <county name="灵丘" /> </city> </province> </provinces> ========================== 2.javascript(弟的js学的不好,q请各位写个更好更简z的Ҏ(gu)) (selectCity.js) ========================== var from=["province","city","county"]; var to=["toprovince","tocity","tocounty"]; function selectFrom(num){ if(num==3) return; var i,j,arrTemp=[]; for(i=0;i<num;i++) arrTemp[i]=document.all(from[i]).options[document.all(from[i]).selectedIndex].text with(document.all(from[num])){ length=0 var obj=document.all.xmlData.XMLDocument.childNodes[1]; for(i=0;i<num;i++) obj=obj.selectSingleNode(from[i]+'[@name="'+arrTemp[i]+'"]'); for(i=0;i<obj.childNodes.length;i++) options[length++].text=obj.childNodes[i].getAttribute("name"); onchange=new Function("selectFrom("+(num+1)+")"); onchange(); } } function selectTo(num){ if(num==3) return; var i,j,arrTemp=[]; for(i=0;i<num;i++) arrTemp[i]=document.all(to[i]).options[document.all(to[i]).selectedIndex].text with(document.all(to[num])){ length=0 var obj=document.all.xmlData.XMLDocument.childNodes[1]; for(i=0;i<num;i++) obj=obj.selectSingleNode(from[i]+'[@name="'+arrTemp[i]+'"]'); for(i=0;i<obj.childNodes.length;i++) options[length++].text=obj.childNodes[i].getAttribute("name"); onchange=new Function("selectTo("+(num+1)+")"); onchange(); } } ========================== 3.面文g:(q里是struts,--q个应该没有关系) (test.jsp) ========================== <script src="selectCity.js"></script> <xml id=xmlData src="city.xml" /> <body onload="selectFrom(0);selectTo(0);"> <html:form> ?lt;html:select property="province" ></html:select><html:errors property="province"/> <html:select property="city"></html:select><html:errors property="city"/> <html:select property="county"></html:select><html:errors property="county"/><br/> ?nbsp;<html:select property="toprovince" ></html:select><html:errors property="toprovince"/> <html:select property="tocity"></html:select><html:errors property="tocity"/> <html:select property="tocounty"></html:select><html:errors property="tocounty"/> </html:form> </body> ========================== q样的三步就构造了一?1个form里含2l?U联菜?,其实q是满麻烦的.之前q见q一U是在js里徏一个三l数l? |
SummaryBy George Franciscus and Danilo Gurovich
In this excerpt from Struts Recipes, (Manning Publications, December 2004) authors George Franciscus and Danilo Gurovich illustrate how to use Hibernate in a Struts application. They also show how to create a Struts plug-in to improve performance. (2,200 words; January 24, 2005)
ersistence is a fundamental piece of an application. Obviously, without persistence all work would be lost. However, persistence means different things to different people. The length of time something must be persisted is a fundamental qualifier in choosing a persistence storage medium. For example, the HTTP session may be suitable when the life of a piece of data is limited to the user's session. In contrast, persistence over several sessions, or several users, requires a database. The volume of data is another important qualifier. For example, best practices suggest large amounts of data should not be stored in an HTTP session. In those circumstances, you need to consider a database. In this recipe we target persistence in a database.
The type of database you choose has an important influence on your architecture and design. As object-oriented developers, we tend to represent data as an interconnected web of objects as a means to describe the business problem at hand—this is often called a domain model. However, the most common storage medium is based on a relational paradigm. Unless our object model mirrors a relational structure, the in-memory representation of our data is at odds with the means to persist it. This problem is called the mismatch paradigm. One of the most popular tools to address the mismatch problem is a category of tools called object-relational mappers. An object-relational mapper is software used to transform an object view of the data into a relational one, and provide persistence services, such as create, read, update, and delete (CRUD). Many good papers have been written on object-relational mappers, but in essence, they all speak to the Data Mapper pattern. One of the most popular object-relational mappers is the open source Hibernate project.
In this recipe, we show you how to employ Hibernate in a Struts application. In addition, we will show you how to create a Struts plug-in to give your Hibernate-powered Struts applications a performance boost.
Recipe
In this recipe, we use an example to illustrate everything you need to do to use Hibernate in a Struts application. We create an application to retrieve and display elements from the chemical periodic table. The application offers the user a search page to look for an element by element symbol. The application responds by searching the database for an element matching the symbol name and returns information about the element.
We'll start by showing you how to get the Hypersonic database server up and running. With the database server started, we create the table and data required to exercise the application. Once the database is ready to go, we'll create all the Hibernate artifacts required to execute this application by using the Hypersonic database server. The next step is to respond to search requests by calling upon Hibernate to handle database access from inside our Action
. Because creating Hibernate factory objects is expensive, we'll create a Struts plug-in to create the factory and store it in context.
Let's start by bringing up the Hypersonic database server. You need to download Hypersonic from http://hsqldb.sourceforge.net/. Place hsqldb.jar
in your classpath and launch Hypersonic by entering the following command in your DOS prompt:
java org.hsqldb.Server
Although the server's response varies from one version of Hypersonic to another, the following response is a typical indication that Hypersonic is ready to serve database requests.
Server 1.6 is running
Press [Ctrl]+{c} to abort
With the database server up and running, we are ready to create the elements table and populate it with data, as shown in Listing 1.
Listing 1. Create and populate elements tables
create table elements (id integer(3) IDENTITY,
name char(30),
number char(30),
mass char(30),
symbol char(2));
CREATE UNIQUE INDEX ui_elements_pk ON elements (symbol)
insert into elements ( name, number, mass, symbol) values ('Manganese','25','55','Mn');
insert into elements ( name, number, mass, symbol) values ('Zinc','30','65','Zn');
insert into elements ( name, number, mass, symbol) values ('Thulium','69','169','Tm');
insert into elements ( name, number, mass, symbol) values ('Californium','98','251','Cf');
insert into elements ( name, number, mass, symbol) values ('Gold','79','197','Au');
insert into elements ( name, number, mass, symbol) values ('Ytterbium','70','173','Yb');
insert into elements ( name, number, mass, symbol) values ('Molybdenum','42','96','Mo');
insert into elements ( name, number, mass, symbol) values ('Palladium','46','106','Pd');
Listing 1 presents the SQL commands necessary to create the elements table, create a unique index on symbol
, and insert data We have only presented a few of the periodic elements. We'll leave it to you to dust off your high school chemistry textbook to create data for the remaining elements.
Listing 2 presents the Element
JavaBean used to store data retrieved from the database.
Listing 2. Element JavaBean
package com.strutsrecipes.hibernate.beans;
public class Element {
private String name;
private String symbol;
private String number;
private String mass;
private int id;
public Element() {
super();
}
public Element(String name, String symbol, String number, String mass) {
this.name = name;
this.symbol = symbol;
this.number = number;
this.mass = mass;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMass() {
return mass;
}
public String getName() {
return name;
}
public String getNumber() {
return number;
}
public String getSymbol() {
return symbol;
}
public void setMass(String mass) {
this.mass = mass;
}
public void setName(String name) {
this.name = name;
}
public void setNumber(String number) {
this.number = number;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
}
Hibernate is an object-relational mapping tool. Its job is to map objects to relational tables and vice versa. Therefore, we must tell Hibernate how to map the columns in the "elements" table to the properties of the Elements
JavaBean. This is done using the Element.hbm.xml
file. The information embodied in this file is required to empower Hibernate to copy data from the table to the Elements
JavaBean. If we were using Hibernate to update data, the information in the Element.hbm.xml
file would be used to extract data from the Elements
JavaBean to generate SQL update statements. Listing 3 presents Element.hbm.xml
.
Listing 3. Element.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sf.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="com.strutsrecipes.hibernate.beans.Element" table="elements">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<property name="number" column="number"/>
<property name="mass" column="mass"/>
<property name="symbol" column="symbol"/>
</class>
</hibernate-mapping>
Let's step through Listing 3
We declare the full package name of the class to be associated with the "elements" table. We then declare the name of the table associated with that class. Next, we declare the mapping from the id
JavaBean property to the id
column. Because the property and column names have the same value, we could have omitted the column attribute, but we have explicitly declared the column for clarity purposes. The <id>
tag is a special tag. It is used to declare the primary key for the table. The enclosing <generator>
tag instructs Hibernate to generate the key in whichever way is most appropriate for the database implementation. You should consult Hibernate documentation for more information on the <id>
tag. Finally, we declare mapping for the remaining JavaBean properties. Once again the column
attribute is declared for clarification purposes.
Once the mapping file has been broken down in detail, it's all rather straightforward. It simply describes which table maps to which class and which JavaBean properties map to which column names. Later on we will tell you where to place this file.
Next, we configure Hibernate by declaring environmental information. In Listing 4, we present the hibernate.cfg.xml
file.
Listing 4. hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">net.sf.hibernate.dialect.HSQLDialect</property>
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<property name="connection.url">jdbc:hsqldb:hsql://127.0.0.1</property>
<property name="show_sql"> </property>
<property name="">true</property>
<mapping resource="/com/strutscookbook/hibernate/beans/Element.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Let's step through Listing 4.
We start by specifying the database implementation dialect that allows Hibernate to take advantage of implementation-specific features. We declare the Hypersonic dialect. You should consult the Hibernate documentation to choose the appropriate dialect for your database. We then declare the database driver. You must ensure this driver is in your application's classpath. We then declare the database username, the database password, and the database connection URL. Next, we instruct Hibernate to display the SQL generated at runtime in the log.
The hibernate.cfg.xml
file must be placed in your classpath.
The procedure to use Hibernate within your application requires the following steps:
A Hibernate best practice is to create and cache the Hibernate factory to enhance performance. Therefore, we will create a Struts plug-in to perform Steps 1 and 2 and cache the Hibernate factory in the servlet context, as shown in Listing 5.
Listing 5. HibernatePlugin.java
package com.strutsrecipes.hibernate.plugin;
import java.net.URL;
import javax.servlet.ServletException;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.MappingException;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
public class HibernatePlugin implements PlugIn {
private Configuration config;
private SessionFactory factory;
private String path = "/hibernate.cfg.xml";
private static Class clazz = HibernatePlugin.class;
public static final String KEY_NAME = clazz.getName();
private static Log log = LogFactory.getLog(clazz);
public void setPath(String path) {
this.path = path;
}
public void init(ActionServlet servlet, ModuleConfig modConfig)
throws ServletException {
try {
URL url = HibernatePlugin.class.getResource(path);
config = new Configuration().configure(url);
factory = config.buildSessionFactory();
servlet.getServletContext().setAttribute(KEY_NAME, factory);
} catch (MappingException e) {
log.error("mapping error", e);
throw new ServletException();
} catch (HibernateException e) {
log.error("hibernate error", e);
throw new ServletException();
}
}
public void destroy() {
try {
factory.close();
} catch (HibernateException e) {
log.error("unable to close factory", e);
}
}
}
Creating a Struts plug-in requires only two steps. First, create a class implementing org.apache.struts.action.PlugIn
(Listing 5). Second, define a <plug-in>
tag in the struts-config.xml
file (Listing 6).
Let's step through Listing 5.
We create a constant to hold the name of the servlet context attribute key. We have chosen to use the HibernatePlugin
class name. Notice the constant is static public final. We use the HibernatePlugin
class to access the key name in the Action
(Listing 7). We define the path property. By default, the Hibernate-Plugin
looks for the Hibernate configuration file at /hibernate.cfg.xml
. You can use this property to load the Hibernate configuration file from another filename and directory anywhere on the classpath. Next, we use the classloader to find the Hibernate configuration file and then we create the Hibernate configuration object. We use the Hibernate configuration object to create a Hibernate factory object and then we store the Hibernate factory object in the servlet context. The factory is now available to any code with a reference to the servlet.
As a good practice, we close the factory in the destroy method.
Listing 6 presents the application struts-config. The only thing out of the ordinary here is the <plug-in>
tag. This is where we declare the Hibernate plug-in, which creates and caches the Hibernate factory object.
Listing 6. struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="searchForm"type="com.strutsrecipes.hibernate.forms.SearchForm"/>
</form-beans>
<global-forwards>
<forward name="search" path="/search.jsp"/>
<forward name="searchsubmit" path="/searchsubmit.do"/>
</global-forwards>
<action-mappings>
<action path="/searchsubmit"
type="com.strutsrecipes.hibernate.actions.SearchAction"
name="searchForm"
scope="request"
input="/search.jsp">
<forward name="success" path="/element.jsp"/>
</action>
</action-mappings>
<plug-in className="com.strutsrecipes.hibernate.plugin.HibernatePlugin">
<set-property property="path" value="/hibernate.cfg.xml"/>
</plug-in>
</struts-config>
Listing 7 presents the SearchForm
used to search for an element. It's very simple because the user can only search by element symbol.
Listing 7. SearchForm.java
package com.strutsrecipes.hibernate.forms;
import org.apache.struts.action.ActionForm;
public class SearchForm extends ActionForm {
String symbol;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
}
Let's have a look at the SearchAction
in Listing 8. Although you may decide to employ Hibernate in other areas of your application architecture, we have chosen to use it in the Action
. We'll defer the discussion of the other alternatives to the discussion section.
Listing 8. SearchAction.java
package com.strutsrecipes.hibernate.actions;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.strutsrecipes.hibernate.beans.Element;
import com.strutsrecipes.hibernate.forms.SearchForm;
import com.strutsrecipes.hibernate.plugin.HibernatePlugin;
public class SearchAction extends Action {
private static Log log = LogFactory.getLog(SearchAction.class);
final public static String HQL_FIND_ELEMENT =
"from com.strutsrecipes.hibernate.beans.Element as e where e.symbol = ?";
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
SearchForm searchForm = (SearchForm) form;
Element element = null;
List elements = null;
SessionFactory factory = null;
Session session = null;
try {
factory =
(SessionFactory) servlet.getServletContext()
.getAttribute(HibernatePlugin.KEY_NAME);
session = factory.openSession();
elements =
session.find(
HQL_FIND_ELEMENT,
searchForm.getSymbol(),
Hibernate.STRING);
if (!elements.isEmpty()) {
element = (Element) elements.get(0);
}
} catch (HibernateException e) {
log.error("Hibernate error", e);
} finally {
log.error("Hibernate exception encountered");
session.close();
}
if (element != null) {
request.setAttribute("element", element);
return mapping.findForward("success");
}
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.notfound"));
saveErrors(request, errors);
return mapping.getInputForward();
}
}
Let's take a quick overview of what happens in the SearchAction
. The SearchAction
uses the SearchForm.getSymbol()
method to obtain the element symbol entered by the user on the search page. Hibernate is used to search the database and convert the data stored in the database to an Element
object. The Element
object is placed in request context for the JavaServer Pages (JSP) page. Let's step through Listing 8 line by line to see how it's done in detail.
First, we declare a constant to search the database. We next cast the form to SearchForm
and then we obtain the Hibernate factory. Recall the Hibernate plug-in has already created the factory and cached it in the servlet context. Next, we obtain a session. The session obtains a connection to the database. Hibernate uses the configuration information we created in Listing 4 to connect to the database. We then search the database.
There are other ways to employ Hibernate to search the database, but the find
method is appropriate whenever a search doesn't use the primary key. Notice, we have the HQL_FIND_ELEMENT
constant declared. The SQL defined in HQL_FIND_ELEMENT
looks somewhat like standard SQL, but not quite. The SQL used by Hibernate is proprietary to Hibernate and reflects an object-oriented version of SQL, rather than the relational SQL to which you are accustomed.
Let's delve into the Hibernate SQL (HQL) code snippet.
from com.strutsrecipes.hibernate.beans.Element as e where e.symbol = ?
This statement tells Hibernate to select all Element
objects residing in the com.strutsrecipes.hibernate.beans
package. The where
clause filters the list to only those elements whose symbols match a runtime parameter. The as e
indicates that e
may be used as an alias elsewhere in the HQL, as we have done in the where
clause. You can see that we are selecting objects, not rows, in the database. Hibernate uses the information in Listing 4 to map the class we are interested in to its associated table. In this example, the relationship between the table and the object are very close, but that does not necessarily need to be the case.
The second and third arguments to the find
method are the value and data type of the HQL replacement parameter. The Hibernate reference material describes other ways to replace runtime parameters.
The find
method always returns a List
. In this case, we obtain a list of Element
objects. We are confident that a maximum of one instance is returned because the "elements" table has a unique key constraint on the symbol
column (see Listing 1).
Returning to Listing 8, we copy the element reference in the first position in the list to the element variable. To deal with any Hibernate exceptions, we have chosen to log the exception and present the user a "not found" message, but you may decide to present a different message or use declarative exception handling. Next, we close the session. Closing the session in the finally
clause guarantees it is attempted even when exceptions are thrown. We store the Element
object in the request context and finally we build the ActionError
when the symbol can't be found. For the sake of completeness, we have presented the search.jsp
(Listing 9) and the element.jsp
(Listing 10).
Listing 9. Search.jsp
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:html>
<body>
<h1>Search for an Element</h1>
<html:form action="/searchsubmit.do">
symbol <form:text property="symbol"/>
<html:submit value="Search"/>
</html:form>
<html:errors/>
</body>
</html:html>
Listing 10. Element.jsp
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:html>
<h1>Periodic Element</h1>
Name: <bean:write name="element" property="name"/><br>
Symbol: <bean:write name="element" property="symbol"/><br>
Number: <bean:write name="element" property="number"/><br>
Mass: <bean:write name="element" property="mass"/><br>
<html:link forward="search">Search</html:link><p>
</html:html>
Before putting Hibernate to work, consult the Hibernate documentation to ensure you have all the required Hibernate jar files in your classpath.
Discussion
Persistence of data is a tedious and laborious job. To make matters worse, a considerable effort must be spent transforming an object-oriented representation of the data to a relational one, and vice versa. Fortunately, several good object-relational mappers exist to ease this burden. In this recipe, we explored Hibernate—one of the most popular open source object-relational mappers available to Java programmers.
Hibernate is a very rich product with many unexplored features left for you to discover. Our simple example is limited to read
behavior, but the rest of the CRUD family is just as easy. Update functionality is as simple as accessing the desired element, calling the desired JavaBean setter, and calling the session commit method. Hibernate takes care of generating the SQL and updating the table. A delete
is also rather simple?CODE>session.delete(element) is all it takes! Finally, create
only requires instantiating the object, calling the setters, and calling session.save(element)
.
Hibernate best practices recommend caching the Hibernate factory object. We chose to create and cache the factory using a Struts plug-in. Alternatively, you could have chosen to cache using any other means in your arsenal.
Although this recipe can serve you well, there are some drawbacks. First, we have exposed Hibernate to the Struts Action
. Migrating to another persistence layer framework requires us to change every Action
employing Hibernate. Second, our persistence is tightly coupled to the presentation layer. This coupling denies us the opportunity to reuse the persistence logic in some other presentation mechanism, such as a batch program.
Although there is room for improvement, this recipe is suitable when you do not expect to reuse your persistence logic. You may find yourself in this situation developing prototypes or small throwaway applications.
About the author
George Franciscus is a J2EE consultant and Struts authority. He is a coauthor of Manning's Struts in Action.
Danilo Gurovich is a manager of Web engineering at an e-commerce company. He has designed e-commerce and ERP/EAI Struts applications, and has led teams who have built them.
MonkeyStruts by Arron Bates. An approach to nesting beans.
REGEXP.VALIDATOR.STRUTS by Emmanuel Boudrant - A validation component that works with Struts 1.0, to manage form validation on server-side and client-side.
Struts-WAS.jar by Christopher Assenza - Modified Struts 1.0 JAR for Websphere 3.5 or 4. Zipped for download. (For additional tips regarding Websphere 3.5 see http://jakarta.apache.org/struts/installation-was352-x.html.)
Struts Layout by Improve - An extension library to improve interfaces creation with Struts.
Indexed Tags [Also available in the nightly build] by Dave Hays - Produce indexed names such as <input type="text" name="parameter[0].value" value="Mac">. Link, Submit, and Select tags are included too.
Struts IF/THEN/ELSE and SWITCH tags by Niall Pemberton.
TextArea Wrapping by Matthias Bauer. Patch to HTML:TextArea tag to provide wrapping of long lines.
RowTag (ZIP file for download) - Source for a Struts-compatible tag to generate alternating row colors in a table by Niall Pemberton. [NOTE: Requires a Struts build dated after 2001-04-28]
Contributor Extensions |
Pow2ACL - Access Control List library. Track of application users roles and permissions. User can be authenticated: - directly using the package API; - using custom JSP tag libraries. Struts .. in Rose by Emmanuel.Boudrant - Use Struts with the Rational Rose UML model. Multi-Controller by Sukachevin, Stoehr - Use more than once ActionServlet in your Struts application JavaScript with html:errors - new Struts validation by Adam Grohs. Scioworks Camino by Scioworks Pte Ltd. A visual tool for Struts. Struts Console by James Holmes. The Struts Console is a Java Swing application that provides an easy to use interface for editing Struts' "struts-config.xml" configuration file. Expresso by JCorporate. An open source application development (AD) framework integrated with Struts. Dynamic ActionForm Properties by Jan Sorensen. Bean Utils with Indexed Strings by Gregor Rayman. Role-Based Actions by Nic Hobs. Set a security role for an Action from with struts-config. Struts CodeMaker by Ravindran Ramaiah - Generate Struts application by reading configuration file or JSP files. Updated 2001-08-21. Struts Generator by David Winterfeldt - Based on the generator.xml and a table/query an xml file is generated. Based on the generated xml file a primary key class, data bean class, jdbc class, and an ActionForm (Struts) can be generated. ValueIterator by Ted Husted - Simple wrapper around a RowSet for use with Struts iterator tag. Also includes generic toMap(), set(map) methods for flexible data transfer. Struts Transformer by Ron Smith - Transformations are responsible for taking an object in one form and transforming it into another. A forward transformation takes an object from its primary form to a secondary form (e.g. Date object to String). A reverse transformation takes an object from a secondary form to its primary form (e.g. String to Date). Struts Extender by Ron Smith - Add extensions to the struts framework via entries in the Struts configuration file. Mapper Framework by Capco - The Mapper framework can be used for automating the process of validating/converting/transferring data fields. (See README to get started. Updated 18-JUL-2001.) Bean factory by Oleg V Alexeev - Adds the ability to easily link data bean creation to any Struts Action. All information about databeans and actions mappings stored in the standard Struts configuraton file. Workflow Extension by Matthias Bauer - An extension to the core Struts framework which provides control flow between actions. Struts Menu by Scott Sayles (ZIP file for download) - A Struts-compatible web menuing component (early release - work in progress) - unzip to a "struts-menu" folder, and see the README. Struts Validator [Also in the nightly build /contrib folder] by David Winterfeldt - Perform basic validations to check if a field is required, matches a regular expression, and some basic type checking. Different validation rules can be defined for different locales. The framework has basic support for user defined constants which can be used in some field attributes. The validation routines are modifiable in the validation.xml file so custom validation routines can be created and added to the framework. TLD to VLM by Mario Busche - Simple Java program to convert standard TLD's to the VLM format used by Homesite, CF Studio, and JRun Studio. UltraDev 4.0 Custom Tag Library Extension - Hosted by Jakarta Taglibs. Tiles Library for building JSP views [Also in the nightly build /contrib folder] by Cedric Dumoulin - A component is a JSP page that can be inserted in another JSP page, like templates, but can take "parameters" (URLs or 'direct' string intemplates). |
Projects and Examples |
Artimus by Ted Husted - Simple news poster application. Demonstrates using helper beans and a JDBC database with Struts. WAR zipped for download. Uses Scaffold package. See WEB-INF/README.txt for setup. Scaffold by Ted Husted - Utility package of classes that can be used with various Web applications. Struts Polls by Ted Husted - Simple poll application. Demonstrates using a database with Struts. Struts-example modified for iPlanet Application Server SP2 by Matt Raible. The Struts Framework by Steve Wilkinson - Excerpt from latest Wrox Professional JSP book. Struts-Simple by Ted Husted - (WAR file zipped for download) A simple skeleton application outlining the files needs to input and re-display data. Now also demonstrates using "nested" beans. myCart - Example Shopping Cart application using Struts - joint project with several contributors. Sample hdml/wireless based struts application by Richard Backhouse. Struts Login (WAR file zipped for download) by Ted Husted - A minimalist Struts application demonstrating form validation and tracking users with a session attribute (WAR file). |
Tutorials |
How To: (Form-Based Authentication) use the form-error page to login by Matt Raible. WebSphere 4 Application Development Handbook - IBM "Redbook" - See "Designing with Frameworks (Chapter 7). Struts Catalog by Ted Husted - Overview of Struts Design Patterns and Strategies. HOWTO Setup and Debug STRUTS Example in Forte by Michael Mok. JBuilder 5, Struts 1.0 & WebLogic 6.0, a Tutorial by Markus Colombo. Using JBuilder5 with Struts 1.0 Release by Anthony Martin. 3148 Configuring AppServer to Work with Struts by Ken Sipe (7/25/2001) 3004 Building Extensible Web Frameworks Using XML, XSL-T, and Java by Richard Vowles 7/21/2001 Strut by Strut by Ted Husted - Building a web application from the ground up (maintenance release 2001/Aug/19). J2EE Tutorial - Early Release chapter featuring Struts 1.0 tags. Welcome to the Struts Framework by Bluestone Software. An Introduction to Struts by Casey Kochmer. Struts UML Diagrams (PDF) by Jean-Pierre Schnyder. Blueprinting a Struts Application by Ted Husted - Sample specification and API for the Struts Example application. |
Seminars |
Fast Track to MVC Frameworks - 2001-Dec-2. BravePoint - Advanced JSP Architecture for J2EE - 2001-11-19, 2001-12-10. |
Articles |
The Struts Framework's Action Mappings Configuration File by Wellington L.S. da Silva Web Development Products Spreadsheet by Dan Cancro. Layering Applications by Scott Stanchfield. MVC and Struts by Steven Sweeting, Clive Jones, and Aaron Rustad. Introduction to Jakarta Struts Framework by Sue Spielman. The Struts Framework's Action Mappings Configuration File by Wellington L.S. da Silva Is Struts Performant? by Ted Husted -- An analysis of framework components, and how they contribute to overall efficiency. Struts for Everyone by Jonathan Asbell -- Word document zipped for download. Early release: still in working draft form. Approaches to User Authentication and Access Control in Web Applications by Craig McClanahan. Slides from the JavaOne BOF (June 2001 #1291). Star Office Format. Zipped for download. Support your application development with Struts [404] by McClanahan, McCay, and Bergenholtz. Introduction to MVC and the Jakarta Struts Framework by Craig Tataryn. Kickstart - The obligatory Struts Q&A. Struts, an open-source MVC implementation by Malcom Davis. Strut Your Stuff With JSP Tags, by Thor Kristmundsson. Using the Struts Framework to Develop a Message Board by Maneesh Sahu (article requires registration with informit.com). |
Books |
|
Selected APIs, RFCs, and JSRs |
|
Other Resource Pages |
More About Struts by Husted dot Com. German Translation of Users Guide by Hartmut Bernecker. |
Mailing List Archives |
Struts FAQ with Mailing List Threads - Clippings from the User Lists |
Powered by Struts |
|
Java / Struts ISPs |
Provided as a reference only. No endorsements given or implied. To be listed, post a documentation enhancement request in Bugzilla. |
Consultants |
Provided as a reference only. No endorsements given or implied. To be listed, post a documentation enhancement request in Bugzilla.
|
1.0 先决条g |
q䆾用户指南是ؓ(f)那些z跃的Web开发者编写的Q假设读者已l了解java Web application是如何工作的。在开始之前,(zhn)应该已l掌握下列基本核心技术?
如果(zhn)在其他q_上开发过web applications,(zhn)也许可以l。在需要的时候参考以上的资料。他们几乎是所有Java web开发项目需要用到的核心技术? |
1.1 前言 Q回C前!Q也是Struts的简Ԍ |
当java servlets被发明出来的时候,很多E序员迅速意识到q是一个好东西。它比标准CGI快速强大,可以ULQƈ且几乎可以无限扩展? 但是无穷无尽的编?println()语句来吧HTML送到览器是费旉q且Ҏ(gu)造成问题。答案就是JavaServer Pages,它把~写servlet的Q务倒了个个ѝ现在开发者可以很Ҏ(gu)的把HTML和Java代码混合hQƈ且仍然拥有servlet的所有好处。只有天I才?x)限Ӟ我们Q! Java webE序很快变成了以JSPZ心的。关?JSP)本nq不是一件坏事,但是它ƈ没有解决程控制和web application的其他一些问? 昄Q我们需要另一个模?.. 很多聪明的程序员认识到JSP和servlets可以?B>一?/B>使用来构造webE序。Servlets可以用来辅助程控制QJSP主要x于实现那些凌qHTML.在这L(fng)q程中,一起用JSP和servlet开始被UCؓ(f)Model 2.(同时只用JSP被称为Model 1)? 当然Q天底下没有C?..很快很多人指出JSP的Model 2 遵@SmallTalk的经典的Model-View-controller设计模式。现在术语Model 2和MVC可以互相替代? Struts工程?000q?月由Craig R. McClanahan开始动工,来ؓ(f)JavaC实现一个标准的MVC框架?001q?月,Struts 1.0发布了。从此,Model 2开发开始变得不同? |
1.2 Model-View-Controller ('MVC') 设计模式 |
在MVC设计模式中,E序程׃个的Controller(控制?居中斡旋。Controller委派h--在我们的情Ş?HTTPh--到合适的handleQ处理程序)厅RHandle和ModelQ模型)相联p,每一个handle的作用就是成为在h和Model之间的适配?adaptor有一个意思是甉|插头--译者注)。Model 代表或者封装了一个程序的商业逻辑或者状态。通常控制由Controller重新转移到对应的View厅R这个{Uȝ一pd的映决定,一般从数据库或者配|文件中取得。这样就为View和Model提供了一个松散的联系Q编写和l护E序变得显而易见的的容易? |
1.3 Struts 框架U览 |
忠实的和Model-View-Controller设计模式对应QStrutsE序有三个主要的部gQ一个Servlet Controller,它由Struts本n提供,JSP 面("view"),q有E序的商业逻辑("model").我们来看看他们是怎么l合CL(fng)? Struts的Controller servlet把HTTP h打包q传送到框架中的其他对象Q包括JavaServer Pages和由Struts开发者编写的 一个ActionMapping通常?x)指?
Action 对象可以处理hq响应客L(fng)(通常是一个web browser),或者指出流E应该被指向另一个地斏V例如,如果d成功Q一个login Action可能希望把流E{Ud主菜单? Action对象可以操作E序的Controller servlet,所以可以操作这个Controller的方法。当转发控制的时候,一个Action对象可以不直接的转发一个或多个׃n对象Q包括JavaBeans,q个q程是通过把它们放到Java servlet׃n的某一个标准collection对象里去? Action对象可以创徏一个购物RBeanQ在购物车里面加上一个条目,把这个bean攑ֈsession l构里去Q然后把控制转发到另一个映。那个映会(x)使用一个JavaServer Page来显C用L(fng)购物车里的内宏V因为每个用户都有他自己的session,他们也会(x)有自q购物车。在一个StrutsE序里,大部分商业逻辑都可以由JavaBeans表示。一个Action可以调用一个JavaBean的属性,不需要知道她实际上是如何工作的。这装?商业逻辑Q所以Action可以专注于错误处理和如何转发控制? JavaBeans也可以用来管理输入的Forms.设计一个webE序的主要问题是得到q检查用户在h中的输入。通过Struts,你可?定义你自qForm Bean c集合,他们都是 Form bean可以被一个JSP使用来从用户攉数据...通过一个Action 对象来检查用戯入的数据...然后再通过JSP来重新显Cform的字Dc(din)如果检查错误,Struts׃个公用的机制来提交和昄错误信息? Struts 的Form bean在配|文件中声明Q在一个Java文g中被定义Qƈ且通过一个通用的属性名字来q接C个ActionMapping厅R当一个请?调用一个需要FormBean 的Action时候,Controller servlet要么从输入中获取form bean,要么自己构造一个form bean,把它传递到Action对象厅RAction 对象可以在显CZ前检查form bean的内容,也可以ؓ(f)要在form里显C的内容排队。准备好之后QAction对象q回控制权ƈ转移到它的输入叶面去。controller可以响应HTTPhQƈ重定向到JavaServer Page厅R? Struts 框架包括自定义的Tag来自动从一个formBean填充子段。JavaServer Page唯一需要知道的是确切的字段名和下一步提交formC处。一些部件例如被Action排队的消息可以在一个自定义tagp?出。也可以定制其他为程序定制的tag来从jsp中隐藏实现细节? 在Struts框架中的自定义tag被设计ؓ(f)使用Javaq_内置的国际化Ҏ(gu)。所有的字段名和消息都可以从消息资源中获取,q且Java可以自动Z个客L(fng)的国家和语言提供惛_应的资源。ؓ(f)了提供另一U语a的支持,只需单的的增加另一个资源文件? 除了国际化之外,q个q步的好处还在于在不同的form中保持一L(fng)标签名字Q也可以全局化的复查所有的标签和消息? 对于最单的E序来说Q有时候一个Action对象可以处理一个请求对应的商业逻辑?B>但是Q在大多数情况下Q一个Action?象应该调用另一个对象,一般是一个JavaBean来处理实际的业务逻辑?/B>q让Action专注于错误处理和程控制Q而非商业?辑。ؓ(f)了在其他q_上重用,商业逻辑JavaBean不应该引用Q何webE序的对象。Action对象应该从HTTPh译必要的细节ƈ 象普通的java变量一样传递到商业逻辑对象厅R? 举个例子Q在一个数据库E序中:(x)
不管是Actionq是JSP都不需要知道结果是从哪儿来的。他们只需要知道如何打包和昄l果? 用户指南的其它部分非常详l的解释了Struts的不同部件。Struts发布版本也包含了一些开发者手册包含几个不同的主题Q也包括例子E序Q标准的Javadoc API,当然q有全部的源代码Q? Struts 在Apache软g基金?x)协议下发布。代码拥有版权,但是可以在Q何程序中自由的用。参?A >ASF license 得到详细信息. |
1.4 ModelQ模型): pȝ状态和商业逻辑JavaBeans |
ZMVC的系l中?I>Model(模型)部分可以被分Z个概念,pȝ的内部状态和可以用来改变状态的动作。从语法上来?Q我们可以把状态信息看成是名词Q而动作是动词Q用来改变状态)? 一般来_(d)c的E序需要用一套包含一个或多个JavaBeans来表辑ֆ部状态,(q些)JavaBean包含了这个状态的详细属性。根?你的E序的复杂程度,他们可能是自我包含的Q自q道怎么样保留持l化信息Q,或者仅是一个知道必要时如何从外部数据源Q如数据库)获取信息的对象。Entity Enterprise JavaBeans (Entity EJBs)一般也用于表示内部状态? 大型E序l常使用一些bean的方法来表示一l可能的商业逻辑Q这些方法维护状态信息。例如,你可能有一个购物RBean,保存 在每个用L(fng)session中,包含用户当前军_购买的条目。这个bean可能有一?CODE>checkOut()Ҏ(gu)来取得用户信用卡 的授权,发送订单到仓库L发送。另一些系l可能把可能的动作单独包装,可能是一个Session Enterprise JavaBeans(Session EJBs). 在一些较?yu)的E序中,相反Q可能的动作?x)内|于 |
1.5 ViewQ视图): JSP面和表C部?/STRONG> |
ZStrutsE序?I>View部分基本上是由JavaServer pages(JSP)技术构成的。JSP面可以包含静态的HTMLQ或者XMLQ文本,被称为“模版文本”,再加上在Ҏ(gu)的标{运行时Q当面被调用的时候)插入动态内容的能力。JSP环境包含一套标准的动作标签Q比?CODE><jsp:useBean>他们?用处?A >JavaServer Pages Specification描述了。另外,q有一U标准的Ҏ(gu)来定义你自己的标{,他们被组l在“自定义标签库”里? Struts包含了一个内容广泛的自定义标{ֺQ用以帮助编写完全国际化的用L(fng)面。它也和处于Model部分?CODE>ActionForm高度互动。关于用这些标{Ҏ(gu)在后面会(x)详细讨论? 除了JSP 面和原有的以及(qing)自定义的标签之外Q有时候让商业逻辑对象拥有把他们自己根据当前的状态渲染成HTMLQ或者XMLQ的能力?是经帔R要的。这些被渲染出来的输出可以很Ҏ(gu)的在一个结果JSP文g里面?CODE><jsp:include>标准动作?{ּ用? |
1.6 ControllerQ控制器Q? ActionServlet ?ActionMapping |
E序?I>ControllerQ控制器Q?/I>部分x于从客户端接收请求(通常是一个用浏览器的用PQ决定那个商业逻辑Ҏ(gu)应该被执行,然后分配dl到一个合适的viewlg来制造下一步的用户界面。在Struts里面QController的主要部分是一个servlet,它是 Struts也支持在 |
3.1 U览 |
q一章关注构造程序的View(视图)部g的Q务,主要是由JavaServer Pages(JSP)技术完成的。特别的QStruts提供对编写国际化E序的支持,同时也支持和(用户)输入的Form交互。其他几个和View(视图)有关的主题也?x)被要的涉及(qing)? |
3.2 Internationalized Messages |
几年前,E序开发者们只期望支持他们自己国家的国民Q只使用一U(有时候是两种Q语aQ也只有一U表达日期,数字Q钱币的格式。然而,ZWeb技术的,在internet和其他一些可以被q泛讉K的网l上的程序开发有了爆炸性的增长Q让国界问题?gu)现在我们的g。这个问题被理解为对于支?I>国际?/I>(l常被称为i18n,因ؓ(f)?国际?一词internationalization中i和n之间?8个字??I>本地?/I>E序的需要? Struts 在Javaq_上编写,可以辅助支持~写国际化和本地化的E序。需要熟(zhn)的概念有:(x)
h意在一个Struts之类的框架中i18n的支持只限于昄国际化的字符串和囑փl用戗支持地区相关的输入?/B>(在日语,中文Q或者韩文之cȝ语言中?被留l客L(fng)讑֤Q一般是一个web览器? 对于一个国际化E序来说Q请遵@JDK中附带的国际化文档中描述的步骤来Z的^台创建每一U语a的properties文g。下面的例子更深入的说明q一点:(x) 假设你的源代码位?CODE>com.mycompany.mypackage?所以它保存?CODE>com/mycompany/mypackage目录中(相对于你的源代码目录Q。要创徏一个名?CODE>com.mycompany.mypackage.MyResources的资源包Q你应该?CODE>com/mycompany/mypackage下创Z列文?
当你配置你webE序中controller servlet的发布描q时Q你需要定义的一个国际化参数是程序的基本资源包的名字。在我们上面丄例子中,它就?CODE>com.mycompany.mypackage.MyResources? <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>application</param-name> <param-value>com.mycompany.mypackage.MyResources</param-value> </init-param> <.../> </servlet> 一仉要的事情是要让你的资源包在你E序可以讉K的class path中。另一个方法是?CODE>MyResources.properties攑֜你的E序?CODE>classes目录下,你就可以单的用“myResource”作为程序的倹{但是要注意如果你的~译脚本Z保证一个“干净”的~译目标Q会(x)删除整个classes目录Q这时要保证q个资源文g不被删除? 如果是这U情形,q儿有一DA(ch)ntd可以包含在你的编译脚本中Q它?CODE>src/conf目录中的内容拯?CODE>classes目录厅R? <!-- Copy any configuration files --> <copy todir="classes"> <fileset dir="src/conf"/> </copy> |
3.3 Forms ?FormBean 的交?/STRONG> |
以前Q大多数web开发者用标准的HTML能力来编写Forms,比如使用 使用标准的HTML和JSP面来满U需求是非常J琐和粗W的QD个例子,一?CODE>username字段的输入框可能是这L(fng)(在JSP?Q? <input type="text" name="username" value="<%= loginBean.getUsername() %>"/> 如果HTMLE序员ƈ没有~程基础知识的话Q这很难输入正确Q而且也会(x)寚w面编辑者带来麻烦。基于JSP1.1中的自定义标{ֺQStruts为编写form提供了很大的方便Q可以取代原始的Ҏ(gu)。上面的例子用Struts来编写的话会(x)是这? <html:text property="username"/> q不需要显式的引用一个JavaBean以取得初始倹{框架自动完成这些事情? HTML form有时候被用来上传一些文件。大部分览器通过<input type="file"> 元素来支持这一点,它会(x)昄一个浏览文件的按钮Q但是(在Server?-译者注Q下面就轮到开发者来处理q些(上传)来的文g了。Struts可以用和普通的form一致的方式来处理这?multipart" form.在下一节里Q我们会(x)谈到用Struts来创Z个简单的login面Q还包括一个简单的multipart form? |
3.3.1 在Struts里编写Form |
一个完整的login面有助于展CStruts如何用比直接的HTML和标准JSP方式更轻杄方式来处理form。考虑如下的页面(ZStruts附带的示例程序)Q名字是 <%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <html:html> <head> <title> <bean:message key="logon.title"/> </title> <body bgcolor="white"> <html:errors/> <html:form action="/logon" focus="username"> <table border="0" width="100%"> <tr> <th align="right"> <html:message key="prompt.username"/> </th> <td align="left"> <html:text property="username" size="16"/> </td> </tr> <tr> <th align="right"> <html:message key="prompt.password"/> </th> <td align="left"> <html:password property="password" size="16"/> </td> </tr> <tr> <td align="right"> <html:submit> <bean:message key="button.submit"/> </html:submit> </td> <td align="right"> <html:reset> <bean:message key="button.reset"/> </html:reset> </td> </tr> </table> </html:form> </body> </html:html> Ҏ(gu)上面的例子,下面描述了Struts里form处理的关键特?
处理multipart form也是很简单的。显而易见,当你~写一个multipart form的时候你创徏的form中具有至一?file"cd的input输入框。编写一个multipart的form的第一步是使用struts-html标签库来创徏昄面Q? <%@page language="java"> <%@taglib uri="/WEB-INF/struts-html.tld" prefix="html"> <html:form action="uploadAction.do"> Please Input Text: <html:text property="myText"><br/> Please Input The File You Wish to Upload:<br/> <html:file property="myFile"><br /> <html:submit /> </html:form> 下一步是创徏你的ActionForm beanQ? import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.upload.FormFile; public class UploadForm extends ActionForm { protected String myText; protected FormFile myFile; public void setMyText(String text) { myText = text; } public String getMyText() { return myText; } public void setMyFile(FormFile file) { myFile = file; } public FormFile getMyFile() { return myFile; } } ?A href="file:///D:/DOWNLOAD/2004822203916/api/index.html">Javadocs里查阅FormFile可以看到在文件上传时它提供的处理文g的方法。也要看Javadoc里面的ActionServlet 和ActionMapping的不同的参数Q你可以指定它们来指明文件如何上传。基本上你在你的Actioncȝperform()Ҏ(gu)中需要调?CODE>((UploadForm) form).getMyFile()得到你的文gq且做出你的处理? |
3.3.2 支持的Input 字段的类?/STRONG> |
下面列出了Struts定义的所有的input字段的类型,带有指向手册的连接?
在Q何情况下Q字D|{N必须内置?CODE>form标签中,q样q些字段才知道用哪个bean来得到初始倹{? |
3.3.3 其它有用的表C层标签 |
有好几个有用的tag用来创徏表示层,h阅它们的标签库的文档和Tag Develipers Guide得到更多的信息:(x)
|
3.3.4 自动form?/STRONG> |
除了上文提到的form和bean之间的交互之外,Strutsq提供了附加的机制来查它接收到的输入字段。要使用q个Ҏ(gu),在你的ActionForm中重载下面的q个c? public ActionErrors validate(ActionMapping mapping, HttpServletRequest request); validate() Ҏ(gu)在bean的属性被自动填充之后Q在对应的Actioncȝ
前面曄提到q,q个Ҏ(gu)完全是可选的。默认的validate()Ҏ(gu)q回 另一个常用的方式是在ActionForm的validate()Ҏ(gu)中进行简单的主要的检查,在Action里面做“商业逻辑”检查? 在夜间编译包和下列地址q有一个可选的ActionForm查的包可以用:(x)David Winterfeldt的网?/A>? |
3.4 其他表示层技?/STRONG> |
虽然你的E序的观感可以完全用标准的JSP和Struts的自定义标签库创建,你也怼(x)考虑动用其他技术来增加部g重用Q减维护工作,q且/或者减错误。下面几节讨Z几种可选项? |
3.4.1 针对E序的自定义标签 |
除了Struts定义的自定义标签Q你针对你正在编写的E序创徏标签也很Ҏ(gu)Q这?x)帮助你~写用户界面。通过针对下面的程序编写tag,Struts附带的示例程序描l了基本原理Q?
q些tag的源代码都在 |
3.4.2 用Include(引用)来组合页?/STRONG> |
用一个JSP面Q包括子定义标签和Bean来取得必要的动态数据)在生成整个表现是一个很普通的方式Q在Struts的示例程序中也出现过。然而,很多E序需要在同一个页面中昄多个不同的单一逻辑部分的组合? 举例Q一个门L(fng)点可能在门户的主上有以下几个功能部分:(x)
如果你能把工作分成不同的部分Qؓ(f)每个部分分配不同的开发者,开发工作会(x)Ҏ(gu)些。那么你需要用JavaServer Pages技术中?I>include(包含)能力Q或者Struts提供的include 标签来把不同的页面结果组合到一起去。取决于你需要在什么时候组合你的输出,有三U不同的include可供选择:
另一个方法是使用Struts Template Tag library(模版标签库)。察看Developer's Guide得到详细信息? Tiles是一个原来的Template Tag library的替代品Q提供几处增强和新功能。Tiles位于夜间~译包,或者在Cedric Dumoulin的网?/A>? |
3.4.3 囑փ生成部g |
有一些程序需要动态生成图像,比如h图或者股报告等{。一般有两种不同的方法满个需求:(x)
|
3.4.4 生成文字 |
有些E序需要动态生成文本或者打包的文本Q例如XML.如果整个面都是被生成的Q可以用PrintWriter输出Q从Action里可以很Ҏ(gu)的办? response.setContentType("text/plain"); // or text/xml PrintWriter writer = response.getWriter(); // use writer to render text return(null); |
4.1 U览 |
现在我们已经理解如何构造你的程序的Model(模型)和View(视图)部gQ现在是时候来x
|
4.2 Action c?/STRONG> |
public ActionForward perform(ActionMapping mapping, ActionForm form, ServletRequest request, ServletResponse response) throws IOException, ServletException; public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; 大部分工E可能只需要用?HttpServletRequest"版本?
在编?CODE>ActioncM码时误住以下几个设计要点:(x)
除此之外Q你q需要警惕你?CODE>ActioncM变得太大。出现这U情冉|Ҏ(gu)的可能就是把功能逻辑攑֜ 只要需要的所有属性都是在Ҏ(gu){中传递的Q指的是通过函数调用传递?——译者注Q,一?CODE>Action可以被分散在几个本地Ҏ(gu)中。JVM把这些属性在堆栈中处理,所以它们就是是U程安全的? Struts附带的例子程序只是设计用于展C某些原理,因ؓ(f)它自q商业逻辑是被嵌入?CODE>ActioncM的。这应该被理解ؓ(f)设计中的某种bugQ而非Struts体系本n的特性,或者应该被模仿的方法? |
4.3 ActionMapping 的实?/STRONG> |
Z能成功的操作Q关于如何把每一个请求URI映射到恰当的
|
4.4 Action Mappings 配置文g |
controller servlet是如何知道你希望的映的Q写一个小javacL创徏新的 开发者的责Q是编写一个命名ؓ(f) ?lt;struts-config>元素之内Q有两个重要的元素被用于描述你的action: <form-beans>
q一D包含你的action的定义。你Z的每一个需要定义的action使用一?lt;action> 元素。每一个action元素需要定义下列的属性:(x)
CZE序中的 <struts-config> <form-beans> <form-bean name="logonForm" type="org.apache.struts.example.LogonForm" /> </form-beans> <global-forwards type="org.apache.struts.action.ActionForward" /> <forward name="logon" path="/logon.jsp" redirect="false" /> </global-forwards> <action-mappings> <action path="/logon" type="org.apache.struts.example.LogonAction" name="logonForm" scope="request" input="/logon.jsp" unknown="false" validate="true" /> </action-mappings> </struts-config> 首先定义的是form bean .一个基? " 你可以看刎ͼq个映射匚w 局部的" <!-- Edit mail subscription --> <action path="/editSubscription" type="org.apache.struts.example.EditSubscriptionAction" name="subscriptionForm" scope="request" validate="false"> <forward name="failure" path="/mainMenu.jsp"/> <forward name="success" path="/subscription.jsp"/> </action> 只用了两个额外的属性,CZE序中的 另一个很有用的部分是 <struts-config> <data-sources> <data-source autoCommit="false" description="Example Data Source Description" driverClass="org.postgresql.Driver" maxCount="4" minCount="2" password="mypassword" url="jdbc:postgresql://localhost/mydatabase" user="myusername"/> </data-sources> </struts-config> 关于如何获取q个数据源,参阅讉K关系数据?/A>q一节? |
2.1 U览 |
很多用于构造webE序的需求文档都是关注于View(视图)的。但是,你需要确认每一个确定的h需要的处理也是?I>Model(模型)层清楚的定义的。一般说来,Model(模型Q?/I>的开发者会(x)x如何建立满所有功能需求的JavaBeancR一个特定的E序所需要的明确定义的bean?x)有很大不同Q取决于他们的需求。然而他们大致上可以被归Z面会(x)讨论的几cR然而,先做一个关于“Scope范围”这个概늚要的回顾?x)是很有用的? |
2.2 JavaBeans ?scope(范围) |
在一个基于web的程序中QJavaBean可以被存攑֜Q也是获取于)几个不同的“属性”集合。每一个集合有不同的关于集合的生存期和储存在其中的bean的可视范围的规则。定义生存期和可视范围的规则共同被称些bean的“scope(范围)”。JavaServer pages(JSP)的规g定义了以下的术语(在servlet API中同L(fng)也有q些定义Q?
C同一个webE序中的JSP面和servlet׃n同样的bean集合是很重要的。例如,如下的代码在一个servlet中把一个bean加入了request的属?
马上在这个servlet转移到的JSP面中可?通过使用一个标准的动作tag,像q样Q?
|
2.3 ActionForm Beans |
注意:ActionForm Beans实际上更靠近View(视图)而非Model(模型)? Struts框架一般会(x)假设你已lؓ(f)你程序中每一个需要输入的Form定义好了一?CODE>ActionFormBean(q是一个从
当你~写你的
你可能注意到了一个在q里讨论?form"Qƈ非必L用户界面端一个单独的JSP面。在很多E序里都?x)出现跨多个页面?form"(从用者的角度来说Q。想一下,举例来说Q在安装新程序时l常?x)出现的向导风格的用L(fng)面。Struts鼓励你定义一个单独的 |
2.4 pȝ状态Beans |
pȝ的实际状态一般会(x)表现Z套包括一个或多个JavaBeanc,它们的属性定义了当前的状态。一个购物RQD例来_(d)?x)包括?f)每一个购物者维护一个bean,q且?x)(和其他属性一P包括一些购物者当前选择的物品条目。另外,pȝ也会(x)包括不同的bean来保存用L(fng)个h资料Q包括他们的信用卡号码和送货地址Q,q有按照他们的购物等U所能得到的可购买物品清单? 对于一个小型的pȝQ或者对不需要长期保存状态信息的pȝ来说Q一套系l状态bean可能已经保存了系l所需要的全部特定l节。否则,大多数情况下Q系l状态bean?x)把它持有的信息包村C个外部的数据库去Q比如一?CODE>CustomerBean对象对应于CUSTOMERS表中的一个特定的行)Qƈ可以在服务器的内存中按照需要创建或者删除。Entity Enterprise JavaBeans 在大规模pȝ也是Zq个目的使用的? |
2.5 商业逻辑 Beans |
你应该把你的E序的功能逻辑装在你为此设计的JavaBean的方法调用中。这些方法可能是同一个系l状态bean,或者他们分布在不同的类中,潜在的体C逻辑。在后一U状况中Q你往往需要把pȝ状态bean作ؓ(f)参数调用以便q些Ҏ(gu)处理? Z最大化代码重用Q商业逻辑bean因ؓ(f)被设计和实现为假讑֮?B>?/B>知道?x)在web环境下被执行。如果你发现你在你的bean中import 取决于你的程序的复杂E度和范?宽广E度)Q商业逻辑bean可能是普通的JavaBeans(它们和作为参C递的pȝ状态bean打交?,或者是通过JDBC调用存取数据库的一般的JavaBeans。对于大规模E序来说Q它们往往是被有状态的或者无状态的Enterprise JavaBeans(EJBs)所取代? |
2.6 讉K关系数据?/STRONG> |
Struts可以在它的标准配|文件中为程序定义datasource.也提供一?B>?/B>的JDBCq接池。参?A href="file:///D:/DOWNLOAD/2004822203916/struts/building_controller.html#config">Action Mappings 配置文g和Utilities Developer Guide(工具开发指?得到更详l的信息? 当datasource被定义号之后Q下面是一个在Action的performҎ(gu)中取得连接的例子? public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { javax.sql.DataSource dataSource = servlet.findDataSource(null); java.sql.Connection myConnection = dataSource.getConnection(); //do what you wish with myConnection } catch (SQLException sqle) { getServlet().log("Connection.process", sqle); } finally { //enclose this in a finally block to make //sure the connection is closed try { myConnection.close(); } catch (SQLException e) { getServlet().log("Connection.close", e); } } } 注意Struts 普通连接池是一?B>可?/B>lg。很多StrutsE序使用其它q接池来获取更高的性能Q特别是大流量的生pȝ? |
一?FONT color=#ff0000>DemoForm(l承 ActionForm)对应一?FONT color=#ff0000>DemoActionQ?extends ActionQ必d?execute
(ActionMapping mapping,ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
里面的ActionForm form对应DemoFormQ?/FONT>
2。DemoForm里面的validate(ActionMapping mapping,HttpServletRequest request)验证Q?/FONT>
不通过转向 input="/index.jsp" /Q?/FONT>
否则?nbsp;type="com.yourcompany.struts.DemoAction" 验证Q?/FONT>
3??xml:namespace prefix = html />
user:
html:form对应action="/user.do">对应UserForm"
property对应UserForm"里的属性!
q可dreset(ActionMapping mapiping,HttpServletRequest request)
4
logic:present:
5 web.xml
tomcat 启动时加?servletc,cM对象保存在httpcontext中,即application范围内,所有组件可׃n?
一.下蝲
我的环境?BR>JDK1.4.2
TOMCAT5.0.28
Eclipse3.0.1
Myeclipse3.8.2
?安装
Eclipse3.0.1+Myeclipse3.8.2的安装就不多说了Q很单?BR>主要的Myeclipse3.8.2的破?BR>我在|上扑ֈ了Myeclipse3.8.2的破解程?BR>q是我的UhI间Q我已经把破解程序上传了Q方便大家?BR>地址是:(x)
下完后解压到
MyEclipse\eclipse\plugins\com.genuitec.eclipse.core_3.8.2
覆盖原来的文Ӟ
然后启动MyEclipse
填入MyEclipse3.6.4的注册信息(E序里面有,|上也很多!Q,可以了?/P>
?基础配置
破解文g覆盖后,启动MyEclipse
q入Window--->Perferences--->MyEclipse---->Subscription输入注册信息?BR>然后在Window--->Perferences--->Java--->Installed JREsd你的jdk路径
在你需要默认的jdk路径前打勾?BR>最后设|tomcat服务?BR>Window--->Perferences--->MyEclipse---->Application Servers--->tomcat5
使得tomcat server Enable
然后选择tomcat HomeQ还要add JDKQ选你刚才在java里面讄的jdkQ然后要记得applyQ?/P>
q样你的环境?yu)配|好了!
L(fng)下篇实战,初学者愚见,请大侠们指点.写这些的目的是想和其他初学者一赯?/P>