Struts 2中的OGNL

来源:互联网 发布:mac 终端文件路径 编辑:程序博客网 时间:2024/05/12 13:32

EL(Expression Language,以下译为表达式语言)表达式语言主要有以下几大好处:

避免(MyType) request.getAttribute()和myBean.getMyProperty()之类的语句,使页面更简洁;
支持运算符(如+-*/),比普通的标志具有更高的自由度和更强的功能;
简单明了地表达代码逻辑,使用代码更可读与便于维护。
Struts 2中的表达式语言
Struts 2支持以下几种表达式语言:

OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;
JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;
Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性;
Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。
Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:

支持对象方法调用,如xxx.doSomeSpecial();
支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 |  值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;
访问OGNL上下文(OGNL context)和ActionContext;
操作集合对象。
OGNL的用法
OGNL是通常要结合Struts 2的标志一起使用,如<s:property value="xx" />等。大家经常遇到的问题是#、%和$这三个符号的使用。下面我想通过例子讲述这个问题:

首先新建名为Struts2_OGNL的Web工程,配置开发环境。之前很多朋友在使用Struts 2的过程中都遇到乱码问题。当然乱码问题由来已久,而且涉及多方面的知识,所以并非三言两语可以说明白,而且互联网上也已经有很多这方便的文章,大家可以Google一下。不过,如果你在开发的过程,多注意一下,避免乱码问题也不难。乱码多数是由于编码与解码所使用的方式不同造成的,所以我建议大家将编码方式都设为“utf-8”,如<%@  page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>。另外,在配置web.xml时使用ActionContextCleanUp过滤器(Filter),如下面代码所示:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4"
    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-app_2_4.xsd">

    <display-name>Struts 2 OGNL</display-name>
    
    <filter>
        <filter-name>struts-cleanup</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.ActionContextCleanUp
        </filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>struts-cleanup</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.FilterDispatcher
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>清单1 WebContent/WEB-INF/web.xml
“#”主要有三种用途:

访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:  名称 作用 例子
parameters 包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameter("id")
request 包含当前HttpServletRequest的属性(attribute)的Map #request.userName相当于request.getAttribute("userName")
session 包含当前HttpSession的属性(attribute)的Map #session.userName相当于session.getAttribute("userName")
application 包含当前应用的ServletContext的属性(attribute)的Map #application.userName相当于application.getAttribute("userName")
attr 用于按request > session > application顺序访问其属性(attribute) #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止

用于过滤和投影(projecting)集合,如books.{?#this.price<100};
构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
下面让我们它们的具体写法,首先是Action类代码:

package tutorial.action;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.util.ServletContextAware;

import tutorial.model.Book;

import com.opensymphony.xwork2.ActionSupport;

public class OgnlAction extends ActionSupport implements ServletRequestAware, SessionAware, ServletContextAware  {
    private static final long serialVersionUID = 1L;
    
    private HttpServletRequest request;
    private Map<String, String> session;
    private ServletContext application;
    private List<Book> books;
            
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;    
    }

    @SuppressWarnings("unchecked")
    public void setSession(Map session) {
        this.session = session;        
    }

    public void setServletContext(ServletContext application) {
        this.application = application;
    }
    
    public List<Book> getBooks() {
        return books;
    }

    @Override
    public String execute() {
        request.setAttribute("userName", "Max From request");
        session.put("userName", "Max From session");
        application.setAttribute("userName", "Max From application");
        
        books = new LinkedList<Book>();
        books.add(new Book("978-0735619678", "Code Complete, Second Edition", 32.99));
        books.add(new Book("978-0596007867", "The Art of Project Management", 35.96));
        books.add(new Book("978-0201633610", "Design Patterns: Elements of Reusable Object-Oriented Software", 43.19));
        books.add(new Book("978-0596527341", "Information Architecture for the World Wide Web: Designing Large-Scale Web Sites", 25.19));
        books.add(new Book("978-0735605350", "Software Estimation: Demystifying the Black Art", 25.19));
        
        return SUCCESS;
    }
}清单2 src/tutorial/action/OgnlAction.java

以上代码分别在request、session和application的范围内添加“userName”属性,然后再在JSP页面使用OGNL将其取回。我还创建了Book对象的列表用于演示“用于过滤和投影(projecting)集合”的功能,至于Book的代码大家可以在我前一文章《在Struts 2中实现CRUD》看到。

