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
- struts2笔记_day04
- 某坑爹公司的笔记_Day04
- 树懒_移动开学笔记_day04.2_XML笔记
- 树懒_移动开学笔记_day04.1_JavaScript_DOM
- 黑马程序员_day04 数组。
- MySQL之旅_Day04
- java学习_day04
- 黑马程序员--Oracle学习_day04
- Android_黑马视频学习_day04
- struts2 笔记
- struts2笔记:
- Struts2 笔记
- struts2笔记
- struts2笔记
- Struts2笔记
- struts2笔记
- Struts2 笔记
- struts2笔记
- 劲爆消息:trip.com被曝交易...
- android studio 获取sha1指纹证书
- 概率(和朋友会面,UVA 11722)
- XML CDATA
- 某值被调用的地方
- struts2笔记_day04
- Xcode8中创建分类、协议等文件的方法
- ReadWriteLock读写文件
- 转义字符
- 工作流学习——Activiti整体认识二步曲
- 详细的vsftpd配置文件讲解(1)
- modelsim仿真ISE工程时出现# ** Error: (vlog-19) Failed to access library 'rtl_work' at "rtl_work"
- jsp的常见动作
- 润乾报表图形报表部署在Linux下出现乱码解决办法