struts2笔记_day04

来源:互联网 发布:mac菜单栏如何清除 编辑:程序博客网 时间:2024/06/16 04:51

1、ognl介绍:

OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言;    比El表达式功能强大。        *xwork提供OGNL表达式        *ognl-3.0.5.jar    struts2将ognl表达式语言,集成到struts2框架中,做为它默认表达式语言。    OGNL提供五大类功能:        1、支持对象方法调用,如:xxx.doSomeSpecial();        2、支持类静态的方法调用和值访问;        3、访问OGNL上下文(OGNL context)和ActionContext;(重点:操作ValueStack值栈);        4、支持赋值操作和表达式串联;        5、操作集合对象。    valueStack是值栈;        1、从技术角度  ValueStack就是一个接口;        2、从使用角度  ValueStack就是一个容器;演示:在struts2中使用ognl表达式    需要结合struts2的标签使用<s:property value="ognl表达式">    <s:property value="'abc'.length()"/>演示对象调用方法    <s:property value="@java.lang.Math@max(10,20)"/>演示静态成员访问    注意:在struts2中使用静态成员访问,必须设置一个常量:    把struts.ognl.allowStaticMethodAccess=false常量在struts.xml中设置为true;

2、ValueStack:

是一个接口com.opensymphony.xwork2.util.ValueStack。我们使用它是将其作为一个容器,用于携带action数据到页面;在页面上通过ognl表达式获取数据。问题1、什么是valueStack?        1、ValueStack有一个实现类叫OgnlValueStack。        2、每一个action都有一个ValueStack(一个请求,一个request,一个action,一个valueStack)valueStack生命周期就是request生命周期(请求--响应)        3、ValueStack中存储了当前action对象以及其它常用web对象(request,session,applicati,parameters)        4、struts2框架将valueStack以“struts.valueStack”为名存储到request域中。问题2、valueStack结构?        ValueStack中 存在root属性(CompoundRoot),context属性(OgnlContext)        *CompoundRoot就是ArrayList        *OgnlContext就是Map        list集合中存储的是action相关信息        map集合中存储的是相关映射信息,包含parameters,request,session,application,attr(前几个依次查)等;        我们想要从list中获取数据,可以不使用#号(它就是ognl的root),        如果我们从map中获取数据,需要使用#号(其实在struts2中的map--context就是ognlContext)    结论:        ValueStack它有两部分List和Map        在struts2中List就是root,Map就是OgnlContext。        默认情况下,在struts2中从valueStack获取数据从root中获取。问题3、值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?    ActionContext ctx = ActionContext.getContext();        if(ctx!=null){            stack = ctx.getValueStack();        }    valueStack是每一次请求时都会创建;    在ActionContext中持有了valueStack的引用。 问题4、如何获得值栈对象?    对于valueStack获取有两种方式:        1、通过request获取:            ValueStack vs = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);        2、通过ActionContext获取:            ValueStack vs2 = ActionContext.getContext().getValueStack();问题5、向值栈保存数据(主要针对root)    主要有两个方法        push(Object obj);---->底层就是root.add(0,obj)将数据存储到栈顶;        set(String name,Object obj);---->底层是将数据封装到HashMap中,在将这个HashMap通过push存储。    在jsp中通过<s:debug/>查看值栈的内容。问题6、在JSP中获取值栈的数据:    root中数据不需要#号,而context中 数据需要#号;    1、如果栈顶是一个Map集合,获取时,可以直接通过Map集合的key来获取value;        <s:property value="username"/>    2、如果栈顶数据不是一个Map,没有key值,可以使用序号来获取:        <s:property value="[0]"/>从0的位置向下查找所有;        <s:property value="[0].top"/>只查找0位置上的数据。    在OgnlContext中获取数据        1、request:<s:property value="#request.username"/>        2、session:<s:property value="#session.username"/>        3、application:<s:property value="#application.username"/>        4、attr:<s:property value="#attr.username"/>  依次从request,session,application中查找        5、parameters:<s:property value="#parameters.cid[0]"/>   获取请求参数---------------------------------------------------------------------------------------------------     ValueStack主流应用:就是解决将action数据携带到jsp页面。    1、文本(字符串)        1.fieldError  校验数据错误信息提示;        2.actionError 关于逻辑操作时错误信息(例如登录失败);        3.message 就是一个信息。        this.addFieldError("msg","字段错误信息");        this.addActionError("Action全局错误信息");        this.addActionMessage("Action的消息信息");        *fieldError 针对某一个字段错误信息(常用于表单校验)、actionError(普通错误信息,不针对某一个字段 登录失败)、actionMessage通用消息        在jsp中使用struts2提供标签 显示消息信息            <s:fielderror fieldName="msg"/>            <s:actionerror/>            <s:actionmessage/>    2、复杂数据        可以使用valueStack存储:        在action中存储数据:            //向valueStack中存储数据(root)            ValueStack vs = ActionContext.getContext().getValueStack();            List<User> users = new ArrayList<User>();            users.add(new User("tom","123",20,"男"));            users.add(new User("张三","456",21,"男"));            users.add(new User("小媚","789",19,"女"));            vs.push(users);            //vs.set("users", users);        在页面上获取数据:            使用了<s:iterator>标签来迭代集合;            使用push存进值栈这样取:            <s:iterator value="[0].top" var="user">//这是将集合中迭代出来的每一个元素起个名字叫user,而user是存储在Context中,不在root中所以访问要加#号                username:<s:property value="#user.username"/><br>                password:<s:property value="#user.password"/>            </s:iterator>            使用set存进值栈这样取:            <s:iterator value="users">                username:<s:property value="username"/>                password:<s:property value="password"/><br>            </s:iterator>    -----------------------------------------------------------------------------------    关于默认压入到valueStack中的数据:        1、每次请求,访问Action对象 会被压入值栈 ------- DefaultActionInvocation 的 init方法 stack.push(action);        * Action如果想传递数据给 JSP,只有将数据保存到成员变量,并且提供get方法就可以了         2、ModelDriven 接口 有一个单独拦截器         <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>        在拦截器中 ,将model对象 压入了 值栈 stack.push(model);        * 如果Action 实现ModelDriven接口,值栈默认栈顶对象 就是model对象 -------------------------------------------------------------------------------------------------问题7、为什么EL表达式可以访问ValueStack中的数据?    struts2框架中所使用的request对象,是增强后的request对象。    ${username}---->request.getAttribute("username");//el表达式本身会这么查找    增强后的request,会首先在request域范围查找,如果查找不到,会在valueStack中查找。        StrutsPreparedAndExecuteFilter的doFilter代码中 request = prepare.wrapRequest(request);          * 对Request对象进行了包装 ,StrutsRequestWrapper         * 重写request的 getAttribute             Object attribute = super.getAttribute(s);            if (attribute == null) {               attribute = stack.findValue(s);            }          访问request范围的数据时,如果数据找不到,去值栈中找     ?  request对象 具备访问值栈数据的能力 (查找root的数据)--------------------------------------------------------------OGNL表达式常见的使用($ # %)    1、#号使用        用法一:#代表ActionContext.getContext()上下文         <s:property value="#request.name" />  ---->  ActionContext().getContext().getRequest().get("name");          #request          #session          #application          #attr          #parameters         用法二:不写#默认在值栈的root中进行查找            <s:property value="name"/>在root中查找name属性            *查询元素时,从root的栈顶元素开始查找,如何访问指定栈中元素?                <s:property value="[1].name"/>访问栈中第二个元素name属性            *访问第二个元素对象<s:property value="[1].top"/>        用法三:进行投影映射(结合复杂对象遍历)           1、集合的投影(只输出部分属性           <h1>遍历集合只要name属性</h1>            <s:iterator value="products.{name}" var="pname">                 <s:property value="#pname"/>            </s:iterator>           2、遍历时,对数据设置条件             <h1>遍历集合只要price大于1500商品</h1>            <s:iterator value="products.{?#this.price>1500}" var="product">                 <s:property value="#product.name"/> --- <s:property value="#product.price"/>                </s:iterator>           3、综合           <h1>只显示价格大于1500 商品名称</h1>            <s:iterator value="products.{?#this.price>1500}.{name}" var="pname">                 <s:property value="#pname"/>            </s:iterator>           用法四:使用#构造map集合             经常结合 struts2 标签用来生成 select、checkbox、radio            <h1>使用#构造map集合 遍历</h1>            <s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">                key : <s:property value="#entry.key"/> , value:  <s:property value="#entry.value"/> <br/>            </s:iterator>    -------------------------------    2、%号使用        %作用:就是用于设定当前是否要解析其为ognl表达式;        %{表达式} 当前表达式会被作为ognl解析;        %{'表达式'}当前表达式不会被作为ognl解析。        <s:property value="表达式"/>对于s:property标签,它的value属性会被默认做为ognl。        以后,所有表达式如果仙姑要让其实ognl就这么写  %{表达式}    3、$号使用        $作用:就是在配置文件中使用ognl表达式来获取valueStack中数据        用法一 :用于在国际化资源文件中,引用OGNL表达式         在properties文件 msg=欢迎您, ${#request.username}        在页面            <s:i18n name="messages">                <s:text name="msg"></s:text>            </s:i18n>            * 自动将值栈的username 结合国际化配置信息显示        用法二 :在Struts 2配置文件中,引用OGNL表达式            <!-- 在Action 提供 getContentType方法 -->            <param name="contentType">${contentType}</param>                  *  ${contentType} 读取值栈中contentType数据,在Action提供 getContentType 因为Action对象会被压入值栈,              contentType是Action属性,从值栈获得    结论: #使用ognl表达式获取数据,% 控制ognl表达式是否解析 ,$ 用于配置文件获取值栈的数据

