一、OGNL概述

1.1 什么是OGNL

  OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。如果把表达式看作是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

1.2 OGNL的作用

  Struts2默认的表达式语言就是OGNL,它具有以下特点:

    ● 支持对象方法调用。例如: objName. methodName( )。

    ● 支持类静态方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[ 方法名|值名 ]。例如:@java.lang.String@format( "foo%s","bar")。

    ● 支持赋值操作和表达式串联,例如: price=100, discount=0.8, calculatePrice( ),在方法中进行乘法计算会返回80。

    ● 访问OGNL上下文( OGNL context)和 ActionContext。

    ● 操作集合对象。

1.3 OGNL的要素

  了解什么是OGNL及其特点后,接下来,分析一下OGNL的结构。OGNL的操作实际上就是围绕着OGNL结构的三个要素而进行的,分别是表达式(Expression)、根对象(Root Object)、上下文环境(Context),下面分别讲解这三个要素,具体如下:

  1、表达式
  表达式是整个OGNL的核心,OGNL会根据表达式去对象中取值。所有OGNL操作都是针对表达式解析后进行的。它表明了此次OGNL操作要”做什么”。表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容。OGNL支持大量的表达式语法,不仅支持这种”链式”对象访问路径,还支持在表达式中进行简单的计算。
  2、根对象(Root)
Root对象可以理解为OGNL的操作对象,表达式规定了”做什么”,而Root对象则规定了”对谁操作”。OGNL称为对象导航语言,所谓对象图,即以任意一个对象为根,通过OGNL可以访问与这个对象关联的其他对象。
  3、Context对象
实际上OGNL的取值还需要一个上下文环境。设置了Root对象,OGNL可以对Root对象进行取值或写值等操作,Root对象所在环境就是OGNL的上下文环境(Context)。上下文环境规定了OGNL的操作”在哪里进行”。上下文环境Context是一个Map类型的对象,在表达式中访问Context中的对象,需要使用”#”号加上对象名称,即”#对象名称”的形式。

  总结来说:OGNL是一种表达式语言,之前我们学过el表达式,el表达式用于在JSP页面中获取域对象里面的值,但OGNL表达式比el表达式功能更加强大,我们使用OGNL表达式主要做的事情是在Struts2里面获取值栈中的数据(OGNL在Struts2里面经常和Struts2标签一起使用)。这就是我们接下来要重点讲解的内容,即在Struts2里面如何获取值栈中数据。

  我们还需要注意一点:OGNL本身不是Struts2框架的一部分,而是一个单独的项目,只不过它经常和Struts2框架一起使用而已。要使用OGNL表达式,首先要导入Jar包,Struts2的包中已经包含了OGNL表达式的Jar包:,所以不需要导入额外的jar包。

二、OGNL的入门

2.1 取值环境

  OGNL表达式作为一种与EL表达式性质相同的语言,主要都是用于取值的语言。我们首先要给这个语言的取值准备一个取值的环境。

  我们先回顾一下EL表达式的取值环境。EL表达式的取值范围是11大内置对象,分别为:requestScope,sessionScope,applicationScope,pageScopepageContext,param,paramValues,header,headerValues,cookie,initParam。

  那么OGNL的取值环境在哪呢?我们需要给它准备一个对象OgnlContext,你写OGNL表达式的时候,就会从OgnlContext这个对象中取值。OgnlContext由两部分构成:一部分是Root,可以放置任何对象作为root,在整个OgnlContext中有且最多只能有一个根对象,可以通过调用OgnlContext.setRoot(obj)设置为根对象;一部分是Context,这里必须是Map,即键值对的形式存放。OGNL就在ROOT和Context这两部分中取值。

  

