以下内容是基于导入struts2-2.3.32.jar包来讲的

1.OGNL

  OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整个对象的结构图,实现对象属性类型的转换等功能。它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。  

  OGNL 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了 java.utils.Map 的接口。

作用:

1、支持对象方法调用,如xxx.doSomeSpecial();
2、支持类静态的方法调用和值访问,表达式的格式:
 @[类全名(包括包路径)]@[方法名 |  值名],例如:
    @java.lang.String@format('foo %s', 'bar')
    或@tutorial.MyConstant@APP_NAME;
3、支持赋值操作和表达式串联,如price=100, discount=0.8,
     calculatePrice(),这个表达式会返回80;
4、访问OGNL上下文(OGNL context)和ActionContext;
5、操作集合对象。

ognl表达式取值,如果是根元素取值不用带#符号, 非根元素取值要带#号!

知识点:

1.OGNL表达式的计算是围绕OGNL上下文进行的。
OGNL上下文实际上就是一个Map对象,由ognl.OgnlContext类表示。它里面可以存放很多个JavaBean对象。它有一个上下文根对象。
上下文中的根对象可以直接使用名来访问或直接使用它的属性名访问它的属性值。否则要加前缀“#key”。
 
2.Struts2的标签库都是使用OGNL表达式来访问ActionContext中的对象数据的。如:<s:propertyvalue="xxx"/>。
 
3.Struts2将ActionContext设置为OGNL上下文,并将值栈作为OGNL的根对象放置到ActionContext中。
 
4.值栈(ValueStack) :
可以在值栈中放入、删除、查询对象。访问值栈中的对象不用“#”。
Struts2总是把当前Action实例放置在栈顶。所以在OGNL中引用Action中的属性也可以省略“#”。
 
5.调用ActionContext的put(key,value)放入的数据,需要使用#访问。

OGNL中重要的3个符号:#、%、$:

#、%和$符号在OGNL表达式中经常出现,而这三种符号也是开发者不容易掌握和理解的部分,需要时间的积累才渐渐弄清楚。
1.#符号

#符号的用途一般有三种。

—    访问非根对象属性,例如#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext. getContext();#session.msg表达式相当于ActionContext.getContext().getSession(). getAttribute("msg") 。

—    用于过滤和投影(projecting)集合,如persons.{?#this.age>25},persons.{?#this.name=='pla1'}.{age}[0]。

—    用来构造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}。

2.%符号

%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值,这个类似js中的eval,很暴力。

3.$符号

$符号主要有两个方面的用途。

—    在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。

—    在Struts 2框架的配置文件中引用OGNL表达式。

2.基本使用

A.往根元素设置并获取值:

 package com.rong.web.test;

 import com.rong.web.entity.User;

 import ognl.Ognl;
import ognl.OgnlContext; public class OGNLTest { public static void main(String[] args) throws Exception{
//Ognl上下文OgnlContext实现了 java.util.Map 的接口,具有Map的功能
OgnlContext ognlContext = new OgnlContext();
ognlContext.put("username", "huge");
System.out.println(ognlContext.get("username")); User user=new User();
user.setId(57);
user.setName("rjl");
user.setAge(18);
//设置上下文根对象
ognlContext.setRoot(user);
//表达式
Object expression1 = Ognl.parseExpression("name");
Object expression2 = Ognl.parseExpression("id");
Object expression3 = Ognl.parseExpression("age");
Object value1 = Ognl.getValue(expression1, ognlContext, ognlContext.getRoot());
Object value2 = Ognl.getValue(expression2, ognlContext, ognlContext.getRoot());
Object value3 = Ognl.getValue(expression3, ognlContext, ognlContext.getRoot()); System.out.println(value1.toString()+value2.toString()+value3.toString());
}
}

B.往非根元素设置并获取值:

 package com.rong.web.test;

 import com.rong.web.entity.Student;

 import ognl.Ognl;
import ognl.OgnlContext; public class OGNLTest { public static void main(String[] args) throws Exception{
//Ognl上下文OgnlContext实现了 java.utils.Map 的接口,具有Map的功能
OgnlContext ognlContext = new OgnlContext();
//往非根元素设置值;非根元素取值要带#号
Student student = new Student(24,"kobe",38);
ognlContext.put("stu", student);
Object expression = Ognl.parseExpression("#stu.sid");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
System.out.println(value);
}
}

3.值栈(ValueStack)

  ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础。

