Struts2 学习笔记(概述)

Struts2 学习笔记

2015年3月7日11:02:55

MVC思想

Strust2的MVC对应关系如下:

在MVC三个模块当中,struts2对应关系如下:

Model:

负责封装应用的状态,并实现应用的功能。通常分为数据模型和业务逻辑模型,数据模型用来存放业务数据,比如订单信息、用户信息等;而业务逻辑模型包含应用的业务操作,比如订单的添加或者修改等。

封装应用状态:某些应用数据封装起来,使得视图只能通过接口获取对应的数据

响应状态查询:对应用的状态改变进行处理

暴露应用功能:暴露接口

通知视图改变:主动向视图传递数据

Controller:

用来控制应用程序的流程和处理视图所发出的请求。当控制器接收到用户的请求后,会将用户的数据和模型的更新相映射,也就是调用模型来实现用户请求的功能;然后控制器会选择用于响应的视图,把模型更新后的数据展示给用户。

接受并验证HTTP请求的数据:对一个url请求,通过Controller将请求分发到指定的处理模块上。

将用户数据域模型的更新相映射:用户数据模型改变并不会立即对应到Model,而是需要controller来分发

选择用于响应的视图:根据配置文件,选择对应与某个模型的视图

View:

用来将模型的内容展现给用户,用户可以通过视图来请求模型进行更新。视图从模型获得要展示的数据,然后用自己的方式展现给用户,相当于提供界面来与用户进行人机交互;用户在界面上操作或者填写完成后,会点击提交按钮或是以其它触发事件的方式,来向控制器发出请求。

解析模型的数据:如velocity的功能

产生HTML的响应:

请求模型的更新:向后台发送表单

发送用户输入给控制器

Struts2工作流程

一个请求在Struts2框架中的处理大概分为以下几个步骤:

  1. 客户端提起一个(HttpServletRequest)请求
  2. 请求被提交到一系列(主要是三层)的过滤器(Filter),如ActionContextCleanUp、其他过滤器、SiteMesh等、FilterDispatcher。注意这里是有顺序的,先ActionContextCleanUp,再其他过滤器(SiteMesh等)、最后到FilterDispatcher。
  3. FilterDispatcher是控制器的核心,就是mvc中controller控制层的核心。FilterDispatcher进行初始化并启用核心doFilter
  4. ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类.
  5. ActionProxy创建一个ActionInvocation的实例,同时ActionInvocation通过代理模式调用Action。但在调用之前ActionInvocation会根据配置加载Action相关的所有Interceptor。(Interceptor是struts2另一个核心级的概念)
  6. Interceptor 的调度流程大致如下:
    1.
    ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。
    2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。

整体流程

l  客户端提交一个HttpServletRequest请求(action或JSP页面)。

l  请求被提交到一系列Filter过滤器,如ActionCleanUp和FilterDispatcher等。

l  FilterDispatcher是Struts2控制器的核心,它通常是过滤器链中的最后一个过滤器。

l  请求被发送到FilterDispatcher后,FilterDispatcher询问ActionMapper时候需要调用某个action来处理这个Request。

l  如果ActionMapper决定需要调用某个action,FilterDispatcher则把请求交给ActionProxy进行处理。

l  ActionProxy通过Configuration Manager询问框架的配置文件struts.xml,找到调用的action类。

l  ActionProxy创建一个ActionInvocation实例,通过代理模式调用Action。

l  action执行完毕后,返回一个result字符串,此时再按相反的顺序通过Intercepter拦截器。

l  最后ActionInvocation实例,负责根据struts.xml中配置result元素,找到与之相对应的result,决定进一步输出。

Action

Struts2的action生命周期

Struts2的action接口隔离

Struts2中的Action,并不需要依赖于特定的Web容器。我们看不到类似HttpServletRequest,HttpServletResponse等Web容器相关的对象。

提问:Struts2Action并不带有任何Web容器相关的对象,Action又是如何工作在Web容器中的呢?