2.2 语法

  • 取值

    public void demo1() throws Exception {
    // 准备OGNLContext
    // 准备Root
    User rootUser = new User("tom", 18);
    // 准备Context
    Map<String, User> context = new HashMap<>();
    context.put("user1", new User("jack", 20));
    context.put("user2", new User("rose", 24));
    // OgnlContext实现了Map接口
    OgnlContext ognlContext = new OgnlContext();
    // 将rootUser作为Root部分
    ognlContext.setRoot(rootUser);
    // 将Context这个Map作为Context部分
    ognlContext.setValues(context);
    // -----------------------------------------------------
    /*
    * public static Object getValue(String expression, Map context, Object root){...}
    * 书写OGNL Ognl.getValue(expression, context, root);
    * expression:表明这次OGNL操作要"做什么"
    * context:规定OGNL的操作"在哪里进行"
    * root:规定"对谁操作"
    */
    // 取出Root中user对象的name属性
    String name = (String) Ognl.getValue("name", ognlContext, ognlContext.getRoot());
    Integer age = (Integer) Ognl.getValue("age", ognlContext, ognlContext.getRoot());
    System.out.println(name);
    System.out.println(age); // -----------------------------------------------------------------
    // 取出Context中键为user1对象的name属性
    String name1 = (String) Ognl.getValue("#user1.name", ognlContext, ognlContext.getRoot());
    String name2 = (String) Ognl.getValue("#user2.name", ognlContext, ognlContext.getRoot());
    Integer age1 = (Integer) Ognl.getValue("#user1.age", ognlContext, ognlContext.getRoot());
    System.out.println(name1);// jack
    System.out.println(name2);// rose
    System.out.println(age1);//
    }

  Ognl在解析表达式的时候如果发现表达式开头带有"#",会去context对象中寻找;如果没有"#",则会默认去根对象中去寻找,由于根对象只有一个,所以只需要属性名字。

  • 赋值

    public void demo2() throws Exception {
    // 准备OGNLContext
    // 准备Root
    User rootUser = new User("tom", 18);
    // 准备Context
    Map<String, User> context = new HashMap<>();
    context.put("user1", new User("jack", 20));
    context.put("user2", new User("rose", 24));
    OgnlContext ognlContext = new OgnlContext();
    // 将rootUser作为Root部分
    ognlContext.setRoot(rootUser);
    // 将Context这个Map作为Context部分
    ognlContext.setValues(context); //----------------------------------------------
    // 为root中的user对象的name属性赋值
    Ognl.getValue("name='mike'", ognlContext, ognlContext.getRoot());
    String name = (String) Ognl.getValue("name", ognlContext, ognlContext.getRoot());
    System.out.println(name); //mike // 为context中的user1对象的name属性赋值
    /*Ognl.getValue("#user1.name='jerry'", ognlContext, ognlContext.getRoot());
    String name1 = (String) Ognl.getValue("#user1.name", ognlContext, ognlContext.getRoot());*/
    // 上述表达式可以合并为:
    String name1 = (String) Ognl.getValue("#user1.name='jerry',#user1.name", ognlContext, ognlContext.getRoot());
    System.out.println(name1);
    }
  • 调用方法
    public void demo3() throws Exception {
    // 准备OGNLContext
    // 准备Root
    User rootUser = new User("tom", 18);
    // 准备Context
    Map<String, User> context = new HashMap<>();
    context.put("user1", new User("jack", 20));
    context.put("user2", new User("rose", 24));
    OgnlContext ognlContext = new OgnlContext();
    // 将rootUser作为Root部分
    ognlContext.setRoot(rootUser);
    // 将Context这个Map作为Context部分
    ognlContext.setValues(context); //-------------------------------------------
    // 调用root中user对象的setName方法
    Ognl.getValue("setName('lucy')", ognlContext, ognlContext.getRoot());
    String name = (String) Ognl.getValue("getName()", ognlContext, ognlContext.getRoot());
    System.out.println(name); //lucy // 调用context中user1对象的setName方法
    String name1 = (String) Ognl.getValue("#user1.setName('kobe'),#user1.getName()", ognlContext, ognlContext.getRoot());
    System.out.println(name1);
    }
  • 调用静态方法
    public void demo4() throws Exception {
    OgnlContext context = new OgnlContext();
    // @类的全路径名@方法名称(参数列表)
    Object value = Ognl.getValue("@java.lang.Math@random()", context, context.getRoot());
    // @类的全路径名@属性名称
    Double pi = (Double) Ognl.getValue("@java.lang.Math@PI", context, context.getRoot());
    System.out.println(value);
    System.out.println(pi);
    }
  • 创建对象(list,map)
    public void demo5() throws Exception {
    // 准备OGNLContext
    // 准备Root
    User rootUser = new User("tom", 18);
    // 准备Context
    Map<String, User> context = new HashMap<>();
    context.put("user1", new User("jack", 20));
    context.put("user2", new User("rose", 24));
    OgnlContext ognlContext = new OgnlContext();
    // 将rootUser作为Root部分
    ognlContext.setRoot(rootUser);
    // 将Context这个Map作为Context部分
    ognlContext.setValues(context); // -------------------------------------------
    // 创建list对象
    Integer size = (Integer) Ognl.getValue("{'tom','jerry','jack'}.size()", ognlContext, ognlContext.getRoot());
    System.out.println(size);//
    String name1 = (String) Ognl.getValue("{'tom','jerry','jack'}[0]", ognlContext, ognlContext.getRoot());
    System.out.println(name1);//tom
    String name2 = (String) Ognl.getValue("{'tom','jerry','jack'}.get(1)", ognlContext, ognlContext.getRoot());
    System.out.println(name2);//jerry
    //----------------------------------------------------
    // 创建map对象
    // 这里的#号表示创建的是map对象,不是从context中取值的#
    Integer size2 = (Integer) Ognl.getValue("#{'name':'tom','age':18}.size()", ognlContext, ognlContext.getRoot());
    System.out.println(size2);//
    String name3 = (String) Ognl.getValue("#{'name':'tom','age':18}['name']", ognlContext, ognlContext.getRoot());
    System.out.println(name3);//tom
    Integer age = (Integer) Ognl.getValue("#{'name':'tom','age':18}.get('age')", ognlContext, ognlContext.getRoot());
    System.out.println(age);
    }

