ognl
object-graph navigation 功能强大的表达式语言 struts2默认表达式语言
提供五大类功能
支持对象方法调用
支持类静态方法调用和值访问
访问OGNL上下文和ActionContext
支持赋值操作和表达式串联
操作集合对象
在struts2中使用ognl表达式
设置常量 <constant name="struts.ognl.allowStaticMethodAccess"value="false">
使用标签库 <%@taglib prefix="s"url="/struts-tags" %>
<s:property:value="ognl表达式">
valueStack 值栈
Struts2提供的一个接口 实现类为OgnlValueStack
每一个action都对应着一个ValueStack
生命周期:request的生命周期
struts2将valueStack 以"struts.valueStack"为名 存储在request域中
组成
ObjectStack (ArrayList) 相当于ognl中的root 存储着action相关信息
ContextMap (Map) 相当ongl中的ognlcontext 必须使用#号获取 存储着相关映射信息 parameters request session application
在struts中 valueStack从root中获取数据
获取
通过request获取 ValueStack vs=(ValueStack) ServletActionContext.getRequest().getAttribute("ServletActiionContext.STRUTS_VALUESTACK_KEY")
通过ActionContext获取 ValueStack vs=ActionContext.getContext().getValueStack();
保存数据(值栈) 针对root
push(Object obj) 将数据存储到栈顶
set(String name,Object obj) 在值栈中创建map 将数据保存在map中 存储在栈顶
在jsp页面中通过<s:debug/>查看值栈内容
jsp中获取数据
如果栈顶是一个map集合 获取时 可以直接通过map集合的key 来获取value
<s:property value="username">
对于<s:property>标签 它的value属性会被默认作为 ognl
如果栈顶不是map集合 可以使用序号来获取
<s:property value="[0]"> 在0位置上 查找所有的数据
<s:property value="[0].top"> 只查找0位置上的数据
<s:property value="#request.user"/>
<s:property value="#session.user"/>
<s:property value="#application.user"/>
<s:property value="#parameters.username"/>获取请求参数中的 name值
作用
将action中的数据携带到jsp页面上进行展示
简单数据:filedError(校验数据错误信息提示) actionError(逻辑操作错误信息提示) message
复杂数据:在action 中存储
List<User> users=new ArrayList<User>();
users.add(new User("tom",20));
users.add(new User("jam",21));
vs.push(users);
在jsp页面中 使用<s:iterator>来迭代集合
<s:iterator value="[0].top" var="user">
username:<s:property value="#user.username"/><br>
password:<s:property value="#user.password"/><br>
</s:iterator>
默认压入valueStack中的数据
1 访问的action对象 在action的init方法中 stack.push(action);
action要传递数据给jsp,只需将数据保存到成员变量,并且提供get方法
2 ModelDriveInterceptor stack.push(model);
将model对象压入了valueStack
使用el表达式访问valueStack
${username} ---------->request.getAttribute("username");
struts2使用的request对象是增强了的request 对象 具备访问值栈数据的能力 会在valueStack中查找attribute
防止表单重复提交
危害:重复注册、购买(刷票)、带来服务器端访问压力
web解决方案
在页面中 生成令牌(随机字符串)存储到当前session中,携带在页面的表单上
<%
String token=UUID.randomUUID().toString();
session.setAttribute("token",token);
%>
<form action="${pageContext.request.contextPath}/regist" method="post">
<input type="hidden"name="token"value=<%=token%>">
</form>
服务器端获取表单数据的同时获取令牌,与session中的token对比,同时清空session中的token
String token=request.getParameter("token");
String _token=request.getSession().getAttribute("token");
request.getSession().removeAttribute("token");
if(!token.equals(_token)){
response.getWriter().write("不能重复提交");
}
struts2解决方案
页面上使用标签 <s:token/> 在页面上生成令牌 存于表单中
在action中使用拦截器 <interceptor name="token"class="org.apache.struts2.interceptor.TokenInterceptor"> token不在默认的18个拦截器defaultStack中
配置错误视图 <result name="invalid.token"></result> 通过<s:actionError/>显示错误信息
国际化 struts.message.invalid.token="您已经重复提交此表单";
在struts2中使用json插件
导入json插件包 在struts2的lib下 struts2-json-plugin- .jar
在struts.xml 中 配置 <package extends="json-default"> <result type="json">
配置后 valueStack栈顶数据 转换为json
<param name="root">p</param> 设置了root属性,只将指定数据转换成json
转换的json对象不包含特定属性 @JSON(serialize=false) 在getXXX方法上设置,也可通过json插件上的interceptor完成