JavaWeb: JSP、EL与JSTL

JSP-EL-JSTL

JSP

JSP : Java Server Page ------ Java 服务器页面,一开始也是运行在服务器端的,但最后都会解析成HTML的形式发送给浏览器

JSP的优势:

既可以开发静态资源:方便编写HTML,CSS,JS代码

又可以开发动态资源:可以编写java代码操作数据动态获取数据

JSP的执行过程

JavaWeb: JSP、EL与JSTL

1.浏览器请求jsp文件时,服务器先将jsp翻译成Servlet

2.将得到的Servlet文件,编译成字节码文件

3.再将字节码文件加载到内存中并创建对象

4.调用Servlet对象的service方法处理请求和响应数据

JSP和Servlet是什么关系

查看源码:看类的继承体系

 public final class showTime_jsp extends org.apache.jasper.runtime.HttpJspBase
 public abstract class HttpJspBase extends HttpServlet 

结论:jsp本身就是Servlet

JSP什么时候翻译成Servlet?

浏览器第一次访问时翻译,如果下一次访问内容没有发生变化,则不会翻译了,直接创建Servlet对像调用service方法。如果JSP文件内容改变了,则会再次执行翻译和编译等工作。

JSP脚本表达式

JSP脚本表达式 说明
语法 <%=变量名或者表达式%>
作用 输出变量的值或表达式计算结果
  • 代码

     <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     <html>
     <head>
      <title>JSP脚本表达式</title>
     </head>
     <body>
       <%--
        需求:利用脚本表达式输出变量的值和计算表达式的值并输出。
        JSP脚本表达式
          语法:<%=变量名或表达式%>
          作用:输出变量的值或表达式的计算结果
          注意:%和=之间不能有空格
        --%>
        <%
            // 定义变量
            int age = 18;
        %>
          <%--输出变量的值
               <%=age%>翻译到Servlet中等价于:out.print(age);
          --%>
          <%=age%> <br>
          <%--输出表达式的值
              <%=3*5%>翻译到Servlet中等价于:out.print(3*5);
          --%>
          <%=3*5%>
     </body>
     </html>
  • 翻译成Servlet的代码

     // 定义变量
     int age = 18;
     ​
     out.print(age);
     out.write(" <br>\n");
     out.print(3*5)

JSP代码片段

JSP代码片段 说明
语法 <%Java代码%>
作用 在JSP页面执行一段Java代码 翻译后出现在Servlet的service方法中
  • 代码

     <%@ page import="java.util.ArrayList" %>
     <%@ page import="java.util.List" %>
     <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     <html>
     <head>
      <title>JSP代码片段</title>
     </head>
     <body>
      <%--
          需求:在脚本中创建一个ArrayList,添加三个名字,在 ol-li 中有序列表输出,
          使用 Java 中的 for 循环输出。
     ​
          JSP代码片段语法:<% 在JSP页面执行Java代码 %>
      --%>
     ​
      <%
          // JSP代码片段中编写的Java代码翻译之后出现在service方法中
          // 定义集合
          List<String> list = new ArrayList<>();
          // 添加元素
          list.add("孙悟空");
          list.add("猪悟能");
          list.add("沙悟净");
      %>
     ​
      <%--有序列表--%>
      <ol>
          <% for (int i = 0; i < list.size(); i++) {  %>
              <li><%=list.get(i)%></li>
          <%}%>
      </ol>
     ​
     </body>
     </html>
  • 生成的Servlet代码

     // 定义集合
     List<String> list = new ArrayList<>();
     // 添加元素
     list.add("孙悟空");
     list.add("猪悟能");
     list.add("沙悟净");
     ​
     out.write("\n");
     out.write("\n");
     out.write("    ");
     out.write("\n");
     out.write("    <ol>\n");
     out.write("        ");
     for (int i = 0; i < list.size(); i++) {  
     out.write("\n");
     out.write("            <li>");
     out.print(list.get(i));
     out.write("</li>\n");
     out.write("        ");
     }
     out.write("\n");
     out.write("    </ol>\n");