三、OGNL与Struts2的结合

3.1 结合原理

  OGNL表达式不管是自己单独拿来用,还是与struts2结合来用,一定要给它提供一个OgnlContext对象(root+context)。我们学习struts2与ognl结合,其实学的就是struts2分别给root部分和context部分准备了什么东西。struts2为OGNL准备的OgnlContext对象是一个ValueStack(值栈),可以简单的理解为OgnlContext在struts2中改名为ValueStack了。ValueStack由两部分组成,一部分叫做Root,放置的是一个栈;一部分是Context,放置的是ActionContext数据中心。

  

3.2 ValueStack

  

  ValueStack是Struts2的一个接口,字面意义为值栈,而OgnlValueStack是它的唯一实现类

  

  在这个类中,有两个属性CompoundRoot root;和Map<String, Object> context;分别与上图对应

  

  CompoundRoot其实就是一个栈:

  

  context部分就是ActionContext数据中心(request、response、ServletContext、requestScope、sessionScope、applicationScope、params、attrs)

  客户端发起一个请求时,Struts2框架会创建一个Action实例,同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个Action的生命周期,Struts2中使用OGNL将请求Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性值。 取栈的属性值时,会从栈顶开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。

  值栈的作用:在我们访问一个action时,会将action加入到栈顶,也就是action会在CompoundRoot的栈顶,而我们提交的各种表单参数(充当了ognl表达式)会在valueStack从顶向下查找对应的属性进行赋值。

3.2.1 使用<debug>查看值栈中两部分内容

  (1)创建一个Action类——ValueStackAction

public class ValueStackAction extends ActionSupport{

    @Override
public String execute() throws Exception {
return SUCCESS;
}
}

  (2)在struts.xml中配置该Action类

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd"> <struts>
<!-- 配置一个包:package -->
<package name="demo" namespace="/" extends="struts-default">
<action name="ValueStackDemo" class="cn.itcast.action.ValueStackAction">
<result name="success">valueStack.jsp</result>
</action>
</package>
</struts>

  (3)创建valueStack.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!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>
