JavaWeb: JSP、EL与JSTL
JSP-EL-JSTL
JSP
JSP : Java Server Page ------ Java 服务器页面,一开始也是运行在服务器端的,但最后都会解析成HTML的形式发送给浏览器
JSP的优势:
既可以开发静态资源:方便编写HTML,CSS,JS代码
又可以开发动态资源:可以编写java代码操作数据动态获取数据
JSP的执行过程
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的三大动作概述
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动作
案例演示
从demo1.jsp 转发到 demo2.jsp
demo1转发的时候带两个参数:username和age,在demo2中获取并且输出
汉字乱码问题的解决
-
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中使用表达式
算术表达式
比较表达式
逻辑表达式
三元运算
${逻辑判断?真的值:假的值}
判空表达式
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>