JSP声明

JSP声明 说明
语法 <%!java代码%>
作用 用于在JSP中定义成员变量或成员方法
  • 代码

     <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     <html>
     <head>
      <title>JSP声明</title>
     </head>
     <body>
      <%--
      需求说明
             - 在JSP代码片段创建一个字符串,使用脚本表达式输出
             - 在声明中也创建一个同名的字符,使用脚本表达式输出,会不会有问题?
     ​
         JSP声明语法:<%! 定义成员变量或成员方法 %>
         --%>
     ​
         <%-- 在JSP代码片段创建一个字符串,使用脚本表达式输出 --%>
         <%
             // 定义字符串:翻译Servlet的service方法中,属于局部变量
             String name = "局部变量";
         %>
     ​
         <%-- 在声明中也创建一个同名的字符串,使用脚本表达式输出 --%>
         <%!
             // 定义字符串:翻译到Servlet中成员变量的位置
            String name = "成员变量";
     ​
             // 定义成员方法
             public int sum(int a,int b){
                 return  a + b;
             }
         %>
         <%--使用脚本表达式输出--%>
         <%=name%> <br> <%--out.print(name);--%>
         <%--使用脚本表达式输出--%>
         <%=this.name%> <br> <%--out.print(name);--%>
     ​
         <%--调用sum方法--%>
         <%=sum(1,1)%> <%--out.print(sum(1,1))--%>
     ​
     </body>
     </html>
  • 生成的Servlet代码

     // 定义字符串:翻译到Servlet中成员变量的位置
     String name = "成员变量";
     ​
     // 定义成员方法
     public int sum(int a,int b){
     return  a + b;
     }
     ​
     // 定义字符串:翻译Servlet的service方法中,属于局部变量
     String name = "局部变量";
     ​
     out.print(name);
     out.write(" <br> ");
     out.write("\n");
     out.write("    ");
     out.write("\n");
     out.write("    ");
     out.print(this.name);
     out.write(" <br> ");
     out.write("\n");
     out.write("\n");
     out.write("    ");
     out.write("\n");
     out.write("    ");
     out.print(sum(1,1));

JSP内置对象概述

JSP九大内置对象

对象名 类型 描述
request HttpServletRequest 请求对象
response HttpServletResponse 响应对象
application ServletContext 上下文对象
out JspWriter 具有缓冲区的字符输出流
pageContext PageContext 页面域对象
exception Throwable 异常对象
config ServletConfig Servlet配置对象
session HttpSession 会话域对象
page this 代表JSP当前页面

JSP四大作用域

JSP中四个作用域对象

作用域 类型和对象名 范围
页面域 PageContext pageContext 同一个页面有效
请求域 HttpServletRequest request 同一个请求有效
会话域 HttpSession session 同一个会话有效
上下文域 ServletContext application 同一个应用有效

与页面域有关的方法

方法名 说明
void setAttribute(String key,Object value) 往页面域中存储数据
Object getAttribute(String key) 从页面域中获取数据
void removeAttribute(String key) 从页面域中删除数据
void removeAttribute(String key, int scope) 从指定的作用域中删除数据
Object findAttribute(String key) 从四个作用域中根据键获取值 从小范围到大范围开始查找 如果找到则停止查找,如果都没有找到则返回null

scope的四个取值

PageContext.PAGE_SCOPE:对应于页面域

PageContext.REQUEST_SCOPE:对应于请求域

PageContext.SESSION_SCOPE:对应于会话域

PageContext.APPLICATION_SCOPE:对应于上下文域

JSP三大指令概述

三大指令

指令名称 语法 作用
page <%@page 属性名=属性值 ...%> 设置页面基本信息 告诉Tomcat服务器如何翻译JSP页面
include <%@include file = "JSP文件地址"%> 在JSP页面静态包含另一个JSP页面
taglib <%@taglib uri = "地址" prefix = "前缀"%> 用于在JSP页面导入标签库