<!-- 使用这个标签可以看到值栈内部结构 -->
<s:debug></s:debug>
</body>
</html>

  (4)访问http://localhost:8080/struts2-02/ValueStackDemo.action后,看到如下界面

    

  (5)点击这个[Debug]即可看到值栈的结构

  

3.2.2 向值栈中存取数据

【方式一:获取值栈对象,调用值栈对象里面的set方法】

  • 使用set方法存数据

    public class ValueStackAction extends ActionSupport {
    
        @Override
    public String execute() throws Exception {
    // 获取ActionContext对象
    ActionContext context = ActionContext.getContext();
    // 获取ValueStack对象
    ValueStack stack = context.getValueStack();
    /*
    * 使用set方法存数据
    * set方法的第一个值:保存的数据的名字,在页面中取数据时使用该名字来取数据
    * set方法的第二个值:要在页面中展示的值
    */
    stack.set("name", "张三");
    return SUCCESS;
    }
    }

    

  • 在页面取set方法存的数据

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s"%>
    <!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>
    <!-- 使用这个标签可以看到值栈内部结构 -->
    <s:debug></s:debug> <!--
    1、ognl表达式必须要在struts2标签中使用
    2、在ognl表达式中可以直接调用Java的方法
    3、value的值就是ognl表达式,就是在set方法中保存数据时的第一个参数的值 name:
    -->
    <s:property value="name" />
    </body>
    </html>

【方式二:获取值栈对象,调用值栈对象里面的push方法】

  • 使用push方法存数据

    public class ValueStackAction extends ActionSupport {
    
        @Override
    public String execute() throws Exception {
    // 获取ActionContext对象
    ActionContext context = ActionContext.getContext();
    // 获取ValueStack对象
    ValueStack stack = context.getValueStack(); /*
    * 使用push方法存数据
    * push方法的值:保存的数据.
    */
    stack.push("李四");
    return SUCCESS;
    }
    }

  

  • 在页面取push方法存的数据

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s"%>
    <!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>
    <!-- 使用这个标签可以看到值栈内部结构 -->
    <s:debug></s:debug> <!--
    1、ognl表达式必须要在struts2标签中使用
    2、在ognl表达式中可以直接调用Java的方法
    3、value的值就是ognl表达式.
    4、push存的数据在值栈中是以数组的方式来存放的
    5、数组的名字是固定的。就是top
    6、在Java中数组的第一个值是top[0],但是在ognl表达式中为[0].top
    -->
    name:<s:property value="[0].top"/>
    </body>
    </html>

【方式三:在action成员变量位置定义变量,生成这个变量的get方法】(重点)

  • 存取字符串:

  (1)往值栈存字符串

public class ValueStackAction extends ActionSupport {

    // 存放字符串数据
// 创建一个字符串对象
private String name; // 创建该对象的getter方法
public String getName() {
return name;
} public String execute() {
// 对字符串对象赋值
name = "王五";
return SUCCESS;
}
}

 

  (2)从值栈中读取字符串

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!--要使用struts2标签,必须要引入struts2标签库 -->
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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>
<!--
1、ognl表达式必须要在struts2标签中使用
2、在ognl表达式中可以直接调用Java的方法
3、value的值就是ognl表达式.是Action中字符串对象的名字
-->
name:<s:property value="name"/>
</body>
</html>  
  • 存取对象

  (1)往值栈中存入对象

public class ValueStackAction extends ActionSupport {

    // 保存对象到值栈中
// 创建实体对象
private User user = new User(); public User getUser() {
return user;
} @Override
public String execute() throws Exception {
// 给对象的属性赋值
user.setName("刘备");
user.setAge(20);
return SUCCESS;
}
}

  (2)从值栈中读取对象

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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>
<!-- 使用这个标签可以看到值栈内部结构 -->
<s:debug></s:debug> <!--
1、ognl表达式必须要在struts2标签中使用
2、在ognl表达式中可以直接调用Java的方法
3、value的值就是ognl表达式.
4、表达式的值为:对象实例名称.对象属性名称
-->
name:<s:property value="user.name"/>
age:<s:property value="user.age"/>
</body>
</html>
  • 存取list集合

  (1)往值栈存list集合

