zoukankan      html  css  js  c++  java
  • 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与标签

    高级主题

  • 相关阅读:
    POJ2355 Railway tickets DP优化
    POJ3280 Cheapest Palindrome 区间DP
    POJ2352 Stars 线段树
    适牛的类岛娘头文件<转载>
    Ural 1519 Formula 1 插头DP(单回路)
    POJ3345 Bribing FIPA 树形DP+分组背包
    6个变态的C语言HelloWorld程序<转载>
    POJ2374 Fence Obstacle Course DP+线段树优化
    POJ3133 Manhattan Wiring 插头DP
    ACdream 完美数 数位DP
  • 原文地址:https://www.cnblogs.com/wangbiaoneu/p/4320950.html
Copyright © 2011-2022 走看看