代码江湖之勇闯天涯——struts2——OGNL表达式

少爷,之前在讲struts2的jar包的时候还记不记得有个ognl-xxx.jar的jar包啊。
“恩,记得,但是福伯你当时只是说是OGNL表达式,没有说这个表达式的jar包是做什么的。”
好吧,今天我们就开始学习修炼OGNL。
什么是OGNL呢?

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个单独的开源项目。Struts框架使用OGNL作为默认的表达式语言。

使用的前提:
OGNL是struts2整合的一个开源项目,所以在struts2中,要想使用OGNL表达式,必须使用Struts2标签库。

我们在开始OGNL之前先了解下EL表达式 (EL表达式只能支持静态方法调用)
EL表达式的具体步骤:

  1. 编写一个普通类,提供一个实现功能的静态方法
    public class MyFunction {
        public static String toUpperCase(String str){
            return str.toUpperCase();
        }
    }
  1. 在WEB-INF目录中创建一个扩展名为.tld的xml文件 注意文件不能放在classes和lib目录


    .tld文件位置

    首先copy。修改需要修改的。
    short-name:是在jsp中使用的对应的taglib的prefix
    uri:是将当前库绑定在一个uri地址上
    function-->name方法名称,在jsp页面上使用的名称
    function-->function-class方法名称,指定执行的自定义类名
    function-->function-signature指定执行的方法。方法名称必须和类中的方法名称保持一致(当方法有参数和返回值时,参数值和返回值必须写类全名,除了基本数据类型之外)

<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
      <description>A tag library exercising SimpleTag handlers.</description>
    <tlib-version>1.0</tlib-version><!-- 指定标签库或版本库的版本号 -->
    <short-name>myfn</short-name><!-- 使用的短名称,对应的是taglib中的prefix -->
    <!-- 把当前的方法库绑定到一个uri地址上,在该网址上不一定存在方法库 -->
    <uri>http://www.wg.com/myfunction</uri>
    <function>
        <name>toUpperCase</name><!-- 方法名称。在jsp页面上使用的名称 -->
        <!-- 指定执行的自定义方法类 -->
        <function-class>com.wg.javaee.web.MyFunction</function-class>
        <!-- 指定执行的方法。方法名称必须和类中的方法名称保持一致 
            当方法有参数和返回值时,参数值和返回值必须写类全名,除了基本数据类型之外
        -->
        <function-signature>java.lang.String toUpperCase(java.lang.String )</function-signature>
    </function>
</taglib>
  1. 在jsp页面中使用taglib指令引入外部的标签库或者方法库
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.wg.com/myfunction" prefix="myfn"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ONGL-Expression</title>
</head>
<body>
    <%--el表达式 ${}
        jsp表达式 <%=%>
     --%>
    <%-- EL表达式:只能调用静态方法 --%>
      abcdefg--->ABCDEFG
      <br/>
      ${myfn:toUpperCase("abcdefg")}
</body>
</html>

运行结果:

使用EL表达式进行大小写转换

注意:EL表达式只能是静态方法


接下来我们开始我们的ONGL表达式啦,少爷,准备好了没,我们开始发车咯~
ONGL不同于EL表达式,OGNL表达式可以访问普通方法。这点要记住啊,少爷。
首先我们要根据uri去找对应的struts2标签库。

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

接下来呢,少爷应该怎么做?
“唔,既然引用了struts2标签库,接下来就是使用了~”

<%--OGNL表达式:它可以访问普通方法 
    OGNL表达式必须写在struts2的标签中
    s:property它就类似于jsp的表达式,把值输出到浏览器上
    value属性中的内容不再是我们看到的字符串,它是一个ognl表达式。必须知道   
--%>
<s:property value="OGNL-Expression"/>这是一个OGNL表达式<br/>

OGNL-Expression表达式

那我们如何表示一个字符串呢,也很简单,只要在要显示的字符串外嵌套一层单引号''

 <s:property value="'OGNL-Expression'"/>这是一个普通的字符串<br/>
OGNL表示一个字符串

接下来我们开始访问方法,上边我们提到OGNL可以访问普通方法,那我们访问一个普通方法,计算字符串长度length()

<s:property value="'OGNL-Expression'.length()"/>使用普通字符串调用了获取长度的方法<br/>
OGNL调用普通方法

少爷,现在我们静下心来思考个问题,OGNL能调用普通方法,那他能调用静态方法么?
···
答案是肯定的。不过我们在调用静态方法之前,我们可以调用下静态属性,从中找出规律

<%-- OGNL访问静态属性 :
     访问静态属性的方式:@全类名@静态属性名称
--%>
<s:property value="@java.lang.Integer@MAX_VALUE"/><br/>

访问静态属性获取int最大值

通过访问静态属性我们可以知道如何访问静态方法:由于struts2默认禁用静态方法调用,我们需要提前开启
在struts.xml中添加

<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

