JSP指令
page指令
include指令
入门小案例
date.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
import="java.util.Date" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<% out.println(new Date().toLocaleString()); %>
</body>
</html>
include.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
显示当前时间:
<%@ include file="date.jsp" %>
</body>
</html>
全局配置:
运行结果:
由于这是引入的是静态页面,所以不会刷新时间
还有, tomcat服务器里只生成了include.jsp的java文件和class文件,date.jsp是被包含在include.jsp文件里,关于这点,除了体现在服务器里的包含外,还体现在html文件的包含,如下图,
JSP隐式对象
九大隐式对象
在JSP页面中,有一些对象需要频繁使用,如果每次都重新创建这些对象则会非常麻烦。为了简化Web应用程序的开发,JSP2.0规范中提供了9个隐式(内置)对象,它们是JSP默认创建的,可以直接在JSP页面中使用。这9个隐式对象的名称、类型和描述如表所示。
例如,
当page指令里有isErrorPage = "ture"时,才会有exception这个隐式对象,否则生成的.java文件里只有八大隐式对象,因为isErrorPage默认值为false
out对象
示例
out.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
out.println("first line<br />");
response.getWriter().println("second line<br />");
%>
</body>
</html>
运行结果:
由此说明,out对象通过print语句写入数据后,直到整个JSP页面结束,out对象中输入缓冲区的数据(first line)才真正被写入到Servlet引擎提供的缓存区。而response.getWriter().print();语句则是直接把内容(second line)写入Servlet引擎提供的缓存区中。
针对上述示例的分析图:
在JSP页面中,经常需要向客户端发送文本内容,这时,可以使用out对象来实现。out对象是javax.servlet.jsp.JspWriter类的实例对象,它的作用与ServletResponse.getWriter()方法返回的PrintWriter对象非常相似,都是用来向客户端发送文本形式的实体内容。不同的是,out对象的类型为JspWriter,它相当于一种带缓存功能的PrintWriter。接下来,通过一张图来描述JSP页面的out对象与Servlet引擎提供的缓冲区之间的工作关系,具体如图所示。
从图可以看出,在JSP页面中,通过out隐式对象写入数据相当于将数据插入到JspWriter对象的缓冲区中,只有调用了ServletResponse.getWriter()方法,缓冲区中的数据才能真正写入到Servlet引擎所提供的缓冲区中。
使用page指令设置out对象缓存区大小
加入buffer=0kb的代码,就可以使输出顺序改变
运行结果:
pageContext对象
在JSP页面中,使用pageContext对象可以获取JSP的其他8个隐式对象。pageContext对象是javax.servlet.jsp.PageContext类的实例对象,它代表当前JSP页面的运行环境,并提供了一系列用于获取其他隐式对象的方法。pageContext对象获取隐式对象的方法如下表所示。
上表中列举了pageContext获取其他隐式对象的方法,这样,当传递一个pageContext对象后,就可以通过这些方法轻松地获取到其他8个隐式对象了。
pageContext对象不仅提供了获取隐式对象的方法,还提供了存储数据的功能。pageContext对象存储数据是通过操作属性来实现的,下表列举了pageContext操作属性的一系列方法,具体如下:
例题
小示例
pageContext.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
//1.获取请求对象
HttpServletRequest req = (HttpServletRequest)pageContext.getRequest();
//req.setAttribute("req", "REQUEST");
pageContext.setAttribute("req", "REQUEST", PageContext.REQUEST_SCOPE);
pageContext.setAttribute("req", "PAGECONTEXT", PageContext.PAGE_SCOPE);
pageContext.setAttribute("req", "APPLICATION", PageContext.APPLICATION_SCOPE);
pageContext.setAttribute("req", "SESSION", PageContext.SESSION_SCOPE);
%>
<%=pageContext.findAttribute("req") %>
<hr />
<%=req.getAttribute("req") %>
<hr />
</body>
</html>
全局配置:
运行结果:
这里解释一下运行结果,第一行PAGECONTEXT是因为PAGE_SCOPE范围最小,优先找他,就像C语言里面的局部变量和全局变量,定义了同名变量req,四个范围内都有,优先找局部变量的,这里就是优先找PAGE_SCOPE范围内的,属性是PAGECONTEXT
第二行的REQUEST是指req的属性,这个毫无疑问,肯定是REQUEST,因为你看代码
HttpServletRequest req = (HttpServletRequest)pageContext.getRequest();
就早已认定是这个了
exception对象
在JSP页面中,经常需要处理一些异常信息,这时,可以通过exception对象来实现。exception对象是java.lang.Exception类的实例对象,它用于封装JSP中抛出的异常信息。需要注意的是,exception对象只有在错误处理页面才可以使用,即page指令中指定了属性<%@ page isErrorPage=”true”%>的页面。
exception.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" errorPage="error.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
int a = 3;
int b = 0;
%>
输出:<%=(a / b) %>
</body>
</html>
error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
输出异常信息:<%=exception.getMessage() %>
</body>
</html>
全局配置:
运行结果
- 浏览器端:
- 服务器端
通过对比我们可以知道,如果页面出现错误,服务器会自己崩了,而如果事先留了跳转页面的路,则浏览器会显示跳转页面的异常处理,不会让用户心态崩。
所以这个errorPage和isErrorPage的思想就是宁可让程序员崩溃也不能让用户崩溃(开个玩笑哈)
JSP动作元素
< jsp:include >
< jsp:include >包含的原理是将被包含的页面编译处理后将结果包含在页面中。当浏览器第一次请求一个使用< jsp:include >包含其他页面的页面时,Web容器首先会编译被包含的页面,然后将编译处理后的返回结果包含在页面中,之后编译包含页面,最后将两个页面组合的结果回应给浏览器。
示例1、
included.jsp(被包含页面)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%-- 休眠5s --%>
<%Thread.sleep(5000); %>
included页面的中文------>这个就是被包含页面。
<br />
</body>
</html>
dynamicInclude.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
dynamicInclude页面的中文------>这个就是包含页面。<br />
<jsp:include page="included.jsp" flush="true"></jsp:include>
</body>
</html>
全局配置:
运行结果:
5s后
示例2、
在示例1的基础上将<jsp:include page=“included.jsp” flush=“true”></jsp:include>中的flush=true改为false,即让刷新停止,那么第一次编译的时候,包含文件dynamicInclude.jsp要等5s和included.jsp页面的输出内容同时显示出来。但是都会生成两个对应的.java文件和.class文件,如下图
运行前我把在示例1留下的他们对应的两个对应的.java文件和.class文件都删了
运行后,
服务器并没有像之前include指令那样,两个.jsp文件最后只生成一个.java文件一个.class文件,而是两个.jsp文件分别都生成了各自的.java文件和.class文件(无论flush是否为true),这就是动态包含和静态包含的区别
include指令和< jsp:include >标签的区别
需要注意的是,虽然include指令和< jsp:include >标签都能够包含一个文件,但它们之间有很大的区别,具体如下:
- < jsp:include >标签中要引入的资源和当前JSP页面是两个彼此独立的执行实体,即被动态引入的资源必须能够被Web容器独立执行。而include指令只能引入遵循JSP格式的文件,被引入文件与当前JSP文件需要共同合并才能翻译成一个Servlet源文件。
- < jsp:include >标签中引入的资源是在运行时才包含的,而且只包含运行结果。而include指令引入的资源是在编译时期包含的,包含的是源代码。
- < jsp:include >标签运行原理与RequestDispatcher.include()方法类似,即被包含的页面不能改变响应状态码或者设置响应头,而include指令没有这方面的限制。
< jsp:forward >动作元素(请求转发)
该请求转发类似于response.setHeader()方法,关于response.setHeader()方法详情请看这篇博客白痴与Servlet的深入交流(一),但是区别就是< jsp:forward >动作元素可以保持当前地址跳转到另一个地址所在的页面,地址栏并不会改变,因为这是服务器端的操作,而response.setHeader()会让地址变为跳转地址,因为那个是浏览器的操作