1、概念
(1)OGNL是Object Graphic Navigation Language(对象图导航语言)。Struts2框架使用OGNL作为默认的表达式语言。OGNL就是EL的升级版。
作用:Action和视图(JSP)之间数据交互的桥梁.
(2)值栈是对应每一个请求对象的轻量级的内存数据中心。每一次请求的时候,都会创建一个新的ValueStack对象,该ValueStack对象封装了这一次请求相关的数据信息.
①ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础。
②ValueStack贯穿整个Action的生命周期(一次请求):每个Action类的实例都拥有一个ValueStack对象。 ValueStack相当于数据的中转站,在其中保存该次请求和当前Action对象和其他相关对象信息。
③Struts2框架把ValueStack对象保存在名为“struts.valueStack”的request属性中。
新的请求:
ValueStack vs = ....;
request.setAttribute("struts.valueStack",vs);
2、获取ValueStack对象
(1)方式一: 在ValueStack在请求中,ValueStack对象属性名为:struts.valueStack
ValueStack stack1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
ValueStack stack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
(2)方式二:通过ActionContext对象获取:推荐
ValueStack stack3 = ActionContext.getContext().getValueStack();
3、ValueStack内部结构
从OgnlValueStack源码可以看到以下两个属性:
①root——类型:CompoundRoot extends CopyOnWriteArrayList。
主要存储Action对象相关的数据信息。一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以action对象是CompoundRoot中的一个元素。有push()、pop()方法,是个栈结构。
从root中获取数据: 直接使用属性名获取. ---><s:property value="属性名"/>
②context(上下文)——类型: Map。主要存储映射关系数据.(key-value).
从context中获取数据: #key ---><s:property value="#key"/>
ActionContext为Action的上下文,其中有重要的6大对象valueStack,parameters,request,session,application,attr
4、值栈root区域值的存取
(1)存入数据
(2)取出数据
必须使用Struts的标签.--->先引入Struts2标签<%@ taglib uri="/struts-tags" prefix="s"%>
访问方式:<s:property value="OGNL表达式"/>
①放入root中的数据,没有属性名。
取出栈顶数据:<s:property value="[0].top"/>
②放入root中的数据,有属性名
取出栈顶数据:<s:property value="属性名"/>
5、值栈context区域值的存取
(1)存入数据
(2)取出数据
6、Struts2标签
可查看:OGNL表达式struts2标签“%,#,$”的区别
(1)Control Tag
eg:if、elseif、else
测试:
eg:iterator
(2)Form Tag
eg:theme默认为xhtml
测试:
7、输入校验
Action中
* 要继承ActionSupport
* 重写Validateable接口中的validate()方法 ,在该方法中完成验证
步骤如下:
* validate()方法在其他的业务方法之前执行
* 验证出错转向的页面
struts.xml配置<result name="input">页面地址</result>
* 什么时候表示验证出错(转向input所指向的页面)
* super.addFieldError("字段名称", "错误信息");
* 当集合不为空时,转向错误页面.
* 若校验失败,不会再执行Action中的业务方法.
以下示例校验用户名是否为空
eg:
①log.jsp
<%@ taglib uri="/struts-tags" prefix="s"%>
<h3>登录页面</h3>
<s:form action="/validate" namespace="/" method="post" theme="simple">
用户:<s:textfield name="username"/><br>
<!-- 显示错误信息 -->
<s:fielderror value="username"/>密码:<input type="text" name="password"><br><input type="submit" value="提交"></s:form>
②ValidationAction.java
public class ValidationAction extends ActionSupport{
private static final long serialVersionUID = 1L;
private String username;
private String password;
public String login(){
System.out.println(username+","+password);
return "none";
}
@Override
public void validate(){
if(username == null || "".equals(username)){
//super.addFieldError("字段名称", "错误信息")
super.addFieldError("username", "用户名不能为空");
//return INPUT视图
}
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
③struts.xml
<struts>
<package name="valiPkg" namespace="/" extends="struts-default">
<action name="validate" class="action.validation.ValidationAction" method="login">
<result name="input">/views/validate/log.jsp</result>
</action>
</package>
</struts>
注意:一定要配置INPUT类型的结果视图
④测试:若不填用户名则返回登录页面,否则在控制台打印用户名和密码。
⑤此时在Action类增加两个方法
public void save(){
System.out.println("保存");
<action name="validate_*" class="action.validation.ValidationAction" method="{1}">
<result name="input">/views/validate/log.jsp</result>
<allowed-methods>save,delete</allowed-methods>
</action>
}public void delete(){System.out.println("删除");}
⑥在struts.xml修改配置
<action name="validate_*" class="action.validation.ValidationAction" method="{1}">
<result name="input">/views/validate/log.jsp</result>
<allowed-methods>save,delete</allowed-methods>
</action>
⑦测试:
可以看到连save、delete方法都进行了验证
为了避免对不需要的方法进行验证,有如下两种方法:
i.在不需要进行校验的方法上添加@SkipValidation注解
ii. 想要验证那个方法,按照规则和一个新的方法:方法名规则 validate + 需要验证的方法名,方法名首字母大写
测试:
可继续参考:
Struts2数据传输的背后机制:ValueStack(值栈)