OGNL

一:OGNL简介

OGNL的全称是Object  Graph  Navigation  Language即对象导航语音。它是一个开源项目,工作在视图层,用来取代页面中的java脚本。简化数据库的访问操作。

OGNL是一种强大的技术,被集成在Struts 2框架中用来帮助实现数据的传输和类型转换。

表达式语音:在视图层将数据从页面传入框架和从框架获取输出数据生成页面的过程,OGNL提供了一个简单的语法,将表单与Struts 2标签与java各种类型的数据绑定起来,列如:

<input  type=”text”  name=”user.name”/>的输入对应Action类中User对象的name属性。

类型转换器:每次数据流入和流出框架,页面中的字符串类型的数据和java数据类型之间都会发生转换。

一、OGNL全称是Object Graph Navigation Language,即对象导航图语言

OGNL在框架中主要做两件事情:表达式语言和类型转换器

二:OGNL在框架中的作用以及数据的流入流出:


二、ValueStack值栈

定义:是内存中的一块空间,栈和堆之外的空间,它具有栈的特征,可以存放多个对象,如果存放多个对象,他们是按照先后顺序压入堆栈的。框架在处理每个请求时,都会创建该请求对应的运行环境,这时会创建值栈和请求对应的Action实例,并将Action实例压入值栈中


三、实现思路

可通过单列(Root)、双列(Context)集合获取ValueStack

单列集合:

创建Action类继承自ActionSupport,首先通过ServletActionContext获取到request对象,其次创建UserInfo对象,通过ValueStack对象的getRoot方法拿到UserInfo对象info

public class ValueStackAction extends ActionSupport {

@Override

public String execute() throws Exception {

HttpServletRequest request = ServletActionContext.getRequest();

ValueStack vs = (ValueStack) request.getAttribute("struts.valueStack");

UserInfo info = new UserInfo();

info.setUsername("呵呵");

info.setPassword("12345");

vs.getRoot().add(info);

return SUCCESS;

}

index.jsp页面进行取数据:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<base href="<%=basePath%>">

<title>My JSP 'index.jsp' starting page</title>

</head>

<body>

valueStack

<s:property value="username"/>

<s:debug></s:debug>

</body>

</html>


双列集合:

index.jsp页面:需注意的是双列集合通过#获取数据

使用ognl表达式:

1)“#”符号有三种用途

a、访问非根对象(struts中值栈为根对象),eg:OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:

名称   作用域

eg:

1-1)parameters :包含当前HTTP请求参数的Map

#parameters.id[0]=>作用相当于request.getParameter("id")

1-2)request:包含当前HttpServletRequest的属性(attribute)的Map

#request.userName=>作相当于于request.getAttribute("userName");

1-3)session:包含当前HttpSession属性(attribute)的Map

#session.userName=>session.getAttribute("userName");

1-4)application:包含当前应用的ServletContext的属性(attribute)的Map

#application.userName=>application.getAttribute("userName");

三:数据的流出

当Action 完成业务处理后,最终会返回一个结果,并生成页面。最关键的地方在于在处理请求的过程中,所有业务数据对象都保留在值栈中值栈充当了一个容器,,通过它在框架的各个地方都可以随时访问这些业务对象,在生成页面的过程中,页面标签都可以访问值栈,并通过OGNL表达式获取对象的值。

四:Value Stack值栈

1.什么是值栈:

值栈就是框架创建的一个存储区域,用来保存Model对象,它具有栈的特性,可以存放多个对象,,但是要按照先后顺序压入栈的。框架处理每个请求时,都会创建对应的运行环境,这是会创建值栈和请求对应的Action 实例,并将每个Action实例压入值栈中。值栈是一个虚拟对象,它可以暴露它所包含的所有对象的的属性,就好像这些属性是它自己的一样。

2.OGNL优先使用:

OGNL访问值栈时从它的上往下访问不管值栈是否有关重复的靠近值栈最上面的属性都

