前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SSH框架之旅-struts2(3)

SSH框架之旅-struts2(3)

作者头像
Wizey
发布2018-08-30 09:39:16
4540
发布2018-08-30 09:39:16
举报
文章被收录于专栏:编程心路

struts.jpg

1.OGNL


1.1 OGNL 概述

OGNL,全称是 Object-Graph Navigation Language(对象导航语言),是一种功能强大的开源表达式语言,通过简单的表达式语法就可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。OGNL 是被集成到 struts2中的,并不是 struts2 项目的一部分,struts2 用 OGNL 来取代原始 java web 项目中的 EL 表达式。

1.2 OGNL 结构

  • 表达式(Expression)

表达式是整个 OGNL 的核心,OGNL 解析表达式才知道该做什么,如:从对象中取值的操作。

  • 根对象(Root Object)

根对象可以理解为 OGNL 的操作对象,而表达式只是说明了对这个对象所做的操作。OGNL 称为对象导航语言,也即是把对象放在一张图中,通过任意一个对象作为根,可以找到与这个对象关联的其他对象。

  • 上下文环境(Context)

OGNL 在取值操作的过程中还需要一个上下文的环境,有了根对象和表达式,OGNL就知道改对谁做什么操作,但还需知道这个操作执行的位置,也就是上下文环境。上下文环境 Context 是一个 Map 类型的对象,在表达式中访问 Context 中的对象需要使用 # 号加上对象的名称。

1.3 OGNL 的简单使用

OGNL 在 struts2 中,要结合 struts2 的标签一起使用,首先要 导入 OGNL 的 jar 包,在jsp页面中我们就可以直接使用 OGNL 表达式完成之前需要使用 EL 表达式结合 java 代码才能做到的事情。

牛刀小试:

记得在 web.xml 文件中配置 struts2 的拦截器。

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
   <!--  引入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>
 <!--  在struts2 标签中使用 ognl 表达式 -->
  <s:property value="'ognl'.length()"/>
 <!-- 页面的输出结果是 ognl 这个字符串的长度 4 -->
</body>
</html>

2.Struts2 中的值栈


2.1 值栈是什么

在原始的 java web 项目,在 servlet 中操作完后,把数据放到域对象中,然后在 jsp 页面中使用 EL 表达式来获取数据值,域对象在一定的范围内可以进行存值和取值。在 struts2 中也提供了一种存储机制,类似于域对象,就是值栈,同样可以存值和取值。这样在 Action 类中把数据放到值栈中,就可以在页面中获取值栈中的数据。

值栈英文是 ValueStack,它其实是 struts2 的一个接口,而 OgnlValueStack 是 ValueStack 的实现类,浏览器访问 一个 action 请求时,struts2 架构会创建一个 action 的实例同时也会创建一个 OgnlValueStack 的值栈实例,OgnlValueStack 贯穿整个 Action 实例的生命周期,struts2 使用 OGNL 来把请求 action 中的参数封装成对象存储在值栈中,并通过 OGNL 表达式来读取值栈中的对象的属性值。

2.2 值栈对象

之前说到的 ActionContext 和 ServletActionContext 中都有获取 ValueStack的方法,可以去看这两个类的源码,所以通过这两个类就可以获取到 ValueStack对象的引用。

servlet 和 action的区别:

    1. Servlet 默认是在第一次访问是创建的,只创建一次,是单实例的对象。
    1. Action 是在每次访问时创建的,每访问一次 action,就会创建一个 action 对象,对应创建一个值栈对象。

示例代码如下:

证明每个 action 对象中的 valueStack 对象只有一个。

代码语言:javascript
复制
package cc.wenshixin.action;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class ActionDemo1 extends ActionSupport {
    @Override
    public String execute() throws Exception {
        //1.获取ActionContext类的对象
        ActionContext context = ActionContext.getContext();
        //2.调用方法获得值栈对象的引用
        ValueStack stack1 = context.getValueStack();
        ValueStack stack2 = context.getValueStack();
        //3.比较两个值栈引用是否为同一个值栈对象的引用
        System.out.println(stack1==stack2); //结果为true
        return NONE;
    }
}

2.3 值栈的内部结构

从名字上就可以看出值栈具有数据结构中栈的结构特性,先进后出(后进先出)。可以查看 OgnlValueStack 类的源码或者 Debug 的方式查看值栈的结构,会发现值栈具有 root 和 context 两个属性,这就是值栈主要的两部分。root 部分基于List集合,root属性继承 ArrayList,实现压栈和出栈的功能,用来存储 action 和实例以及请求的参数,我们一般操作的都是 root 中的数据。context 基于Map集合,也即是 OnglContext(上下文),存储了一些对象的引用,如 parameters、request、response、session、application等。

