JavaWeb-05-JSP规范-06-EL表达式
JavaWeb-05-JSP规范-06-EL表达式
1.JSP的繁琐之处
当使用JSP将作用域对象中存放的数据写入到响应体时,
按传统的方式实现共有三步:
- 在执行标记中通过java代码从作用域对象中读取数据
- 完成数据类型转化
- 在输出标记中将转换后的数据写入响应体内
<%
String value = (String)request.getAttribute("key1");
%>
<%=value%>
这在企业级开发中是非常繁琐的。
为了降低使用JSP文件开发时Java命令开发强度,EL表达式诞生了。
2.EL表达式概述
2.1EL工具包
- 由Java技术开发的一个jar包
- 作用:降低JSP文件开发时Java命令开发强度
- Tomcat服务器本身自带了EL工具包(Tomcat安装地址/lib/el-api.jar)
EL表达式是EL工具包提供的一种特殊命令格式【表达式命令格式】。
2.2EL命令格式
${作用域对象别名.共享数据key名}
2.3EL命令作用
EL表达式用于JSP文件中,负责从作用域对象读取指定的共享数据并输出到响应体。
3.EL表达式中作用域对象的别名
3.1JSP文件中可以使用的作用域对象
作用域对象类型 | 作用域对象 | 描述 |
---|---|---|
ServletContext | application | 全局作用域对象 |
HttpSession | session | 会话作用域对象 |
HttpServletRequest | request | 请求作用域对象 |
PageContext | pageContext | 当前页作用域对象 |
其中,当前页作用域对象【pageContext】是JSP文件独有的作用域对象,Servlet中不存在当前页作用域对象。
在pageContext中存放的共享数据仅能在当前JSP文件中使用,不能共享给其他Servlet或其他JSP文件。
在真实开发过程中,主要用于JSTL标签与JSP文件间的数据共享。
数据
JSTL------------>pageContext------------>JSP
3.2EL表达式中作用域对象的别名
EL表达式为了区分,提供了作用域对象别名。
作用域对象 | 在EL中的别名 |
---|---|
application | $ |
session | $ |
request | $ |
pageContext | $ |
4.演示EL表达式的使用
4.1演示流程
- 新建一个网站【MyWeb】,创建一个Servlet接口实现类【OneServlet】和一个JSP文件【test.jsp】
- 在OneServlet中分别向全局作用域对象、会话作用域对象、请求作用域对象中添加共享数据。
- 在test.jsp中读取三个作用域对象中的共享数据并写入到响应体中。
OneServlet:
package com.tsccg.controller;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Author: TSCCG
* @Date: 2021/08/24 21:19
*/
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = "张三";
Integer age = 20;
String sex = "男";
//全局作用域对象
ServletContext application = request.getServletContext();
application.setAttribute("userName",userName);
//会话作用域对象
HttpSession session = request.getSession();
session.setAttribute("age",age);
//请求作用域对象
request.setAttribute("sex",sex);
//通过请求转发向服务器申请调用test.jsp
request.getRequestDispatcher("/test.jsp").forward(request,response);
}
}
4.2使用传统方式实现
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--1.传统方式--%>
<%--1.1读取作用域对象中的共享数据--%>
<%
String userName = (String)application.getAttribute("userName");
Integer age = (Integer)session.getAttribute("age");
String sex = (String)request.getAttribute("sex");
%>
<%--1.2将共享数据写入响应体--%>
姓名:<%=userName%>
<br>
年龄:<%=age%>
<br>
性别:<%=sex%>
4.4使用EL表达式实现
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--2.EL表达式--%>
姓名:${applicationScope.userName}<br>
年龄:${sessionScope.age}<br>
性别:${requestScope.sex}
5.使用EL表达式将引用对象类型属性写入响应体
5.1命令格式
${作用域对象别名.引用对象名.引用对象属性名}
注意:引用对象属性名一定要和引用类型的属性名完全一致,包括大小写。
5.2命令作用
从作用域对象中读取指定共享数据所关联的引用对象的属性值,并自动将属性值写入到响应体里。
注意:EL表达式没有提供遍历集合的方法,所以无法从作用域对象中读取集合的内容并输出。
5.3演示将引用对象类型属性写入响应体
5.3.1演示流程
创建一个Student类、一个Servlet接口实现类【TwoServlet】和一个JSP文件【test2.jsp】。
- Student类有两个私有属性【Integer id,String name】,提供Getter和Setter方法。
- 在TwoServlet中创建一个Student实例对象并写入数据,然后将实例对象写入请求作用域中。然后通过请求转发方式向Tomcat申请调用test2.jsp文件。
- 在test2.jsp中分别使用传统方法和EL表达式读取实例对象中的属性并写入响应体内。
5.3.2编写Student
package com.tsccg.entity;
/**
* @Author: TSCCG
* @Date: 2021/08/24 22:33
*/
public class Student {
private Integer id;
private String name;
public Student() {
}
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5.3.3编写TwoServlet
package com.tsccg.controller;
import com.tsccg.entity.Student;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: TSCCG
* @Date: 2021/08/24 22:32
*/
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Student student = new Student(1,"张三");
request.setAttribute("student",student);
request.getRequestDispatcher("/test2.jsp").forward(request,response);
}
}
5.3.4编写test2.jsp
<%@ page import="com.tsccg.entity.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--1.传统方式--%>
<%
//1.1读取请求作用域中的共享数据,获得引用对象
Student student = (Student)request.getAttribute("student");
%>
<%--1.2调用get方法获得引用对象属性值并写入响应体--%>
学生ID:<%=student.getId()%>
<br>
学生姓名:<%=student.getName()%>
<hr>
<%--2.EL表达式--%>
学生ID:${requestScope.student.id}
<br>
学生姓名:${requestScope.student.name}
5.3.5查看结果
6.EL表达式简化版
6.1演示简化版表达式的使用
6.1.1格式
为了进一步降低开发难度,可以将EL表达式标准版中的作用域对象别名省去。
${共享数据名}
6.1.2实例演示
OneServlet
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.向当前全局作用域对象中添加一个共享数据
ServletContext application = request.getServletContext();
application.setAttribute("key1","张三");
//2.请求转发调用one.jsp
request.getRequestDispatcher("/one.jsp").forward(request,response);
}
}
one.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
标准版EL表达式输出作用域对象中key1的值:${applicationScope.key1}
<hr>
简化版EL表达式输出作用域对象中key1的值:${key1}
结果:
6.2简化版表达式存在隐患
6.2.1演示简化版EL表达式从不同作用域对象中定位同名数据
当我们再向会话作用域对象session中添加一个共享数据:
OneServlet
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.向当前全局作用域对象中添加一个共享数据,共享数据名为【key1】
ServletContext application = request.getServletContext();
application.setAttribute("key1","张三");
//2.向当前会话作用域对象中添加一个共享数据,共享数据名仍为【key1】,但值不同
HttpSession session = request.getSession();
session.setAttribute("key1","李四");
//请求转发调用one.jsp
request.getRequestDispatcher("/one.jsp").forward(request,response);
}
}
one.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
标准版EL表达式输出全局作用域对象中key1的值:${applicationScope.key1}<br/>
标准版EL表达式输出会话作用域对象中key1的值:${sessionScope.key1}
<hr>
简化版EL表达式输出作用域对象中key1的值:${key1}<br/>
简化版EL表达式输出作用域对象中key1的值:${key1}
结果:
6.2.2简化版EL表达式工作原理
EL表达式简化版因为没有指定作用域对象,所以在执行时采用【猜】算法。
EL表达式简化版定位共享数据过程:
- 首先在【pageContext】定位共享数据
- 如果存在则直接读取并输出然后结束执行
- 如果不存在则去【request】中定位共享数据
- 如果存在则直接读取并输出然后结束执行
- 如果不存在则去【session】中定位共享数据
- 如果存在则直接读取并输出然后结束执行
- 如果不存在则去【application】中定位共享数据
- 如果存在则直接读取并输出然后结束执行
- 如果不存在则返回null
定位顺序:
pageContext------>request------>session------>application
6.2.3简化版EL表达式的隐患
简化版EL表达式执行时,需要从多个作用域对象中按顺序定位共享数据,因此存在隐患:
- 容易降低程序执行速度
- 容易导致数据定位错误
6.3简化版EL表达式的应用场景
简化版EL表达式最初的设计目的,就是为了简化从【pageContext】中读取共享数据并输出的难度。
尽管简化版EL表达式存在诸多隐患,但在实际开发中,开发人员为了节省时间,一般都使用简化版,拒绝使用标准版。
7.EL表达式支持运算表达式
7.1前提
在JSP文件中,有时需要将读取的共享数据进行运算后,再将运算结果写入到响应体。
同样,EL表达式也能够计算共享数据。
7.2支持的运算表达式
运算表达式类型 | 常用符号 |
---|---|
数学运算 | 加减乘除(+ - * /) |
关系运算 | (> < == >= <= !=)或(gt lt eq ge le !=) |
逻辑运算 | 与、或、非(&& || !) |
7.3使用EL表达式演示数学运算
OneServlet
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//在当前请求作用域对象中添加一个字符串和一个数字
String num1 = "100";
Integer num2 = 500;
request.setAttribute("num1",num1);
request.setAttribute("num2",num2);
//请求转发调用one.jsp
request.getRequestDispatcher("one.jsp").forward(request,response);
}
}
one.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--使用传统java代码计算结果--%>
<%
String value1 = (String)request.getAttribute("num1");
Integer value2 = (Integer)request.getAttribute("num2");
int sum = Integer.parseInt(value1) + value2;
%>
使用传统的java命令计算输出的结果:<%=sum%>
<hr>
使用EL表达式计算输出的结果:${num1+num2}
结果:
7.4使用EL表达式演示关系运算
TwoServlet
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer age = 19;
request.setAttribute("age",age);
request.getRequestDispatcher("two.jsp").forward(request,response);
}
}
two.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--使用传统java方式实现关系运算输出--%>
<%
Integer age = (Integer)request.getAttribute("age");
if (age >= 18) {
%>
欢迎光临<br>
<%
} else {
%>
谢绝入内<br>
<%
}
%>
<hr>
<%--使用EL表达式实现关系运算输出--%>
EL表达式:${age>=18?"欢迎光临":"谢绝入内"}
结果:
8.EL表达式内置对象
8.1内置对象1:param
处理:http://localhost:8080/MyWeb/one.jsp?userName=Tom&passWord=123
8.1.1命令格式
${param.请求参数名}
8.1.2命令作用
通过请求对象读取当前请求头中的请求参数内容,并将请求参数内容写入到响应体。
8.1.3代替命令
<%
String userName = request.getParameter("userName");
String passWord = request.getParameter("passWord");
%>
userName:<%=userName%><br>
passWord:<%=passWord%>
8.1.4使用EL表达式内置对象param演示读取输出请求头中的参数
one.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--传统java方式获取请求头中请求参数参数--%>
<%--http://localhost:8080/MyWeb/one.jsp?userName=Tom&passWord=123--%>
<%
String userName = request.getParameter("userName");
String passWord = request.getParameter("passWord");
%>
传统java方式读取输出请求参数:<br>
userName:<%=userName%><br>
passWord:<%=passWord%>
<hr>
<%--使用EL表达式--%>
EL表达式读取输出请求参数:<br>
userName:${param.userName}<br>
passWord:${param.passWord}
结果:
8.2内置对象2:paramValues
8.2.1命令格式
${paramValues.请求参数名[下标]}
8.2.2命令作用
如果浏览器发送的请求参数是一个请求参数并且这个参数关联多个值,那么就可以通过paramValues读取请求参数下指定位置的值,并写入到响应体。
处理:http://localhost:8080/MyWeb/two.jsp?pageNo=1&pageNo=2&pageNo=3
此时pageNo请求参数在请求包中以数组的形式存在:
pageNo[1,2,3]
8.2.3代替命令
<%
String[] array = request.getParameterValues("pageNo");
%>
第一个值:<%=array[0]%>//1
第二个值:<%=array[1]%>//2
8.2.4使用EL表达式内置对象paramValues演示读取输出请求头中的参数
two.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
第一个值:${paramValues.pageNo[0]}<br>
第二个值:${paramValues.pageNo[1]}<br>
第三个值:${paramValues.pageNo[2]}
结果: