Struts2复习(二)

一、OGNL表达式
定义:是Object Graphic Navigation Language(对象图导航语言)的缩写,Struts2框架使用OGNL作为默认的表达式语言。
功能:1.支持普通方法的调用
2.访问静态成员(静态属性,静态方法)
3.操作集合对象:
a.创建List对象

<%-- 使用的是s:radio的标签,创建list集合
         {}就相当于创建了一个list集合
         list属性中的取值是一个OGNL表达式
     --%>
    <s:radio name="gender" list="{'男','女'}"></s:radio><br/>

b.创建Map对象

<%--使用s:radio创建一个map 
        #{}表示创建一个map
        10作为value给raido标签的value属性赋值
        男和女作为key,显示到页面的内容
    --%>
    <s:radio name="gender1" list="#{'1':'男','0':'女'}" />

二、contextMap
明确1:动作类是多例的,每次动作访问,动作类都会实例化。所以是线程安全的。struts1的动作类是单例的。
明确2:在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter都会创建一个ActionContext和ValueStack对象。且每次动作访问都会创建。这两个对象存储了整个动作访问期间用到的数据。并且把数据绑定到了线程局部变量(ThreadLocal)上了。所以是线程安全的。
contextMap:存储数据
这里写图片描述
注意:除了value stack之外,全是map,而contextMap也是一个map。其实就是Map中又封装的Map。

contexMap数据操作
这里写图片描述

①利用ActionContext存数据

public class Demo1Action extends ActionSupport {

    public String execute(){
        //1.得到ActionContext对象
        ActionContext context = ActionContext.getContext();//这是从当前线程的局部变量中获取引用
        //2.往map中存入数据
        context.put("contextMap", "hello contextMap");//把数据直接存到了大Map中

        //往session中存数据
        //第一种方式:获取key为session的map
        Map<String,Object> sessionAttribute = context.getSession();//得到key值为session的小map
        sessionAttribute.put("sessionMap", "hello sessionMap");
        //第二种方式:直接使用原始的HttpSession对象
        HttpSession session = ServletActionContext.getRequest().getSession();
        session.setAttribute("sessionMap1", "hello sessionMap1");

        //往ServletContext域中存数据
        //第一种方式:获取key值为application的map
        Map<String,Object> applicationAttribute = context.getApplication();
        applicationAttribute.put("applicationMap", "hello applicationMap");
        //第二种方式:获取原始ServletContext对象
        ServletContext application = ServletActionContext.getServletContext();
        application.setAttribute("applicationMap1", "hello applicationMap1");
        return SUCCESS;
    }
}

②利用ValueStack存数据

public class Demo2Action extends ActionSupport {

    private String name = "泰斯特2";

