[目标]
实现一个最简单的struts程序。程序包括一个输入页和输出页,输入页。
对于学习程序设计,我们已习惯于从hello程序开始,实践证明,这是一个最有效的入门方法。下面就着手设计我们的第一个struts程序—-hello程序。hello程序的目标是实现从一个输入jsp页面中的输入框输入一个“hello”单词,在另一个输出jsp页面中显示“hello”一词。根据struts框架的要求,这个hello程序将包含输入jsp文件、输出jsp文件、action文件、formaction文件及配置文件。也就是说,这个hello程序是一个完整的struts程序,它可直接在tomact、resin等服务器上运行。
[效果]
输入页面:
输出页面:
[背景知识]
以前使用servlet开发应用系统的人深深感受到在java代码中嵌入大量html代码是一件非常痛苦的事,于是sun推出了jsp,解决了java代码中嵌入html代码的问题。但是很快程序员们就知道,用jsp“在html代码中嵌入大量java代码”跟“在java代码中嵌入大量html代码”是一样的非常痛。jsp是这样,asp也是这样。于是,craig r. mcclanahan借用mvc的思想,把java web应用程序的java和html分离开放在不同的文件中,分成了三部分,也就是struts;后来,微软也学会了这种分离方法,但微软懒一些,只分成了两部分,也就是asp.net。
struts (org.apache.struts)是一个开放源代码的web应用框架,基于mvc设计模式,使用servlet和jsp api建立,可以用来构建复杂的web应用。它允许我们分解一个应用程序的商业逻辑、控制逻辑和表现逻辑的代码,使它的重用性和维护性更好。struts框架是jakarta工程的一部分,由apache软件基金会管理。struts可以从http://jakarta.apache.org/ struts站点下载。
struts框架提供以下服务。
作为mvc结构中的controller的servlet.
jsp里用于bean管理、html和javascript生成、模板处理和流程控制的jsp标签库。
用于国际化消息的框架。国际化你的web应用,意味着你的web应用在使用时可以让用户以喜爱的语言显示。这意味着你需要创建一个应用资源文件,包含每种语言的信息。
一个jdbc的实现来定义数据源和数据库连接池。
一个通用的的错误和异常处理机制,包括从一个应用程序资源文件读取错误信息。
xml语法分析。
文件上载工具。
注册机制。
一个基于struts的应用程序的表示层(view)使用struts标签库(taglibs)构建。来自客户的请求被传递给叫actionservlet的servlet,它作为controller.使用了struts的应用程序,所有需要通过框架的请求都通过actionservlet传递。这个actionservlet把数据从请求传递到actionform javabean。
actionform是代表从一个表单view组件输入数据的javabean。这些表单由jsp用struts html标签库产生。这个beam由 actionservlet生成,带request参数,它还请求actionform来验证用户提交数据的合法性。
actionservlet通过定义一组actionmapping来配置。一个actionmapping是一个对象,它将请求中的url映射到由应用程序开发者提供的处理请求的组件。actionservlet和actionmapping的配置在xml配置文件中完成。
专用的应用程序用于处理请求的组件叫action类。在mvc结构中,它们代表模型。它们可能用于验证用户输入的合法性,假如在信息处理过程中出现了应用程序错误,action类可以创建一个error对象的实例,然后保存庆http request对象中。如果在action类中的逻辑成功地被招待类给controller传递一个actionforward对象,代表所需的描绘响应的jsp。actionforward有两种:专门转发给特定的action类或全局转发(任何一个action类可以把这些actionforwards转给controller)。
[步骤]
1、打开visual struts开发环境:
(1)把文件拷贝到本地硬盘的一个目录下,例如
f:\javawebstudio\
(2) 运行bin目录下的javawebstudio.exe文件(同时自动在桌面建立一个快捷方式,第二次启动时,只需点击桌面的快捷方式即可),出现如下启动界面:
另外,第一次运行javawebstudio,会提示是否要自动配置环境变量,建议选择自动配置。
2、建立一个“空的struts普通模板”应用程序:
选择菜单“文件”—“新建”—“新建项目”,弹出新建项目对话框,如图3-1所示:
在对话框中选择“空的struts普通用模板”,在项目名称中输入“simple”,package (包名)和位置(项目的路径)采用默认的值就行,当然也可以根据需要改变。最后点击“确定”按钮完成新项目的建立。
从文件管理器中可看出simple项目的文件结构如下:
simple
+——config
+——lib
+——src
+——web
——-build.xml
——-hello.prj
在simple项目根目录下包含四个子目录和两个文件,这是jspstudio项目的标准结构,最好不要改变它们默认的名称,否则会出现问题。
3、利用struts文件向导建立新的应用:
在jspstudio文件管理器内点击鼠标右键,在弹出的菜单中选择“struts文件向导”进入struts文件向导对话框,也可以选择菜单“文件”—“新建”—“ struts文件向导”进入struts文件向导对话框。如图3-3所示:
在struts文件向导对话框jsp文件标签下的文件名输入栏中输入“hellword”文件名,其它文件采用默认的设置,点击“确定”按钮完成在struts文件向导。
刷新jspstudio文件管理器,这时发现web目录下自动生成了两个文件,分别是hellword.jsp和hellword.jsp,前者是输入jsp文件,后者是输出jsp文件;src\emptyprj目录下自动生成了两个文件,分别是hellword action.java和hellword form.java,前者是action文件,后者formaction文件。
4、编译、启动服务器:
点击工具条上的编译按钮或选择菜单“生成”—“编译”开始项目的编译。编译过程和结果在输出栏中显示出来,内容如下:
c:\documents and settings\administrator\桌面>f:
f:\>cd f:\javawebstudio\javawebstudioworkdir\simple
f:\javawebstudio\javawebstudioworkdir\simple>ant -buildfile build.xml
buildfile: build.xml
prepare:
[mkdir] created dir: f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple
[copy] copying 2 files to f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple
[mkdir] created dir: f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple\web-inf
[copy] copying 6 files to f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple\web-inf
[mkdir] created dir: f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple\web-inf\classes
[copy] copying 5 files to f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple\web-inf\classes
[mkdir] created dir: f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple\web-inf\lib
[copy] copying 18 files to f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple\web-inf\lib
[mkdir] created dir: f:\javawebstudio\javawebstudioworkdir\wars
compile:
[javac] compiling 3 source files to
f:\javawebstudio\jakarta-tomcat-5.0.24\webapps\simple\web-inf\classes
dist:
[jar] building jar: f:\javawebstudio\javawebstudioworkdir\wars\simple.war
build successful
total time: 5 seconds
上述输出表明利用ant 编译build.xml所设置的项目已成功。把编译结果拷贝到tomcat服务器webapps目录下,并生成打包文件simple.war。
5、启动服务器:
点击工具条上的启动服务器按钮或选择菜单“运行”—“ 启动服务器”启动服务器jakarta-tomcat服务器。内容如下:
6、运行:
展开文件管理器simple项目下web目录,可见到helloword.jap和hellowordout.jsp文件,通过双击打开helloword.jap文件,如图所示。编辑窗口分上下两部分,上部分是源程序编辑,下部分是可视化编辑,与dreamweaver mx编辑窗口相似。
点击工具条上的运行按钮或选择菜单“运行”—“ 运行(web浏览)”这时打开显示出helloword.jsp的运行结果。在运行结果页面中的输入框中输入“hello word”,点击“提交”按钮,这时转发到hellowordout.jsp文件,hellowordout.jsp页面中输出“hello word”一词。
生成的源代码如下:
<html><head><title></title>
<meta http-equiv=content-type content="text/html; charset=gb2312">
</head>
<body bgcolor=white>
<base href="http://localhost:8080/simple/helloword.jsp"> <form name="hellowordform" method="post" action="/simple/hellowordaction.do;jsessionid=cffac422c4a779419348832d588ca5be">
<input type="text" name="mybeanvariable1" value=""> <input type="submit" value="提交"> <input type="reset" value="重写">
</form>
</body>
</html>
生成的源代码如下:
<html><head><title></title>
<base href="http://localhost:8080/simple/hellowordout.jsp">
</head>
<body bgcolor="white">
hello word
</body>
</html>
[项目文件结构]
config目录下包含了所有的配置文件和struts标签的描述文件,例如web.xml、struts-config.xml、struts-bean.tld、struts-html.tld、struts-logic.tld和struts-template.tld等文件。
lib包含了struts库文件和带用其它库文件,例如struts.jar、struts-legacy.jar、commons-lang.jar和xerces.jar等文件。
src目录下包含了java原文件和资源文件,例如applicationresources.properties和applicationresources_ch.properties资源文件,前者是英语资源文件,后者是中文资源文件。新建时这个目录里还有一个子目录“emptyprj”,这个名称与建立项目时输入的package名称是一至的。emptyprj目录下有“filters”、“jdbc”两个子目录,前者是过滤器目录,是中文解决方案,详细分析请看后面的有关滤器程序设计、中文解决方案章节,后者是数据库连接池文件,详细分析请看后面的struts数据库应用程序设计章节。
web目录下包含了jsp、html等web文件和web文件用到的图片文件。新建时这个目录是空的。
build.xml文件是编译是所需的配置文件,由于jspstudio采用的是ant编译器,所以这个文件是jspstudio项目中必不可少的,它是ant标准的配置文件,所有的项目目录结构也符合ant编译器的要求,可见jspstudio项目与ant具有非常好的兼容性,这也是jspstudio的优点之一。
hello.prj文件是项目文件,xml结构,内容如下:
<projectname>simple</projectname>
<projecttype>struts</projecttype>
<title>这是一个建立空的struts普通模板</title>
<package>emptyprj</package>
<typepath>\jave web 项目\空的struts普通模板</typepath>
<projectpath>f:\javawebstudio\javawebstudioworkdir\simple</projectpath>
<projectname>标签内是项目名称;<projecttype>标签内是项目的类型,这个标签的内容最好不要改变;<title>标签内是项目的简单说明,可根据需要填写;<package>标签内是默认的package名称;<typepath>标签内是项目模板的相对路径;<projectpath>标签内是项目保存的绝对路径。
[关键技术]
struts使用mvc结构;图2.1所示的逻辑图描述了框架的高层结构。
我们现在讨论图中的每个元素。
一个基于struts的应用程序的表示层(view)使用struts标签库(taglibs)构建。来自客户的请求被传递给叫actionservlet的servlet,它作为controller.使用了struts的应用程序,所有需要通过框架的请求都通过actionservlet传递。这个actionservlet把数据从请求传递到actionform javabean。
actionmapping
actionform (模型的数据)
action (模型的业逻辑)
发送
actionservlet (controller)
jsp (view)
taglib (view)
使用
实例化
调用
使用
使用
图2.1
actionform是代表从一个表单view组件输入数据的javabean。这些表单由jsp用struts html标签库产生。这个beam由 actionservlet生成,带request参数,它还请求actionform来验证用户提交数据的合法性。
actionservlet通过定义一组actionmapping来配置。一个actionmapping是一个对象,它将请求中的url映射到由应用程序开发者提供的处理请求的组件。actionservlet和actionmapping的配置在xml配置文件中完成。
专用的应用程序用于处理请求的组件叫action类。在mvc结构中,它们代表模型。它们可能用于验证用户输入的合法性,假如在信息处理过程中出现了应用程序错误,action类可以创建一个error对象的实例,然后保存庆http request对象中。如果在action类中的逻辑成功地被招待类给controller传递一个actionforward对象,代表所需的描绘响应的jsp。actionforward有两种:专门转发给特定的action类或全局转发(任何一个action类可以把这些actionforwards转给controller)。
本例主要文件之间的关系:
输入页面:
helloword.jsp
actionform (模型的数据)
hellowordform.java
actionservlet (controller)
通过struts-config.xml配置实现
actionmapping
输入页面:
hellowordout.jsp
action (模型的业逻辑)
hellowordaction.java
[关键源代码分析]
4.3.1 输入jsp页面文件
输入jsp页面文件名是hello.jsp,主要实现一个带有文本框的表单,文件代码如下:
<%@ page contenttype="text/html;charset=gb2312" language="java" %>
<%@ taglib uri="/web-inf/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/web-inf/struts-html.tld" prefix="html" %>
<%@ taglib uri="/web-inf/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/web-inf/struts-template.tld" prefix="template" %>
<html:html>
<head>
<title></title>
<html:base/>
</head>
<body bgcolor="white">
<html:form action="/helloaction.do" method="post">
<html:text property="mybeanvariable1" />
<html:submit value="提交" />
<html:reset value="重写" />
</html:form>
</body>
</html:html>
首先是把本页定义为支持中文显示,中文编码采用gb2312格式,程序语言为java:
<%@ page contenttype="text/html;charset=gb2312" language="java" %>
接着定义支持四种struts标签bean、html、logic和template,在该文件中没用到的标签可以去掉相应的定义,如果在文件中还需要用到自定义标签,也需要在这里加入相应的定义:
<%@ taglib uri="/web-inf/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/web-inf/struts-html.tld" prefix="html" %>
<%@ taglib uri="/web-inf/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/web-inf/struts-template.tld" prefix="template" %>
<html:html>就不用说了。<html:base/>标签对应html的<base>标签,用来设定测览器中文件的绝对路径,然后在文件中只需写下文件的相对位置,在测览器中测览的时候这些位置会自动附在绝对路径后面,成为完整的路径。在文档中所有相对地址形式的url是相对于这里定义的utrl而言的。一篇文档中的<base>标记不能多于一个,必须放于<head>标签内,并且应该在任何包含url地址的语句之前定义。<html:form>这里用了黑体字,表示是要重点讲解的地方。
<html:form action="/helloaction.do" method="post">
<html:text property="mybeanvariable1" />
<html:submit value="提交" />
<html:reset value="重写" />
</html:form>
<html:form>标签定义了一个表单,提交时的目标url是“/helloaction.do”,方法是“post”,post方法是将用户在表单中填写的数据包含在表单的主体中,一起传送到服务器上的处理程序中,该万法没有字符的限制,它包含了iso10646的字符集,是一种邮寄的万式,在测览器的地址栏不显示提交的信息,这种万式传送的数据是没有限制。当然也可以选择get方法,get方法是将表单内容附加在url地址后面,所以对提交信息的长度进行了限制,最多不可以超过8192个字符,如果信息大长,将被截去,从而导致意想不到的结果,而且不能传送非ascii码的字符。表单内包含一个文本输入框<html:text>,它的值与bean中属性为"mybeanvariable1"的变量相对应,如果结mybeanvariable1付了初值,则在启动这个页面时文本框中就显示默认的mybeanvariable1初值。另外表单内还包含了两个最常见的提交按钮<html:submit value="提交" />和重写按钮<html:reset value="重写" />。
4.3.2 输出jsp页面文件
输出jsp页面文件名是helloout.jsp,主要实现输入文件提交的文本框的值,文件代码如下:
<%@ page contenttype="text/html;charset=gb2312" language="java" %>
<%@ taglib uri="/web-inf/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/web-inf/struts-html.tld" prefix="html" %>
<%@ taglib uri="/web-inf/struts-logic.tld" prefix="logic" %>
<html:html>
<head>
<title></title>
<html:base/>
</head>
<body bgcolor="white">
<html:html>
<head>
<title></title>
<html:base/>
</head>
<body bgcolor="white">
<bean:write name="helloform" property="mybeanvariable1" />
</body>
</html:html>
</body>
</html:html>
输出文件与前面输入文件唯一不同的是把<html:form>标签变成了<bean:write>标签:
<bean:write name="helloform" property="mybeanvariable1" />
<bean:write>标签实现bean属性值的输出,其中name保存bean名,这里是“helloform”,从后面的配置文件可以看出,它对应的类是helloform类;property保存属性名,这里是“mybeanvariable1”,与输入文件的文本框取的属性名一至。
4.3.3 actionform bean文件
hello程序的actionform bean文件实现只包含一个变量的bean,文件名是helloform.java,文件代码如下:
package emptyprj;
import javax.servlet.http.httpservletrequest;
import org.apache.struts.action.actionerror;
import org.apache.struts.action.actionerrors;
import org.apache.struts.action.actionform;
import org.apache.struts.action.actionmapping;
public final class hellowordform extends actionform
{
private string mybeanvariable1;
public string getmybeanvariable1()
{
return (this.mybeanvariable1);
}
public void setmybeanvariable1(string mybeanvariable1)
{
this.mybeanvariable1=mybeanvariable1;
}
}
首先是定义package名:
package emptyprj;
这是选用了jspstudio默认的package名emptyprj,需注意的是package名要与目录名对应。接着引入了actionform bean设计中常用的五个类httpservletrequest、actionerror、actionerrors、actionform和actionmapping,这是jspstudio自动加入的,实际上helloform类只用于actionform类,其它部分可以删除,但这里保留它以方便以后扩展程序时用。
import javax.servlet.http.httpservletrequest;
import org.apache.struts.action.actionerror;
import org.apache.struts.action.actionerrors;
import org.apache.struts.action.actionform;
import org.apache.struts.action.actionmapping;
接下来就是定义了helloform、一个参数mybeanvariable1和它对应的get()、set()函数,这与普通bean定义的方法一模一样。
4.3.4 action文件
hello程序的action文件实现对输入文件提交的表单的处理,文件名是helloaction.java,文件代码如下:
package emptyprj;
import java.lang.reflect.invocationtargetexception;
import java.util.locale;
import javax.servlet.servletexception;
import javax.servlet.http.httpsession;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import org.apache.commons.beanutils.propertyutils;
import org.apache.commons.logging.log;
import org.apache.commons.logging.logfactory;
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 org.apache.struts.action.actionservlet;
import org.apache.struts.util.moduleexception;
import org.apache.struts.util.messageresources;
public final class hellowordaction extends action
{
// 变量定义:
private log log = logfactory.getlog("org.apache.struts.webapp.example");
//函数定义:
public actionforward execute(actionmapping mapping,
actionform form,
httpservletrequest request,
httpservletresponse response)
throws exception
{
// extract attributes and parameters we will need
locale locale = getlocale(request);
messageresources messages = getresources(request);
httpsession session = request.getsession();
hellowordform myform = (hellowordform) form;
string variable1= myform.getmybeanvariable1();
try
{
if(variable1.trim().equals(""))
{
return new actionforward(mapping.getinput());
}
//其它代码
return (mapping.findforward("success"));
}
catch (exception e)
{
//log.error("出错", e);
//log.trace("出错");
throw new runtimeexception(e.getmessage());
}
}
}
首先定义处理函数execute(),可以理解为当hello输入文件表单提交到服务器的actionservlet,由actionservlet调用action的execute()函数实现商业逻辑处理,处理完成后把结果转发到输出文件中。execute()函数定义一个helloform实例“myform”,并从提交的输入actionform对象实例form中读取数据,把mybeanvariable1变量的值赋给新的字符串变量variable1:
helloform myform = (helloform) form;
string variable1= myform.getmybeanvariable1();
接下来是出错处理,try语句用于组合一个引起异常的代码块,它使我们告诉java要注意有可能出现异常的代码段;catch:一旦掷出一个异常,需要捕获住这个异常,catch语句使程序员定义一个捕获;finally:在try/catch块结尾,程序可能需要确保一个代码块不管是否掷出了异常,总是被执行,例如不管发生什么,我们可能都需要确保关闭特定的文件; exceptlon:一种用于存放在代码中发现的关于一个"exception"或"error"的信息的类;throws:当某些事需要关注时,我们"掷出"一个异常。这个异常被我们创建的一段处理异常的特殊代码"抓住"。涣句话说,通过掷出一个异常,我们告诉代码:出错啦,需要调用一些特殊的逻辑去处理问题。下面完它的完整结束:
try
{
//正常代码
}
catch (exception e)
{
//出错处理代码
throw new runtimeexception(e.getmessage());
}
finally
{
//最后都必需进行的处理代码
}
在try块中我们进行的变量variable1是否为空的判断,如果为空就转发到输入页,否则转发到定义为success的输出页:
if(variable1.trim().equals(""))
{
return new actionforward(mapping.getinput());
}
//其它代码
return (mapping.findforward("success"));
mapping.getinput()函数用于获取输入页的url值,这个值与配置文件struts-config.xml中<action>项的input属性值相对应。
4.3.5 struts程序配置
<?xml version="1.0" encoding="iso-8859-1" ?>
<!doctype struts-config public
"-//apache software foundation//dtd struts configuration 1.0//en"
"http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
<struts-config>
<form-beans>
<form-bean name="hellowordform"
type="emptyprj.hellowordform" />
</form-beans>
<action-mappings>
<action path="/hellowordaction"
type="emptyprj.hellowordaction"
name="hellowordform"
scope="session"
input="/helloword.jsp">
<forward name="success" path="/hellowordout.jsp" />
</action>
</action-mappings>
</struts-config>