include指令的好处:实现页面复用

page指令常用属性

page指令常用属性名 作用
language = "java" 设置页面使用编程语言 默认是java且只能是java
import = "{package.class | package.*}" 在页面中导入java类
errorPage = "relative_url" 设置当前页面出现错误时跳转的页面
isErrorPage = "true | false" 设置当前页面是否是一个错误页面 true:是错误页面,可以使用exception对象 false:不是,则不能使用exception对象
contentType = "mimeType [ ;charset=characterSet]" 设置当前页面的内容类型和编码
isELIgnored = "true | false" 设置是否忽略EL表达式 true:忽略,EL不起作用 false:不忽略,EL能起作用
session = "true | false" 设置是否禁用session false:禁用,无法操作会话域的数据 true:不禁用,默认值

错误页面的三种跳转方式

  • 设置errorPage属性

    <%@ page contentType="text/html;charset=utf-8" language="java" errorPage="error.jsp"%>

  • 设置错误码

    在web.xml配置文件中指定错误码的方式

     <error-page>
      <!--出现500错误-->
      <error-code>500</error-code>
      <!--location:出错后跳转到哪一个页面-->
      <location>/500.jsp</location>
     </error-page>
     ​
     <error-page>
      <!--出现404错误-->
      <error-code>404</error-code>
      <!--location:出错后跳转到哪一个页面-->
      <location>/404.jsp</location>
     </error-page>
  • 设置错误类型

     <error-page>
      <!--异常的类型,指定异常类全名-->
      <exception-type>java.lang.NullPointerException</exception-type>
      <!--location出错后跳转到哪一个页面-->
      <location>/404.jsp</location>
     </error-page>

JSP的三大动作概述

JavaWeb: JSP、EL与JSTL

JSP三大常用动作名称 语法 作用
Jsp:include <jsp:include page="被包含的JSP页面地址" ><jsp:include/> 动态包含另一个JSP页面
Jsp:forward <jsp:forward page="转发的页面地址"></jsp:forward> 转发到另一个JSP页面
Jsp:param <jsp:param name="参数名" value="参数值"></jsp:param> 用于给动态包含或转发的页面传递参数

JSP之include动态包含

include动作与include指令的区别

  include指令:静态包含 include动作动态包含
语法 <%@include file="header.jsp"%> <jsp:include page="header.jsp"></jsp:include>
包含方式 静态包含:包含的是页面的内容 动态包含:包含的是页面的执行结果
生成Servlet个数 1个 2个

注意:如果2个页面中有相同的变量,不能使用静态包含,而应该使用动态包含。

JSP之forward和param动作

案例演示

  1. 从demo1.jsp 转发到 demo2.jsp

  2. demo1转发的时候带两个参数:username和age,在demo2中获取并且输出

  3. 汉字乱码问题的解决

  • demo1.jsp代码

     <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     <html>
     <head>
      <title>JSP动作之forward</title>
     </head>
     <body>
     <%
         // 设置请求参数的编码
         request.setCharacterEncoding("utf8");
     %>
      <%--直接转发到demo06.jsp并传递参数--%>
      <jsp:forward page="demo2.jsp">
          <jsp:param name="username" value="小武"/>
          <jsp:param name="age" value="20"/>
      </jsp:forward>
     ​
     </body>
     </html>
  • demo2.jsp代码

     <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     <html>
     <head>
      <title>获取参数显示</title>
     </head>
     <body>
      <%--获取请求参数--%>
      <%
     ​
          // 获取用户名
          String username = request.getParameter("username");
          // 获得年龄
          String age = request.getParameter("age");
          // 输出用户名和年龄
          out.print(username+"==>" + age);
      %>
     </body>
     </html>

EL表达式概述

EL表达式主要用于替换JSP页面中的脚本表达式,让Jsp的代码更加简化。

EL:Expression Language(表达式语言)

EL的作用:

1.获取作用域中的数据

2.用于执行各种运算:算术、逻辑、三目运算。。。