    public String execute(){
        //获取ValueStack对象的引用
        //第一种方式:获取HttpServletRequest对象,通过对象的getAttribute方法,从域中取
        //1.获取request对象
        HttpServletRequest request = ServletActionContext.getRequest();
        //2.根据key获取ValueStack对象的引用
        ValueStack vs1 = (ValueStack)request.getAttribute("struts.valueStack");
        System.out.println(vs1.hashCode());

        //第二种方式:先获取ActionContext对象,再取出requestMap,然后通过map的get方法获取
        //1.获取ActionContext对象
        ActionContext context = ActionContext.getContext();
        //2.获取requestMap
        Map<String,Object> requestAttribute = (Map<String,Object>)context.get("request");
        //3.根据key获取对象的引用
        ValueStack vs2 = (ValueStack)requestAttribute.get("struts.valueStack");
        System.out.println(vs2.hashCode());


        //第三种方式:使用ActionContext对象的方法,直接获取ValueStack对象的引用
        ValueStack vs3 = context.getValueStack();
        System.out.println(vs3.hashCode());


        //栈的操作
        ActionContext context = ActionContext.getContext();
        ValueStack vs = context.getValueStack();
        //压栈操作
        vs.push(new Student("泰斯特",21));
        /*
         * ValueStack的其他方法
         * setValue(String expr, Object value);
         *      String expr:它是一个OGNL表达式
         *      Object value:我们要操作的数据
         *  把数据存到哪里去?
         *      看expr是否使用了#
         *      如果使用了#,操作的就是ContextMap中
         *      如果没使用#,操作的就是ValueStack
         */
        vs.setValue("#name", "张三");//把数据放到ContextMap中。 key是name valeu=张三
        vs.setValue("name", "李四");//把ValueStack中第一个name属性的值换成李四。如果没有一个name属性的对应的setName方法,会报错。


        /*
         *set(String key, Object o);
         *  String key : Map的key
         *  Object o : map的value
         *  如果栈顶是一个Map元素,直接把key作为map的key,把Object作为map的value存入。存入的是栈顶。
         *  如果栈顶不是一个Map元素,创建一个Map对象,把key作为map的key,把Object作为map的value,压入栈顶。
         */
        vs.set("s1", new Student("王五",18));
        vs.push(new Student("test",23));
        vs.set("s2", new Student("aaa",28));
        return SUCCESS;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

③获取数据
取contextMap中的数据,使用#

<body>
    <s:debug/>
    <%--使用s:property来获取ActionContext中的数据。
        value属性的取值是一个OGNL表达式。--%>
    <br/>---------获取大Map中的数据-------------<br/>
    <%--获取大Map中的数据,在取的时候是#key名称--%>
    <s:property value="#contextMap"/>
    <br/>---------获取小Map中的数据-------------<br/>
    <%--获取大Map中小Map的数据 ,使用#大Map的key.小Map的key--%>
    <s:property value="#session.sessionMap1"/>
    <s:property value="#application.applicationMap1"/>
  </body>

④取contextMap里面ValueStack中对象的属性:直接写属性名。

 <body>
    <%--使用s:property标签,获取ValueStack中的元素。
        value属性的取值是一个OGNL表达式。它只能获取元素中的属性。
        注意:
            取ValueStack中的对象属性时,不使用#。
        它是从栈顶逐个对象查找指定的属性名称。只要找到了,就不再继续查找。
    --%>
    <s:property value="name"/><br/>
    <%--获取ValueStack中指定位置的属性 :
        详情请见解释图
    --%>
   0-name <s:property value="[0].name" /><br/>
   1-name <s:property value="[1].name" /><br/>
   2-name <s:property value="[2].name" /><br/>
   3-name <s:property value="[3].name" /><br/>
   4-name <s:property value="[4].name" /><br/>
    <%--去栈顶map中的元素 --%>
    <s:property value="s1.name" /><br/>

    <%--s:property什么都不写:
        默认取栈顶元素
     --%>
    <s:property />
    <%//模拟原理:其实全是ValueStack的findValue和findString
      ValueStack vs = ActionContext.getContext().getValueStack();
      Object obj = vs.findValue("[1].name");
      out.print("<br/>-------------------------<br/>");
      out.print(obj);
    %>
    <s:debug/>
  </body>

三、Struts2对EL表达式的改变
前提:如果我们没有往值栈(根)中放入数据的话,那么我们的动作类默认是在值栈的栈顶。
分析:我们知道EL表达式是从四大域对象中依次查找属性。搜索范围是由小到大。page Scope—>request Scope—>sessionScope—>application Scope
OGNL表达式:page Scope—>request Scope—>valueStack(根中)—>contextMap—>sessionScope—>application Scope

四、S标签配合OGNL的使用

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

1、iterator标签(很重要)

<table width="500px" border="1" align="center">
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <%--s:iterator:struts2的迭代标签
            属性详解:
            begin,end,step和jstl的forEach标签是一样的 
            value属性:要遍历的集合,是OGNL表达式。
            var属性:取值就是一个字符串
                如果写了该属性:把var的值作为key,把当前遍历的元素作为value。存到ActionContext这个大Map中
                如果不写该属性:把当前遍历的元素压入栈顶
            status属性:遍历时的一些计数信息。
                int getIndex() 从0开始
                int getCount() 从1开始
                boolean isFirst() 
                boolean isLast()
                boolean isOdd()
                boolean isEven()
            --%>
        <s:iterator value="students" var="s" status="vs" >
            <tr>
                <td><s:property value="#vs.index"/></td>
                <td><s:property value="#s.name" /></td>
                <td><s:property value="#s.age" /></td>
            </tr>
        </s:iterator>
    </table>

2、使用过滤条件投影

<%--OGNL的投影:(以下内容全是了解)添加过滤条件 
        a.“?#”:过滤所有符合条件的集合,如:users.{?#this.age > 19}   
        b.“^#”:过滤第一个符合条件的元素,如:users.{^#this.age > 19}    
        c.“$#”:过滤最后一个符合条件的元素,如:users.{$#this.age > 19}
    --%>
    <hr/>
        <table width="500px" border="1" align="center">
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <s:iterator value="students.{?#this.age>21}" status="vs">
            <tr>
                <td><s:property value="#vs.count"/></td>
                <td><s:property value="name" /></td>
                <td><s:property value="age" /></td>
            </tr>
        </s:iterator>
    </table>
    <%--OGNL的投影:指定输出内容 
        students.{name}========{"name1","name2","name3"}
    --%>
    <hr/>
        <table width="500px" border="1" align="center">
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <s:iterator value="students.{name}" status="vs" >
            <tr>
                <td><s:property value="#vs.count"/></td>
                <td><s:property /></td>
                <td><s:property /></td>
            </tr>
        </s:iterator>
    </table>

3、Struts2中#,$,%符号的使用(重要)

3.1、#

a、取contextMap中key时使用,例如<s:property value="#name" />
b、OGNL中创建Map对象时使用,例如:<s:radio list="#{'male':'男','female':'女'}" />

3.2、$

a、在JSP中使用EL表达式时使用,例如${name}
b、在xml配置文件中,编写OGNL表达式时使用,例如文件下载时,文件名编码。
struts.xml->${@java.net.URLEncoder.encode(filename)}

3.3、%

在struts2中,有些标签的value属性取值就是一个OGNL表达式,例如<s:property value="OGNL Expression" />
还有一部分标签,value属性的取值就是普通字 符串,例如<s:textfield value="username"/>,如果想把一个普通的字符串强制看成时OGNL,就需要使用%{}把字符串套起来。
例如<s:textfield value="%{username}"/>。当然在<s:property value="%{OGNL Expression}" />也可以使用,但不会这么用。

4、url和a标签

<br/>-------s:url------------<br/>
    <%--s:url标签:
        value属性:是把值直接输出到页面上
        action属性:是把动作的请求地址输出到页面上 ${pageContext.request.contextPath}/action1
        var属性:把action的取值作为value,把var的取值作为key,放到ActionContext中
        注意:它会自动根据struts配置,来转换后缀名。
    --%>
    <s:url value="action1"/>
    <s:url action="action1" var="url" >
        <%--把name作为key,把value作为值,绑定到请求连接地址后面。相当于get方式拼接请求参数 
            注意:
                name的取值就是一个普通的字符串
                value的取值是一个OGNL表达式,要想转成字符串请使用''
        --%>
        <s:param name="name" value="'张三'"></s:param>
    </s:url>
    <br/>
    <a href="${pageContext.request.contextPath}/action1">来吧 page context</a><br/>
    <a href="<s:property value='#url' />" >点击 s:url</a>
    <s:debug/>

五、S标签小案例

<body>
    <s:form action="saveCustomer">
        <s:textfield name="name" label="用户名" />
        <s:password name="password" label="密码" />
        <s:checkbox name="married" label="已婚" value="true" />
        <s:checkboxlist name="hobby" list="{'摄影','旅行','足球'}" label="爱好" />
        <s:select name="city" label="故乡"  list="#{'BJ':'北京','SH':'上海','SZ':'苏州'}" headerKey="" headerValue="---请选择---"/>
        <s:textarea name="description" label="个人介绍" rows="5"  cols="25" />
        <s:radio name="gender" list="#{'male':'男','female':'女'}" label="性别" value="'male'" /><%--value是一个OGNL表达式 --%>
        <s:submit value="提交" theme="simple"/><s:reset value="重置" theme="simple" />
    </s:form>
    <hr/>
    <s:form action="saveCustomer" theme="simple">
        <s:textfield name="name" label="用户名" />
        <s:password name="password" label="密码" />
        <s:checkbox name="married" label="已婚" value="true" />
        <s:checkboxlist name="hobby" list="{'摄影','旅行','足球'}" label="爱好" />
        <s:select name="city" label="故乡"  list="#{'BJ':'北京','SH':'上海','SZ':'苏州'}" headerKey="" headerValue="---请选择---"/>
        <s:textarea name="description" label="个人介绍" rows="5"  cols="25" />
        <s:radio name="gender" list="#{'male':'男','female':'女'}" label="性别" value="'male'" /><%--value是一个OGNL表达式 --%>
        <s:submit value="提交" theme="simple"/><s:reset value="重置" theme="simple" />
    </s:form>
    <%-- <s:debug/> --%>
  </body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值