context 部分的存储结构表

key(固定)

value

request

request对象的引用

session

httpSesion对象的引用

application

servletContext对象的引用

parameter

传递相关的参数

att

三个域对象的值

在 struts2 中提供了一个调试值栈的标签,s:debug,使用这个标签就可以查看到值栈结构以及存储的值。

相关代码如下:

jsp页面

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
   <!--  引入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>
<!-- 使用debug标签查看值栈中的值 -->
  <s:debug></s:debug>
</body>
</html>

Action 类

代码语言:javascript
复制
package cc.wenshixin.action;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class ActionDemo2 extends ActionSupport {
    @Override
    public String execute() throws Exception {
        return "success";
    }
}

struts 配置

代码语言:javascript
复制
    <package name="demo1" extends="struts-default" namespace="/">
        <action name="action2" class="cc.wenshixin.action.ActionDemo2">
          <result name="success">/debug.jsp</result>
        </action>
    </package>

Debug的结果1

3.值栈的相关操作


3.1 值栈存放数据

向值栈中放数据的方式很多,下面介绍几种常见的方式。

3.1.1 使用值栈对象,调用对象中的 set() 方法

将上面 Action 类中的部分代码改为下面的,重新刷新页面,查看debug标签中的结构,发现值栈中多出一个 map对象,使用 set() 方法,会将对象存储到一个map集合中。

代码语言:javascript
复制
public String execute() throws Exception {
        //1.获取ActionContext类的对象
        ActionContext context = ActionContext.getContext();
        //2.调用方法获得值栈对象的引用
        ValueStack stack = context.getValueStack();
        
        //调用set方法   
        stack.set("name", "小明");
        
        return "success";
    }

set方法

3.1.2 使用值栈对象,调用对象中的 push() 方法

将上面 Action 类中的部分代码改为下面的,重新刷新页面,查看debug标签中的结构,发现值栈中多出一个 String 对象,使用 push() 方法,会将对象存储到一个 String 字符串中。

代码语言:javascript
复制
public String execute() throws Exception {
        //1.获取ActionContext类的对象
        ActionContext context = ActionContext.getContext();
        //2.调用方法获得值栈对象的引用
        ValueStack stack = context.getValueStack();
        
        //调用push方法
        stack.push("小明");
        
        return "success";
    }

push方法

3.1.3 在 Action 中定义变量,生成变量的 get 方法

将上面 Action 类中的代码改为下面的,重新刷新页面,查看debug标签中的结构,发现值栈的属性中多了一个定义的变量的名称,并且该属性的值就是 Action 中赋予该变量的值。

代码语言:javascript
复制
package cc.wenshixin.action;

import com.opensymphony.xwork2.ActionSupport;

public class ActionDemo5 extends ActionSupport {
    
    private String name; //定义变量
    
    //生成变量的get方法
    public String getName() {
        return name;
    }

    @Override
    public String execute() throws Exception {
        name = "小明"; //给变量赋值
        
        return "success";
    }
}

get方法

3.1.4 向值栈中放对象

实现步骤:

    1. 创建实体类对象
    1. 定义实体类对象的变量
    1. 生成变量的get方法

将上面 Action 类中的代码改为下面的,实体类的对象自己创建,重新刷新页面,查看debug标签中的结构,发现值栈的属性中多了一个定义的变量的名称,并且该属性的值就是 Action 中赋予该变量的值。

代码语言:javascript
复制
package cc.wenshixin.action;

import com.opensymphony.xwork2.ActionSupport;

import cc.wenshixin.entity.Student;

public class ActionDemo6 extends ActionSupport {
    //1.定义对象变量,这里也可以不创建对象内容,在下面new
    private Student student = new Student();
    //2.生成对象的get方法
    public Student getStudent() {
        return student;
    }

    @Override
    public String execute() throws Exception {
        //给对象赋值
        student.setName("小明");
        student.setSex("女");
        
        return "success";
    }
}

存放对象

3.1.5 向值栈中放 list 集合

实现步骤:

    1. 创建实体类对象
    1. 定义实体类对象的 list 集合变量
    1. 生成变量的get方法

将上面 Action 类中的代码改为下面的,实体类的对象自己创建,重新刷新页面,查看debug标签中的结构,发现值栈的属性中多了一个定义的list集合的名称,并且该属性的值就是 Action 中添加到list集合的对象。

代码语言:javascript
复制
package cc.wenshixin.action;

import java.util.ArrayList;
import java.util.List;

import com.opensymphony.xwork2.ActionSupport;

import cc.wenshixin.entity.Student;

public class ActionDemo7 extends ActionSupport {

    private List<Student> list = new ArrayList<Student>();

    public List<Student> getList() {
        return list;
    }