虽然Struts2的Action只是一个非常普通的Java对象,并不具备任何Web容器的特质,但是我们需要把Action放到一个更加大的环境中来看。事实上,Struts2为Action的执行,准备了完整的数据环境和执行环境。而这个执行环境,就保证了Action在Web容器中的顺利运行。

在Struts2中,每个Http的请求,会被发送到一个Filter。而这个Filter,就会针对每个请求,创建出一个代码的执行环境,并在这个基础上,为每个执行环境配备与之对应的数据环境,这个数据环境中的内容,就来自于Web容器中的一个又一个对象。这样,就能够顺利调用Action执行代码而无需担心它是否运行在Web容器中了。

提问:Struts2Action并不带有任何Web容器相关的对象,Action中又如何与Web容器进行通信并获取Web容器的相关对象呢?

刚刚我们提到Struts2会为每个Http的请求建立一个执行环境和数据环境。其中,数据环境就成为了Action获取Web容器的基础。所以,当Action需要获取Web容器的相关对象,需要通过数据环境来进行。

Struts2设置的优点

1. 使得Struts2的Action非常易于测试

如果我们完全不考虑Action的执行环境,仅仅把Action看作一个普通的Java对象,那么我们甚至可以直接new一个Action的对象,通过执行其中的方法完成测试。这样,我们就不需要任何的Mock,来模拟Web容器的环境。

2. 结合Action的执行环境,使得Struts2在Control这个层次上,能够定义更加丰富的执行层次

因为Action是一个普通的Java类,而不是一个Servlet类,完全脱离于Web容器,所以我们就能够更加方便地对Control层进行合理的层次设计,从而抽象出许多公共的逻辑,并将这些逻辑脱离出Action对象本身。事实上,Struts2也正是这么做的,无论是Interceptor,还是Result,其实都是抽象出了Action中公共的逻辑部分,将他们放到了Action的外面,从而更加简化了Action的开发。

3. 使得Struts2的Action看上去更像一个POJO,从而更加易于管理

Struts2的Action是一个线程安全的对象。而Web容器传递过来的参数,也会传递到Action中的成员变量中。这样,Action看上去就更像一个POJO,从而能够方便的被许多对象容器进行管理。比如说,你可以非常方便得把Action纳入到Spring的容器中进行管理。

数据交互上下文 ActionContext(BeatContext)

由于Action是应对于一个又一个的URL请求,所以ActionContext应该具备以下的特性:

1. ActionContext应成为Action与Web容器之间的桥梁

2. ActionContext中应该保存有针对某个请求的详细信息

3. ActionContext应该是一个线程安全的类对象

Struts2拦截器与过滤器

拦截器和过滤器的区别:

1、拦截器是基于java的反射机制的,而过滤器是基于函数回调

2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器

3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用

4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能

5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

过滤器

首先讨论struts2过滤器,struts2的主要过滤器是FilterDispatcher,相当于MVC框架当中的controller,有如下几个功能:

(1)执行Actions:过滤器通过ActionMapper对象,来判断是否应该被映射到Action.如果mapper对象指示他应该被映射,过滤链将会被终止,然后Action被调用。这一点非常重要,如果同时使用SiteMesh filter,则SiteMesh filter应该放到该过滤器前,否则Action的输出将不会被装饰。

(2)清除ActionContext:过滤器为了确保内存溢出,会自动的清除ActionContext。这可能会存在一些问题,在和其它的框架集成时,例如SiteMesh(一致的web页面布局框架,类似装饰器)。ActionContextCleanUp提供了怎么处理这些问题的一些信息。在配置了FilterDispatcher的前提下已经配置了ActionContextCleanUp拦截器。