ValueStack贯穿整个 Action 的生命周期
(每个 Action 类的对象实例都拥有一个ValueStack 对象).
相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.
Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中。

Action中获取值栈对象的两种方式:

 package com.rong.web.action;

 import javax.servlet.http.HttpServletRequest;

 import org.apache.struts2.ServletActionContext;

 import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L; @Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
//ValueStack是执行Ognl表达式的基础。也是从OgnlContext中去获取值、设置值的基础
//ValueStack值栈
ValueStack valueStack = actionContext.getValueStack();
//com.opensymphony.xwork2.ognl.OgnlValueStack@55195240
System.out.println(valueStack); //Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中。
HttpServletRequest request = ServletActionContext.getRequest();
Object object = request.getAttribute("struts.valueStack");
//com.opensymphony.xwork2.ognl.OgnlValueStack@55195240
System.out.println(object);
return SUCCESS;
}
}

ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中--List
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
Struts 会把下面这些映射压入 ContextMap 中
  parameters: 该 Map 中包含当前请求的请求参数
  request: 该 Map 中包含当前 request 对象中的所有属性
  session: 该 Map 中包含当前 session 对象中的所有属性
  application:该 Map 中包含当前 application 对象中的所有属性
  attr: 该 Map 按如下顺序来检索某个属性: request, session, application

值栈中有根元素 和 非根元素。
非根元素就是OgnlContext

OgnlContext中引用了值栈的根元素数据

Struts每次访问action的时候:
1. 创建一个ActionContext对象
2. 创建值栈对象
  把域中存放的数据、以及Action对象,放到值栈中!
  这时候,值栈就有了struts运行时期的数据!
3. 把值栈的数据,拷贝一份给ActionContext!
4. 最后,把值栈放到request的请求中!

操作根元素数据:

      ActionContext actionContext = ActionContext.getContext();
//ValueStack是执行Ognl表达式的基础。也是从OgnlContext中去获取值、设置值的基础
//ValueStack值栈
ValueStack valueStack = actionContext.getValueStack();
//com.opensymphony.xwork2.ognl.OgnlValueStack@55195240
System.out.println(valueStack);
Student student = new Student(24,"kobe",38);
valueStack.pop();//移出根元素
valueStack.getRoot().push(student);//设置根元素 boolean empty = valueStack.getRoot().isEmpty();
System.out.println("根元素是否为空:"+empty);
Student pop = (Student) valueStack.getRoot().pop();//移出根元素,并返回该元素
System.out.println(pop.getSname());

操作非根元素数据:

 package com.rong.web.action;

 import java.util.Map;

 import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.rong.web.entity.Student; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L; @Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
Student student = new Student(24,"kobe",38);
Map<String, Object> request = actionContext.getContextMap();
request.put("one", "ONE");
Map<String, Object> session = actionContext.getSession();
session.put("two", student);
Map<String, Object> application = actionContext.getApplication();
application.put("three", "Three");
System.out.println(request.get("one"));
System.out.println(((Student)session.get("two")).getSname());
System.out.println(application.get("three")); return SUCCESS;
}
}

4.struts标签(实际开发很少用,用jstl较多)

标签防止重复提交

<s:token />标签防止重复提交,用法如下:第一步:在表单中加入<s:token />
<s:form action="helloworld_other" method="post" namespace="/test">
<s:textfield name="person.name"/><s:token/><s:submit/>
</s:form>
第二步:
<action name="helloworld_*" class="com.rong.web.action.HelloWorldAction" method="{1}">
<interceptor-ref name="defaultStack"/>
<!-- 增加令牌拦截器 -->
<interceptor-ref name="token">
<!-- 哪些方法被令牌拦截器拦截 -->
<param name=“includeMethods">save</param>
</interceptor-ref>
<!-- 当表单重复提交转向的页面 -->
<result name="invalid.token">/WEB-INF/page/message.jsp</result>
</action>
以上配置加入了“token”拦截器和“invalid.token”结果,因为“token”拦截器在会话的token与请求的token不一致时,将会直接返回“invalid.token”结果。

在debug状态,控制台出现下面信息,是因为Action中并没有struts.token和struts.token.name属性,我们不用关心这个错误:
严重: ParametersInterceptor - [setParameters]: Unexpected Exception caught setting 'struts.token' on 'class xxx: Error setting expression 'struts.token' with value '[Ljava.lang.String;@39f16f'
严重: ParametersInterceptor - [setParameters]: Unexpected Exception caught setting 'struts.token.name'

$符号配置文件取值用:

 package com.rong.web.action;

 import com.opensymphony.xwork2.ActionSupport;

 public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String execute() throws Exception {
username="rjl";
return SUCCESS;
}
}
<struts>
<package name="default" namespace="/" extends="struts-default" >
<action name="test" class="com.rong.web.action.MyAction">
<result type="redirect">/one.jsp?username=${username}</result>
</action>
</package>
</struts>