public class ValueStackAction extends ActionSupport {

    // 往值栈中存放list集合数据
// 声明一个list对象
private List<User> list = new ArrayList<>();
public List<User> getList() {
return list;
} @Override
public String execute() throws Exception {
// 创建对象,并设置属性值
User user1 = new User("关羽", 18);
User user2 = new User("张飞", 21);
// 将对象放入list中
list.add(user1);
list.add(user2);
return SUCCESS;
}
}

  (2)从值栈中读取list集合(四种方式)

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%--要使用struts2标签,必须要引入struts2标签库 --%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<%--要使用jstl标签,必须要引入jstl标签库 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!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>
<!-- 使用这个标签可以看到值栈内部结构 -->
<s:debug></s:debug> <!--
第一种读取方式
value的值:list[0]表示集合中的第一个对象
表达式:Action中的集合名称[第几个对象].对象的属性名称
缺点:要知道集合中对象的个数,如果个数太多,则代码太长
-->
name:<s:property value="list[0].name" />
age:<s:property value="list[0].age" /> name:<s:property value="list[1].name" />
age:<s:property value="list[1].age" />
<br> <!--
第二种读取方式
该方式使用struts2的<s:iterator>标签来读取
<iterator>标签中value的值:Action中的集合名称
<property>标签中value的值:对象的属性名称
-->
<s:iterator value="list">
name:<s:property value="name" />
age:<s:property value="age" />
</s:iterator>
<br> <!--
第三种读取方式
该方式使用struts2的<s:iterator>标签来读取
<iterator>标签中value的值:Action中的集合名称
<iterator>标签中var的值:相当于遍历时的每一个对象的名称
<property>标签中value的值:#var属性的值.对象属性的值
机制:遍历list集合。得到list集合中的每一个对象,将对象以map的方式保存到context中
key就是var属性的值,值是每一个对象的引用。
在ognl表达式中要访问context中的数据时,要在表达式前面加上#
-->
<s:iterator value="list" var="user">
name:<s:property value="#user.name" />
age:<s:property value="#user.age" />
</s:iterator>
<br> <!--
第四种读取方式
该方式使用jstl的<c:foreach>标签来读取
<c:forEach>标签中value的值:Action中的集合名称
<c:forEach>标签中var的值:相当于遍历时的每一个对象的名称 el表达式能取到值栈数据的原因:struts2底层增强了request的setAttribute方法,
在增强中,首先去域对象中取值,如果在域对象中没有取到值,就去值栈中取值,将从值栈
中取到的值保存到域对象中返回。 缺点:需要先去域对象中取值,没有才去值栈中取值,取到后又要保存到域对象中返回,所有效率不高
一般不使用此方法
-->
<c:forEach items="${list }" var="user">
name:${user.name }
age:${user.age }
</c:forEach> </body>
</html>

四、struts2标签库

  Struts2中OGNL表达式必须配合Struts2标签使用,不然没什么效果

  对于一个MVC框架而言,重点是实现两部分:业务逻辑控制器部分和视图页面部分。Struts2作为一个优秀的MVC框架,也把重点放在了这两部分上。控制器主要由Action来提供支持,而视图则是由大量的标签来提供支持。

4.1 Struts2标签库概述

  在JavaWeb中,Struts2标签库是一个比较完善,而且功能强大的标签库,它将所有标签都统一到一个标签库中,从而简化了标签的使用,它还提供主题和模板的支持,极大地简化了视图页面代码的编写,同时它还提供对ajax的支持,大大的丰富了视图的表现效果。与JSTL(JSP Standard Library,JSP 标准标签库)相比,Struts2标签库更加易用和强大。