(3)维护静态内容:过滤器也会维护在Struts2中使用的一些公共的静态的内容,例如JavaScript文件,CSS文件等。搜索/struts/*范围内的请求,然后将/struts/后面的值映射到一些struts的公共包中,也可以在你的类路径中搜索。

默认情况下会去查找以下包:org.apache.struts2.static.template。这样你只用请求/struts/xhtml/styles.css,XHTML UI主题默认的样式表将会被返回。同样,AJAX UI组件需要的JavaScript文件,也可以在org.apache.struts2.static包中被找到。如果你想加入其它被搜索的包,在web.xml中设置filter时,通过给"actionPackages"初始参数一个逗号隔开的包列表值来设定。

(4)清除request生命周期内的XWork的interceptors

自定义过滤器

应该知道如果我们自己定义过滤器的话, 是要放在strtus2的过滤器之前的, 如果放在struts2过滤器之后,你自己的过滤器对action的过滤作用就废了,不会有效!除非你是访问jsp/html!

那我现在有需求, 我必须使用Action的环境,而又想在执行action之前拿filter做一些事, 用FilterDispatcher是做不到的.

那么StrutsPrepareAndExecuteFilter可以把他拆分成StrutsPrepareFilter和StrutsExecuteFilter,可以在这两个过滤器之间加上我们自己的过滤器.!

过滤器也可以自己定义,在使用新的StrutsPrepareAndExecuteFilter作为核心过滤器的情况下,可以将自定义的过滤器放在各种位置上。

具体的配置在web.xml当中进行配置。

拦截器

在使用拦截器的时候,在Action里面必须最后一定要引用struts2自带的拦截器缺省堆栈defaultStack,如下所示:

<interceptor-ref name="checkbox">
 
<param name="uncheckedValue">0</param>
</interceptor-ref>
<interceptor-ref
name="defaultStack"/>(
必须加,否则出错)

Strust2拦截器构成拦截器栈,在使用过程中,相当于递归调用这些拦截器的intercept方法。通常我们采用struts2的默认拦截器,自己开发,则要遵循以下的步骤:

1 自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。

2 在strutx.xml中注册上一步中定义的拦截器。

3 在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。

开发

Interceptor接口声明了三个方法:

public interface Interceptor extends
Serializable {

void destroy();

void init();

String intercept(ActionInvocation invocation) throws Exception;

}

Init方法在拦截器类被创建之后,在对Action镜像拦截之前调用,相当于一个post-constructor方法,使用这个方法可以给拦截器类做必要的初始话操作。

Destroy方法在拦截器被垃圾回收之前调用,用来回收init方法初始化的资源。

Intercept是拦截器的主要拦截方法,如果需要调用后续的Action或者拦截器,只需要在该方法中调用invocation.invoke()方法即可,在该方法调用的前后可以插入Action调用前后拦截器需要做的方法。如果不需要调用后续的方法,则返回一个String类型的对象即可,例如Action.SUCCESS。另外AbstractInterceptor提供了一个简单的Interceptor的实现。

注册拦截器

<interceptors>

<interceptor name="login" class="com.jpleasure.teamware.util.CheckLoginInterceptor"/>

<interceptor-stack
name="teamwareStack">

<interceptor-ref
name="login"/>

<interceptor-ref
name="defaultStack"/>

</interceptor-stack>

</interceptors>

将上述拦截器设定为默认拦截器

<default-interceptor-ref
name="teamwareStack"/>

这样在后续同一个package内部的所有Action执行之前都会被login拦截。

每一个拦截器都有两个默认的参数:

excludeMethods - 过滤掉不使用拦截器的方法和

includeMethods – 使用拦截器的方法。

需要说明的几点:

1 拦截器执行的顺序按照定义的顺序执行

2 使用默认拦截器配置每个Action都需要的拦截器堆栈

3 如何访问HttpServletRequest,HttpServletResponse或者HttpSession

有两种方法可以达到效果,使用ActionContext:

Map attibutes =
ActionContext.getContext().getSession();

或者实现相应的接口:

HttpSession           SessionAware

HttpServletRequest    
ServletRequestAware

HttpServletResponse   
ServletResponseAware

剩余部分

集成spring与hibernate

OGNL与标签

高级主题

上一篇:Docker Demo on Docker


下一篇:EF 复杂语句的使用