Struts六大组件工作原理

写在前面: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

作者:键盘上的钢琴师_v5
来源:CSDN
原文:https://blog.csdn.net/daijin888888/article/details/51461043
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/weixin_43671743/article/details/89449108
今日推荐