[Servlet&JSP] 表达式语言EL

EL简介

对于JSP中一些简单的属性、请求参数、标头与Cookie等信息的取得,一些简单的运算或判断,可以使用表达式语言来处理,还可以将一些常用的功用函数编写为EL函数,这样可以减少网页上一部分的Scriptlet。

例如,对于以下的Scriptlet:

<%
    String a = request.getParameter("a");
    String b = request.getParameter("b");
    out.println("a + b = " + (Integer.parseInt(a) + Integer.parseInt(b)));
%>

如果使用EL,则可以只用一行程序代码来改写,甚至加强这段Scriptlet。例如:

<body>
    ${param.a} + ${param.b} = ${param.a + param.b}
</body>

EL使用${}来包括要进行处理的表达式。可使用点运算符(.)指定要访问的属性,使用加号(+)运算符进行加法运算。param是EL的隐含对象之一,表示用户的请求参数,param.a表示取得用户所发出的请求参数a的值,所输入的请求参数自动转换为基本类型并进行运算。

在参数为null时,EL直接以空字符串表示,不会直接显示null值,在进行运算是时,也不会因此发生错误而抛出异常。

EL的点运算符可以连续访问对象,就如同在Java程序代码中一样。例如,原来需要这样写:

<%= ((HttpServletRequest)pageContext.getRequest()).getMethod() %>
<%= ((HttpServletRequest)pageContext.getRequest()).getQueryString() %>
<%= ((HttpServletRequest)pageContext.getRequest()).getRemoteAddr() %>

使用EL,则可以这样编写:

<b>${pageContext.request.method}</b><br />
<b>${pageContext.request.queryString}</b><br />
<b>${pageContext.request.remoteAddr}</b><br />

pageContext也是EL的隐含对象之一。通过点运算符之后街上xxx名称,表示嗲用调用getXxx()方法。如果必须转换类型,EL也会自行处理。

可以使用page指示元素的isELIgnored属性(默认为true),来设置JSP网页是否使用EL。会这样做的原因可能在于,网页中已含有与EL类似的${}语法功能。例如,使用了某个模板(Template)框架之类。

也可以在web.xml中设置<el-ignored>标签为true,来决定不使用EL。例如:

<web-app ...>
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <el-ignored>true</el-ignored>
        </jsp-property-group>
    </jsp-config>
</web-app>

以上标签用来设置符合<url-pattern>的JSP网页是否使用EL。如果JSP网页使用page命令元素的isElIgnored来设置是否支持EL,则以page命令元素的设置为主。

使用EL访问属性

在EL中,可以使用EL隐含对象指定范围来访问属性。如果不指定属性的存在范围,则默认是以page、request、session、application的顺序来寻找EL中所指定的属性。

如果EL所访问的对象是一个数组对象或者List类型对象,则可以使用[]运算符来指定索引以访问数组中的元素。

使用点运算符与[]运算符的总结:

  • 如果使用点运算符,则左边可以是JavaBean或Map对象。
  • 如果使用[]运算符,则左边可以是JavaBean、Map、数组或List对象。

当左边是Map对象时,建议使用[]运算符,因为设置Map时键(key)名称可能有空白或点字符。

EL隐含对象

在EL中提供了11个隐含对象,其中除了pageContext银行对象对应pageContext之外,其他隐含对象都对应Map类型。

pageContext隐含对象

对应于PageContext类型,PageContext本身就是一个JavaBean,只要是getXxx()方法,就可以用${pageContext.Xxx}来取得。

与属性范围有关的隐含对象

与属性范围相关的隐含对象由pageScope、requestScope、sessionScope与applicationScope,分别可以取得使用JSP隐含对象pageContext、request、session与application的setAttribute()方法所设置的属性对象。如果不使用EL隐含对象指定作用范围,则默认从pageScope的属性开始查找。

EL隐含对象pageScope、requestScope、sessionScope与applicationScope不等同于JSP隐含对象pageContext、request、session与application。EL隐含对象仅仅代表作用范围。

与请求参数相关的隐含对象

与请求参数相关的EL隐含对象由param与paramValues。对应request的getParameter()和getParameterValues()方法。

与标头(Header)相关的隐含对象

如果要取得用户请求的标头数据,则可以使用header或headrValues隐含对象。对应request的getHeader()和getHeaders()方法。

cookie隐含对象

cookie隐含对象可以用来取得用户的Cookie设置值。如果在Cookie中设置了username属性,则可以使用${cookie.username}来取得值。

初始化参数隐含对象

initParam可以用来取得web.xml中设置的ServletContext初始参数,也就是在<context-param>中设置的初始参数。

EL运算符

  1. 算数运算符
    + - * (/或div) (%或mod) ?:
  2. 逻辑运算符
    and or not
  3. 关系运算符
    小于:< 或 lt
    小于或等于:<= 或le
    大于:> 或 gt
    大于或等于:>=或 ge
    等于:== 或 eq

EL运算符的优先级与Java运算符对应

EL自定义函数

自定义函数的第一步是编写类,它必须是一个公开类,而想要调用的方法也必须是公开的且为静态方法。例如:

public class Infix {
    public static double eval(String infix) {
        double result = 0;
        //other process
        return result;
    }
}

web容器必须知道如何将这个类的eval()方法当做EL函数来使用,所以必须编写一个标签链接库描述文件(Tag Library Descriptor, TLD)文件,这个文件是个XML文件,扩展名为*.tld

infix.tld:

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" 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/j2eeweb-jsptaglibrary_2_0.xsd">
  <tlib-version>1.0</tlib-version>
  <short-name>infix</short-name>
  <uri>http://club.chuxing/infix</uri>  <!-- 设置URI对应名称 -->
  <function>
    <description>Eval Infix</description> 
    <name>eval</name>    <!-- 自定义的EL函数名称 -->
    <function-class>
        cc.openhome.InFix   <!-- 对应到哪个类 -->
    </function-class>
    <function-signature>
        double eval(java.lang.String)  <!-- 对应到该类的哪个方法 -->
    </function-signature>
  </function>
</taglib>

${infix:eval(...)}中,eval名称就对应于<name>标签的设置,而实际上eval名称背后执行的类与真正的静态方法,分别是由<function-class><functio-signature>设置的。

可以将这个TLD文件直接放在WEB-INF文件夹下,容器会自动找到TLD文件并将其加载。现在可以编写一个JSP来使用这个自定义的EL函数,例如:
express.jsp:

<%@ page language="java" contentType="text/html; utf-8" pageEncoding="utf-8"%>
<%@taglib uri="http://club.chuxing/infix" prefix="infix" %> <!-- 使用taglib元素 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>自定义EL函数</title>
    </head>
    <body>
        ${param.expression} = ${infix:eval(param.expression}} <!-- 使用自定义EL -->
    </body>
</html>

taglib指示元素告诉容器在转译JSP时,会用到对应uri属性的自定义函数,prefix则用来设置前置名称。当JSP中有来自多个不同设计者的EL自定义函数时,就可以避免名称冲突问题。

你可能感兴趣的:(EL)