#号%号略。

struts标签使用:

导入标签库:<%@ taglib uri="/struts-tags" prefix="s"%>

1、条件标签 if…elseif…else

 package com.rong.web.action;

 import java.util.Map;

 import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
@Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
Map<String, Object> session = actionContext.getSession();
session.put("number", 57);
return SUCCESS;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/struts-tags" prefix="s"%>
<c:set var="basePath" value="${pageContext.request.contextPath }"></c:set>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
one.jsp!
<s:debug></s:debug>
<s:if test="#session.number>57">great!</s:if>
<s:elseif test="#session.number<57">less!</s:elseif>
<s:else>equal!</s:else>
</body>
</html>

2、迭代标签 iterator

用于循环数组,集合和Map

属性:

value:数组,集合或Map

var:当前元素

status:当前元素的状态index,count,even,odd,first,last

其余的标签略。

5.Action中验证(代码验证)

后台向前台返回校验信息,数据校验由后台进行(较少用,一般前台做数据校验)

A.验证所有方法

<struts>
<package name="default" namespace="/" extends="struts-default" >
<action name="check" class="com.rong.web.action.MyAction">
<result>/one.jsp</result>
<!-- 验证信息错误时,框架固定返回input视图 -->
<result name="input">/index.jsp</result>
</action>
</package>
</struts>

index.jsp

<body>
<form action="${pageContext.request.contextPath }/check" method="post">
<input type="text" name="student.sname"/>
<!-- 获取后台返回的校验信息 -->
<s:fielderror key="#student.sname"></s:fielderror>
<input type="submit" value="登录"/>
</form>
</body>

MyAction.java

 package com.rong.web.action;

 import com.opensymphony.xwork2.ActionSupport;
import com.rong.web.entity.Student; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
//重写validate方法校验前台信息,在执行execute方法之前执行。此Action里所有的方法都会走这个验证。
@Override
public void validate() {
if(student.getSname().trim().length()==0){
//向前台返回校验信息
this.addFieldError("student.sname", "学生名字不能为空!");
}
}
@Override
public String execute() throws Exception {
System.out.println("execute!!!");
return SUCCESS;
}
}

B.验证某个方法

public void validate方法名(){

  //方法名首字母需要大写!!!

}

 package com.rong.web.action;

 import com.opensymphony.xwork2.ActionSupport;
import com.rong.web.entity.Student; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
//针对某一个方法做验证:validate方法名,其中方法名首字母要大写
public void validateExecute(){
if(student.getSname().trim().length()==0){
//向前台返回校验信息
this.addFieldError("student.sname", "学生名字不能为空!");
}
}
@Override
public String execute() throws Exception {
System.out.println("execute!!!");
return SUCCESS;
}
}

C.添加/显示错误

添加:    
   @Override
public void validate() {
if(student.getSname().trim().length()==0){
//向前台返回校验信息
this.addFieldError("student.sname", "学生名字不能为空!");
}
}

  显示:

<body>
<form action="${pageContext.request.contextPath }/check" method="post">
<input type="text" name="student.sname"/>
<!-- 获取后台返回的校验信息 -->
<!-- 显示指定错误信息 -->
<s:fielderror key="#student.sname"></s:fielderror>
<!-- 显示指定错误信息 -->
<s:fielderror fieldName="student.sname"></s:fielderror>
<!-- 可以显示所有的错误信息 -->
<s:fielderror></s:fielderror>
<input type="submit" value="登录"/>
</form>
</body>
fielderror标签样式问题:
struts默认添加额外的ul-li样式,去除这种效果便于显示!
解决方式:
1.新建src\\template\\simple包
2.拷贝一个fielderror.ftl
3.修改fielderror.ftl文件,把ul和li去掉即可

