OGNL简介

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访问值栈时从它的上往下访问不管值栈是否有关重复的靠近值栈最上面的属性都

会被优先使用。

五:类型转换器

  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中的数据

 

转载于:https://www.cnblogs.com/dkz1/p/8024675.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/107843.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 网络编程socket原理_socket的基本概念和原理

    网络编程socket原理_socket的基本概念和原理一、客户机/服务器模式在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Servermodel)。该模式的建立基于以下两点:1、非对等作用;2、通信完全是异步的。客户机/服务器模式在操作过程中采取的是主动请示方式:首先服务器方要先启动,并根据请示提供相应服务:(过程如下)1、打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求。2、等待客户请求到

    2022年10月10日
  • Linux下自动检测Tomcat宕机,并自动重启[通俗易懂]

    Linux下自动检测Tomcat宕机,并自动重启[通俗易懂]Linux下自动检测Tomcat是否宕机,并自动重启公司服务器tomcat经常自动挂掉,具体原因无法找到。所以做了这次调整。让Linux自动检测tomcat是否宕机1.新建一个名字为XX.sh的文件,文件内容如下#!/bin/sh#获取tomcat进程ID/usr/local/tomcat_ds_api#TomcatID=$(ps-ef|greptomcat|grep-…

  • 7款开源Java反编译工具

    7款开源Java反编译工具今天我们要来分享一些关于Java的反编译工具,反编译听起来是一个非常高上大的技术词汇,通俗的说,反编译是一个对目标可执行程序进行逆向分析,从而得到原始代码的过程。尤其是像.NET、Java这样的运行在虚拟机上的编程语言,更容易进行反编译得到源代码。当然,也有一些商业软件,对其程序进行了混淆加密,这样我们就很难用工具反编译了。1、Java反编译插件——JadclipseJadClipse是J…

  • jquery nextsibling_javascript中预编译

    jquery nextsibling_javascript中预编译JavaScript中的nextSibling和previousSibling和作用类似于jquery的next()和prev(),都是获取下一个/上一个同胞元素,如果下一个同级节点不存在,则此属性返

  • sql注入之报错注入「建议收藏」

    sql注入之报错注入「建议收藏」报错注入报错注入在没法用union联合查询时用,但前提还是不能过滤一些关键的函数。报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。这里主要记录一下xpath语法错误和concat+rand()+group_by()导致主键重复xpath语法错误利用xpath语法错误来进行报错注入主要利用extractvalue和updatexml两个函数。使用…

  • Java判断对象是否为空的方法:isEmpty,null,” “[通俗易懂]

    Java判断对象是否为空的方法:isEmpty,null,” “[通俗易懂]今天修改辞职同事遗留的代码才发现这个问题,不能用isEmpty来判断一个对象是否为null,之前没在意这个问题,在报了空指针之后才发现这个问题。查了一下关于判断为空的几个方法的区别,这里做一个简单的总结:null一个对象如果有可能是null的话,首先要做的就是判断是否为null:object==null,否则就有可能会出现空指针异常,这个通常是我们在进行数据库的查询操作时,查询结果首…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号