OGNL简介
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访问值栈时从它的上往下访问不管值栈是否有关重复的靠近值栈最上面的属性都
会被优先使用。
五:类型转换器
- 为什么要使用类型转换器:
在基于HTTP协议的web应用中,客户端请求的所有内容,均以文本编码的形式传入到服务器端,但服务器端的编程语言,有着丰富的数据类型,如int,boolean,Date及自定义类型等,因此当这些参数进入应用程序时,它们必须转换为合适的服务器端编程语言的数据库类型。
- 内置类型转换器:
(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.)数组的方式:
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>
六:自定义转换器:
- 创建自定义转换器
- 配置自定义转换器
- 创建和配置日期转换器
示例如下:在此之前先创建一个这样的类:
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.)启动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.)访问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简介的更多相关文章
- 3:2 OGNL 简介
OGNL : (对象图导航语言) 从一个对象到另一个对象 OGNL来源于Xwork: OGNL的作用: OGNL在数据进出值栈的时候进行类型转换
- OGNL和ValueStack
OGNL简介 OGNL的全称是Object Graph Navigation Language,即对象导航图语言.它是一个开源项目,工作在视图层,其通过简单一致的表达式语言来读取合适者Java对象的属 ...
- 十七、OGNL表达式
十七.OGNL OGNL简介: OGNL是对象导航图语言.它是一个独立的项目.早期的webwork框架用到了OGNL作为自己的表达式语言, 所以struts2也是用OGNL作为表达式语言,当然也可以使 ...
- Java实战之01Struts2-04拦截器、上传下载、OGNL表达式
十二.Struts2中的拦截器 1.拦截器的重要性 Struts2中的很多功能都是由拦截器完成的.比如:servletConfig,staticParam,params,modelDriven等等. ...
- Struts 2 OGNL
1.什么是OGNL? 2.Struts 2 OGNL 表达式 ====================== 华丽丽的分割线 ====================== 1.什么是OG ...
- JavaWeb框架SSH_Struts2_(四)----->表达式语言OGNL
1. 表达式语言OGNL OGNL简介 OGNL基本语法 常量 操作符 OGNL表达式 OGNL基础 OGNL上下文 OGNL值栈 OGNL的访问 2. 具体内容 2.1 OGNL简介 OGNL(Ob ...
- struts2之OGNL和struts2标签库和ValueStack对象
OGNL简介: (1)OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. struts2框架默认就支持Ognl表达式语言(所以 ...
- JavaWeb框架_Struts2_(四)----->表达式语言OGNL
2. 表达式语言OGNL 2.1 OGNL简介 OGNL(Object-Graph Navigation Language)对象图导航语言的缩写,OGNL是一种表达式语言(Expression L ...
- Struts2 OGNL表达式、ValueStack
OGNL简介 OGNL,即Object-Graph Navigation Language,对象视图导航语言,是一种数据访问语言,比EL表达式更加强大: EL只能从11个内置对象中取值,且只能获取属性 ...
随机推荐
- Excel 查找某列中的数据在另一列是否存在及输出第三例的数据
最近在操作Excel文件数据导入数据库时,经常需要检查Excel中哪些数据数据库中已经存在,哪些不存在,然后再将不存在数据库中的Excel数据导入:在此过程中,经常需要操作Excel中的数据,所以.也 ...
- c#public、private、protected、internal、protected internal修饰符及访问权限
c#public.private.protected.internal.protected internal修饰符及访问权限 public 公有访问.不受任何限制. private 私有访问.只限于本 ...
- 爬取朋友圈,Get年度关键词
人生苦短,我用Python && C#. 1.引言 最近初学Python,写爬虫上瘾.爬了豆瓣练手,又爬了公司的论坛生成词云分析年度关键词.最近琢磨着2017又仅剩两月了,我的年度关键 ...
- C++实现引用和被引用对象分离
上一篇博客简单介绍了C++中引用的底层实现,接下来,通过简单的代码验证如何将引用和被引用对象分离. 代码如下; #include <iostream> #include<string ...
- ASP.NET Core的身份认证框架IdentityServer4(6)- 开始
安装和概述 启动一个新的IdentityServer项目有两种基本方法: 从头开始 从Visual Studio中的ASP.NET身份模板开始 如果从头开始,我们提供了一些文档.项目帮助和内存存储支持 ...
- Redis的各项功能解决了哪些问题?
先看一下Redis是一个什么东西.官方简介解释到:Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存中的一个存储系统,你可以把它作为数据库,缓存和消息中间件来使用.同时支持string ...
- Java多线程synchronized关键字
synchronized关键字代表着同步的意思,在Java中被synchronized修饰的有三种情况 1.同步代码块 //锁为objsynchronized(obj){ while(true){ i ...
- web前端学习路线和步骤
H5+全栈工程师 (学习下列技术可以加QQ: 1416 7596 61)第一阶段:初级入门阶段基本功 1.HTML入门 Windows概述.浏览器概述.HTML简介.HTML标签详解.前端开发工具概 ...
- Deploy .Net project automatically with MsBuild and MsDeploy (0)
I will use a example of my project to show how to use MS Build and MS Deploy in a real project and s ...
- C#中制作MDI窗体
在VB中做 MDI窗体很简单.在C#里就没有这个轻松了,不过还是很方便的. 首先在C#里添加一个窗体,命名为MdiMain,将其IsMdiContainer设定成true,这样MDI主窗体就建立了.然 ...