Struts2学习笔记__Struts标签库和OGNL

Struts2 标签库概述(了解)

 Struts2标签库相对struts1.x进行了巨大的改进,支持OGNL表达式,不再依赖任何表现层技术。
 我们可以在struts2-core-2.5.8.jar压缩文件的META-INF目录下找到struts-tags.tld文件,这个文件#定义了Struts2的标签。

Struts2可以将所有标签分成三类:(了解)

 用户界面标签(UI标签):主要用来生成HTML元素的标签。
− 表单标签:主要用于生成HTML页面的FORM元素,以及普通表单元素的标签。
− 非表单标签:主要用于生成页面上的tree,Tab页等。
 非用户界面标签(非UI标签):主要用于数据访问,逻辑控制。
− 数据访问标签:主要包含用于输出值栈(ValueStack)中的值,完成国际化等功能的标签。
− 流程控制标签:主要包含用于实现分支,循环等流程控制的标签。
 AJAX标签:用于支持Ajax效果

要在jsp中使用Struts2的标志,先要指明标志的引入。通过jsp的代码的顶部加入以下的代码:

<%@taglib prefix="s" uri="/struts-tags" %>

标记语言-OGNL

 OGNL(Object-Graph Navigation Language)的全称是对象图导航语言,它是一种功能强大的开源表达式语言,比EL(只能从域或内置对象中)表达式更强大
 特点:

– OGNL可以存取Java任意对象的任意属性,调用Java对象的方法
– ONGL能够自动实现必要的类型转换。

如果把表达式看作是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。
 Struts2的默认表达式语言就是OGNL
 OGNL有三个参数(表达式、根对象和上下文环境)

− 表达式是OGNL的核心,所有的OGNL操作都是通过解析表达式后进行的。表达式指出了OGNL操作要做的工作。例如,name、student.name等表达式,表示取name或者student中的name的值。

− OGNL的取值还需要一个上下文环境。设置了Root对象,OGNL可以对Root对象进行取值或写值等操作,Root对象所在环境就是OGNL的上下文环境(Context)。根对象是OGNL要操作的对象,在表达式规定了要完成的工作后,需要指定工作的操作对象。

− 上下文环境规定了OGNL的操作"在哪里进行"。上下文环境Context是一个Map类型的对象,在表达式中访问Context中对象,需要使用"#“号加上对象名称,即”#对象名称"的形式。例如<s:property value="#request.name"/>中,request就是对象,这个对象取出name属性的值。


OGNL可以让我们用非常简单的表达式访问对象层,例如,当前环境的根对象为user1,则表达式person.address[0].province可以访问到user1的person属性的第一个address的province属性。

OGNL是通常要结合Struts 2的标志一起使用。主要是#、%和$这三个符号的使用。使用方法如下:
新建名为Struts2_OGNL的Web工程

