第6章 JSP技术
学习目标
- 了解JSP的概念和特点、熟悉JSP的运行原理和基本语法
- 掌握JSP指令、动作元素、隐式对象的使用
在动态网页开发中,经常需要动态生成HTML内容,例如,一篇新闻报道的浏览次数需要动态生成。如果使用Servlet实现HTML页面数据的生成,需要调用大量的Servlet输出语句,使静态内容和动态内容混合在一起,导致程序非常臃肿。为了克服Servlet的这些缺点,Oracle(Sun)公司推出了JSP技术。
1. JSP概述
1.1 什么是JSP
(1) JSP的概念
JSP全名是Java Server Pages,即Java服务器页面,它是Servlet更高级别的扩展。
JSP = HTML + Java脚本
- HTML代码用来实现网页中静态内容的显示,
- Java脚本用来实现网页中动态内容的生成和显示。
最终,JSP文件会通过Web服务器的Web容器编译成一个Servlet,用来处理各种请求。
(2) JSP的特征
- 跨平台 java跨平台 一次编译,到处运行
- 界面与业务代码相分离 用HTML设计界面,使用JSP标签和脚本动态生成页面上的内容(业务)。
- 组件重用 使用JavaBean编写业务组件----重用
- 预编译 首次访问jsp文件时,服务器将对JSP页面代码进行编译,并且仅执行一次编译。
1.2 编写第一个JSP文件
参照ch04创建ch06_zzh项目,创建ch06首页index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<title>ch06 JSP技术(郑佐汉)</title>
</head>
<body>
<h1>ch06 JSP技术(郑佐汉)</h1>
<hr>
<a href="01helloworld_zzh.jsp">1. 我的第1个JSP网页</a><br>
<a href="02timeInfo_zzh.jsp">2. JSP页面的基本构成--显示当前时间</a><br>
<a href="03example01_zzh.jsp">3. JSP Scriptlets、声明变量、表达式</a><br>
<a href="04example02_zzh.jsp">4. JSP声明语句</a><br>
<a href="05example03_zzh.jsp">5. JSP注释、html注释</a><br>
<a href="06example04_zzh.jsp">6. 动态注释</a><br>
<a href="07include_zzh.jsp">7. 静态包含< %@ include file="date.jsp"% ></a><br>
<a href="08dynamicInclude_zzh.jsp">8. 动态包含<jsp:include page="included.jsp" flush="true" /> </a><br>
<a href="09jspforward_zzh.jsp">9. 转发forward </a><br>
<a href="10out_zzh.jsp">10. out与response.getWriter()输出的区别 </a><br>
<a href="10out2_zzh.jsp">10. out与response.getWriter()输出的区别 --- buffer="0kb" </a><br>
<a href="11pageContext_zzh.jsp">11. pageContext.set|get|findAttribute 设置、提取、查找属性</a><br>
<a href="12exception_zzh.jsp">12. 异常对象测试</a><br>
<a href="13table_zzh.jsp">13. 应用Java程序片段动态生成表格</a><br>
<a href="页面转发/forward_zzh.jsp">任务1. 页面转发</a><br>
<a href="用户注册/user_register_zzh.jsp">任务2. 用户注册</a><br>
<hr>
<p><a href="http://101.42.158.247/21javaweb.html">返回课程首页</a>
郑佐汉 <script>document.write(document.lastModified); </script> 制作</p>
</body>
</html>
运行结果如下:
01helloworld_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>My First JSP 郑佐汉</title>
</head>
<body>
<h1>My First JSP 郑佐汉</h1>
</body>
</html>
运行结果显示如右:My First JSP 郑佐汉
1.3 JSP运行原理
(1) 解读Tomcat 9.0.65\conf\web.xml
- 268~280行 如下的servlet定义
- 442~446行 如下的servlet-mapping定义
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
说明:*.jsp或.jspx由org.apache.jasper.servlet.JspServlet.java解析执行。
(2) 解读jsp执行原理
- 原理上是通过org.apache.jasper.servlet.JspServlet.java将xxx.jsp生成对应的.java,编译成相应的.class文件并执行进行服务器端响应。
- 在idea中,jsp生成的java和class文件路径为: C:\Users\zxc\AppData\Local\JetBrains\IntelliJIdea2020.2\tomcat\项目名\work\Catalina\localhost\虚拟路径\org\apache\jsp
01helloworld_zzh.jsp对应的Servlet文件_01helloworld_005fzzh_jsp.java
- 15行 extends org.apache.jasper.runtime.HttpJspBase
- 106行 response.setContentType("text/html;charset=UTF-8");
- 114-124行 输出 html网页内容
- 95-100行 定义隐式对象 pageContext,session,application,config,out,page = this;
- 107-113行 赋值隐式对象 pageContext,application,config,session,out
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.65
* Generated at: 2022-09-22 16:15:16 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class _01helloworld_005fzzh_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
final java.lang.String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
return;
}
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>My First JSP 郑佐汉</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write(" <h1>My First JSP 郑佐汉</h1>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
2. JSP基本语法
2.1 JSP页面的基本构成
JSP页面 = Σ 指令标识(动)、HTML代码(静)、CSS代码(静)、JavaScript代码(静)、嵌入的Java代码(动)、JSP动作标识(动)、注释
02timeInfo_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<html>
<head>
<title>JSP页面---显示当前时间</title>
</head>
<body>
<h1>JSP页面的基本构成(郑佐汉)</h1>
<p><mark>JSP页面 = Σ 指令标识(动)、HTML代码(静)、CSS代码(静)、JavaScript代码(静)、嵌入的Java代码(动)、注释JSP动作标识(动)、注释</mark></p>
<hr>
<%
Date date = new Date();
// 此处的当前时间时Web服务器端的当前时间
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss");
String today =df.format(date);
%>
Web服务器端的当前时间:<%=today%>
<hr>
客户端浏览器的当前时间:
<script>
function getNowDate(){
var nowdate = new Date(); // 客户端浏览器的当前时间
var year = nowdate.getFullYear(); // 返回的是年份
var month = nowdate.getMonth() + 1; // 返回的月份上个月的月份,记得+1才是当月
var dates = nowdate.getDate(); // 返回的是几号
var day = nowdate.getDay(); // 周一返回的是1,周六是6,但是周日是0
var week = [ "星期日","星期一","星期二","星期三","星期四","星期五","星期六"];
var h = nowdate.getHours();
var m = nowdate.getMinutes();
var s = nowdate.getSeconds();
month = checkTime(month);
dates = checkTime(dates);
h = checkTime(h);
m = checkTime(m);
s = checkTime(s);
return year + "年" + month + "月" + dates + "日 " + week[day] + " " + h +":" + m + ":" + s;
}
var checkTime = function (i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
document.write(getNowDate());
</script>
</body>
</html>
运行结果:
2.2 JSP脚本元素
- JSP Scriptlets
<%多条Java语句%>
- 声明标识
<%!变量或方法声明%>
- JSP表达式
<%=Java表达式%>
需要注意的是,
- “<%!”和“%>”里面定义的属性是成员属性,相当于类的属性,方法相当于是全局方法也相当于是类里面的方法,但是在“<%!”和“%>”里面是不可以进行输出的,只能在里面进行方法的定义和属性的定义。
- “<%=”是一个完整的符号,“<%”和“=”之间不能有空格,且JSP表达式中的变量或表达式后面不能有分号(;)。
03example01_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSP Scriptlets、声明变量、表达式</title>
</head>
<body>
<h1>JSP Scriptlets、声明变量、表达式(郑佐汉)</h1>
<hr>
JSP Scriptlets 执行的输出:
<%
int a = 1, b = 2; //定义两个变量a,b
out.println(a+b);
%>
<hr>
<%!
int x = 3, y = 4; //定义两个变量x,y
String 单位名称 = "信息工程学院";
%>
=表达式 执行的输出:<br>
3+4=<%=x+y %><br>
单位名称、用户名称 = <%=单位名称 + " 郑佐汉"%><br>
</body>
</html>
运行结果:
04example02_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSP声明语句</title>
</head>
<body>
<h1>JSP声明方法和调用方法(郑佐汉)</h1>
<%!
public int add(int a, int b) { //定义add方法
return a+b;
}
%>
<hr>
add(1,2)=<%
out.println(add(1,2));//调用add()方法,输出其返回值
%> <br>
add(3,4)=<%
out.println(add(3,4));
%> <br>
add(5,6)=<%
out.println(add(5,6));
%>
</body>
</html>
运行结果:
2.3 JSP注释
//注释内容 java代码的单行注释
/*
java代码的多行注释1
java代码的多行注释2
......
*/
/*
* java代码的多行美观注释1
* java代码的多行美观注释2
* ......
*/
/**
提示信息1 能被Javadoc文档工具生成文档时提取的注释
提示信息2
......
*/
/**
* 美观提示信息1 能被Javadoc文档工具生成文档时提取的注释
* 美观提示信息2
* ......
*/
<%-- 隐藏注释 生成的html源代码不显示 --%>
<!-- HTML注释 html源代码显示 -->
05example03_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP注释</title>
</head>
<body>
<h2>JSP注释(浏览器中查看源代码)</h2>
<!-- 这个是HTML注释 -->
<%-- 这个是JSP注释 --%>
</body>
</html>
06example04_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.Date" %>
<html>
<head>
<meta charset="UTF-8">
<title>动态注释</title>
</head>
<body>
<h2>动态注释(浏览器中查看源代码)</h2>
<!-- 动态注释 <%=new Date()%> -->
</body>
</html>
3. JSP指令
3.1 page指令
<%@ page 属性名1= "属性值1" 属性名2= "属性值2" ...%>
page指令的常用属性
属性名称 | 取值范围 | 描述 |
---|---|---|
language | java | 指定JSP页面所用的脚本语言,默认为Java,可缺省 |
import | 任何包名、类名 | 指定在JSP页面翻译成的Servlet源文件中导入的包或类。import是唯一可以声明多次的page指令属性。一个import属性可以引用多个类,中间用英文逗号隔开。需要注意的是,JSP 容器自动导入以下4个包:java.lang.* javax.servlet.* javax.servlet.jsp.* javax.servlet.http.* |
session | true、false | 指定该JSP内是否内置Session对象,如果为true,则说明内置Session对象,可以直接使用,否则没有内置Session对象。默认情况下,session属性的值为true。 |
isErrorPage | true、false | 指定该页面是否为错误处理页面,如果为true,则该JSP内置有一个Exception对象的exception,可直接使用。默认情况下,isErrorPage的值为false |
errorPage | 某个JSP页面的相对路径 | 指定一个错误页面,如果该JSP程序抛出一个未捕捉的异常,则转到errorPage指定的页面。errorPage指定页面的isErrorPage属性为true,且内置的exception对象为未捕捉的异常 |
contentType | 有效的文档类型 | 指定当前JSP页面的MIME类型和字符编码,例如: HTML格式为text/html 纯文本格式为text/plain JPG图像为image/jpeg GIF图像为image/gif Word文档为application/msword |
pageEnCoding | 当前页面 | 指定页面编码格式 |
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.awt.*" %>
<%@ page import="java.util.*","java.awt.*"%>
需要注意的是,page指令对整个页面都有效,而与其书写的位置无关,但是习惯上把page指令写在JSP页面的最前面。
3.2 include指令(静态包含)
<%@ include file="被包含的文件地址"%>
需要注意的是,插入文件的路径一般不以“/”开头,而是使用相对路径。
07date.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<html>
<head>
<title>date</title>
</head>
<body>
当前时间是:
<%
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss");
String today =df.format(date);
out.println(today);
%>
</body>
</html>
07include_zzh.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<html>
<head>
<title>静态包含</title>
</head>
<body>
<h1>静态包含:<%@ include file="相对路径资源"%></h1>
<hr>
<p>静态包含:把要被包含的文件(如07date.jsp)插入包含文件(如本文件)中编译、执行。</p>
<%@ include file="07date.jsp"%>
<p>include file="07date.jsp" 执行之后的段落。</p>
</body>
</html>
运行结果:
使用include指令的常见问题
- (1)被引入的文件必须遵循JSP语法,其中的内容可以包含静态HTML、JSP脚本元素和JSP指令等普通JSP页面所具有的一切内容。
- (2)除了指令元素之外,被引入的文件中的其他元素都被转换成相应的Java源代码,然后插入进当前JSP页面所翻译成的Servlet源文件中,插入位置与include指令在当前JSP页面中的位置保持一致。
- (3)file属性的设置值建议使用相对路径,如果以“/”开头,表示相对于当前Web应用程序的根目录(注意不是站点根目录);否则,表示相对于当前文件。需要注意的是,这里的file属性指定的相对路径是相对于文件(file),而不是相对于页面(page)。
- (4)在应用include指令进行文件包含时,为了使整个页面的层次结构不发生冲突,建议在被包含页面中将<html>,<body>等标签删除,因为在包含页面的文件中已经指定了这些标签。
3.3 taglib指令 (下章jstl会讲到)
在JSP文件中,可以通过taglib指令标识该页面中所使用的标签库,同时引用标签库,并指定标签的前缀。
<%@ taglib prefix="tagPrefix" uri="tagURI" %>
- prefix:用于指定标签的前缀,该前缀不能命名为jsp、jspx、java、sun、servlet和sunw。
- uri:用于指定标签库的uri标识,不是url位置。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
4. JSP动作元素
4.1 动态包含文件元素<jsp:include>
在JSP页面中,<jsp:include>动作元素用于向当前页面引入其他的文件,被引入的文件可以是动态文件,也可以是静态文件。
<jsp:include page="URL" flush="true|false" />
- page:用于指定被引入文件的相对路径。例如,指定属性值为top.jsp,则表示将当前JSP文件相同文件夹下的top.jsp文件引入到当前JSP页面中。
- flush:用于指定是否将当前页面的输出内容刷新到客户端,默认情况下,flush属性的值为false。
- <jsp:include>包含的原理是将被包含页面编译处理后的结果包含在当前页面中。
include指令与<jsp:include>动作元素的区别
- include指令通过file属性指定被包含的文件,file属性不支持任何表达式;
- <jsp:include>动作元素通过page属性指定被包含的文件,page属性支持JSP表达式。
- 使用include指令时,被包含的文件内容会原封不动地插入到包含页中,然后JSP编译器再将合成后的文件最终编译成一个Java文件;
- 使用<jsp:include>动作元素包含文件时,当该元素被执行时,程序会将请求转发到被包含的页面,并将执行结果输出到浏览器中,然后返回包含页,继续执行后面的代码。因为服务器执行的是多个文件,所以如果一个页面包含了多个文件,JSP编译器会分别对被包含的文件进行编译。
- 在应用include指令包含文件时,由于被包含的文件最终会生成一个文件,所以在被包含文件、包含文件中不能有重复的变量名或方法;
- 而在应用<jsp:include>动作元素包含文件时,因为每个文件是单独编译的,所以被包含文件和包含文件中的重名变量和方法是不冲突的。
08included.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>include</title>
</head>
<body>
<%Thread.sleep(5000);%>
included.jsp内的中文<br>
</body>
</html>
08dynamicInclude_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>dynamicInclude page</title>
</head>
<body>
<h1>动态包含<jsp:include page="08included.jsp>"</h1>
<hr>
dynamicInclude.jsp内的中文
<br />
<jsp:include page="08included.jsp" flush="true" />
</body>
</html>
运行结果:
4.2 请求转发元素<jsp:forward>
<jsp:forward>动作元素可以将当前请求转发到其他Web资源(HTML页面、JSP页面和Servlet等),执行请求转发之后,当前页面将不再执行,而是执行该元素指定的目标页面。
<jsp:forward page="relativeURL" />
page属性用于指定请求转发到的资源的相对路径,该路径的目标文件必须是当前应用中的内部资源。
09welcome.jsp
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>欢迎进入首页</title>
</head>
<body>
你好,欢迎进入首页,当前访问时间是:
<%
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss");
out.print(df.format(new java.util.Date()));
%>
</body>
</html>
09jspforward_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>forword page</title>
</head>
<body>
<!--运行是再控制台能看到【转发之前】,看不到【转发之后】-->
<%
System.out.println("转发之前");
%>
<jsp:forward page="09welcome.jsp" />
<%
System.out.println("转发之后");
%>
</body>
</html>
运行结果:
5. JSP隐式对象
5.1 隐式对象的概述
JSP中的9个隐式对象
名称 | 类型 | 描述 |
---|---|---|
out | javax.servlet.jspJspWriter | 用于页面输出 |
request | javax.servlet.http.HttpServletRequest | 得到用户请求信息 |
response | javax.servlet.http.HttpServletResponse | 服务器向客户端的回应信息 |
config | javax.servlet.ServletConfig | 服务器配置,可以取得初始化参数 |
session | javax.servlet.http.HttpSession | 用来保存用户的信息 |
application | javax.servlet.ServletContext | 所有用户的共享信息 |
page | java.lang.Object | 指当前页面转换后的Servlet类的实例 |
pageContext | javax.servlet.jsp.PageContext | JSP的页面容器 |
exception | java.lang.Throwable | 表示JSP页面所发生的异常,在错误页中才起作用 |
5.2 out对象
在JSP页面中使用out对象向客户端发送文本内容。out对象是javax.servlet.jsp.JspWriter类的实例对象,它的作用与ServletResponse.getWriter()方法返回的PrintWriter对象非常相似,都是用来向客户端发送文本形式的实体内容。不同的是,out对象的类型为JspWriter,它相当于带缓存功能的PrintWriter。
10out_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>out与response.getWriter()输出的区别</title>
</head>
<body>
<h1>out与response.getWriter()输出的区别(郑佐汉)</h1>
<hr>
<%
out.println("第1行 first line。out输出。<br>");
response.getWriter().println("第2行 second line。response.getWriter()输出<br>");
%>
</body>
</html>
10out2_zzh.jsp 和上述代码区别:仅首行多 buffer="0kb"
<%@ page contentType="text/html;charset=UTF-8" language="java" buffer="0kb" %>
<html>
<head>
<title>out与response.getWriter()输出的区别</title>
</head>
<body>
<h1>out与response.getWriter()输出的区别(郑佐汉) --- buffer="0kb" </h1>
<hr>
<%
out.println("第1行 first line。out输出。<br>");
response.getWriter().println("第2行 second line。response.getWriter()输出<br>");
%>
</body>
</html>
运行结果:
5.3 pageContext对象
在JSP页面中,使用pageContext对象可以获取JSP的其他8个隐式对象。pageContext对象是javax.servlet.jsp.PageContext类的实例对象,它代表当前JSP页面的运行环境,并提供了一系列用于获取其他隐式对象的方法。
(1) pageContext对象获取其他8个隐式对象的方法
方法名 | 功能描述 |
---|---|
JspWriter getOut() | 用于获取out隐式对象 |
Object getPage() | 用于获取page隐式对象 |
ServletRequest getRequest() | 用于获取request隐式对象 |
ServletResponse getResponse() | 用于获取response隐式对象 |
HttpSession getSession() | 用于获取session隐式对象 |
Exception getException() | 用于获取exception隐式对象 |
ServletConfig getServletConfig() | 用于获取config隐式对象 |
ServletContext getServletContext() | 用于获取application隐式对象 |
(2) pageContext操作属性的相关方法
方法名 | 功能描述 |
---|---|
void setAttribute(String name,Object value,int scope) | 用于设置pageContext对象的属性 |
Object getAttribute(String name,int scope) | 用于获取pageContext对象的属性 |
void removeAttribute(String name,int scope) | 用于删除指定范围内名称为name的属性 |
void removeAttribute(String name) | 用于删除所有范围内名称为name的属性 |
Object findAttribute(String name) | 用于从4个域对象中查找名称为name的属性 |
(3) pageContext对象的作用范围
pageContext操作属性的相关方法中参数name指定的是属性名称,参数scope指定的是属性的作用范围。pageContext对象的作用范围有4个值,具体如下:
- pageContext.PAGE_SCOPE:表示页面范围。
- pageContext.REQUEST_SCOPE:表示请求范围。
- pageContext.SESSION_SCOPE:表示会话范围。
- pageContext.APPLICATION_SCOPE:表示Web应用程序范围。
上述4个范围的顺序,时间角度从短到长的顺序:当前页面 -> 本次请求 -> 本次会话 -> 本应用程序;空间角度从小到大的顺序:当前页面 -> 本次请求所涉及的JSP页面或Servlet -> 本次会话所涉及的JSP页面或Servlet -> 本应用程序所涉及的JSP页面或Servlet。
需要注意的是,当调用findAttribute()方法查找名称为name的属性时,会按照page、request、session和application的顺序依次进行查找,如果找到,则返回属性的名称,否则返回null。
11pageContext_zzh.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<html>
<head>
<title>pageContext</title>
</head>
<body>
<h1>pageContext.set|get|findAttribute 设置、提取、查找属性</h1>
<hr>
<%
//获取request对象
HttpServletRequest req = (HttpServletRequest) pageContext
.getRequest();
// pageContext包含Request和Response
// HttpServletResponse resp = (HttpServletResponse) pageContext.getResponse();
//设置page范围内属性
pageContext.setAttribute("书名", "《Java程序设计》",pageContext.PAGE_SCOPE);
//设置request范围内属性
req.setAttribute("书名", "《Java Web程序设计》");
pageContext.setAttribute("书名2", "《Java Web程序设计》(第2版)",pageContext.REQUEST_SCOPE);
//设置session范围内属性
pageContext.setAttribute("图书名", "《Java Sesion详解》", pageContext.SESSION_SCOPE);
//获得的page范围属性
String str1 = (String)pageContext.getAttribute("书名",
pageContext.PAGE_SCOPE);
//获得的request范围属性
String str2 = (String)pageContext.getAttribute("书名",
pageContext.REQUEST_SCOPE);
String str3 = (String)pageContext.getAttribute("书名2",
pageContext.REQUEST_SCOPE);
//获得的request范围属性
String str4 = (String)pageContext.getAttribute("图书名",
pageContext.SESSION_SCOPE);
//获得的默认范围属性
String str5 = (String)pageContext.getAttribute("书名");
String str6 = (String)pageContext.findAttribute("书名");
%>
<%="page范围 getAttribute(\"书名\"):"+str1 %><br>
<%="request范围 getAttribute(\"书名\"):"+str2 %><br>
<%="request范围 getAttribute(\"书名2\"):"+str3 %><br>
<%="session范围 getAttribute(\"图书名\"):"+str4 %><br>
<%="pageContext.getAttribute(\"书名\"):"+str5 %><br>
<%="pageContext.findAttribute(\"书名\"):"+str6 %><br>
</body>
</html>
运行结果:
5.4 exception对象
在JSP页面中,经常需要处理一些异常信息,处理异常信息可以通过exception对象实现。exception对象是java.lang.Exception类的实例对象,它用于封装JSP中抛出的异常信息。
需要注意的是,exception对象只有在错误处理页面才可以使用,即page指令中指定了属性<%@ page isErrorPage="true"%>的页面。
异常处理程序 12error.jsp @page定义中 isErrorPage="true"
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>出错处理</title>
</head>
<body>
<h2>异常信息</h2>
<hr>
<!-- 显示异常信息 -->
<%=exception.getMessage()%><br />
</body>
</html>
指定异常处理程序 12exception_zzh.jsp @page定义中 errorPage="12error.jsp"
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" errorPage="12error.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>exception object test</title>
</head>
<body>
<h1>异常隐藏对象测试</h1>
<%
int a = 3;
int b = 0;
%>
输出结果为:<%=(a / b)%><!--此处会产生异常 -->
</body>
</html>
运行结果:
13table_zzh.jsp 应用Java程序片段动态生成表格
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>应用Java程序片段动态生成表格</title>
</head>
<body>
<h1>应用Java程序片段动态生成表格</h1>
<hr>
<%
String[] bookName = {"JavaWeb程序开发入门","JavaWeb程序开发进阶","Java基础案例教程"};
%>
<table border="1" align="center" style="font-size:25px;">
<tr>
<td align="center">编号</td>
<td align="center">书名</td>
</tr>
<%
for (int i=0;i<bookName.length;i++){
%>
<tr>
<td align="center"><%=i %></td>
<td align="center"><%=bookName[i]%></td>
</tr>
<%}%>
</table>
</body>
</html>
任务:将页面转发到用户登录页面
在实际的项目开发过程中,Servlet 中的service() 方法由Servlet 容器调用,所以一个 Servlet 的对象是无法调用另一个 Servlet 的方法的,但是在实际项目中,对于客户端请求做出的响应可能会比较复杂,例如用户登录,需要多个Servlet 来协作完成,这就需要使用请求转发技术了。本任务要求使用
web/页面转发/login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录</title>
</head>
<body>
<form name="form1" method="post" action="">
用户名: <input name="name" type="text" id="name" style="width:
200px"><br><br>
密 码: <input name="pwd" type="password" id="pwd" style="width: 200px"><br><br>
<input type="submit" name="Submit" value="提交">
</form>
</body>
</html>
web/页面转发/forward_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>中转页</title>
</head>
<body>
<jsp:forward page="login.jsp"/>
</body>
</html>
运行结果:
任务:网上蛋糕商城JSP页面
注册页面动态包含头部和脚部jsp:include page="header.jsp|footer.jsp"
web/用户注册/header.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div class="header">
<div class="container">
<nav class="navbar navbar-default" role="navigation">
<!--navbar-header-->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="/index" >首页</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle " data-toggle="dropdown">商品分类
<b class="caret"></b>
</a>
<ul class="dropdown-menu multi-column columns-2">
<li>
<div class="row">
<div class="col-sm-12">
<h4>商品分类</h4>
</div>
</div>
</li>
</ul>
</li>
<li><a href="#" >热销</a></li>
<li><a href="#" >新品</a></li>
<li><a href="#" class="active">注册</a></li>
<li><a href="#" >登录</a></li>
</ul>
<!--/.navbar-collapse-->
</div>
<!--//navbar-header-->
</nav>
<div class="header-info">
<div class="header-right search-box">
<a href="javascript:;">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</a>
<div class="search">
<form class="navbar-form" action="/">
<input type="text" class="form-control" name="keyword">
<button type="submit" class="btn btn-default" aria-label="Left Align">
搜索
</button>
</form>
</div>
</div>
<div class="header-right cart">
<a href="goods_cart.jsp">
<span class="glyphicon glyphicon-shopping-cart " aria-hidden="true">
<span class="card_num"></span>
</span>
</a>
</div>
<div class="clearfix"> </div>
</div>
<div class="clearfix"> </div>
</div>
</div>
<!--//header-->
web/用户注册/footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!--footer-->
<div class="footer">
<div class="container">
<div class="text-center">
<p>挚诚天下(杜兆将) 123.57.28.35 © 版权所有</p>
</div>
</div>
</div>
<!--//footer-->
web/用户注册/user_register_zzh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<title>用户注册</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!--header-->
<jsp:include page="header.jsp"/>
<!--//header-->
<!--account-->
<div class="account">
<div class="container">
<div class="register">
<form action="/user_rigister" method="post">
<div class="register-top-grid">
<h3>注册新用户</h3>
<div class="input">
<span>用户名 <label style="color:red;">*</label></span>
<input type="text" name="username" placeholder="请输入用户名" required="required">
</div>
<div class="input">
<span>邮箱 <label style="color:red;">*</label></span>
<input type="text" name="email" placeholder="请输入邮箱" required="required">
</div>
<div class="input">
<span>密码 <label style="color:red;">*</label></span>
<input type="password" name="password" placeholder="请输入密码" required="required">
</div>
<div class="input">
<span>收货人<label></label></span>
<input type="text" name="name" placeholder="请输入收货">
</div>
<div class="input">
<span>收货电话<label></label></span>
<input type="text" name="phone" placeholder="请输入收货电话">
</div>
<div class="input">
<span>收货地址<label></label></span>
<input type="text" name="address" placeholder="请输入收货地址">
</div>
<div class="clearfix"> </div>
</div>
<div class="register-but text-center">
<input type="submit" value="提交">
<div class="clearfix"> </div>
</div>
</form>
<div class="clearfix"> </div>
</div>
</div>
</div>
<!--//account-->
<!--footer-->
<jsp:include page="footer.jsp"/>
<!--//footer-->
</body>
</html>
运行结果: