Java Web 学习(2) —— JSP

JSP

一、 什么是 JSP

JSP 和 Servlet

Servlet 有两个缺点是无法克服的:首先,写在 Servlet 中的所有 HTML 标签必须包含 Java 字符串,这使得处理HTTP响应报文的工作十分繁琐;第二,所有的文本和 HTML 标记是硬编码,导致即使是表现层的微小变化,如改变背景颜色,也需要重新编译。

JavaServer Pages(JSP)解决了上述两个问题。同时,JSP 不会取代 Servlet,相反,它们具有互补性。
JSP 页面本质上是一个 Servlet。然而,用 JSP 页面开发比使用 Servlet 更容易。首先,不必编译 JSP 页面;其次,JSP 页面是一个以 jsp 为扩展名的文本文件,可以使用任何文本编辑器来编写它们。

JSP 不需要添加注解或在部署描述符配置映射 URL。应用程序目录中的每一个JSP页面可以直接在浏览器中输入路径页面来访问。添加新的 JSP 界面后,无需重启 Tomcat。

二、 运行 JSP

JSP页面在JSP容器中运行,一个Servlet容器通常也是JSP容器。例如,Tomcat 就是一个 Servlet/JSP 容器。
当一个 JSP 页面第一次被请求时,Servlet/JSP 容器主要做以下两件事情:

1. 把 JSP 页面转换到 JSP 页面实现类,该实现类是一个实现 javax.servlet.jsp.JspPage 接口或子接口 javax.servlet.jsp.HttpJspPage 的 Java 类。JspPage 是 javax.servlet.Servlet 的子接口,这使得每一个 JSP 页面都是一个 Servlet。该实现类的类名由 Servlet/JSP 容器生成。如果出现转换错误,则相关错误信息将被发送到客户端。
2. 如果转换成功,Servlet/JSP 容器随后编译该 Servlet 类,并装载和实例化该类,像其他正常的 Servlet 一样执行生命周期操作。

对于同一个 JSP 页面的后续请求,Servlet/JSP 容器会先检查 JSP 页面是否被修改过。如果是,则该 JSP 页面会被重新转换、编译并执行。如果不是,则执行已经在内存中的 JSP Servlet。
这样一来,一个JSP页面的第一次调用的实际花费总比后来的花费多。

JSP页面可以包含模板数据和语法元素(如:'<%'元素表示Java代码块的开始)。除语法元素之外的一切都是模板数据。模板数据会原样发送给浏览器。例如,JSP页面中的HTML标记和文字都是模板数据。

在 Tomcat 中,welcome.jsp 页面在第一次请求时被转换成名为 welcome_jsp 的 Servlet。你可以在 Tomcat 工作目录下的子目录中找到生成的 Servlet,该 Servlet 继承自 org.apache.jasper.
runtime.HttpJspBase,这是一个抽象类,它继承自 javax.servlet.http.HttpServlet 并实现了 javax.
servlet.jsp.HttpJspPage。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.DateFormat" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Date</title>
</head>
<body>
<%
    DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
    out.println(dateFormat.format(new Date()));
%>
</body>
</html>

三、 注释

JSP支持两种不同的注释格式:

  • JSP注释。该注释记录页面中做了什么,不会被发送到浏览器。以"<%--"开始,以"--%>"结束
  • HTML/XHTML注释。这些注释不会被容器处理,会原样发送到浏览器。

四、 隐式对象

Servlet 容器会传递几个对象给它运行的 Servlet。例如,可以通过 Servlet 的 service 方法获取 HttpServletRequest 和 HttpServletResponse 对象。在 JSP 中,可以通过隐式对象来访问上述对象。

pageContext 提供了上下文信息,可以用于获取和设置属性(getAttribute, setAttribute)。属性值可被存储在4个范围之一:页面(JSP),请求(ServletRequest),会话(HttpSession),应用程序(ServletContext)。

public void setAttribute(String name, Object value); // page scope
public Object getAttribute(String name);        // page scope
public void setAttribute(String name, Object value, int scope);
public Object getAttribute(String name, int scope);

out 引用了一个 javax.servlet.jsp.JspWriter 对象,这类似于你在调用 HttpServletResponse 的 getWriter 方法时得到 java.io.PrintWriter。可以通过调用它的 print 方法将消息发送到浏览器。

 

五、 指令

指令指示 JSP 转换器如何把 JSP 页面转换为 Servlet。

page

<%@ page attribute1="value1" attribute2="value2" ... %>