会被优先使用。

五:类型转换器

  1. 为什么要使用类型转换器:

在基于HTTP协议的web应用中,客户端请求的所有内容,均以文本编码的形式传入到服务器端,但服务器端的编程语言,有着丰富的数据类型,如int,boolean,Date及自定义类型等,因此当这些参数进入应用程序时,它们必须转换为合适的服务器端编程语言的数据库类型。

  1. 内置类型转换器:

(1.)Stirng:将int,long,double,Boolean,String类型的数组,或java.util.Date类型转换为字符串。

(2.)boolean/Boolean:在字符串和布尔类型之间进行类型转换。

(3.)char/Character:在字符串和字符串之间进行转换。

(4.)int /Integer,float/Fload,long/Long,double/Doubl:在字符串和数值之间进行转换。

(5.)Date:在字符串和日期类型之间进行转换,具体输入/输出格式与当前的Local相关。

(6.)数组和集合:在字符串数组和数组对象,集合对象之间转换。

1.原始类型和包装类

示例如下:

public class ShowOrginalAndJavaBeanAction extends ActionSupport {

private User user;

private String msg;

public User getUser() {

return user;

}

public void setUser(User user) {

this.user = user;

}

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

public String execute(){

User user=new User();

user.setName("accp");

user.setAge(22);

Adderss address=new Adderss();

address.setGj("中国");

address.setCity("北京");

address.setStreet("城府路");

//user.setAdderss(adderss);

setMsg("展示原始类型和JavaBean");

return SUCCESS;

}

}

页面展示代码如下:

<body>

<h2>直接量:</h2>

<s:property value="msg" /><br>

姓名:<s:property value="user.name" /><br/>

年龄:<s:property value="user.age" /><br/>

国家:<s:property value="user.address.gj" /><br/>

城市:<s:property value="user.address.city" /><br/>

街道:<s:property value="user.address.street" /><br/>

</body>

  1. 多值类型请求参数的处理

(1.)数组的方式:

public class ArrayAction extends ActionSupport{

private String[] hobbies;

private Double[] numbers=new Double[3];

public String[] getHobbies() {

return hobbies;

}

public void setHobbies(String[] hobbies) {

this.hobbies = hobbies;

}

public Double[] getNumbers() {

return numbers;

}

public void setNumbers(Double[] numbers) {

this.numbers = numbers;

}

public String execute(){

for (int i = 0; i < hobbies.length; i++) {

System.out.println("数组第:"+i+"元素,为"+hobbies[i]);

}

System.out.println();

for (int i = 0; i < numbers.length; i++) {

System.out.println("第"+i+"个元素,为"+numbers[i]);

}

return SUCCESS;

}

}

页面显示代码如下:

<body>

<h2>数组:</h2>

<s:form action="arrayAction" method="post" />

<s:textfield name="hobbies" label="爱好:" />

<s:textfield name="hobbies" label="爱好:" />

<s:textfield name="hobbies" label="爱好:" />

---------------------------

<s:textfield name="numbers[0]" label="数字:" />

<s:textfield name="numbers[1]" label="数字:" />

<s:textfield name="numbers[2]" label="数字:" />

<s:submit value="提交"></s:submit>

</body>

(2.)集合的方式:

public class ListAction extends ActionSupport{

private List hobbies;

private List<Integer> numbers;

private List<User> users;

public List getHobbies() {

return hobbies;

}

public void setHobbies(List hobbies) {

this.hobbies = hobbies;

}

public List<Integer> getNumbers() {

return numbers;

}

public void setNumbers(List<Integer> numbers) {

this.numbers = numbers;

}

public List<User> getUsers() {

return users;

}

public void setUsers(List<User> users) {

this.users = users;

}

public String execute1(){

for (int i = 0; i < hobbies.size(); i++) {

System.out.println("数组第:"+i+"元素,为"+hobbies.get(i));

}

System.out.println();

for (int i = 0; i < numbers.size(); i++) {

System.out.println("第"+i+"个元素,为"+numbers.get(i));

}

System.out.println();

for (int i = 0; i < numbers.size(); i++) {

System.out.println("第"+i+"个元素,为"+users.get(i).getName());

}

return SUCCESS;

}

}

