[Day 20] Expression Language (EL)笔记

前言

今天来整理一下关于EL的介绍
内容为本书的ch8

Expression Language目的

使用标准动作已经可以减少使用scripting的方式
但所接受的特性为string或基本的资料型别
当遇到特性为物件时,并没有办法完整呈现
在这里用一个简单的例子做示范

首先我们有两个class
分别是Student以及Highschool

Student.java

package com.java.test;

public class Student {
  private String Name;
  private Highschool Highschool;

public Highschool getHighschool() {
	return Highschool;
}

public void setHighschool(Highschool highschool) {
	Highschool = highschool;
}

public String getName() {
	return Name;
}

public void setName(String name) {
	Name = name;
}
}

Highschool.java

package com.java.test;

public class Highschool {
  private String Name;

public String getName() {
	return Name;
}

public void setName(String name) {
	Name = name;
}
}

这个时候假设我们已经在Highschool设定好name的值
但是透过Student的getHighschool去呼叫
并将它使用request.setSAttribute

//s为s物件
request.setSAttribute("Student",s)

这样的状况下在scripting是可以的

<%=((Student)request.getAttribute("student")).getHighschool().getName() %>

但在标准动作下会有问题

//highschool是一个物件的名称
//并不是字串或基本的资料型别
//这样只会得到物件的toSrting()

因此这时就需要EL来处理
除了可以解决这类型的问题
还可以更精简及直觉的表示
使网页开发人员即便不懂java仍不影响开发
且增加可维护的便利性

此case使用EL表示为

${student.highschool.name}

.及[]运算子

  • 基本结构
    EL的表示方法很简单,主要由$号及括号组成

    ${ }
    
  • .号运算子
    .点号在EL的表示规则如下:
    1.变数后接点号,左边的变数衣锭是Map或是bean物件
    2.点号右边一定是Map的key或是bean的特性
    3.点号右边的名称必须符合java名称规则(因为会对应到java程序)

  • []运算子
    []具有和.号一样的功能,但可以更弹性,规则如下:
    1.变数后面接[],[]左边可以为Map,bean,List以及Array
    2.[]里是一个字串(可以以双引号或无双引号)
    里面的内容可以是Map key,bean的特性,List的index或是Array的index

    针对这些可扩充的表示内容,整理如下:

    • 阵列

      ${myArray}      //呼叫物件的toString()
                      //但在List,会印出其内容 
      ${myArray[0]}   //index = 0
      ${myArray["0"]} //index = 0(在array和List来说,字串的index会被强制转换成int)
      ${myArray["my"]} //错误,因为没有index为my这种东西
      
    • bean及Map

      • []或是.都可以使用,意义相同
      //两种结果相同
      ${myMap.Name}
      ${myMap["Name"]}
      
      • 有无双引号差异
        若在呼叫key或特性名称时,没有加双引号,则Container会自动去找
        简单说就是
        有加双引号的 =>必定是key或是特性名称
        没有双引号的 =>container会去找其内容相同的属性名称下的对应值

      • 巢状表示
        EL提供巢状结构的形式存在
        举个例子

        myMap.put("a", "aaa");
        myMap.put("b", "bbb");
        myMap.put("c", "ccc");
        
        ${myMap[myMap[0]]} //结果为"aaa" 
        

EL隐含物件

EL也有提供一些隐含物件,如下

  • pageScope/requestScope/sessionScope/applicationScope
    提供使用XXXXScope来取得XXXX作用域的属性
    可搭配pageContext使用来取得物件的特性

    ${requestScope.Student.name}
    
    //因为属性名称为字串,不需要符合java变数命名规则
    //因像这样是合法的宣告request.setAttribute("com.java.Student",s);
    ${requestScope.com.java.Student.name} //不合法,会错
    ${requestScope[com.java.Student].name} //XXXXScope另一个功用
    
  • param/paramValues
    取得HTML表单的值

    //
    ${param.name}
    //也可以拿来取多个值
    //
    //
    ${param.number}//预设会取number得第一个内容
    ${paramValues.number[0]}
    ${paramValues.number[1]}
    
  • header/headerValues
    取得标头内容

    ${header.host}
    ${header["host"]}
    
  • cookie
    取得cookie

    //取得user cookie
    ${cookie.user.value}
    
  • initParam
    取得context的初始参数(非servlet的初始参数,和init-param完全不相同)

    //context的初始参数
    //context-param
    ${initParam.name}
    
  • pageCpontext
    请求物件的特性

    ${pageContext.request.UpdateName}
    

EL function

EL也可以表示function,使用function来呼叫要执行的动作
步骤如下:

  • 1.撰写java class(必须为public 且static的)

    public class TestFunction{
      public static int counter(){
      	return 10*2;
      }
    }
    
  • 2.撰写TLD标签程序库描述子(一般和DD放在同一层)

    myFunction
    
      countAmt
      
          com.java.test.TestFunction
      
      
          int counter()
      
    
    
  • 3.在JSP新增taglib指令
//myFunction要和TLD对应
<%@ taglib prefix="first" uri="myFunction" %>
  • 4.使用EL呼叫
//对应到设定档TLD的name
//name又会去执行对应的java methhod
//并回传结果
${first.countAmt()}

其他运算子

尽量不要在JSP里面进行逻辑的判断
但若必须要使用它去做简单的运算或是逻辑处理
可以使用下列运算子:
http://ithelp.ithome.com.tw/upload/images/20161220/20103425oyRuEXU8gA.png
null的处理机制:

  • 算数运算子
    显示空白

  • 逻辑运算子
    null当作为0(div会丢出infinity,mod会丢出exception)

  • 关系运算子
    将null的变数处理成false