您的位置:首页 > 编程语言 > Java开发

Struts2工作原理(图解)—六大核心组件关系

2016-05-20 14:34 483 查看
写在前面:Struts2主要包含前端控制器FC、Action、ValueStack容器、Result、Interceptor拦截器、Tags标签6个核心组件,本文主要介绍这几个组件的合作关系,由此构成Struts2的工作流程,以便更好地理解和使用Struts2。

背景知识

1、Struts2基础标签

    1)用于输出的标签

        --*<s:property value="name"/>    value的值实际上是OGNL表达式

        --特殊用法

            <s:property />    用于输出栈顶数据

    2)用于调试的标签

        <s:debug/>

        --该标签仅仅是给程序员用的,用于调试,即用于观察ValueStack中的数据

        --当代码提交给测试、客户时,要把该标签删除

        --该标签具有互斥性(可以理解为BUG),如果页面上出现多次这个标签时,实际上只有第一个有效

    3)用于循环的标签

        a、用于循环集合

            --比如Action中有集合属性List<User> users

            <s:iterator value="users">

                <s:property value="userName"/>

            </s:iterator>

        b、用于循环数字

            <s:iterator begin="1" end="3" var="i">

                <s:property value="#i"/>

            </s:iterator>

2、OGNL表达式

    1)类似于EL表达式,但是比EL功能强大

    2)表达式允许我们通过一个字符串,来访问JAVA对象。从而避免了在JSP上嵌套着写JAVA代码。即,表达式可以通过字符串间接的帮助我们访问JAVA对象。

    3)基本原理

        --OGNL表达式将被OGNL引擎解析,这个过程是Struts2自行完成的

        --OGNL引擎允许我们访问两种类型的对象,一种是JavaBean类型,称之为root对象;另一种为Map类型,称之为context对象。

        --当OGNL表达式以#开头时,OGNL引擎会访问context对象,否则会访问root对象

    4)root对象

        --我们写OGNL表达式时(不以#开头的情况),首先要明确谁是root对象,其次从该对象的下级属性写起。

        举例:

        --比如以Action为root对象,Action中有String name, User user属性,那么要在页面显示这两个属性的话,写法如下:

            <s:property value="name"/>

            <s:property value="user.userName"/>

        --比如以User为root对象,要在页面上显示它的名称,写法如下:

            <s:property value="userName"/>

    5)context对象

        --OGNL表达式以#开头,则访问context对象

        --#后面写的是context对象的key,context对象是Map类型

3、ValueStack

    1)什么是ValueStack

        Struts2中并不是直接将OGNL组件搬过来使用,而是使用一个对象容器ValueStack对这个组件进行了改造及封装,因此我们在Struts2中是通过ValueStack来使用OGNL表达式。并且ValueStack中封装了Action的数据,上下文等数据,这些数据我们都可以通过OGNL表达式来获得。

    2)原理

        --结构:ValueStack中封装了OGNL引擎、context对象、Stack对象。

        --规则:当我们在标签中写一个OGNL表达式时,该表达式被Struts2自动的传递给ValueStack中的OGNL引擎,引擎会判断表达式是否以#开头,若是则直接从context对象中取值,否则向Stack中取值。

        --如何向Stack取值:OGNL表达式从栈顶向下依次取值,它是以栈的每一级对象作为root对象从中取值的,若取到值则直接返回,否则继续向下取值,直到栈底为止。

    3)*栈顶的变化

        a、默认情况下,栈顶是Action

        *b、在循环时,栈顶将发生变化,规则如下:

            --在未循环时,栈顶依然是Action

            --在第一次循环时,Struts2将循环变量(如user)压入到栈中,因此循环变量占据栈顶位置,而Action处于栈的第二位。

            --在第n次循环时,Struts2将第n-1次的循环变量从栈顶移除,然后再将本次循环的变量压入栈中,因此本次循环的变量占据栈顶位置,而Action依然处于栈的第二位。

            --当最后一次循环结束时,Struts2将最后一次循环的变量从栈顶移除,而没有新的变量压入栈中,那么Action再次成为栈顶。

            简而言之:

                --在循环过程中,栈顶是循环变量

                --循环结束后,栈顶是Action

    4)*总结(OGNL,ValueStack)

        a、在没有循环时,栈顶是Action,即可以以Action为root来写OGNL表达式

        b、在循环时,栈顶是循环变量,栈第二位是Action

            --循环集合

                栈顶是集合中的对象,那么可以以该对象为root,来写OGNL表达式,即直接从该root对象的下级属性写起

                举例:Action中有属性List<User> users,在页面上循环users

                <s:iterator value="users">

                    <s:property value="userName"/>

                </s:iterator>

                即:循环过程中,栈顶是User对象,以它为root来写OGNL表达式的话,就写userName

            --循环数字

                栈顶是循环变量(数字),但是由于我们不能以数字为root(以JavaBean为root)来写OGNL表达式,因为数字已经是基本类型数据,没有下级属性让我们访问。如果我们想直接输出栈顶可以用<s:property/>,如果我们想引用循环变量,则需要写<s:property value="#i"/>,从context对象中依然可以取得这个值。

                举例:从1循环到3

                <s:iterator begin="1" end="3" var="i">

                    <s:property value="#i"/>

                </s:iterator>

工作原理

总结8句话,方便记忆:

        请求提交控制器,根据配置找Action。创建VS栈容器,实例Action放栈顶。

        调用Action算输出,历经层层拦截器。根据方法返回值,调用Result做输出。

详细流程如下(结合图示理解):

1、请求传入前端控制器FC

2、前端控制器FC根据Struts.xml配置文件查找Action

3、创建ValueStack值栈容器

4、创建Action并存入ValueStack栈顶

5、6、7、FC调用并执行Action逻辑,此过程可能先被Interceptor拦截器拦截处理

8、9、FC根据Action返回的result通过Result组件跳转到相应的JSP界面

10、在解析JSP时,若发现OGNL表达式,则向ValueStack容器中的OGNL引擎传入表达式,按照先前介绍的方式查询对应的值

11、OGNL引擎返回查找到的值给JSP,待所有数据加载完成,呈现JSP(通过Tags标签)界面

Tips:当重新提交请求(比如刷新界面)时,Action、ValueStack均会被重新创建。



转载请注明出处:
http://blog.csdn.net/daijin888888/article/details/51461043
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  struts2.0