页面显示代码如下:

<body>

<h2>数组:</h2>

<s:form action="listyAction" method="POST" />

<s:textfield name="hobbies" label="爱好:" />

<s:textfield name="hobbies" label="爱好:" />

<s:textfield name="hobbies" label="爱好:" />

---------------------------

<s:textfield name="numbers[0]" label="数字:" />

<s:textfield name="numbers[1]" label="数字:" />

<s:textfield name="numbers[2]" label="数字:" />

---------------------------

<s:textfield name="user.name" label="姓名:" />

<s:textfield name="user.name" label="姓名:" />

<s:textfield name="user.name" label="姓名:" />

<s:submit value="提交"></s:submit>

</body>

六:自定义转换器:

  1. 创建自定义转换器
  2. 配置自定义转换器
  3. 创建和配置日期转换器

示例如下:在此之前先创建一个这样的类:

public class DateAction extends ActionSupport{

private String currentDate;

public String getCurrentDate() {

return currentDate;

}

public void setCurrentDate(String currentDate) {

this.currentDate = currentDate;

}

public String dates(){

return SUCCESS;

}

}

然后在创建:

public class DateConverter extends StrutsTypeConverter {

private final DateFormat[] dfs={

new SimpleDateFormat("yyyy年MM月dd日"),

new SimpleDateFormat("yyyy-MM-dd"),

new SimpleDateFormat("MM/dd/yy"),

new SimpleDateFormat("yyyy.MM.dd"),

new SimpleDateFormat("yyyyMMdd"),

new SimpleDateFormat("yyyy/MM/dd")

};

/*

* 将指定格式的字符串转换为日期类型

* (non-Javadoc)

* @see org.apache.struts2.util.StrutsTypeConverter#convertFromString(java.util.Map, java.lang.String[], java.lang.Class)

*/

@Override

public Object convertFromString(Map context, String[] values, Class toType) {

// TODO Auto-generated method stub

String dateStr=values[0]; //获取日期的字符串

for (int i = 0; i < dfs.length; i++) { //遍历日期支持的格式进行转换

try {

return dfs[i].parse(dateStr);

} catch (Exception e) {

// TODO: handle exception

continue;

}

}

//如果遍历完毕后仍没有转换成功,表明出现转换异常

throw new TypeConversionException();

}

/*

* 将日期格式转换为指定字符串

* (non-Javadoc)

* @see org.apache.struts2.util.StrutsTypeConverter#convertToString(java.util.Map, java.lang.Object)

*/

@Override

public String convertToString(Map context, Object object) {

// TODO Auto-generated method stub

Date date=(Date)object;

//输出的格式是yyyy--MM-dd

return new SimpleDateFormat("yyyy-MM-dd").format(date);

}

}

页面显示代码如下

<body>

<s:form action="datesAction" />

<h2>自定义类型转换器</h2><br/>

请输入日期:<s:textfield name="currentDate" />

<s:submit value="提交" />

</body

七:处理类型转换器错误

  1. 前提条件:如果在服务器端判断类型转换错误。则需要满足一下条件。

(1.)启动StrutsConversionErrorLnterceptor拦截器。该拦截器已经包含在defaultStack拦截器栈中,参看Struts-default.xml文件,如果拓展此包启动时自动加载。

(2.)实现ValidationAware接口,ActionSupport实现了该接口。

(3.)配置input结果映射。出现类型转换错误将在所配置页面显示错误的信息,如果没有配置将出现错误的提示,提示没有指定的input页面。

