JSP技术特点
JSP 和 Servlet 是本质相同的技术。当一个 JSP 文件第一次被请求时,JSP 引擎会将该 JSP编译成一个 Servlet,并执行这个 Servlet。如果 JSP 文件被修改了,那么 JSP 引擎会重新编译这个 JSP。
JSP 引擎对 JSP 编译时会生成两个文件分别是.java 的源文件以及编译后的.class 文件,并放到 Tomcat 的 work 目录的 Catalina 对应的虚拟主机目录中的 org\apache\jsp 目录中。两个文件的名称会使用 JSP 的名称加”_jsp”表示。如:index_jsp.java、index_jsp.class。
简而言之,jsp的本质是一个“类”,而所有的前端代码都会被out.write()包含,输出到页面上。
JSP三种原始标签
注意,使用<%! %>声明的变量是成员变量,所有用户共享,线程不安全。
JSP指令标签分类
page
主要声明JSP页面的一些属性
-
language: 设置JSP页面使用的脚本语言,默认值为
java
。由于JSP主要与Java配合使用,此属性几乎总是保持默认值。 -
contentType: 指定响应的MIME类型和字符编码,例如
text/html;charset=UTF-8
,用于告诉浏览器如何解析返回的内容。 -
pageEncoding: 指定JSP页面本身的编码方式,这影响到JSP文件中的文本和字符常量如何被读取和处理。
-
import: 允许导入Java类或包,使得可以在JSP页面中使用这些类,格式与Java的
import
语句相似。 -
session: 控制JSP页面是否创建或使用HTTP会话,默认值为
true
。设为false
时,表示不参与会话管理。 -
errorPage: 指定当JSP页面产生未被捕获异常时重定向到的错误处理页面。
-
isErrorPage: 用于标识该页面是否作为错误处理页面,如果设为
true
,则可以访问exception
对象,默认为false
。 -
buffer: 设置输出缓冲区的大小,或者通过设置为
none
禁用缓冲,默认是服务器特定的。 -
autoFlush: 控制输出缓冲区满时是否自动刷新,默认通常是
true
,表示缓冲区满时内容会被立即写入客户端。 -
extends: 指定JSP页面编译后所继承的Java类,允许自定义JSP页面的行为,但这会影响性能且不常见。
-
info: 提供关于JSP页面的描述性文本,可以被服务器用于记录或其他目的。
include
静态包含
-
语法
<%@include file="relativeURL" %>
-
特点:
-
静态包含使用JSP指令(
<%@ include %>
)实现,指定一个相对URL来包含另一个文件。 -
在JSP页面转换为Servlet源代码的过程中,被包含的文件内容会被直接插入到当前JSP页面中,形成一个单一的Servlet源文件。这意味着在编译阶段就已经完成了包含操作。
-
因此,静态包含的几个文件最终会被合并成一个大的Servlet类,执行效率较高,但不适用于包含动态变化的内容。
-
如果被包含文件和包含文件中有重复的声明(如变量声明、指令等),可能会导致编译错误。
-
动态包含
-
语法:
<jsp:include page="relativeURL" flush="true" />
-
特点:
-
动态包含使用JSP标准动作标签(
<jsp:include>
)实现,同样指定一个相对URL来包含文件。 -
动态包含不是在编译阶段完成的,而是在请求处理阶段,每当请求到达包含该标签的页面时,服务器会单独处理被包含的文件,然后将其输出合并到响应中。
-
这意味着每个请求时都会检查被包含文件的变化,适合包含那些可能随时间或不同请求而变化的内容。
-
支持传递参数给被包含页面,因此可以在包含时动态地控制被包含内容,适用于需要数据交互或个性化处理的场景。
-
动态包含会导致额外的处理开销,因为每次请求都需要单独处理被包含的资源。
-
taglib
引入和定义自定义标签库(Tag Library)的指令标签。
语法:
<%@ taglib uri="库的URI" prefix="自定义前缀" %>
-
uri:这是必须的属性,用于指定标签库的统一资源标识符(URI)。这个URI指向一个描述标签库的TLD(Tag Library Descriptor)文件,该文件包含了关于标签库的所有信息,如标签名、属性等。
-
prefix:这也是必须的属性,用于为引入的标签库定义一个简短的前缀。在JSP页面中使用该标签库中的标签时,需要通过这个前缀来调用。例如,如果前缀是
myTags
,则使用该库中的一个标签时会像这样编写:<myTags:myCustomTag />
。
示例:
假设有一个自定义标签库的URI为/WEB-INF/mytags.tld
,并且我们想给它定义前缀为mt
,则在JSP页面顶部可以这样声明:
<%@ taglib uri="/WEB-INF/mytags.tld" prefix="mt" %>
之后,在页面中就可以使用mt:
前缀来调用该库中的标签了,比如
<mt:myCustomTag someAttribute="value" />
请求转发与重定向
forword
-
内部处理:请求转发发生在服务器端,是一个内部过程。当服务器接收到客户端的请求后,使用
RequestDispatcher
的forward()
方法将请求转发给另一个资源(如Servlet、JSP页面)进行处理,然后再将处理结果返回给客户端。整个过程对客户端透明,客户端并不知道中间的转发过程。 -
请求次数:仅一次请求。客户端发送一个请求,服务器处理并完成转发,不会引发新的请求。
-
URL地址栏:不变。浏览器地址栏显示的是客户端最初请求的URL。
-
数据共享:转发过程中,请求对象(
HttpServletRequest
)和响应对象(HttpServletResponse
)保持不变,因此可以在转发前后的资源间共享数据,如request作用域中的属性。 -
效率:因为没有额外的网络往返,所以请求转发通常效率更高。
-
功能限制:只能在同一个Web应用内部转发请求,不能直接跳转到外部资源或不同应用的资源。
sendRedirect
-
客户端行为:重定向是由服务器向客户端(通常是浏览器)发送一个特殊的状态码(通常是302 Found或303 See Other),指示客户端浏览器发起一个新的请求到指定的URL。这意味着重定向是客户端行为,需要两次请求/响应过程。
-
请求次数:两次请求。首先客户端发起初始请求,服务器响应一个重定向指令,然后浏览器依据该指令发送第二个请求到新URL。
-
URL地址栏:改变。在重定向后,浏览器地址栏显示的是重定向的目标URL。
-
数据共享:因为涉及到两个独立的请求,所以无法直接在重定向前后共享request作用域中的数据。数据需要通过其他方式(如session、cookies或URL重写)传递。
-
效率:重定向比转发慢,因为它涉及到至少两次网络请求。
-
功能灵活:可以重定向到任何位置的资源,包括同一应用的不同页面、不同应用、甚至是完全不同域名的网站。