Java web之JSP技术详解
write:2022-4-16
上一篇文章学习了java web的一个核心组件Servlet:Servlet技术详解,本篇文章学习java web的另一个核心组件JSP。
1. 理解JSP的概念和运行过程
1.1 JSP(Java Server Page)简介
在传统的网页HTML文件(.htm,.html)中加入Java程序片段(Scriptlet)和JSP标签,就构成了JSP网页。
Java程序片段可以(完成与Servlet同样的功能,例如:)操纵数据库、重新定向网页以及发送E-mail等,实现建立动态网站所需要的功能。
1.2 HTML页面与JSP页面的区别
1.3 Tomcat服务器初次执行JSP的过程
从Servlet容器处理JSP的过程可以看出,JSP虽然形式上像HTML文件,但其本质上是Servlet。因此Servlet的功能和特性也都适用于JSP。
1.4 由JSP生成的Servlet类
由JSP生成的Servlet类实现了javax.servlet.jsp.JspPage接口,该接口扩展了javax.servlet.Servlet接口。
在javax.servlet.jsp.JspPage接口中定义了方法jspInit()、jspService()和jspDestroy(),对应于Servlet借口的init()和service()和destroy()方法。对于Servlet容器来说,运行JSP文件是把它作为Servlet来运行的。
参考hello.jsp的Servlet源文件,与hello.jsp文件对应的Servlet源文件和类文件的路径分别为:
<CATALINA_HOME>\work\Catalina\localhost\helloapp\org\apache\jsp\hello_jsp.java
<CATALINA_HOME>\work\Catalina\localhost\helloapp\org\apache\jsp\hello_jsp.class
2. 掌握JSP语法
JSP文件包含如下内容:
JSP指令(或称为指示语句)
JSP声明
Java程序片段(Scriptlet)
变量数据的 Java 表达式
隐含对象
2.1 JSP指令
用来设置和整个JSP网页相关的属性,如网页的字符编码和脚本语言等。
JSP 指令的一般语法形式为:<%@ 指令名 属性=“值” %>
常用的3种指令:
page
include
taglib (用来声明当前网页所引用的标签库)
2.1.1 JSP指令(page指令)
page指令可以指定所使用的脚本语言、导入的软件包以及字符编码等。
例如:
<%@ page language =“java” %> //默认JSP语言都是java
<%@ page import =“java.io.*,java.util.Hashtable” %>
<%@ page content_type=“text/html; charset=GB2312” %> //文档类型,字符编码
对比在Servlet类中的语法:
import java.io.*;
import java.util.Hashtable;
response.setContentType(“text/html; charset=GB2312”);
Servlet类纯粹是java类,因此用java语言编写各种功能;而JSP文件从形式上向HTML文档靠拢,因此尽量使用标记的形式来完成各种功能
2.1.2 JSP指令(include指令)
JSP可以通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。
include指令的语法:<%@ include file=“URL” %>
在开发网站时,如果多数JSP网页都包含相同的内容,可以把这部分相同的内容单独放到一个文件中,其他的JSP文件通过include指令将这个文件包含进来,这样做可以提高(代码的可重用性)开发网站的效率,而且便于维护网页。
eg:下面这个index.jsp由其他的jsp页面组成:
index.jsp:
<table width="100%" height="100%">
<tr>
<%-- Sidebar section --%>
<td width="150" valign="top" align="left" bgcolor="#CCFFCC">
<%@ include file="sidebar.jsp" %> </td>
<%-- Main content section --%>
<td height="100%" width="*">
<table width="100%" height="100%">
<tr> <%-- Header section --%>
<td valign="top" height="15%">
<%@ include file="header.jsp"%> </td> </tr>
<tr> <%-- Content section --%>
<td valign="top" height="*">
<%@ include file="indexContent.jsp" %> </td> </tr>
<tr> <%-- Footer section --%>
<td valign="bottom" height="15%">
<%@ include file="footer.jsp" %> </td> </tr>
</table>
</td></tr></table>
2.2 JSP声明
JSP声明(在**<%!和%>**内的)用于声明JSP对应的Servlet类的成员变量和方法。语法如下:
<%! declaration;[declaration;] …%>
例如:
<%! int v1=0; %>
<%! int v2,v3,v4 ;%>
<%! String v5="hello";
static int v6;
%>
<%!
public String amethod(int i){
if(i<3)return "i<3";
else return "i>=3";
}
%>
2.3 Java程序片段
在JSP文件中,可以在**<%** 和 **%>**标记间直接嵌入任何有效的Java语言代码(这是jsp与html最大的区别)。这样嵌入的程序片段称为Scriptlet(即脚本)。
例如:
<%
String gender="female";
if(gender.equals("female")){
%>
She is a girl.
<% }else{ %>
He is a boy.
<% } %>
以上代码等价于以下Servlet的service方法:
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String gender="female"; //局部变量
if(gender.equals("female"))
out.println("She is a girl.");
else
out.println("He is a boy.");
}
2.4 变量数据的 Java 表达式
JSP中表达式标记为**<%=** 和 %>。该表达式的值会显示在网页上。
例如,以下是hitcount.jsp的部分代码:
<%! int hitcount=0;%> //实例变量
<% int count=0; %> //所有在java程序片段中定义的变量都是局部变量,相当于在Servlet的service()中定义的变量
<H1>hitcount=<%= hitcount++ %> </H1><br>
<H1>count=<%= count++ %> </H1><br>
2.5 隐含对象
在编写JSP程序时,可以直接使用Servlet容器提供的隐含对象(9个)。使用这些对象的引用变量时不需要做任何变量声明:
例如,在JSP中可以直接通过request变量获取HTTP请求信息中的参数:
<%
String username = request.getParameter("username");
out.println(username);
%>
或者
<%
String username = request.getParameter("username");
%>
<%=username %>
3. 了解Cookie的用法
3.1 Cookie的运行机制
Cookie的英文原意是“点心”,它是用户访问Web服务器时,服务器在用户硬盘上存放的信息,好像是服务器送给客户的“点心”。
服务器可以根据Cookie来跟踪用户,这对于需要区别用户的场合(如电子商务)特别有用。
用健身馆为会员办会员卡做比方:此处的会员卡类似于Cookie
Cookie在浏览器和服务器之间传输的过程:
Cookie的运行机制是由HTTP协议规定的,Web服务器为了支持Cookie,需要具备以下功能:
在HTTP响应结果中添加Cookie数据。(Cookie数据的具体数据格式都是由HTTP协议规定)
解析HTTP请求中的Cookie数据。
浏览器为了支持Cookie,需要具备以下功能:
解析HTTP响应结果中的Cookie数据。
把Cookie数据保存到本地硬盘。
读取本地硬盘上的Cookie数据,把它添加到HTTP请求中。
3.2 在JSP中处理Cookie
一个Cookie包含一对Key/Value。下面的代码生成一个Cookie并将它写到客户端的硬盘上:
Cookie theCookie=new Cookie(“username",“Tom");
response.addCookie(the Cookie); //向客户端写Cookie,把一个Cookie添加到响应结果中
默认情况下,maxAge的值为-1 ,表示当浏览器程序被关闭时,Cookie就结束生命周期。
也可以用Cookie类的setMaxAge()方法设置Cookie的生命周期,以秒为单位。例如:
cookie.setMaxAge(60*60*24*365); //设置一年的有效期
读取来自客户端的Cookie,参考jspCookie.jsp
<html>
<head><title>jspCookie.jsp</title></head>
<body>
<%!
int count1 = 0;
%>
<%
response.addCookie(new Cookie("name_"+count1 , "value_" + count1++));
%>
<%
Cookie[] cookies = request.getCookies(); //读取当前HTTP请求中的所有Cookie数据
if(cookies==null)return;
for(int i = 0; i < cookies.length; i++)
{
%>
<p>
<b>Cookie name:</b>
<%= cookies[i].getName() %>
<b>Cookie value:</b>
<%= cookies[i].getValue() %>
</p>
<%
}
%>
</body></html>
分析jspCookie.jsp的输出结果。
4. 请求转发
4.1 在JSP中转发请求
Servlet规范为Web组件之间的协作提供了两种途径:
请求转发(forward)
包含(include,参见前面介绍的include指令)
在JSP文件中,jsp:forward标签用于将客户请求转发到其他的HTML文件、JSP文件或者Servlet。
jsp:forward的语法为:<jsp:forward page=“转发的目标Web组件的URL" />
4.2 在Servlet中转发请求
RequestDispatcher rd = request.getRequestDispatcher(“转发的目标Web组件的URL”); //RequestDispatcher接口表示请求分发器
rd.forward(request,response); //Servlet源组件和转发的目标组件享用同一个request和response对象
4.3 请求转发的特点
当一个web原组件把请求转发给目标web组件时,有以下特点:
1)如果JSP文件中包含jsp:forward标签,那么这个JSP文件中的所有(源组件试图向客户端发送的)输出数据都不会被发送到客户端。(也就是说客户端收到的响应结果由目标文件生成)
2)jsp:forward标签后面的代码不会被执行。
3)转发目标组件与源组件共享同一个ServletRequest对象和ServletResponse对象。
参考source1.jsp、source2.jsp和target.jsp:
运行过程结果:
4.4 区分jsp:forward和a
a标记和jsp:forward标记有着不同的运行机制。
source1.jsp:
<a href= "target.jsp"> target </a>
source1.jsp与target.jsp不共享HttpServletRequest对象
source2.jsp:
<jsp:forward page="target.jsp" />
source2.jsp与target.jsp共享HttpServletRequest对象
target.jsp:
<p>hello, <%= request.getParameter("name")%> </p>
5. JSP异常处理
如果在执行JSP的Java代码时发生异常,可以通过下面的指令将HTTP请求转发给另一个专门处理异常的网页:
<%@ page errorPage=“errorpage.jsp” %> //errorPage属性:指定为当前文件处理异常
在处理异常的网页中,应该通过如下语句将该网页声明为异常处理网页:
<%@ page isErrorPage=“true” %>
在处理异常的网页中可以直接访问exception隐含对象,获取详细的异常信息,例如:
<p>
错误原因为:
<% exception.printStackTrace(new PrintWriter(out));%>
</p>
注意:源文件和处理异常文件共享同一个ServletRequest对象和ServletResponse对象
6. 比较Servlet和JSP
JSP在本质上就是Servlet。Servlet和JSP在形式上不一样
JSP的优点是擅长于网页制作,生成动态页面,比较直观。JSP的缺点是不容易跟踪与排错。
Servlet是纯Java语言,擅长于处理流程和业务逻辑。Servlet的缺点是生成动态网页不直观。
7. 练习题
- 问题:source2.jsp要把请求转发给target.jsp,应该在source2.jsp中如何实现?
选项:
(A) < a href=“target.jsp”>target.jsp </ a>
(B) <jsp:forward page=“target.jsp”>
答案:B - 问题:source2.jsp要把请求转发给target.jsp,在转发的时候,希望把一个属性(username= “Tom”)传给target.jsp,如何实现?
选项:
(A) request.setParameter(“Tom”);
(B) request.setAttribute(“username”, “Tom”);
© <a href=“target.jsp?username=Tom”>target.jsp< /a>
答案:B
(A) request.setParameter(“Tom”); //request没有这个方法 - 问题:当浏览器第二次访问该JSP网页时的输出结果是什么?
<!% int a=0; %>
<%
int b=0;
a++;
b++;
%>
a:<%= a %>
b:<%= b %>
选项:
(A) a=0 b=0
(B) a=1 b=1
© a=2 b=1
答案:C //a实例变量,b局部变量