(4.)在页面使用Struts 2表单标签或使用<s:fielderror>标签输出转换错误。Struts 2表单标签内嵌了输出错误的信息功能。

2.修改所有类型的转换错误信息。

可修改默认文本信息:

<constant  name=”struts.custom.il8n.resources” value=”message”>

然后在src目录下创建资源文件message.properties并添加文本如下:

Xwork.default.invalid.fieldvalue=字段”{0}”的值无效

3.制定特定字段类型转换错误信息。

Invalid.fieldvalue.timeDate=日期转换错误

八:OGNL表达式

  1. 表达式语音

(1.)访问Bean属性:代码如下

<s:form   action=”Register”>

<s:textfield  name=”user.address.streetName” label=”请输入街道名称.”  />

<s:submit  />

</s:form>

(2.)访问集合对象

public class ListAction extends ActionSupport{

private List hobbies;

private List<Integer> numbers;

private List<User> users;

public List getHobbies() {

return hobbies;

}

public void setHobbies(List hobbies) {

this.hobbies = hobbies;

}

public List<Integer> getNumbers() {

return numbers;

}

public void setNumbers(List<Integer> numbers) {

this.numbers = numbers;

}

public List<User> getUsers() {

return users;

}

public void setUsers(List<User> users) {

this.users = users;

}

public String execute1(){

for (int i = 0; i < hobbies.size(); i++) {

System.out.println("数组第:"+i+"元素,为"+hobbies.get(i));

}

System.out.println();

for (int i = 0; i < numbers.size(); i++) {

System.out.println("第"+i+"个元素,为"+numbers.get(i));

}

System.out.println();

for (int i = 0; i < numbers.size(); i++) {

System.out.println("第"+i+"个元素,为"+users.get(i).getName());

}

return SUCCESS;

}

}

页面代码如下:

<body>

!!!!!!迭代数组输出:

<h1>!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</h1>

<br />

<s:iterator value="likes">

<s:property />

<br />

</s:iterator>

<h1>!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</h1>

!!!!!!迭代集合(元素类型为Double):

<br />

<s:iterator value="numbers">

<s:property />

<br />

</s:iterator>

<h1>!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</h1>

!!!!!!迭代集合(元素类型为User):

<br />

<s:iterator value="users">

!!!!!! 用户名:<s:property value="name" />

<br />

!!!!!!年龄:<s:property value="age" />

<br />

!!!!!!国家:<s:property

value="address.country" />

<br />

!!!!!!城市:<s:property value="address.city" />

<br />

<h1>!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</h1>

</s:iterator>

<s:debug></s:debug>

</body>

(3.)对于集合对象的访问,在开发过程中往往还有一些几种情况

访问列表或者数组的某一个元素,可以使用属性[index]的方式。如userList[1].name

访问Map的某一个元素。可以使用属性名[key]如userMap[‘userA’].name

通过size或者length来访问集合的长度。

九:访问ActionContext中的数据