下面是Ognl.jsp的代码,内容如下:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Struts OGNL Demo</title>
</head>
<body>    
    <h3>访问OGNL上下文和Action上下文</h3>
    <p>parameters: <s:property value="#parameters.userName" /></p>
    <p>request.userName: <s:property value="#request.userName" /></p>
    <p>session.userName: <s:property value="#session.userName" /></p>
    <p>application.userName: <s:property value="#application.userName" /></p>
    <p>attr.userName: <s:property value="#attr.userName" /></p>
    <hr />
    <h3>用于过滤和投影(projecting)集合</h3>
    <p>Books more than $35</p>
    <ul>
        <s:iterator value="books.{?#this.price > 35}">
            <li><s:property value="title" /> - $<s:property value="price" /></li>
        </s:iterator>
    </ul>
    <p>The price of "Code Complete, Second Edition" is: <s:property value="books.{?#this.title=='Code Complete, Second Edition'}.{price}[0]"/></p>
    <hr />
    <h3>构造Map</h3>
    <s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
    <p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>
</body>
</html>清单3 WebContent/Ognl.jsp
以上代码值得注意的是“<s:property value="books.{?#this.title=='Code Complete, Second Edition'}.{price}[0]"/>”,因为“books.{?#this.title=='Code Complete, Second Edition'}.{price}”返回的值是集合类型,所以要用“[索引]”来访问其值。

最后是Struts 2的配置文件struts.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.devMode" value="true" />
    <package name="Struts2_OGNL_DEMO" extends="struts-default">
        <action name="Ognl" class="tutorial.action.OgnlAction">
            <result>/Ognl.jsp</result>
        </action>        
    </package>
</struts>清单4 src/struts.xml

发布运行应用程序,结果如下所示:


清单5 示例运行结果1

“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:

<hr />
    <h3>%的用途</h3>
    <p><s:url value="#foobar['foo1']" /></p>
    <p><s:url value="%{#foobar['foo1']}" /></p>清单6 演示%用途的代码片段
刷新页面,结果如下所示:

清单7 示例运行结果2

“$”有两个主要的用途

用于在国际化资源文件中,引用OGNL表达式,例子请参考《在Struts 2.0中国际化(i18n)您的应用程序》
在Struts 2配置文件中,引用OGNL表达式,如 <action name="AddPhoto" class="addPhoto">
            <interceptor-ref name="fileUploadStack" />            
            <result type="redirect">ListPhotos.action?albumId=${albumId}</result>
        </action>清单8 演示$用途的代码片段
总结
OGNL是一种功能很大的表达式语言,熟悉它可以使我们的开发变得更快捷。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 魔域密码忘了怎么办 魔域账号忘记了怎么办 魔域91密码忘了怎么办 魔域人数满了怎么办 部队玩手机被逮怎么办 脑子很笨怎么办17岁 跑步心肺功能差怎么办 剧烈运动后恶心想吐怎么办 运动后头晕想吐怎么办 跑步后反胃想吐怎么办 长跑后恶心想吐怎么办 离职前请假不批怎么办 酷派x7无限重启怎么办 钢铁雄心3资源多怎么办 汽车智能钥匙没电了怎么办 辐射3食物有辐射怎么办 辐射3玩起来很卡怎么办 辐射3多余的瓶盖怎么办 辐射4开锁太快怎么办 极度恐慌3没子弹怎么办 辐射3道德值低怎么办 辐射3任务做完了怎么办 极限竞速6闪退怎么办 两个睾丸都碎了怎么办 快递退回去了钱怎么办 想登录老公微信怎么办 养狗家里味道大怎么办 实在不想养狗了怎么办 培训完不想干了怎么办 干了几天想离职怎么办 药流开始流血了怎么办 药流期间同房了怎么办 想学韩语可是没基础怎么办 鞋子多买了一双怎么办 胳膊抻着了怎么办妙招 胳膊抻筋了 很疼怎么办 干活胳膊抻筋了怎么办 胳膊上的筋扭了怎么办 一岁宝宝脖子歪怎么办 3岁宝宝轻微斜颈怎么办 2岁宝宝轻微斜颈怎么办