2014-08-12|1857阅|作者:jun|举报 摘要:1.ognl与valueStack(重点)
2.struts2标签库(了解)
3.关于表单重复提交(次重点)
4.json插件.(了解)
-------------------------------------------------------------------
1.ognl与valueStack
1.ognl
Object Graphic Navigation Language(对象图导航语言)
ognl是一个开源项目
2.valueStack
我们学习它的目的:为了在视图上获取信息.
ValueStack本质上是一个接口.它的一个实现类OgnlValueStack。
每一次请求会创建一个Action,每一个Action有对应的一个valueStack。
valueStack会被存储在request中,名称叫 "struts.valueStack"
内部结构:
Map:context
CompoundRoot: root CompoundRoot本质上是一个ArrayList。
context中存储的是:web常见对象
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application
root中存储的是Action相关的信息
ValueStack与ActionContext关系
在ActionContext中持有ValueStack的引用.
怎样获取ValueStack
1.从request获取
ServletActionContext.getRequest().getAttribute("struts.valueStack");
2.从ActionContext获取
ActionContext.getContext().getValueStack();
向valueStack中存储(主要针对于root)
push() list.add(0,obj);
set(String name,Object value) list.add(0,new HashMap());
获取root中数据,不使用#号.
[0].name 得到从第一个开始的一个子集,依次查找是否有name属性
[1].name 得到从第二个开始的子集,依次查找是否有name属性
[0].top.name 得到从第一个开始栈顶的元素是否有name属性
[1].top.name 得到从第二个开始的栈顶元素,是否有name属性.
--------------------------------------------------------------------------------
在jsp中获取值栈信息
<s:property value="#request.username"/><br>
<s:property value="#session.username"/><br>
<s:property value="#application.username"/><br>
<s:property value="#attr.username"/>
================================================================================================
Action 向JSP 传递数据处理结果 ,结果数据有两种形式
1.消息数据
addFieldError();存储校验错误信息
addActionError(); 存储Action操作中的逻辑上错误信息
addActionMessage();Action中的信息.
在页面上可以通过
<s:fielderror/> 对于这个标签可以通过指定name属性来得到指定的信息
<s:actionerror/>
<s:actionmessage />
2.复杂数据
哪些数据默认会放入到值栈 ???
1.Action会被装入到值栈中.
2.对于Action中的属性,它们会在值栈中存在
3.使用modeldriven实现,对象也会被装入到valuestack中.
简单说:关于Action的相关信息都会被装入到ValueStack的root中。
为什么通过el可以获取root中的值?
${username} page request
在struts2框架中,对request对象进行了增强.当通过request对象去获取数据 getAttribute()如果得到不到,会从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常见使用
#、 % 、$ 符号使用
#使用
root中数据获取不需要使用#。不是root中的数据获取使用#
<s:property value="#request.username">
#request.username----->ActionContext.getContext().getRequest().get("username");
所#就相当于ActionContext.getContext();
进行投影映射 (结合复杂对象遍历 )
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>
--------------------------------------------------------------------------
%用法
就是通知当前是否是一个ognl表达式.
%{表达式} 那么将表达式做为ognl表达式处理.
%{'表达式'} 将表达式以原样输出,就是不当它为ognl表达式.
对于struts2中的表单标签,它的value值,默认都是文本,如果想要通过ognl表达式来赋值,必须使用%{};
<s:property>它不是表单标签.
------------------------------------------------------------------------------
$用法
1.国际化文件中可以使用
username=${#request.username} 可以 $将数据从request中获取到username
username=%{#request.username} 可以 %它的作用是将内容以ognl表达进行解析
在页面上
<%
request.setAttribute("username", "llllll");
%>
<s:i18n name="cn.itcast.action.message">
<s:text name="username"></s:text>
</s:i18n>
2.在配置文件中使用
<result type="stream">
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachement;filename=${filename}</param>
<param name="inputStream">${inputStream}</param>
</result>
当访问action时,action会被压入到valueStack。在action中的getXxx方法在root中有对应的值.
getContentType();
getFilename()
getInputStream();
当使用${contentType}时会在valueStack 中查找contentType,就会调用action中的getContentType方法.
结论: #用于写ognl表达式获取数据,% 控制ognl表达式是否解析 ,$ 用于配置文件获取值栈的数据
-------------------------------------------------------------------------------------------
struts2的标签库(了解)
使用struts2标签必须先在web.xml文件配置filter
struts2分成两部分
1.generic Tag
ctrl tag
1.if else if else
注意在使用时要对属性test赋值(boolean值)
2.iterator 遍历集合
<s:iterator value="集合" var="迭代的元素名称">
注意:var的值它在root中不存在。要想获取必须使用#来获取.
3.url
<s:url action="" namespace="" method="" var="" value="">
action代表要访问的action的name值
namespace代表要访问的struts.xml文件中namespace值
var起个名称
method代表的是访问的方法名称
value:如果有这个值,我们可以不用action与namespace,value的值直接就是namespace+action的name值就可以。
4.a
<s:a href="">
href值可以直接引入一个<s:url>的值.
<s:a action="" method="" namespace="">
注意:对于url与a标签都可以使用<s:param>这个标签来带参数.
<s:param name="" value=""> 对于value属性,它的值,默认是ognl,如果只是一个常量 ,可以通过%{'值'}来控制.
5.set
<s:set var="username" scope="request" value="%{'李四'}"></s:set>
相当于
request.setAttribute("username","李四");
注意:对于这些非表单标签,它的value值,一般都会认为是ognl。
------------------------------------------
2.ui tag
form tag
对于struts2表单标签,它默认情况下是使用table对格式进行了控制.
在<s:form>这个标签中有一个属性 theme这个属性默认值为xhtml,它采用的是struts-core jar包下的template下的xhtml模板.
对theme这个属性,如果只在<s:form>上使用,它代表的是只对当前这个表单有效.
还可以在表单的标签上使用
还可以在struts.xml文件中通过常量来配置
<constant name="struts.ui.theme" value="simple"></constant>
对于<s:password>这个标签,它默认情况下是不回显的。
struts标签优点:回显方便
-------------------------------------------------------------------------------------------------
表单重复提交
表单防止重复提交
表单重复提交 危害: 刷票、 重复注册、带来服务器访问压力(拒绝服务)
怎样防止表单重复提交:采用令牌技术
jsp:
页面:生成一个随机字符串(uuid)
将生成的uuid存储到session中.
表单在提交时,将uuid值也带到了服务器端<input type="hidden">
服务器:
从request中获取uuid,在从session中获取uuid。
对比一样,完成操作. 从session中将uuid删除。
当重复提交表单时,session中的uuid已经没有了,那么我们就知道,它在做重复提交.
struts2:
页面:
在表单中添加一个struts2的标签 <s:token/>
服务器端
action类中不用做特殊处理.
在struts.xml文件中配置.
因为struts2的表单重复提交是通过tokenInterceptor拦截器完成。
<action name="login" class="cn.itcast.action.LoginAction">
<result>/tag/2.jsp</result>
<result name="invalid.token">/index.jsp</result>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="token"/>
</action>
在页面上可以通过<s:actionerror>得到错误信息.
国际化:在Action所在的包下创建一个properties文件
struts.messages.invalid.token=您已经重复提交表单,请刷新后重试
---------------------------------------------------------------------------------------------------
struts2对ajax支持
1.使用ajax向action发送请求,action返回一个字符串.
页面:
//1.得到XMLHttpRequest对象
var xmlhttp = createXMLHttpRequest();
//2.设置回调函数
xmlhttp.onreadystatechange = function() {
//5.处理操作
if (xmlhttp.status == 200 && xmlhttp.readyState == 4) {
alert(xmlhttp.responseText);
}
};
//3.open
xmlhttp.open("GET", "${pageContext.request.contextPath}/ajax1");
//4.send
xmlhttp.send();
action处理
ServletActionContext.getResponse().getWriter().write("hello world");
-------------------------------------------------------------------------------------------------
struts2与ajax整合时它提供一个json插件包
struts2-json-plugin-2.3.15.1.jar包
将这个jar包复制到lib下.
在这个jar下有一个struts-plugin.xml文件,这个xml文件会在我们的struts.xml文件之间加载 。
如果使用这个jar包,两个注意事项:
1.在自己的struts.xml文件中 <package name="default" namespace="/" extends="json-default">
2.在<result>中它的type值必须是json <result type="json"></result>
通过示例发现:action中的属性,会被默认的封装成json数据响应到浏览器端.
如果想对action中的属性,不封装到json中可以通过 @JSON(serialize=false)添加到getXxx方法上.
示例1:判断用户名是否重复