4.2 Struts2标签库的分类

  早期的JSP页面需要嵌入大量的Java脚本来进行输出,这样使得一个简单的JSP页面加入了大量的代码,不利于代码的可维护性和可读性。随着技术的发展,逐渐的采用标签库来进行JSP页面的开发,这使得JDP页面能够在很短的时间内开发完成,而且代码通俗易懂,大大的方便了开发者,Struts2的标签库就是这样发展起来的。

  Struts2框架对整个标签库进行了分类,按其功能大致可分为两类,如图所示。

  

  

  由图中可以看出, Struts2标签库主要分为两类:普通标签和UI标签。普通标签主要是在页面生成时,控制执行的流程。UI标签则是以丰富而可复用的HTML文件来显示数据。

  普通标签又分为控制标签( Control Tags)和数据标签( Data Tags)。控制标签用来完成条件逻辑、循环逻辑的控制,也可用来做集合的操作。数据标签用来输出后台的数据和完成其他数据访问功能。

  UI标签又分为表单标签( Form Tags)、非表单标签( non-form Tags)和Ajax标签。表单标签主要用来生成HTML页面中的表单元素,非表单标签主要用来生成HTML的<div>标签及输出 Action中封装的信息等。Ajax标签主要用来提供Ajax技术支持。

4.3 Struts2标签的使用

  Struts2标签库被定义在 struts-tags tld文件中,我们可以在 struts-core-2.3.24jar中的META-INF目录下找到它。要使用 struts2的标签库,一般只需在JsP文件使用 taglib指令导入 Struts2标签库,具体代码如下:

<%@taglib prefix="s" uri="/struts-tags" %>

  在上述代码中, taglib指令的uri属性用于指定引入标签库描述符文件的URI, prefix属性用于指定引入标签库描述符文件的前缀。需要注意的是,在JSP文件中,所有的 Struts2标签库的使用“s”前缀。  

4.4 控制标签

<!-- 遍历标签 iterator -->
<!-- ------------------------------------- -->
<s:iterator value="#list" >
<s:property /><br>
</s:iterator>
<!-- ------------------------------------- --><hr>
<s:iterator value="#list" var="name" >
<s:property value="#name" /><br>
</s:iterator>
<!-- ------------------------------------- --><hr>
<s:iterator begin="1" end="100" step="1" >
<s:property />|
</s:iterator>
<!-- ------------------if else elseif------------------- --><hr> <s:if test="#list.size()==4">
list长度为4!
</s:if>
<s:elseif test="#list.size()==3">
list长度为3!
</s:elseif>
<s:else>
list不3不4!
</s:else>

4.5 数据标签

<!-- ------------------property 配合ognl表达式页面取值 ------------------- -->
<s:property value="#list.size()" />
<s:property value="#session.user.name" />

4.6 表单标签

  <!-- struts2表单标签 -->
<!-- 好处1: 内置了一套样式. -->
<!-- 好处2: 自动回显,根据栈中的属性 -->
<!-- theme:指定表单的主题
xhtml:默认
simple:没有主题
-->
<s:form action="Demo3Action" namespace="/" theme="xhtml" >
<s:textfield name="name" label="用户名" ></s:textfield>
<s:password name="password" label="密码" ></s:password>
<s:radio list="{'男','女'}" name="gender" label="性别" ></s:radio>
<s:radio list="#{1:'男',0:'女'}" name="gender" label="性别" ></s:radio>
<s:checkboxlist list="#{2:'抽烟',1:'喝酒',0:'烫头'}" name="habits" label="爱好" ></s:checkboxlist>
<s:select list="#{2:'大专',1:'本科',0:'硕士'}" headerKey="" headerValue="---请选择---" name="edu" label="学历" >
</s:select>
<s:file name="photo" label="近照" ></s:file>
<s:textarea name="desc" label="个人简介" ></s:textarea>
<s:submit value="提交" ></s:submit>
</s:form>

4.7 非表单标签

<s:actionerror/>

