以下内容是基于导入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. Python-条件语句和循环语句

    ·条件语句 笔记: If  布尔值: print(‘hello,world!’) 当表达式为布尔表达式时,Flase   None  0   ””    ()    []    {} 都视为假! @ ...

  2. python 数据类型、进制转换

    数据类型 存储单位 最小单位是bit,表示二进制的0或1,一般写作b 最小的存储单位是字节,用byte表示,1B = 8b 1024B = 1KB 1024KB = 1MB 1024MB = 1GB ...

  3. homebrew 使用心得

    ''' 安装anaconda 安装命令: brew search anaconda brew cask install anaconda 添加环境变量: vi ~/.bash_profile expo ...

  4. 格式化输出%02hhx

    每次看到人家的十六进制输出,对齐的很好,ff就显示了,而我的总是0xffffffff.如果是"%02x",是以0补齐2位数,如果超过2位就显示实际的数:"%hhx&quo ...

  5. c语言宏

    使用 c语言的宏是在预处理时候对字符进行简单替换. 优点:1.如果要改一个变量,只需要改宏就可以了,也就是只改一次;2.宏函数展开和普通函数一样,但是它没有普通函数调用的过程,不需要压栈出栈等操作,所 ...

  6. js 修改字符串中某些字符的样式

    var str = 'abcdefghijklmnobqrstuvwxyz'; function HightLight(e){ var reg = new RegExp(e, 'g') str = s ...

  7. 20155204 实验3《敏捷开发与XP实践》实验报告

    20155204 实验3<敏捷开发与XP实践>实验报告 一.实验内容与步骤 1.研究IDEA的code菜单. 老师给的任务的是把一串代码格式化,这个任务很简单.code菜单主要是关于编辑代 ...

  8. 学号20155308 2006-2007-2 《Java程序设计》第3周学习总结

    学号20155308 2006-2007-2 <Java程序设计>第3周学习总结 教材学习内容总结 对象(Object):存在的具体实体,具有明确的状态和行为 类(Class):具有相同属 ...

  9. 适配iOS11和iPhoneX

    详细见参考链接吧, 其他不多说了. 适配iOS11&iPhoneX的一些坑 http://www.cocoachina.com/ios/20170921/20623.html http://w ...

  10. CF 833 B. The Bakery

    B. The Bakery http://codeforces.com/contest/833/problem/B 题意: 将一个长度为n的序列分成k份,每份的cost为不同的数的个数,求最大cost ...