3、防止表单重复提交

问题:什么是表单重复提交?    regist.jsp---->RegistServlet    表单重复提交  危害:刷票、重复注册、带来服务器访问压力(拒绝服务)解决方案:    在页面上生成一个令牌(token,就是一个随机字符串),将其存储到session中,并在表单中携带;    在服务器端,获取数据时,也将令牌获取,将它与session中存储的token对比,没问题,将session中令牌删除。struts2中怎样解决表单重复提交:    在struts2中解决表单重复提交,可以使用它定义的一个interceptor。    <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>     步骤:        1、在页面上需要使用一个token标签            在表单中添加一个标签<s:token/>            就会在页面上生成一个令牌,并存在于表单中。        2、需要在action中引入token拦截器            <interceptor-ref name="token"></interceptor-ref>        3、需要配置视图            <result name="invalid.token">/token.jsp</result>        通过 <s:actionError/> 显示错误信息         覆盖重复提交信息  struts.messages.invalid.token=您已经重复提交表单,请刷新后重试

4、struts2中json插件使用:

知识点 :struts2 的 Ajax 开发 Ajax开发客户端 和 服务器交互数据格式  --------------- json   * json 是最轻量级,体积最小 服务器将程序处理结果,转换为json格式发送给 客户端   * json-lib 、 flexjson  工具类库   * struts2-json-plugin-2.3.7.jar 案例一: 输入用户名,鼠标点击密码(触发用户名元素离焦事件),使用Ajax 将用户名发送到服务器 判断是否存在 jquery 1.4 、 1.6 新特性比较多  (企业主流 1.4 )使用struts2 json插件    要点1 : <package> extends 继承 json-default    要点2 : <result> type 类型写 json  * struts2 json插件 ,默认将值栈root顶端对象 所有属性返回(get方法)不想将company属性返回 ,在get方法上 @JSON(serialize=false)案例二 :服务器将 商品对象 List列表返回 如果Action 实现ModelDriven , model对象就是值栈栈顶对象,struts2 json插件默认 将model返回 通过设置root属性,修改插件返回 根对象   * <param name="root">action</param> 将Action作为根对象返回 只想要每个商品的 name 属性    方案一: 在pnum 、price 的get方法上 添加 @JSON(serialize=false)  --------> 只要@JSON注解,属性将永远不能参与 json返回    方案二: 设置 includeProperties 属性 <param name="includeProperties">products\[\d+\]\.name</param>       
0 0
原创粉丝点击