struts2学习笔记(五)—— OGNL

一、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);// 20
        }

   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);//3
            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);//2
            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/>
原文地址:https://www.cnblogs.com/yft-javaNotes/p/10268723.html