一、struts2入门
1. Struts2的由来:
Struts 1是全世界第一个发布的MVC框架,它由Craig McClanahan在2001年6月发布,该框架一经推出,就得到了世界上Java Web开发者的拥护,经过长达6年时间的锤炼,Struts 1框架更加成熟、稳定,性能也有了很好的保证。因此,到目前为止,Struts 1依然是世界上使用最广泛的MVC框架。
目前,基于Web的MVC框架非常多,发展也很快,每隔一段时间就有一个新的MVC框架发布,例如像JSF、Tapestry和Spring MVC等。除了这些有名的MVC框架外,还有一些边缘团队的MVC框架也很有借鉴意义。
对于企业实际使用MVC框架而言,框架的稳定性则应该是最值得考虑的问题。一个刚刚起步的框架,可能本身就存在一些隐藏的问题,会将自身的BUG引入自己的应用。
虽然Struts 2号称是一个全新的框架,但这仅仅是相对Struts 1而言。Struts 2与Struts 1相比,确实有很多革命性的改进,但它并不是新发布的新框架,而是在另一个赫赫有名的框架:WebWork基础上发展起来的。从某种程度上来讲,Strut2没有继承Struts 1的血统,而是继承了WebWork的血统。或者说,WebWork衍生出了Struts 2,而不是Struts 1衍生了Struts 2。因为Struts 2是WebWork的升级,而不是一个全新的框架,因此稳定性、性能等各方面都有很好的保证;而且吸收了Struts 1和WebWork两者的优势,因此,是一个非常值得期待的框架。
2、下载Struts2
进入apache的官方网:
http://struts.apache.org/download.cgi#struts209
下载struts2的GA完整版,当前最新版本是2.0.9。本文以struts2.0.9为例。
下载完后,解压到本地磁盘,该文件夹包含如下文件结构:
l apps:该文件夹下包含了struts 2 的示例应用。
l docs:struts2的相关文档,包含struts2的快速入门、struts2的帮助文档及API文档等内容。
l j4:该文件夹下包含了让struts2支持JDK1.4的JAR文件。
l lib:该文件夹下包含了struts2框架的核心类库,以及struts2的第三方插件类库。
l src:该文件下包含了struts2框架的全部源代码。
3、3.1配置Struts2
将struts2的必需类库:struts2-core-2.0.9.jar、xwork-2.0.4.jar、ognl-2.6.11.jar、freemarker-2.3.8.jar、commons-logging-1.0.4.jar复制到web应用的WEB-INF/lib路径下。当然,如果你的web应用需要使用struts2的更多特性,则需要从lib目录把其它相应Jar包复制到WEB-INF/lib目录下。
3、3.1配置Struts2
将struts2的必需类库:struts2-core-2.0.9.jar、xwork-2.0.4.jar、ognl-2.6.11.jar、freemarker-2.3.8.jar、commons-logging-1.0.4.jar复制到web应用的WEB-INF/lib路径下。当然,如果你的web应用需要使用struts2的更多特性,则需要从lib目录把其它相应Jar包复制到WEB-INF/lib目录下。
3.2. struts2应用的平台要求:
struts2应用默认需要Java 5运行时环境,需要web容器支持Servlet API2.4和JSP API2.0。若使用jdk1.4运行时环境,则使用j4下的包。
1、Struts2类型转换,对于8个基本数据类型以及Date,String等常见类型,Struts2可以使用内建的类型转换器实现类型转换;但是对于自定义的对象类型来说,就需要我们自己指定类型转换的方式
2、对于自定义的类型转换器来说,需要提供3个信息:Action的名字,Action中待转换的属性名以及该属性对应的类型转换器。其中Action的名字是通过属性文件名来获得的,Action中待转换的属性名是通过属性文件中的KEY获得的,该属性对应的类型转换器是通过KEY对应的value来获得的
3.可以使用Struts2框架自带的类型转换器StrutsTypeConverter简化类型转换代码的编写,StrutsTypeConverter继承于DefaultTypeConverter父类,并且提供了两个抽象方法:converterfromstring和convertertostring分别表示从页面字符串转换为后台对象和从后台对象转换为前台页面字符串,我们只需实现这两个抽象方法即可实现类型转换
4. Struts2第一个示例:
4.1. 实例描述:
假设有一个名为test的用户,其密码是test,程序要完成的任务是,呈现一个登录界面给用户,如果用户输入的名称和密码都正确返回一个欢迎页面给用户,否则,就返回登录页面要求用户重新登录并显示相应的出错信息。
4.2. 创建Web应用:
Eclipse工程视图:
4.3. 配置struts2的核心Filter:
编辑web应用的web.xml配置文件,配置struts2的核心Filter:
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
web-app
version
=
"2.4"
xmlns
=
"http://java.sun.com/xml/ns/j2ee"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<
welcome-file-list
>
<
welcome-file
>
index.jsp
</
welcome-file
>
</
welcome-file-list
>
</
web-app
>
|
Struts2应用中所有的用户请求由Struts2框架的核心控制器FilterDispatcher处理,它默认拦截所有后缀为.action的请求,再由它根据*.action请求的前面部分决定调用哪个业务控制器。
4.4. 实现业务控制器类:
Struts2下的控制器不再像Struts1.x下的控制器,需要继承一个Actiono类,它甚至可以不实现任何接口,struts2的业务控制器就是一个包含execute()方法的普通POJO。该类包含多个属性用于封装用户的请求参数和要呈现给客户端的数据。
/*
* ClassName: LoginAction.java
* Author: qiujy
* CreateTime: Sep 26, 2007
*
* Copyright 2007 ++YONG All rights reserved.
* EMail: qiujiayong@126.com
*/
package
org.qiujy.web.struts2.action;
/**
*
@author
qiujy
*
@version
1.0
*/
publicclass
LoginAction {
private
String
userName
;
private
String
password
;
/**
*
@return
the
userName
*/
public
String getUserName() {
return
userName
;
}
/**
*
@param
userName
the
userName
to
set
*/
publicvoid
setUserName(String userName) {
this
.
userName
= userName;
}
/**
*
@return
the
password
*/
public
String getPassword() {
return
password
;
}
/**
*
@param
password
the
password
to
set
*/
publicvoid
setPassword(String password) {
this
.
password
= password;
}
/**
*
处理用户请求的
excute()
方法
*
@return
结果导航字符串
*
@throws
Exception
*/
public
String execute()
throws
Exception{
if
(
"test"
.equals(
this
.
userName
) &&
"test"
.equals(
this
.
password
)){
return
"success"
;
}
else
{
return
"error"
;
}
}
}
|
4.5. 配置Action:
为了让该Action能处理用户的请求,还需要将该Action配置在struts.xml文件中。struts.xml文件要存放在classes路径下,它主要用来配置Struts2的Action定义及Action处理结果和物理资源之间的映射关系。
<!
DOCTYPE
struts
PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
<
struts
>
<
include
file
=
"struts-default.xml"
/>
<!-- struts2
的
action
必须放在一个指定的包空间下定义
-->
<
package
name
=
"default"
extends
=
"struts-default"
>
<!--
定义处理请求
URL
为
login.action
的
Action -->
<
action
name
=
"login"
class
=
"org.qiujy.web.struts.action.LoginAction"
>
<!--
定义处理结果字符串和资源之间的映射关系
-->
<
result
name
=
"success"
>
/success.jsp
</
result
>
<
result
name
=
"error"
>
/error.jsp
</
result
>
</
action
>
</
package
>
</
struts
>
|
如上表示的意思是:该Action将负责处理URL为login.action的用户请求。处理时,Action将调用它的execute()方法处理用户请求,如果execute()方法返回success这个结果字符串,请求将被转发到/success.jsp页面,如果execute()方法返回error,则请求被转发到error.jsp页面。
4.6. 创建视图页面:
1. index.jsp:此处两个要提交的表单域的名字必须和Action声明的属性同名。
<%@
page
language
=
"java"
pageEncoding
=
"UTF-8"
%>
<
html
>
<
head
>
<
title
>
用户登录页面
</
title
>
</
head
>
<
body
>
<
h2
>
用户入口
</
h2
>
<
hr
>
<
form
action
=
"login.action"
method
=
"post"
>
<
table
border
=
"1"
>
<
tr
>
<
td
>
用户名
:
</
td
>
<
td
><
input
type
=
"text"
name
=
"userName"
/></
td
>
</
tr
>
<
tr
>
<
td
>
密码
:
</
td
>
<
td
><
input
type
=
"password"
name
=
"password"
/></
td
>
</
tr
>
<
tr
>
<
td
colspan
=
"2"
>
<
input
type
=
"submit"
value
=
"
确定
"
/>
</
td
>
</
tr
>
</
table
>
</
form
>
</
body
>
</
html
>
|
2. success.jsp:这里用到struts2的标签库了
<%@
page
language
=
"java"
pageEncoding
=
"UTF-8"
%>
<%@
taglib
prefix
=
"s"
uri
=
"/struts-tags"
%>
<
html
>
<
head
>
<
title
>
登录成功
</
title
>
</
head
>
<
body
>
<
h2
>
登录成功
</
h2
>
<
br
>
欢迎
<
s:property
value
=
"userName"
/>
!!!
</
body
>
</
html
>
|
3. error.jsp:
<%@
page
language
=
"java"
pageEncoding
=
"UTF-8"
%>
<
html
>
<
head
>
<
title
>
登录失败
</
title
>
</
head
>
<
body
>
<
h2
style
=
"color:red"
>
登录失败
</
h2
>
<
br
>
请重试!!!
</
body
>
</
html
>
|
5. Struts 2框架的处理流程:
一个请求在Struts2框架中的处理大概分为以下几个步骤
1) 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2) 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
3) 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action。
4) 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
5) ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类。
6) ActionProxy创建一个ActionInvocation的实例。
7) ActionInvocation实例使用命名模式来调用,回调Action的execute方法,该execute方法先获取用户请求参数,然后它会调用业务逻辑组件来处理用户的请求。在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8) 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper。
在上述过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。
6、Struts2的类型转换1、Struts2类型转换,对于8个基本数据类型以及Date,String等常见类型,Struts2可以使用内建的类型转换器实现类型转换;但是对于自定义的对象类型来说,就需要我们自己指定类型转换的方式
2、对于自定义的类型转换器来说,需要提供3个信息:Action的名字,Action中待转换的属性名以及该属性对应的类型转换器。其中Action的名字是通过属性文件名来获得的,Action中待转换的属性名是通过属性文件中的KEY获得的,该属性对应的类型转换器是通过KEY对应的value来获得的
3.可以使用Struts2框架自带的类型转换器StrutsTypeConverter简化类型转换代码的编写,StrutsTypeConverter继承于DefaultTypeConverter父类,并且提供了两个抽象方法:converterfromstring和convertertostring分别表示从页面字符串转换为后台对象和从后台对象转换为前台页面字符串,我们只需实现这两个抽象方法即可实现类型转换
4.执行流程
1)首先执行类型转换
2)进行输入验证(重写validate方法)
3)如果在上述过程中出现任何错误,都不会再去执行execute方法,会转向struts.xml中该action中名为input的result所对应的页面
5、ActionSupprot类中的addActionerror方法的实现:首先创建一个ArraryList对象然后将错误信息添加到该ArraryList对象中
6、当调用getActionErrors()方法返回Action级别的错误信息列表时,返回的实际上是集合的一个副本而不是集合本身,因此对集合副本调用clear()方法清除依旧是副本中元素而非原集合中的元素,因此此时原集合中的内容没有受到任何影响,换句话说action错误级别的错误信息列表对于开发者来说是只读的
7、Struts框架校验(有效XML文件)
具体分为字段优先校验器与校验器优先校验器