EL的语法;${变量名或者表达式}

EL获取作用域数据

作用域 Java代码 EL的写法
页面域 <%=pageContext.getAttribute("name")%> ${pageScope.keyName}
请求域 <%=request.getAttribute("name")%> ${requestScope.keyName}
会话域 <%=session.getAttribute("name")%> ${sessionScope.keyName}
上下文域 <%=application.getAttribute("name")%> ${applicationScope.keyName}
自动查找 <%=pageContext.findAttribute("name")%> ${keyName}

EL获取不同类型的数据

操作 EL的写法
EL获取JavaBean数据 ${对象名.成员变量名}
EL获取List集合数据 ${集合名[索引]} 或 ${集合名.get(索引)}
EL获取数组数据 ${数组[索引]}
EL获取Map集合数据 ${map集合名['键']}

EL中使用表达式

算术表达式

JavaWeb: JSP、EL与JSTL

比较表达式

JavaWeb: JSP、EL与JSTL

逻辑表达式

JavaWeb: JSP、EL与JSTL

三元运算

${逻辑判断?真的值:假的值}

判空表达式

JavaWeb: JSP、EL与JSTL

JSTL标签库概述

为什么使用JSTL:

  • 因为JSP页面主要用于显示的,最好不要写java代码<%%>,如果不用JSTL就得写java代码。

  • 对于页面设计人员来说,使用Java语言操作动态数据是比较困难的,而采用标签和表达式语言相对容易一些, JSTL 的使用为页面设计人员和后台开发人员的分工协作提供了便利。

  • 为了简化 JSP 页面的设计。

JSTL是什么:

JSP Standdard Tag Library(JSP标准标签库)

JSTL的作用:

用来替代JSP代码片段

JSTL的使用步骤:

  • 下载JSTL相关类库

  • jstl-impl.jar

  • javax.servlet.jsp.jstl.jar

  • 将类库导入到项目中

  • 在JSP页面引入标签库

  • 在JSP页面使用标签库的标签操作数据

JSTL核心标签之<c:if>

作用:用于页面执行判断

语法:<c:if test="${条件表达式}"></c:if>

示例

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <%--引入核心标签库--%>
 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <html>
 <head>
     <title>JSTL核心标签之if</title>
 </head>
 <body>
     <%-- http://localhost:8080/day05/demo09.jsp?age=20
      需求:如果用户提交的age大于18,则显示"你已经成年,可浏览器该网站...",否则显示未成年
     if标签的作用:用于JSP页面进行判断
         test属性:设置判断条件,必须设置,如果条件成立则执行标签体的代码
     注意事项:if标签没有对应的else标签
 ​
     param是EL内置对象,用于获取用户提交的请求参数
     --%>
     <c:if test="${not empty param.age}">
         <c:if test="${param.age >= 18}">
             你已经成年,可浏览器该网站...
         </c:if>
         <c:if test="${param.age < 18}">
             你还未成年,需要在父母陪同下浏览该网站...
         </c:if>
     </c:if>
 </body>
 </html>

JSTL核心标签之<c:choose>

作用:用于多分支判断 语法: <c:choose> <c:when test="条件表达式"> ...... </c:when> ........ <c:otherwise> ........ </c:otherwise> </c:choose>

示例

 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
     <title>JSTL核心标签之choose</title>
 </head>
 <body>
     <%--
     需求:通过输入分时,得到评级。
         - 在一个表单 grade.jsp 输入一个分数,提交给自己。然后在同一个页面中根据分数输出相应的等级:
         80~100  优秀
         60~80  及格
         0~60  不及格  其它输出分数不正确,效果图如下
     --%>
     请输入分数:
     <form action="demo10.jsp" method="get">
         <input type="text" name="score" value="${param.score}">
         <input type="submit" value="评级">
     </form>
 ​
     <%--
         choose标签作用:用于执行多分支判断
         常用子标签:
             when标签:等价于switch语句的case,test属性:设置条件
             otherwise标签:等价于switch语句的default语句
     --%>
     <c:if test="${not empty param.score}">
         <c:choose>
             <c:when test="${param.score >= 80 && param.score <=100 }">
                 优秀
             </c:when>
             <c:when test="${param.score >= 60 && param.score < 80 }">
                 及格
             </c:when>
             <c:when test="${param.score >= 0 && param.score < 60 }">
                 不及格
             </c:when>
             <c:otherwise>
                 你输入的分数有误
             </c:otherwise>
         </c:choose>
     </c:if>
 </body>
 </html>

