JSP与EL表达式

207 阅读4分钟

JSP 规范

介绍:

  • 来自JavaEE 规范中的一种
  • JSP规范制定了如何开发JSP 文件代替响应对象将处理结果写入到响应体的开发过程
  • JSP 规范指定了HTTP 服务器应该如何调用管理 JSP 文件

响应对象存在的弊端

(response的弊端)

  • 适合将数量较少的处理结果写入到响应体
  • 如果处理结果数量较多,使用响应体对象,增加开发的难度(用PrintWriter流来拼凑输出一大堆html代码,可想而知……)

JSP 文件中如何书写 Java 命令

JSP 文件时如何识别 Java 命令和 HTML 标记的呢?

执行标记的语法格式

在 JSP 文件中,只有书写在执行标记中的内容才会被当做 Java命令

可以声明的运行表达式:数学运算,逻辑运算,关系运算

  • 注意,虽然在 JSP 里可以执行 数学运算,逻辑运算,关系运算,但一般对于参数的处理是不会在 JSP里处理的

    在实际开发中,是 Servlet 和 Service 来对参数处理,JSP 来输出,所以,JSP 并不需要做复杂的判断和循环

<% Java 命令 %>

输出标记语法格式

在 JSP 文件,通过输出标记,通知 JSP 将 Java 变量的值写入到响应体中,也可以将Java 变量的运行结果写入响应体

格式:<%= 变量 %>
​
比如:
<%
 int i = 100;
 int j = 200;
 int sum = i + j;
%>
<!--通过输出标记,输出变量sum-->
sum的值:<%=sum%>
​
<!--浏览器上运行效果:sum的值:300 -->

JSP 文件的内置对象

  • 请求作用域对象:request
  • 会话作用域对象:session
  • 全局作用域对象:application
  • 当前页作用域对象:pageContext

在 JSP 文件执行时,可以借助内置的作用域对象,读取共享数据的参数信息

JSP 与 Servlet 的分工

分工

  • Servlet :负责处理业务,并得到【处理结果】
  • JSP :不负责业务处理,主要任务将 Servlet 中的【处理结果】写入到响应体

Servlet 与 JSP 的调用关系

Servlet 将处理结果添加到【作用域对象】

JSP 文件在运行时,从【作用域对象】中得到处理结果

HTTP 服务器调用 JSP 文件的步骤

  • 1、HTTP 服务器将 JSP 文件内容【编辑】成一个 Servlet 接口的实现类( .java 文件)
  • 2、HTTP 服务器将 Servlet 接口的实现类【编译】成一个 class 文件( .class)
  • 3、HTTP 服务器负责创建这个 class 的实例对象,这个实例对象就是 Servlet 实例对象
  • 4、HTTP 服务器通过 Servlet 实例对象调用 _jspService 方法,将 .jsp 文件内容写入到响应体

JSP 文件的位置

在 .IntelliJIdeaxxx.x\system\tomcat\工作空间

Tomcat 工作空间下的 work 文件夹下,work\Catalina\localhost\myweb\org\apache\jsp

EL 表达式

EL工具包

  • 是由 Java 技术开发的一个 jar 包
  • 作用是降低 JSP 文件开发时 Java 命令的开发强度
  • Tomcat 服务器本身自带了 EL 工具包(Tomcat 的安装地址的 lib 文件夹中)

若不想配置MySQL的 jar 包,可以吧 MySQL 的 jar 包复制进 tomcat 的 lib 中。tomcat就自带 mysql 的 jar 包了,不用手动配置

EL 表达式的语法格式

1、一般取值情况

<!--假设在 Servlet 中,请求作用域对象中存在共享属性,并且对JSP文件共享-->
request.setAttribute("key1","value1");
<!--通过请求转发的方式,调用JSP文件-->
request.getRequestDispatcher("/jsp_1.jsp");
​
======================
则在 JSP 中,可以直接对这个请求作用域对象做取值操作
key1 = ${requestScope.key1}
​
<!--在浏览器的运行效果:
key1 = value1
-->

2、假如,请求作用域对象中存放的value值是一个Object类型,则取出数据的方式:

<!-- 在 Servlet 文件中 -->
Student stu = new Student(001,"zhangsan");<!--Student类型中有:sno,sname 属性-->
request.setAttribute("key1",stu);
request.getRequestDispatcher("/jsp_1.jsp");
​
<!-- 在 JSP 文件中 -->
studentNo = ${requestScope.key1.sno}
studentName = ${requestScope.key1.sname}
​
<!--在浏览器的运行效果:
studentNo = 001
studentName = zhangsan
-->

3、假如,共享数据是个集合

<!-- 在 Servlet 文件中 -->
Student stu1 = new Student(001,"zhangsan");
Student stu2 = new Student(002,"lisi");
Student stu3 = new Student(003,"wangwu");
List stuList = new ArrayList();<!-- 数组 -->
stuList.add(stu1);  将对象填充入数组
stuList.add(stu2);  将对象填充入数组
stuList.add(stu3);  将对象填充入数组
request.setAttribute("key1",stuList);<!-- 将集合放入请求作用域对象 -->
request.getRequestDispatcher("/jsp_1.jsp");
​
<!-- 在 JSP 文件中 -->
需要遍历取出,这时候不能用上 EL 表达式了,要用 JSTL(没学)
<%
List stuList = (Student)request.getAttribute("key1");
//然后逐一遍历出来
%>

EL 表达式简化版

EL 表达式允许开发人员开发时,省略作用域对象的别名

${共享数据名}

工作原理

EL 表达式简化版由于没有指定作用域对象,所以在执行时采用【猜】的算法

  • 首先到【 pageContext 】定位共享数据,如果存在,则直接读取输出结束执行
  • 如果在【 pageContext 】没定位成功,则到【 request 】定位共享数据,如果存在,则直接读取输出结束执行
  • 如果在【 request 】没定位成功,则到【 session 】定位共享数据,如果存在,则直接读取输出结束执行
  • 如果在【 session 】没定位成功,则到【 application 】定位共享数据,如果存在,则直接读取输出结束执行
  • 如果在【 application 】没定位成功,则返回 null

pageContext --------> request --------> session --------> application

存在隐患

  • 1、容易降低程序的执行速度
  • 2、如果不同的作用域对象存在相同的 [ key ],则容易导致数据定位错误
  • 3、可读性很差

应用场景

既然设计师设计出来这个功能,自然有他的价值

  • 设计目的,就是简化从 pageContext 读取共享数据并输出的难度

    因为一开始就去pageContext 中找,所以不存在什么效率问题

EL 表达式其他的内置对象

param

paramValues

${paramValues.请求参数名[下标]}

作用:如果浏览器发送的请求参数是【一个请求参数关联多个值】,此时可以通过 paramValues 读取请求参数下指定位置的值,并写入到响应体

jsp 老式命令来输出

<%
//用一个数组来接收 请求参数组
String[] array = request.getParameterValues("pageNo");
%>
第一个值:<%=array[0]%>
第二个值:<%=array[1]%>
第三个值:<%=array[2]%>