Struts2(六)的更多相关文章

  1. Struts2(六):ResultType

    本章节将继续学习struts2的返回类型的使用方法. 学习文档下载struts2 full包解压后会在doc下包含离线html文档. 点击运行后页面: 点击Guides向导终将会有向导列表 再点开后, ...

  2. Struts2六、为应用指定多个配置文件

    为了使用Struts.xml更简洁,更利于维护,我们可以把Struts.xml要配置的Action信息分类别放在其他的XML文件中,使用include在struts.xml中加载这些文件: 将Web. ...

  3. Struts2(六) 用Struts完成客户列表显示

    Struts完成客户列表显示 所用的基础知识 在之前的随笔中已经讲过.这篇是介绍如何使用Struts 完成客户列表显示  . 下面是  完成的代码执行逻辑图: 抽取项目部分代码 相信大家认真看一遍就明 ...

  4. struts2(六) 文件上传和下载

    前面对文件下载提过一点点,这里正好要讲文件上传,就放在一起在说一遍. --WH 一.单文件上传 在没学struts2之前,我们要写文件上传,非常麻烦,需要手动一步步去获取表单中的各种属性,然后在进行相 ...

  5. Struts2(六)result

    一.result简述 result:输出结果:第个Action返回一个字符串,Struts2根据这个值来决定响应结果 name属性:result的逻辑名.和Actin里的返回值匹配,默认"s ...

  6. Struts2(六.用标签显示用户列表及Value Stack和Stack Context)

    一.用Struts2标签显示用户列表 原理: 在struts中可以通过在action中将所有用户的信息存入到某个范围中,然后转向userlist.jsp,进行访问 原则: 在jsp网页上,尽量不要出现 ...

  7. 二十六:Struts2 和 spring整合

    二十六:Struts2 和 spring整合 将项目名称为day29_02_struts2Spring下的scr目录下的Struts.xml文件拷贝到新项目的scr目录下 在新项目的WebRoot-- ...

  8. Struts2(十六)Json

    一.JSON Json就是浏览器和服务器之间交换数据的一种轻量级对象 javaSctipt中类似的对象操作 $(function() { var person = { "name" ...

  9. 六、Struts2的配置文件

    六.Struts2的配置文件 1.default.properties:在struts2-core-**.jar的org.apache.struts包中 关于Struts2一些常量配置(框架内部) s ...

  10. struts2总结六: Struts2的拦截器

    一.Struts2的系统结构图

随机推荐

  1. 海思平台交叉编译curl支持SSL功能

    1.准备工具 1).交叉编译工具 2).下载libcurl和openssl源代码,我使用的是(openssl-1.0.2o.tar,curl-7.59.0.tar) 3).查看cpu详细 ~ # ca ...

  2. 排序 permutation

    习题2-6 排序 permutation 用1,2,3……9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3.按照“abc def ghi”的格式输出 ...

  3. 用GO写一个连接比特币JSONRPC接口的程序

    比特币钱包默认是不开启JSONRPC接口的,要在比特币区块文件夹下新建bitcoin.conf这个文件,并写入以下内容 server=1  rpcuser=xxmm  rpcpassword=1234 ...

  4. Egret 菜鸟级使用手册--第二天

    ################新的一天,我还是大佬 今天加载个英雄,先在GameScene里搞一个英雄出来,然后再创建一个Hreo类 接下来又一个新的API egret.TouchEvent.TOU ...

  5. Java使用POI导出excel(上)——基本操作

    相关的介绍参考自:http://zc985552943.iteye.com/blog/1491546 一.概述 1.概念 受上文博文博主的启发,有必要先对excel的各个概念先做了解! //上述基本都 ...

  6. 20155229实验二 《Java面向对象程序设计》实验报告

    20155229实验二 <Java面向对象程序设计>实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 ...

  7. [note]左偏树(可并堆)

    左偏树(可并堆)https://www.luogu.org/problemnew/show/P3377 题目描述 一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 ...

  8. 【LG4103】[HEOI2014]大工程

    [LG4103][HEOI2014]大工程 题面 洛谷 题解 先建虚树,下面所有讨论均是在虚树上的. 对于第一问:直接统计所有树边对答案的贡献即可. 对于第\(2,3\)问:记\(f[x]\)表示在\ ...

  9. KEIL5的安装

    安装注意事项 1.最好不要安装在带有中文路径的文件夹. 2.试用版的Keil MDK只能编译32K以下的代码,代码大于32K只能使用正版或破解版才能编译通过. 安装MKD 这里选择MKD512A版本安 ...

  10. 面试时让你说一个印象最深的bug,该怎么回答

    其实,面试官并不关心你描述的这个bug是否真的有价值,或有多曲折离奇?他只是: * 了解你平时工作中的测试能力 所以,这就要求的你平时工作中遇到bug时试着自己去定位,定位bug的过程远比你的单纯的执 ...