    @Override
    public String execute() throws Exception {
        Student student1 = new Student();
        student1.setName("小明");
        student1.setSex("男");
        
        Student student2 = new Student();
        student2.setName("小红");
        student2.setSex("女");
        
        list.add(student1);
        list.add(student2);
        
        return "success";
    }
}

list集合

3.2 获取值栈数据

上面实在 Action 中向值栈中放数据,下面在 jsp 页面中使用 Struts2标签 + OGNL 表达式把这些数据显示出来。

3.2.1 获取字符串的值

使用上面 3.1.3 中的 Action 类的代码,显示 Action 中字符串里面的值。

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
   <!--  引入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>
  <!-- 获取字符串的值 -->
  <s:property value="name"/>
</body>
</html>
3.2.2 获取对象的值

使用上面 3.1.4 中的 Action 类的代码,显示 Action 中对象的值,在上面的jsp代码中追加下面的代码访问。

代码语言:javascript
复制
    <!-- 获取对象的值 -->
  <s:property value="student.name"/>
  <s:property value="student.sex"/>
3.2.3 获取 list 集合的值

获取 list 集合中的值,有三种方式。

使用上面 3.1.5 中的 Action 类的代码,显示 Action 中 list 集合的值,在上面的jsp代码中追加下面的代码访问。

  • 第一种方式需要知道 list 集合中的元素的个数。
代码语言:javascript
复制
 <!-- 第一种方式获取list集合中的值 -->
  <s:property value="list[0].name"/>
  <s:property value="list[0].sex"/>
  <s:property value="list[1].name"/>
  <s:property value="list[1].sex"/>
  • 第二种方式通过 <s:iterator> 标签遍历 <s:property>标签中的值
代码语言:javascript
复制
<!-- 第二种方式获取list集合中的值 -->
  <s:iterator value="list">
    <s:property value="name"/>
    <s:property value="sex"/>
  </s:iterator>
  • 第三种方式使用 # 取出list种的元素

机制:把每次遍历出来的元素对象放到 context 里面,用 OGNL 表达式获取 context 中的数据需要特殊符号 #

代码语言:javascript
复制
<!-- 第三种方式获取list集合中的值 -->
  <s:iterator value="list" var="student">
    <s:property value="#student.name"/>
    <s:property value="#student.sex"/>
  </s:iterator>
3.2.4 其他获取方式

使用上面 3.1.1 中的 Action 类的代码,获取用 set() 方法存到值栈中的值,使用 set() 方法中设置的值的名称。

代码语言:javascript
复制
  <!-- 其他获取方式 -->
  <s:property value="name"/>

使用上面 3.1.2 中的 Action 类的代码,获取用 push() 方法存到值栈中的值,因为使用 push() 方法设置值没有名称,只有设置的值,使用值栈的数据名 top,根据数据名来获取值,不过写法有点怪,数组名在后面。

代码语言:javascript
复制
  <!-- 其他获取方式 -->
  <s:property value="[0].top"/>

1.4 OGNL 中 # 和 % 的使用总结

1.4.1 # 的使用

在前面获取 list 集合中的第三种方式,使用了 # 来获取 context 种的数据。

1.4.2 % 的使用

struts2 中还定义了表单输入标签,如果在 struts2 的表单标签中使用 OGNL 表达式是不能识别的,需要 %{OGNL表达式} 才能识别。

使用上面 3.1.3 中的 Action 类的代码,将字符串中的值放在一个表单输入项中。

代码语言:javascript
复制
    <!-- struts2的表单输入项 -->
  <s:textfield name="name" value="%{name}"></s:textfield>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.10.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.OGNL
    • 1.1 OGNL 概述
      • 1.2 OGNL 结构
        • 1.3 OGNL 的简单使用
        • 2.Struts2 中的值栈
          • 2.1 值栈是什么
            • 2.2 值栈对象
              • 2.3 值栈的内部结构
              • 3.值栈的相关操作
                • 3.1 值栈存放数据
                  • 3.1.1 使用值栈对象,调用对象中的 set() 方法
                  • 3.1.2 使用值栈对象,调用对象中的 push() 方法
                  • 3.1.3 在 Action 中定义变量,生成变量的 get 方法
                  • 3.1.4 向值栈中放对象
                  • 3.1.5 向值栈中放 list 集合
                • 3.2 获取值栈数据
                  • 3.2.1 获取字符串的值
                  • 3.2.2 获取对象的值
                  • 3.2.3 获取 list 集合的值
                  • 3.2.4 其他获取方式
              • 1.4 OGNL 中 # 和 % 的使用总结
                • 1.4.1 # 的使用
                  • 1.4.2 % 的使用
                  相关产品与服务
                  对象存储
                  对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档