struts2学习笔记(五)—— OGNL的更多相关文章

  1. Struts2学习笔记(OGNL表达式)

    Struts 2支持以下几种表达式语言: OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言: JSTL(JSP Standard T ...

  2. Struts2学习笔记四 OGNL

    OGNL,全称为Object-Graph Navigation Language(对象图表达语言),它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,调用java对象的方法,同时能够自动 ...

  3. Struts2学习笔记五 拦截器

    拦截器,在AOP中用于在某个方法或字段被访问之前,进行拦截,然后在之前或之后加入某些操作.拦截是AOP的一种实现策略. Struts2中,拦截器是动态拦截Action调用的对象.它提供了一种机制可以使 ...

  4. Struts2学习笔记(五)——Action访问Servlet API

    在Strut2中访问Servlet API有三种方式: 1.通过ActionContext访问Servlet API,推荐使用这种,但是这种方案它获取的不是真正的事Servlet API. 步骤: 1 ...

  5. Struts2 学习笔记(概述)

    Struts2 学习笔记 2015年3月7日11:02:55 MVC思想 Strust2的MVC对应关系如下: 在MVC三个模块当中,struts2对应关系如下: Model: 负责封装应用的状态,并 ...

  6. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  7. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  8. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

  9. Struts2学习笔记⑧

    今天是Struts2学习笔记的最后一篇文章了.用什么做结尾呢,这两天其实还学了很多东西,没有记录下,今天就查漏补缺一下. 文件上传与下载.FreeMarker以及昨天没做完的例子 文件上传与下载 文件 ...

  10. Struts2学习笔记①

    Struts2 学习笔记① 所有的程序学习都从Hello World开始,今天先跟着书做一个HW的示例. Struts2是一套MVC框架,使用起来非常方便,接触到现在觉得最麻烦的地方是配置文件.我的一 ...

随机推荐

  1. PHP内核介绍及扩展开发指南—Extensions 的编写

    Extensions 的编写 理解了这些运行机制以后,本章着手介绍Extensions 的编写,但凡写程序的人都知道hello world,那好,就从hello world开始. 1.1Hello W ...

  2. MySql 之 FIND_IN_SET 和IN

    CREATE TABLE `test` (   `id` int(8) NOT NULL auto_increment,   `name` varchar(255) NOT NULL,   `list ...

  3. os.chdir("/deepmatching") OSError: [Errno 2] No such file or directory: '/deepmatching'

    #os.chdir("/deepmatching")os.chdir(os.path.dirname(os.path.abspath("deepmatching1&quo ...

  4. Java 基于quartz实现定时 之一(注解方式配置)

    需要在项目里,导入quartz.jar package cn.zr.pringmvctest.trigger; import org.springframework.context.annotatio ...

  5. 在CentOS7.5里安装FTP服务器

    安装了一台CentOS7.5,字符界面,为方便上传文件到这台机器上,拟采用FTP服务上传和下载文件,在CentOS上搭建vsftpd服务环境. 记录我的安装过程,供有需要的人参考. 一.系统环境 1. ...

  6. ensemble 的2篇入门 文章

    python 篇: http://machinelearningmastery.com/ensemble-machine-learning-algorithms-python-scikit-learn ...

  7. pip指定安装包版本

    pip是目前最好用的python包关系工具,没有之一. 1.版本范围符号:==.>=.<=.>.<. 2.单个安装示例: 1 2 3 pip install cchardet  ...

  8. HTTP请求:POST和GET的差异

    1,一般情况下应用目的不同:GET是从服务器上获取数据,POST是向服务器传送数据. 2,将数据提交到服务器的方式不同:GET是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各 ...

  9. .html与.text的异同

    .html与.text的方法操作是一样,只是在具体针对处理对象不同 .html处理的是元素内容,.text处理的是文本内容 .html只能使用在HTML文档中,.text 在XML 和 HTML 文档 ...

  10. Python基础-3

    目录 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 知识插入:嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 一.函数基本语法 函数是什么? 函数一词 ...