JSTL核心标签之<c:forEach>

forEach标签的作用:用来遍历集合或数组 forEach标签的语法: <c:forEach items="数组或集合" var="元素">

</c:forEach>

属性名 属性类型 是否支持EL 属性描述
items 数组或集合 true 使用EL表达式,代表集合或数组
var String flase var的变量名代表集合中的每一个元素
varStatus String flase 代表每一个元素的状态对象,一共有4个元素 属性的含义见下表
varStatus对象的属性 数据类型 含义
index int 当前遍历的索引
count int 遍历到当前元素为止遍历的元素个数
first boolean 当前元素是否为第一个元素
last boolean 当前元素是否为最后一个元素

示例

  • 遍历集合

     <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     <html>
     <head>
         <title>学生信息表</title>
     </head>
     <body>
         <table border="1" width="600" cellspacing="0" cellpadding="0">
             <tr>
                 <th>序号</th>
                 <th>学号</th>
                 <th>姓名</th>
                 <th>性别</th>
                 <th>成绩</th>
                 <th>是第一个吗</th>
                 <th>是最后一个吗</th>
             </tr>
     ​
             <%--
                 forEach标签作用:用于遍历集合或数组
                     items属性:设置要遍历的数组或集合
                     var属性:用来记录当前遍历的元素
                     varStatus属性:当前遍历元素的状态对象
     ​
     ​
                 varStatus对象常用属性:
                     index:当前遍历元素在集合中的索引
                     count:遍历到当前元素为止,一共遍历了多少个元素
                     first:当前遍历的元素是否是集合中的第一个元素,是返回true
                     last: 当前遍历的元素是否是集合中的最后一个元素,是返回true
     ​
                 for(Student stu:stus){
                     stu.getId();
                 }
             --%>
             <c:forEach items="${requestScope.stus}" var="stu" varStatus="status">
                 <tr>
                     <td>${status.index + 1}</td>
                     <td>${stu.id}</td>
                     <td>${stu.name}</td>
                     <td>${stu.gender? "男":"女"}</td>
                     <td>${stu.score}</td>
                     <td>${status.first}</td>
                     <td>${status.last}</td>
                 </tr>
             </c:forEach>
         </table>
     </body>
     </html>
  • 遍历数组和Map

     <%@ page import="java.util.Map" %>
     <%@ page import="java.util.HashMap" %>
     <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     <html>
     <head>
         <title>JSTL核心标签之forEach遍历map和数组</title>
     </head>
     <body>
     ​
         <%
             // 创建数组
             int[] arr = {100,54};
     ​
             // 创建Map集合
             Map<String,String> map = new HashMap<>();
             map.put("no1", "牛魔王");
             map.put("no2", "猪八戒");
             map.put("no3", "白骨精");
     ​
             pageContext.setAttribute("arr", arr);
             pageContext.setAttribute("map", map);
         %>
     ​
         <h1>ForEach遍历数组</h1>
         <c:forEach items="${arr}" var="num">
             ${num}
         </c:forEach>
     ​
         <h1>ForEach遍历map</h1>
     ​
         <%--遍历map时获得的是一个一个Entry对象:一个Entry对象就封装一个键值对数据
             可以通过EL获取Entry对象的key和value --%>
         <c:forEach items="${map}" var="entry">
             ${entry.key} ==> ${entry.value} <br>
         </c:forEach>
     ​
     </body>
     </html>