attributes :

  • import:定义本页面中被导入的 java 类型。类型间可用','分隔。
  • session:值为 True,本页面加入会话管理;值为 False 则相反。默认值为True,访问该页面时,若当前不存在javax.servlet.http.HttpSession实例,则会创建一个。
  • buffer:以 kB 为单位,定义隐式对象 out 的缓冲大小。必须以 kB 后缀结尾。默认大小为8kB或更大(取决于JSP容器)。该值可以为 none,这意味着没有缓冲,所有数据将直接写入PrintWriter。
  • autoFlush:默认值为 True。若值为True,则当输出缓冲满时会自写入输出流。而值为 False,则仅当调用隐式对象的flush方法时,才会写入输出流。因此,若缓冲溢出,则会抛出异常。
  • isThreadSafe:定义该页面的线程安全级别。不推荐使用。
  • info:指定生成的 Servlet 类的 getServletlnfo 方法的返回值。
  • errorPage:定义当出错时用来处理错误的页面。
  • isErrorPage:标识本页是一个错误处理页面。
  • contentType:定义本页面隐式对象 response 的内容类型,默认是 "text/html"。
  • pageEncoding:定义本页面的字符编码,默认是"ISO-8859-1"。
  • isELIgnored:配置是否忽略 EL(Expression Language) 表达式。
  • language:定义本页面的脚本语言类型,默认是 Java,这在JSP2.2中是唯一的合法值。
  • extends:定义JSP实现类要继承的父类。较少使用,仅在非常特殊理由下使用。
  • deferredSyntaxAllowedAsLiteral:定义是否解析字符串中出现"#{"符号,默认是False。"{#"是一个表达式语言的起始符号,因而很重要。
  • trimDirectiveWhitespaces:定义是否不输出多余的空格/空行,默认是False。

大部分 page 指令可以出现在页面的任何位置,但当 contentType 或 pageEncoding 属性时,必须出现在 Java 代码发送任何内容之前。
page 指令也可以出现多次,但出现多次的指令属性必须具有相同的值,import 属性除外,多个包含 import 属性的 page 指令的结果是累加的。

include

include 指令将其他文件中的内容包含到当前JSP页面。

<%@ include file="url" %>

taglib

taglib 指令引入一个自定义标签集合的定义,包括库路径、自定义标签。

<%@ taglib uri="uri" prefix="prefixOfTag" %>

六、 脚本元素

脚本程序是 java 代码块,以"<%"符号开始,以"%>"符号结束。

Today is
<%
    out. print(Calendar.getInstance().getTime());
%>

表达式会被JSP容器执行,并使用隐式对象 out 的打印方法输出结果。表达式以
"<%="开始,并由"%>"结束。表达式无需分号结尾。

Today is <%= Calendar.getInstance().getTime() %>

声明以"<%!"开始,以"%>"结束,声明页面中使用的变量和方法。

<%!
    public String getTodaysDate() { return new Date().toString(); }
%>
<!DOCTYPE html>
<html>
<head><title>Declarations</title></head>
<body>
    Today is <%= getTodaysDate() %>
</body>
</html>


在 JSP 页面中,一个声明可以出现在任何地方,并且一个页面可以有多个声明。
可以使用声明来重写 JSP 页面,实现类的 init 和 destroy 方法。通过声明 jsplnit 方法,来重写 init 方法。通过声明 jspDestroy 方法,来重写 destory 方法。

注意:尽量不要在 JSP 页面中编写 Java 代码。除非应用程序只包含一个或两个简单的 JSP 页面,并且永远不会增长;否则,你应该采用模型2,它规定 JSP 页面仅用于显示 Java 对象中的值。

七、 动作

动作是第三种类型的语法元素,它们被转换成 Java 代码来执行操作,如访问一个 Java 对象或调用方法。

useBean

useBean将创建一个关联 Java 对象的脚本变量。这是早期分离表示层和业务逻辑的努力之一。随着其他技术的发展,如自定义标签和表达语言,现在很少使用useBean方式。

setProperty 和 getProperty

setProperty 动作可对一个 Java 对象设置属性,而 getProperty 则会输出 Java 对象的一个属性。

 

include

include 动作用来动态地引入另一个资源。可以引入另一个 JSP 页面,也可以引入一个 Servlet 或一个静态的 HTML 页面。

<! DOCTYPE html>
<html><head>
<title>Include action</title>
</head>
<body>
<jsp:include page="menu.jsp">
    <jsp:param name="text" value="How are you?"/>
</jsp:include>
</body></html>


对于 include 指令,资源引入发生在页面转换时,即当 JSP 容器把页面转换为生成的 Servlet 时。而 include 动作,资源引入发生在请求页面时。因此,使用 include 动作是可以传递参数的,而 include 指令不支持。

forward

forward 动作把当前页面转向到其他资源。

<jsp:forward page="login.jsp">
<jsp:param name="text" value="Please login"/>
</jsp:forward>

 

param

用于传递参数。可以通过 request.getParameter(String name) 取出参数值。

plugin

用于指定插件。

八、 错误处理

page 指令的 isErrorPage 属性标志一个 JSP 页面是否为错误页面。
page 指令的 errorPage 属性指向错误处理页面。

<%-- errorHandler.jsp --%>
<%@ page isErrorPage="true" %>
<! DOCTYPE html><html>
<head><title>Error</title></head>
<body>
An error has occurred.<br/>
Error message:
<%
    out.print1n(exception. toString());
%>
</body></html>
<%@ page errorPage="errorHandler.jsp"%>
Deliberately throw an exception
<%
    Integer. parseInt("Throw me");
%>

猜你喜欢

转载自www.cnblogs.com/JL916/p/11761638.html