OGNL简介的更多相关文章

  1. 3:2 OGNL 简介

    OGNL : (对象图导航语言) 从一个对象到另一个对象 OGNL来源于Xwork: OGNL的作用: OGNL在数据进出值栈的时候进行类型转换

  2. OGNL和ValueStack

    OGNL简介 OGNL的全称是Object Graph Navigation Language,即对象导航图语言.它是一个开源项目,工作在视图层,其通过简单一致的表达式语言来读取合适者Java对象的属 ...

  3. 十七、OGNL表达式

    十七.OGNL OGNL简介: OGNL是对象导航图语言.它是一个独立的项目.早期的webwork框架用到了OGNL作为自己的表达式语言, 所以struts2也是用OGNL作为表达式语言,当然也可以使 ...

  4. Java实战之01Struts2-04拦截器、上传下载、OGNL表达式

    十二.Struts2中的拦截器 1.拦截器的重要性 Struts2中的很多功能都是由拦截器完成的.比如:servletConfig,staticParam,params,modelDriven等等. ...

  5. Struts 2 OGNL

    1.什么是OGNL? 2.Struts 2 OGNL 表达式      ======================  华丽丽的分割线  ======================  1.什么是OG ...

  6. JavaWeb框架SSH_Struts2_(四)----->表达式语言OGNL

    1. 表达式语言OGNL OGNL简介 OGNL基本语法 常量 操作符 OGNL表达式 OGNL基础 OGNL上下文 OGNL值栈 OGNL的访问 2. 具体内容 2.1 OGNL简介 OGNL(Ob ...

  7. struts2之OGNL和struts2标签库和ValueStack对象

    OGNL简介: (1)OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目.  struts2框架默认就支持Ognl表达式语言(所以 ...

  8. JavaWeb框架_Struts2_(四)----->表达式语言OGNL

      2. 表达式语言OGNL 2.1 OGNL简介 OGNL(Object-Graph Navigation Language)对象图导航语言的缩写,OGNL是一种表达式语言(Expression L ...

  9. Struts2 OGNL表达式、ValueStack

    OGNL简介 OGNL,即Object-Graph Navigation Language,对象视图导航语言,是一种数据访问语言,比EL表达式更加强大: EL只能从11个内置对象中取值,且只能获取属性 ...

随机推荐

  1. 一次从0到1的java项目实践清单

    虽说工作就是简单的事情重复做,但不是所有简单的事你都能有机会做的. 我们平日工作里,大部分时候都是在做修修补补的工作,而这也是非常重要的.做好修补工作,做好优化工作,足够让你升职加薪! 但是如果有机会 ...

  2. 剖析Linux系统调用的执行路径

    在什么是操作系统这篇文章中,介绍过操作系统像是一个代理一样,为我们去管理计算机的众多硬件,我们需要计算机的一些计算服务.数据管理的服务,都由操作系统提供接口来完成.这样做的好处是让一般的计算机使用者不 ...

  3. IdentityServer4 登录成功后,跳转到原来页面

    IdentityServer4 登录成功后,默认会跳转到Config.Client配置的RedirectUris地址http://localhost:5003/callback.html,用于获取 T ...

  4. css 行内元素设置宽高

    有2中实现方法: 1.设置display:block   inline-block,使其width属性生效 2.如果设置float:left | right, 使其width属性生效. (浮动)使得指 ...

  5. 一个“”字引发的痛苦经历

    (一篇老文章,还有点价值,特意整理了一下.由于涉及客户项目,已经进行了脱敏处理) 1 写在前面的话 虽然这个问题是有解决方案的,但我不建议大家提供给客户,理由见此. 2 问题描述 2010.10.12 ...

  6. 30个CSS3选择器的应用

    或许大家平时总是在用的选择器都是: id class 以及标签选择器.可是这些还远远不够,为了在开发中更加得心应手,本文总结了30个CSS3选 或许大家平时总是在用的选择器都是:#id  .class ...

  7. airodump-ng使用手册

    选项: -i, --ivs 捕捉WEP加密的包,忽略出IV之外的所有的包,保存为.ivs格式 airodump-ng wls35u1 -i -w captures airodump-ng wls35u ...

  8. 如何将一个div水平垂直居中?4种方法做推荐

    方案一: div绝对定位水平垂直居中[margin:auto实现绝对定位元素的居中], 兼容性:,IE7及之前版本不支持 div{ width: 200px; height: 200px; backg ...

  9. Vue.js优雅的实现列表清单的操作

        一.Vue.js简要说明 Vue.js (读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架.与前端框架Angular一样, Vue.js在设计上采用MVVM模式,当Vie ...

  10. mybatis取数据库为null的字段

    数据库中存在int型的字段,但是初始值为null,mybatis取值之后就会报错, org.apache.ibatis.binding.BindingException: Mapper method ...