本文是作者学习《JavaWeb入门经典》一书时整理的读书笔记,仅供学习和参考。如有相关版权问题请及时联系作者
一、Struts 2框架概述
Struts 2 框架起源于WebWork框架,是一个MVC框架。
1、MVC原理
模型、视图、控制器
2、Struts 2的产生
Struts 2框架是在WebWork的基础上发展而来的,所以是WebWork技术与Struts技术的结合。WebWork是开源组织OpenSymphony上一个非常优秀的开源Web框架。
3、Struts2的结构体系
Struts2通过过滤器拦截要处理的请求,当客户端发送一个HTTP请求时,需要经过一个过滤器链。这个过滤器链包括ActionContextClearUp过滤器、其他Web应用过滤器及StrutsPrepareAndExecuteFilter过滤器,其中StrutsPrepareAndExecuteFilter是必须配置的。
当StrutsPrepareAndExecuteFilter过滤器被调用时,Action映射器将查找需要调用的Action对象,并返回该对象的代理。然后Action代理将从配置管理器中读取Struts 2的相关配置。(struts.xml)。Action容器调用指定的Action对象,在调用前需要经过Struts2的一系列拦截器。拦截器与过滤器的原理相似。
当Action处理请求后,将返回响应的视图结果(JSP和FreeMarker等),在这些视图之中可以使用Struts标签显示数据并控制数据逻辑。然后HTTP请求回应给浏览器,在回应的过滤中同样经过过滤器链。
二、Struts 2 入门
1、获取与配置
开发Struts 2项目需要添加的类库
名称 | 说明 |
struts2-core-2.3.4.jar | Struts 2的核心类库 |
xwork-core-2.3.4.jar | xwork的核心类库 |
ongl-3.0.4.jar | OGNL表达式语言类库 |
freemarkder-2.3.19.jar | Freemarker模板语言支持类库 |
commons-io-2.0.1.jar | 处理IO操作的工具类库 |
commons-fileupload-1.2.2.jar | 文件上传支持类库 |
javassist-3.11.0GA.jar | 分析、编辑和创建Java字节码的类库 |
asm-commons-3.3.jar
asm-3.3.jar
| ASM是一个Java字节码处理框架,使用它可以动态生成stub类和proxy类,在Java虚拟机装载类之前动态修改类的内容 |
commons-lang3-3.1.jar | 包含了一些数据类型工具类,是java.lang.*的扩展 |
2、创建第一个Struts 2程序
Struts 2框架主要通过一个过滤器将Struts继承到Web应用中,这个过滤器对象时org.apache.Struts 2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter。通过它Struts2 即可拦截Web应用中的HTTP请求,并将这个HTTP请求转发到指定的Action处理,Action根据处理的结果返回给客户端响应的页面。因此在Struts2框架中,过滤器StrutsPrepareAndExecuteFilter是Web应用与Struts 2API之间的入口,它在Struts 2 应用中具有重要的作用。
(1)创建项目,将Struts 2类库文件添加到WEB-INF目录中的lib文件夹中。
(2)在web.xml文件中声明Struts 2提供的过滤器,类名为 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExcecuteFilter
(3) 在Web项目的源码文件夹中创建配置文件,在其中定义Struts 2中的Action对象
(4)创建主页面,在其中编写一个超链接用于访问上面所定义的Action对象。
(5)创建页面作为Action对象处理成功后的返回页面。
三、Action对象
1、认识Action对象
Action对象是Struts2框架中的重要对象,主要用于处理HTTP请求。在Struts2的API中,Action对象时一个接口,位于com.opensymphony.xwork2包中。通常情况下,我们在编写Struts 2项目时,创建Action对象都要直接或间接实现com.opensymphony.xwork2.Action接口,在该接口中,除了定义execute()方法外,还定义了5个字符串类型的静态常量。
该接口的关键代码:
public interface Action{
public static final String SUCCESS="success";
public static final String NONE="none";
public static final String ERROR="error";
public static final String INPUT="input";
public static final String LOGIN="login";
public String execute() throws Exception;
}
在Action接口中,包含了5个静态常量,他们是Struts 2API为处理结果定义的静态常量。
(1)SUCCESS
代表Action执行成功的返回值,在Action执行成功的情况下需要返回成功页面,则可设置返回值为SUCCESS
(2)NONE
代表Action执行成功的返回值,但不需要返回到成功页面,主要用于处理不需要返回结果页面的业务逻辑
(3)ERROR
代表Action执行失败的返回值,在一些信息验证失败的情况下可以使Action返回此值
(4)INPUT
代表需要返回某个输入信息页面的返回值
(5)LOGIN
静态变量LOGIN代表需要用户登录的返回值
2、请求参数的注入原理
在Struts 2框架中,表单提交的数据会自动注入到与Action对象中相对应的属性,它与Spring框架中IOC注入原理相同,通过Action对象为属性提供setter方法进行注入。
需要注入属性值的Action对象必须为属性提供setter()方法,因为Struts 2的内部实现是按照JavaBean规范中提供的setter方法自动为属性注入值的。
*由于Struts 2中的Action对象的属性通过其setter方法注入,所以需要为属性提供setter方法。但在获取这个属性的数值时需要通过getter方法,因此在编写代码时最好为Action对象的属性提供setter和getter方法。
3、Action的基本流程
Struts2框架主要通过Struts2的过滤器对象拦截HTTP请求,然后将请求分配到指定的Action处理。
由于在Web项目中配置了Struts2的过滤器,所以当浏览器向Web容器发送一个HTTP请求时,Web容器就要调用Struts2过滤器的doFilter()方法。此时Struts2接收到HTTP请求,通过Struts2的内部处理机制会判断这个请求是否与某个Action对象相匹配。如果找到匹配的Action,就会调用该对象的execute()方法,并根据处理结果返回响应的值。然后Struts2通过Action的返回值查找返回值所映射的页面,最后通过一定的视图回应给浏览器。
*在Struts2框架中,一个“*.action”请求的返回视图由Action对象决定。其发现方法是通过查找返回的字符串对应的配置项确定返回的视图,如Action中的execute()方法返回的字符串为success,那么Struts2就会在配置文件中查找名为success的配置项,并返回这个配置项对应的视图。
4、动态Action
Struts2框架提供了Dynamic Action的概念,称为动态Action。通过动态请求Action对象中的方法实现某一业务逻辑的处理。
动态Action处理方式通过请求Action对象中一个具体方法来实现动态操作,操作方式是通过请求Action对象中一个具体方法来实现动态操作,操作方式是通过在请求Action的URL地址后方加上请求字符串(方法名)与Action对象中的方法匹配,注意Action地址与请求字符串之间以!号分隔。
5、应用动态Action
(1)创建Java Web项目,将Struts2的支持类库文件添加到WEB-INF目录中的lib文件夹中,然后再web.xml文件中注册Struts2提供的过滤器。
(2)创建Action对象,并在其中分别编写add()和update()方法,用于处理添加用户信息及更新用户信息的请求并将请求返回到相应的页面
(3)在Web项目的源码文件夹(Eclipse中默认为src目录)中创建名为struts.xml的配置文件。在其中配置UserAction
(4)创建名为user_add.jsp的JSP页面作为成功添加用户信息的返回页面。
(5)创建JSP页面作为成功的返回页面。
(6)创建程序中的首页,在其中添加两个超链接,通过Struts2提供的动态Action功能将这两个超链接请求分别指向于类的添加于更新请求。
*使用Struts2的动态Action时,在Action请求的URL地址中使用“!”号分隔Action请求与请求字符串,而请求字符串的名称需要与Action类中的方法名称相对应,否则抛出java.lang.NoSuchMethodException
四、Struts 2的配置文件
1、Struts 2的配置文件类型
名称 | 说明 |
struts-default.xml | 位于Struts 2-core-2.3.4.jar文件的org.apache.Struts2包中 |
struts-plugin.xml | 位于Struts2提供的各个插件的包中 |
struts.xml | Web应用默认的Struts2配置文件 |
struts.properties | Struts2框架中属性配置文件 |
web.xml | 此文件时Web应用中的web.xml文件,在其中也可以设置Struts2框架的一些信息 |
其中struts-default.xml和struts-plugin.xml文件时Struts2提供的配置文件,他们都在Struts2提供的包中;而struts.xml文件时Web应用默认的Struts2配置文件;struts。properties文件是Struts框架中的属性配置文件,后两个配置文件需要开发人员编写
2、配置Struts 2包
在struts.xml文件中存在一个包的概念,类似Java中的包。配置文件struts.xml中的包使用<package>元素声明,主要用于防止一些项目中的相关配置,可以理解为配置文件中的一个逻辑单元。已经配置好的包可以被其他包所继承,从而提高配置文件的重用性。
<struts>
<package name="" extends="">
</package>
</struts>
包使用<package>元素声明,必须拥有一个name属性来指定包的名称
<package>元素包含的属性
属性 | 说明 |
name | 声明包的名称,必须 |
extends | 声明继承的包,父包 |
namespace | 指定名称空间,即防范此包下的Action需要访问的路径 |
abstract | 将包声明为抽象类型 |
3、配置名称空间
Struts 2的配置文件提供了名称空间的功能,用于指定一个Action对象的访问路径,它的使用方式是通过在配置文件struts.xml的包声明中使用namespace属性进行声明。
<package name="" extends="" namespace="">
*在<package>元素中指定名称空间属性,名称空间的值需要以“/”开头,否则找不到Action对象的访问地址。
在WebContent节点中创建与名称空间相同的文件夹,需要访问页面时在页面前加上名称空间/文件夹名.
4、Action的相关配置
Struts2框架中的Action对象是一个控制器的角色,Struts2框架通过它处理Http请求,其请求地址的映射需要在struts.xml文件中使用<action>元素配置
配置文件中的<action>元素主要用于建立Action对象的映射,通过该元素可以指定Action请求地址及处理后的映射页面。
<action>元素常用属性
属性 | 说明 |
name | 用于配置Action对象被请求的URL映射,必须 |
class | 指定Action对象的类名 |
method | 设置请求Action对象时调用该对象的哪一个方法 |
converter | 指定Action对象类型转换器的类 |
调用一个Action对象,默认执行的是execute()方法。如果在多业务逻辑分支的Action对象中,需要请求指定的方法,则可通过<action>元素的method属性配置。即将一个请求交给指定的业务逻辑方法处理
<action>元素的method属性主要用于为一个action请求分发一个指定业务逻辑方法,如设置为add,那么这个请求就会交给Action对象的add()方法处理,此种配制方法可以减少Action对象的数目。
*<action>元素的method属性值必须与Action对象中的方法名一直,这是因为Struts2框架通过method属性值查找与其匹配的方法。
5、使用通配符简化配置。
“*”:匹配0个或多个字符
“\”:一个转义字符,如需匹配“/”,则使用“\/”匹配
6、配置返回结果
Action对象是Struts2框架中的请求处理对象,针对不同的业务请求及处理结果返回一个字符串,即Action处理结果的逻辑视图名。Struts2框架根据逻辑视图名在配置文件struts.xml中查找与其匹配的视图,在找到后将这个视图回应给浏览器。
在配置文件struts.xml文件中结果映射使用<result>元素
<action name="" class="">
<result> xxx.jsp</result>
<result name="error"> yyy.jsp</result>
<result name="input">zzz.jsp</result>
</action>
<result>元素的两个属性为name和type,其中name属性用于指定Result的逻辑民称,与Action对象中方法的返回值向对应。type属性用于设置返回结果的类型,如请求转发和重定向等。
*无name属性的<result>元素默认值为success
五、Struts2的标签库
要在JSP中使用Struts2的标签库,首先要制定标签库的引入。
<%@taglib prefix="s" url="/Struts-tags"%>
1、应用数据标签
(1)property标签
作用是获取数据值并直接输出到页面中
property标签的属性
名称 | 说明 |
default | 可选 |
escape | 可选 |
escapeJavaScript | 可选 |
value | 可选 |
(2)set标签
用于定义一个变量并为其赋值,同时设置变量的作用域。默认情况下,通过set标签定义的变量被放到值栈中。
set标签的属性
名称 | 是否必须 | 类型 | 说明 |
scope | 可选 | String | 设置变量的作用域。application、request、session、page或action(默认) |
value | 可选 | String | 变量值 |
var | 可选 | String | 变量名 |
*在set标签中还包含id与name属性,在struts2中已过时。
(3)a标签
用于构建一个超链接,最终构建效果形成一个HTML中的超链接
a标签常用属性
名称 | 是否必须 | 类型 | 说明 |
action | 可选 | String | 将超链接的地址指向action |
href | 可选 | String | 超链接地址 |
id | 可选 | String | 设置HTML中的属性名称 |
method | 可选 | String | 如果超链接的地址指向action,method同时可以为action声明所调用的方法 |
namespace | 可选 | String | 如果超链接的地址指向action,namespace可以为action声明名称空间 |
(4)param标签
用于为参数赋值,可以作为其他标签的子标签。
名称 | 是否必须 | 类型 | 说明 |
name | 可选 | String | 设置参数名称 |
value | 可选 | Object | 设置参数值 |
(5)action标签
常用标签,用于执行一个Action请求。当在一个JSP页面通过action标签执行Action请求时,可以将其返回结果输出到当前页面中,也可以不输出。
名称 | 是否必须 | 类型 | 说明 |
executeResult | 可选 | boolean | 是否使Action返回执行结果,默认false |
flush | 可选 | boolean | 输出结果是否刷新,默认true |
ignoreContextParams | 可选 | boolean | 是否将页面请求参数传入被调用的Action,默认值为false |
name | 必须 | String | Action对象映射的名称,即struts.xml中配置的名称 |
namespace | 可选 | String | 指定名称空间的名称 |
var | 可选 | String | 引用此action的名称 |
(6)push标签
用于将对象或值压入到值栈中并防止在顶部,因为值栈中的对象可以直接调用,所以该标签的主要作用是简化操作。Push标签的属性只有value,用于声明压入值栈中的对象
<s:push value=""></s:push>
(7)date标签
date标签用于格式化日期时间,可以通过指定的格式化样式格式化日期时间值
名称 | 是否必须 | 类型 | 说明 |
format | 可选 | String | 设置格式化日期的样式 |
name | 必须 | String | 日期值 |
nice | 可选 | boolean | 是否输出给定日期与当前日期之间的时间差,默认值为false,不输出 |
var | 可选 | String | 格式化时间的名称变量,通过此变量可以对其进行引用 |
(8)include标签
作用类似jsp中的<include>动作标签,用于包含一个页,可以通过param向目标页面中传递参数。只有一个必选的file属性,用于指定一个JSP或Servlet
<%@include file=""%>
(9)url标签
名称 | 是否必须 | 类型 | 说明 |
action | 可选 | String | Action对象的映射URL,即对象的访问地址 |
anchor | 可选 | String | 此URL的锚点 |
encode | 可选 | boolean | 是否编码参数,默认true |
escapeAmp | 可选 | String | 是否将“&”转义为"&" |
forceAddSchemeHostAndPort | 可选 | boolean | 是否添加URL的主机地址及端口号,默认值为false |
includeContext | 可选 | boolean | 生成的URL是否包含上下文路径,默认值为true |
includeparams | 可选 | String | 是否包含可选参数,none/get/all默认none |
method | 可选 | String | 指定请求Action对象所调用的方法 |
namespace | 可选 | String | 指定请求Action对象映射地址的名称空间 |
scheme | 可选 | String | 指定生成URL所使用的协议 |
value | 可选 | String | 指定生成URL的地址值 |
var | 可选 | String | 定义生成URL的变量名称,可以通过此名称引用URL |
2、应用控制标签
(1)if
1.<s:if>
2.<s:elseif>:与<s:if>配合使用
3.<s:else>:与<s:if><s:elseif>配合使用
<s:if>与<s:elseif>都有一个名为test的属性,用于设置标签的判断条件,其值是一个布尔类型的条件表达式。
(2)iterator
iterator是一个迭代数据的标签,可以根据循环条件便利数组和集合中的所有或部分数据,并迭代出集合或数组的所有数据,也可以指定迭代数据的起始位置、步长及中止位置来迭代数据集合或数组中的部分数据。
名称 | 是否必须 | 类型 | 说明 |
begin | 可选 | Integer | 起始位置,默认0 |
end | 可选 | Integer | 结束位置,默认为全长 |
status | 可选 | String | 迭代过程中的状态 |
step | 可选 | Integer | 迭代的步长,默认1 |
value | 可选 | String | 指定迭代的集合或数组对象 |
var | 可选 | String | 设置迭代元素的变量,如果指定此属性,那么迭代的变量将压入到值栈中 |
status属性用于获取迭代过程中的状态信息,在struts2框架的内部结构中该属性实质是获取了struts2封装的一个迭代状态的org.apache.Struts2.views.jsp.IteratorStatus对象,通过此对象可以获取迭代过程中的如下信息。
1.元素数:getCount()
2.是否为第一个元素:isFirst()
3.是否为最后一个:isLast()
4.当前索引值:getIndex()
5.索引值是否为偶数:isEven()
6.索引值是否为奇数:isOdd()
(3)应用表单标签
常用表单标签
名称 | 说明 |
form | 生成一个form表单 |
hidden | 生成一个HTML中的隐藏表单元素 |
textfield | 生成一个HTML中的文本框 |
password | 生成一个HTML中的密码框 |
radio | 生成一个HTML中的单选钮 |
select | 生成一个HTML中的下拉列表 |
textarea | 生成一个HTML中的文本域 |
checkbox | 生成一个HTML中的选择框 |
checkboxlist | 生成一个或多个HTML中的选择框 |
submit | 生成一个HTML中的提交按钮 |
reset | 生成一个HTML中的重置按钮 |
表单标签常用属性
名称 | 说明 |
name | name属性 |
title | title属性 |
cssStyle | style属性 |
cssClass | Class属性 |
required | 用于在label上添加*号,其值为布尔型,如果为true则添加,否则不添加 |
disable | disable属性 |
value | value属性 |
labelposition | label的位置,默认left |
requireposition | label上添加*的位置,默认right |
Struts2提供了主题功能,可以为Struts2框架中的表单与UI标签设置主题样式。默认有4种
1.simple:只提供简单的HTMl输出
2.xhtml:simple上的扩展,提供了简单的布局样式,可将元素用到表格布局中,提供了lable的支持。默认
3.css_xhtml:在xhtml上的扩展,功能上强化了xhtml主题在CSS上的样式控制
4.ajax:css_xhtm主题上的扩展,功能上主要强化了css_xhtml主题在Ajax方面的应用
xhtml主题使用固定样式设置,非常不方便。如果不希望直接使用HTML来设计页面中的主题,则可以应用simple主题样式。
六、Struts2的开发模式
1、实现与Servlet API的交互
Struts2中提供了Map类型的request、session、application。可以从ActionContext对象中获得。该对象位于com.opensymphony.xwork2包中,是Action执行的上下文。
常用API方法:
(1)实例化ActionContext
通常情况下能够该对象提供的getContext()方法创建,声明如下:
public static ActionContext getCont()
该方法是一个静态方法,可以直接调用,返回值ActionContext
(2)获取Map类型的request
public Object get(Object key)
入口参数为Object类型的值,获取request可以将其设置为request
(3)获取map类型的session
public Map getSession()
返回一个Map对象,作用域HttpSession范围中
(4)获取Map类型的application
public Map getApplication()
返回一个Map对象,作用于servletContext
2、域模型DomainModel
在Struts2框架中提供了操作域对象的方法,不仅可以在Action对象中医用某一个实体对象,而且可以将Http请求中的参数值注入到实体对象的属性中,这种方式即Struts2提供的使用Domain Model 方法。
3.驱动模型ModelDriven
Struts2框架的API中提供了一个名为ModelDriven的接口,Action对象可以通过实现此接口获取指定的实体对象。获取方式是实现该接口提供的getModel()方法
T getModel();
Struts首先实例化Action对象,然后判断该对象是否使ModelDriven对象,如果是,则调用getMode()方法来获取实体对象模型,并将其返回。在之后的操作中已经存在明确的实体对象,所以不用再表单中的元素名称上添加指定实例对象的引用名称。
七、Struts2的拦截器
拦截器其实是AOP(面向方面编程)的一种实现方式,通过它可以在Action执行前后处理一些响应的操作。Struts2提供了多个拦截器,开发人员可以根据需要配置拦截器。
1、拦截器概述
拦截器是Struts2框架中的一个重要的核心对象,它可以动态增强Action对象的功能,Struts2框架中很多重要功能都是通过拦截器实现。
拦截器动态作用域Action与Result之间,可以动态的增强Action及Result
客户端发送的请求会被Struts2的过滤器所拦击,此时Struts2对请求持有控制权。它会创建Action的代理对象,并通过一系列拦截器处理请求,最后交给指定的Action处理。在这一期间,拦截器对象作用Action和Result的前后可以执行任何操作,所以Action对象编写简单是由于拦截器进行了处理。
2、拦截器API
Struts2中有一个名为com.opensymphony.xwork2.interceptor的包,其中有一些struts2的拦截器对象,他们具有不同的功能。在这些对象中,Interceptor接口是Struts2框架中定义的拦截器对象,其他拦截器都直接或间接地实现于此接口。
Interceptor中包含了3个方法
public interfac Interceptor extends Serializable{
void destroy();
void init();
String intercept(ActionInvocation invocation) throws Exception;
}
destroy()方法只是拦截器的声明周期结束,它在拦截器被销毁前调用,用于释放拦截器在初始化时占用的一些资源。
init()方法用于对拦截器执行一些初始化操作,此方法在拦截器被实例化后和intercept()方法执行前调用。
intercept()方法是拦截器中的主要方法,用于执行Action对象中的请求处理方法及其前后的一些操作,动态增强Action的功能。
*只有调用了intercept()方法中invocation参数的invoke()方法,才可以执行Action对象中的请求处理方法。
虽然Struts2提供了拦截器对象Interceptor,但此对象是一个接口。为了简化程序开发,可以同Struts2API中的AbstractInterceptor对象创建拦截器对象。它是一个抽象类,实现了Interceptor接口,在创建拦截器是可以通过继承该对象创建。在继承AbstractInterceptor对象后,创建拦截器的方式更加简单,除了重写必须的intercept()方法外,如果没有用到init()与destroy方法,则不必实现。
*AbstractInterceptor对象已经实现了Interceptor接口的init()与destroy()所以通过继承该对象创建拦截器,则不需要实现这两个方法。如果需要,可以重写。
3、使用拦截器
配置后才可以应用到Action对象,配置是使用<interceptor-ref>标签。
八、数据验证机制
1、手动验证
使用validate()方法可以验证用户请求的多个Action方法,并且验证逻辑相同。如果在一个Action类中编写了多个请求处理方法,而此Action重了写validate()方法,那么默认执行每一个请求方法的过程中都会经过validate()方法的验证处理。
2、验证文件的命名规则
使用Struts2验证框架,验证文件名需要遵循一定的命名规则,必须为“ActionName-validation.xml”或“ActionName-Aliasname-validation.xml”形式。其中ActionName是Action对象的名称,AliasName为Action配置中的名称,即struts.xml配置文件中Action元素对应的那么属性名。
(1)以“ActionName-validation.xml”方式命名
在这种命名方式中,数据的验证会作用于整个Action对象,并验证该对象的请求业务处理方法。如果Action对象中只存在单一的处理方法或在多个请求处理方法中验证处理的规则相同,则可以应用此种命名方式
(2)以“ActionName-AliasName-validation.xml”方式命名
更加灵活,如果一个Action对象中包含多个请求处理方法,而又没有必要验证每一个方法。即只需要处理Action对象中的特定方法,则可使用此种命名方式。
3、验证文件的编写风格
在struts2 框架中使用数据验证框架,期验证文件的编写有如下两种风格
(1)字段验证器编写风格
是指在验证过程中主要针对字段进行验证,此种方法是在验证文件根元素<validators>下使用<field-validator>元素编写验证规则的方式。
*如果在xml文件中使用中文,需要将其字符编码设置为支持中文编码的字符集,如UTF-8
(2)非字段验证器编写风格
指在验证过程中即可针对字段验证,也可以针对普通数据验证。此种方式是在验证文件根元素<validator>下使用<filed-validator>元素编写验证规则的方式。
*如果使用非字段验证器编写风格编写验证文件,需要使用<param>标签传递字段参数,其参数名为fieldName,值为字段的名称。
使用第一种风格编写的验证文件能够对任何一个字段返回一个明确的消息,而使用第二种编写验证文件,则不能对任何一个字段返回一个明确的验证消息,因为这是将多个字段设置在一起。
*虽然使用非字段验证器编写风格也能够验证字段,但没有字段验证器编写风格的针对性强,所以验证字段是通常使用字段验证器编写风格。