在jsp中使用:

 <%-- OGNL访问静态方法 :
      访问静态方法的方式:@全类名@静态方法名称
      struts2的框架默认禁用静态方法调用,我们可以通过配置开启
      struts.ognl.allowStaticMethodAccess=false把它改为true
--%>
<s:property value="@java.lang.Math@random()"/>

接下来我们开始修炼OGNL的应用了~
之前我们接触过radio,在struts2中给我们封装好了radio,使用list进行添加数据,这个就是OGNL表达式的应用。
OGNL可以操作map和list的:

<%--
    使用的是s:radio的标签创建list集合
    {}就相当于创建了一个list集合
    list属性中的取值:是一个ognl表达式
--%>
<s:radio name="gender" list="{'男','女'}"></s:radio><br/>
OGNL操作list

通过浏览器显示源码:



但是使用list进行post时,传递过去的数据的value是'男','女'这样的字符串。
但是在开发中我们几乎不会使用这样的方式的,我们要传递的value和展示的可能不会一样,比如传1表示男,0表示女。那么男、女就相当于key,1、0相当于value了,我们可以想一下什么样的数据类型才会有这样的key,value的对应关系呢?
“我知道了,是map。”
哈哈,是的,少爷有进步啊。就是map,我们可以使用OGNL进行操作map。
那么上边的男女的radio可以进行修改。

<%--使用s:radio创建一个map 
    #{}表示创建一个map
    1和0作为value给radio标签的value属性赋值
--%>
<s:radio name="genderMap" list="#{'1':'男','0':'女'}"></s:radio>

通过浏览器显示源码:


通过源码我们可以看到list与map的value值是不一样的。
{}表示list,#{}表示map


现在我们要解决一个之前留下的小问题了,少爷,你还记得前几天学习的文件上传与下载么?
“记得啊,怎么了?有什么问题么?”
呵呵,当时写文件下载的时候我们固定写死了下载下的文件名:

<param name="contentDisposition">attachment;filename=photo.png</param>

“想起来了,那个时候确实是写死的。”
恩,我们现在学习了OGNL表达式之后就可以进行动态设置了。
首先我们在文件下载动作类中添加一个filename,set、get方法,我们在动作方法返回SUCCESS结果视图之前,给filename赋值"皂片.png"

/**
 * 文件下载的动作类
 * @author asmin
 *
 */
public class DownLoadAction extends ActionSupport {
    //注意:再给InputStream指定名称时,不能使用in
    private InputStream inputStream;
    //创建一个文件名的属性
    private String filename;
    public String getFilename() {
        return filename;
    }
    public void setFilename(String filename) {
        this.filename = filename;
    }
    public String download() throws Exception{
        //1.知道文件在哪  找到文件的存储路径
        String filePath = ServletActionContext.getServletContext().getRealPath("WEB-INF/files/5.png");
        //2.把文件读到一个InputStream中
        inputStream = new FileInputStream(filePath);
        //再返回之前。在filename赋值
        filename="皂片.png";
        //3.返回成功
        return SUCCESS;
        //4.由一个叫stream的结果类型为我们把剩下的做完
    }

    public InputStream getInputStream() {
        return inputStream;
    }
    public void setInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }
}

接下来我们就要使用OGNL表达式了。将原本的filename="photo.png"写成filename=${@java.net.URLEncoder@encode(filename,"UTF-8")}我们调用了静态方法,所以我们要在struts.xml中开启调用静态方法。

<action name="download" class="com.wg.javaee.action.DownLoadAction" method="download">
    <result name="success" type="stream">
        <!-- 给Stream的结果类型注入参数:Content-Type -->
        <param name="contentType">application/octet-stream</param>
        <!-- 使用OGNL表达式,动态获取文件名
            ${@java.net.URLEncoder@encode(filename,"UTF-8")}把${}中间的作为OGNL表达式
         -->
        <param name="contentDisposition">attachment;filename=${@java.net.URLEncoder@encode(filename,"UTF-8")}</param>
        <!-- 注入字节输入流:取值要写动作类中的set方法名称,首字母小写 -->
        <param name="inputName">inputStream</param>
    </result>
</action>
使用ONGL表达式进行动态设置下载的文件名
使用ONGL表达式进行动态设置下载的文件名
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 概述 什么是Struts2的框架Struts2是Struts1的下一代产品,是在 struts1和WebWork的...
    inke阅读 2,242评论 0 50
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,587评论 18 399
  • 标签 如果要配置的标签,那么必须要先配置标签,代表的包的概念。 包含的属性 name包的名称,要求是唯一的,管理a...
    偷偷得路过阅读 1,312评论 0 0
  • 本文包括:1、OGNL 表达式概述(了解)2、值栈概述3、值栈的存值与取值4、EL 表达式也会获取到值栈中的数据5...
    廖少少阅读 1,241评论 0 14
  • 缘起 最近在帮人做一个计步器,其中涉及到身高、体重等信息的采集;我参考了众多app的实现,觉得"乐动力"中滑动刻度...
    LichFaker阅读 10,177评论 9 30