#”主要有三种用途:
访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性: 名称 作用 例子
parameters 包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameterValues(“id”).get(0);
request 包含当前HttpServletRequest的属性(attribute)的Map #request.userName相当于request.getAttribute(“userName”)
session 包含当前HttpSession的属性(attribute)的Map #session.userName相当于session.getAttribute(“userName”)
application 包含当前应用的ServletContext的属性(attribute)的Map #application.userName相当于application.getAttribute(“userName”)
attr 用于按request > session > application顺序访问其属性(attribute) #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
用于过滤和投影(projecting)集合,如books.{?#this.price<100};
构造Map,如#{‘foo1’:‘bar1’, ‘foo2’:‘bar2’}。

扫描二维码关注公众号,回复: 5640048 查看本文章

OGNL与Stucts2的结合

– OGNL表达式语言结构

 Struts 2中的OGNL Context即为ActionContext

 当Struts2接受一个请求时,会迅速创建ActionContext,再创建ValueStack、action ,然后把action存放进ValueStack,所以action的实例变量可被OGNL访问。

 StackContext(map):stack上下文,它包含一系列对象,包括request、session、attr、application等。访问Stack Context中的对象的属性时要使用"#对象名.属性名"的方式,例如#application、#session。
在这里插入图片描述

值栈 【ValueStack】

− 本质是一个ArrayList,充当OGNL的root,给一次请求中共享数据的功能

− 之前web阶段,在servlet里面进行操作,把数据放到域对象里面,在页面中使用el表达式获取到。域对象在一定范围内存值和取值。

− 在struts2里面提供了本身的一种存储机制,类似于域对象,是值栈可以存值和取值。 值栈

− 在action里面把数据放到值栈里面,在页面中获取到值栈的数据。


参考:https://blog.csdn.net/q714699280/article/details/52267956

值栈的简单定义:

 (1)简单的说,值栈是对应每一个请求对象的轻量级的数据存储中心,在这里统一管理着数据,供Action、Result、Interceptor等Struts2的其他部分使用,这样数据被集中管理起来而不凌乱。

 (2)当有请求的时候,Struts2会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的,不同的请求,值栈也不一样, 而值栈封装了一次请求所有需要操作的相关的数据。

 (3)正是因为值栈和请求的对应关系,因此值栈能保证线程安全的为每个请求提供公共的数据存取服务。

 (4)就是ROOT根对象,ognl访问值栈不用加任何的访问前缀,只需action中声明相应的属性,并且生成属性对应的set和get方法,页面中通过struts2标签就可以存放/取出值栈中的值,EL表达式${username}如果没有加访问范围,访问的也是值栈,这只是最简单的值栈应用

 (5)值栈的特点:如果访问的值栈里有多个对象,且相同的属性在多个对象中同时出现,则值栈会按照从栈顶到栈底的顺序,寻找第一个匹配的对象。

向值栈里面放数据

  1. 获取值栈对象,调用值栈对象里面的 set 方法
    ValueStack stack=ActionContext.getContext().getValueStack();
    stack.set("username","FireLang");
    在用set方法添加值栈数据之后,会在root栈顶多一个HashMap对象
  1. 获取值栈对象,调用值栈对象里面的 push 方法
ActionContext.getContext().getValueStack().push(xxx);
调用push之后,就会在root栈顶放入一个`String`类型的对象!
  1. 在action定义变量,生成变量的get方法(主要)
public class pr_action{
	private String name;
	public String getName(){
	    return name;
	}
	public String execute(){
	    name="FireLang";
	    return "success";
	}
}

在用第三种方法之后,struts2并不会在值栈root的栈顶放入新的对象,它的存储路径还是存储在action里面,所以这就起到了资源的合理应用,当想要获取name属性的时候,就会在值栈里面调用action的getName方法。这也就是为什么会在值栈里面存储action的原因了。

向值栈中放对象

实现步骤:
第一步:定义对象变量
第二步:生成变量的get方法
第三步:在执行的方法里面向对象中设置值

向值栈中放List对象

第一步:定义List集合变量
第二步:生成变量的get方法
第三步:在执行的方法里面向List集合设置值

public class Pr_fangList {
    private List<User> lu;
    
    public String execute(){
        lu=new ArrayList<User>();
        User u1=new User();
        u1.setName("胡艺宝");
        u1.setPassword("123");
        lu.add(u1);
        User u2=new User();
        u2.setName("胡家源");
        u2.setPassword("456");
        lu.add(u2);
        System.out.println(lu);
        return "success";
    }
    
    public List<User> getLu() {
        return lu;
    }
}

从值栈的root里面取数据

使用struts2的标签+OGNL表达式获取值栈数据
<s:property value="OGNL表达式"/>
  1. 获取set值
<!—通过直接key值,从root域里面取对应值 -->
<s:property value="us"/><br><br>  key=us
<s:property value="lang"/>  key=lang
//us、lang均为key值
  1. 获取push值

//这里要注意的是push方法是直接把数据存放在root中的。不像set一样可以通过key来取值。
//push的取值方法有点特殊,是通过直接把栈顶元素取出来的。

    <s:property value="[0].top"/>//取第一个
    <s:property value="[1].top"/>//取第二个,这里的top是root的域实体对象名称,
    也就是List对象的名称
  1. 获取action中的属性字段
    \<s:property value="name"/>

这里的name是OGNL表达式。表示获取action中的name字段值,必须要写get方法,因为字段读或者写的功能按照规定,都必须通过读或者写方法来给变量赋值

  1. 获取对象
    //再次强调必须要get方法。
<s:property value="us.name" /><br><!-- value中的值是OGNL表达式 -->

<s:property value="us.password" /><!-- 获取到us对象后,再获取us中的name属性和password属性,
再次强调获取字段基本上都是按照规定通过get和set方法进行操作! -->

再次强调获取字段基本上都是按照规定通过get和set方法进行操作!

  1. 获取List集合
    通过OGNL+struts标签获取List集合共有三种方式
第一种方式:
//这种代码非常不好,在很多时候你永远不可能知道服务端传来的List里面到底有多少参数。
<s:property value="usl[0].name"/>
<s:property value="usl[0].password"/>
	第二种方式:
	类似jstl中的foreach标签
	<s:iterator value="usl">
	    <s:property value="name"/>
	    <s:property value="password"/>
	</s:iterator>
第三种方式:
<s:iterator value="usl" var="singleus">
    <s:property value="#singleus.name"/>
    <s:property value="#singleus.password"/>
</s:iterator>

第三种方式较第二种方式多加了一个var,
根本区别就是iterator把遍历出来的值放进了值栈的第二部分空间context,contex因为是Map结构的所以要加上一个键作为取值方式,也就是var的值作为context的键,

其实这种方式算是一种优化,不用在root中去拿值了。而第二种方式还会到root里面去拿值。速度没有在context中的快

猜你喜欢

转载自blog.csdn.net/qq_40803626/article/details/88716126