【Java.Web】JSP —— 语法基础 —— 包含include

  • 在JSP 指令中,可以通过include指令来包含其他文件的方法,include指令的语法为:

<%@ include file="被包含组件的绝对或相对URL" %>


  • 除了使用include指令,还可以使用include标签来包含其他文件,include标签的语法为:

<jsp:include page="被包含的组件的绝对或相对URL" />



include指令用于静态包含;而include标签用于动态包含

无论是静态包含还是动态包含,源组件和被包含的目标组件都共享请求范围内的共享数据。


静态包含

假设源JSP文件为include_source.jsp,被包含的目标JSP文件为include_destination.jsp。

当客户端请求访问源JSP时,JSP容器按照一下流程响应客户请求:

  • 解析源JSP文件include_source.jsp;在解析<%@ include file="include_destination.jsp" %>时,把目标JSP文件include_destination.jsp的所有的源代码融合到include_source.jsp中。
  • 把融合后的JSP源代码翻译为Servlet源文件,再把它翻译成为Servlet类。
  • 初始化源JSP文件include_source.jsp对应的Servlet,再运行它的服务方法。


由此可见,静态包含发生在解析JSP源组件阶段,被包含的目标文件中的内容被原封不动地添加到JSP源组件中,Servlet容器然后再对JSP源组件进行翻译和编译。

静态包含的目标组件可以为HTML文件或者JSP文件,但不允许为Servlet。

如果目标组件为JSP文件,那么该JSP文件可以访问在源组件中定义的局部变量,因为实际上JSP源组件和JSP目标组件对应的是同一个Servlet。


为了区分JSP源组件及被静态包含的JSP或HTML目标组件,可以将静态包含的JSP文件用“*.jspf”作为文件扩展名,被静态包含的HTML文件用“*.htmf”作为文件扩展名;或者被静态包含的JSP或HTML文件都用“.inc”作为文件扩展名。


示例:

include_source.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Static Include Source JSP</title>
</head>
<body>
    <%  int var = 1;
        request.setAttribute("username", "New User"); %>
        
    The output is from include_source.jsp before include include_destination.jsp <br/>    
    <%@ include file="include_destination.jsp" %>
    The output is from include_source.jsp after include include_destination.jsp <br/>    
    
</body>
</html>


include_destination.jsp

<p>
    Output is from include_destination.jsp<br/>
    
    var = <%= var %><br/>
    username = <%= request.getAttribute("username") %><br/>
</p>


【Java.Web】JSP —— 语法基础 —— 包含include_第1张图片

在浏览器中访问如下URL:

http://localhost:8080/base-webapp/jsp/include_source.jsp

浏览器显示为:

【Java.Web】JSP —— 语法基础 —— 包含include_第2张图片


动态包含

将源组件include_source.jsp中的include指令改为:

<%-- 
    <%@ include file="include_destination.jsp" %>
--%>
    <jsp:include page="include_destination.jsp" />


在浏览器中访问上面的URL,将会得到一个编译错误,变量var无法解析。


这是因为对于动态包含,目标组件和源组件分别对应不同的Servlet,两个不同的Servlet之间无法访问对方的服务方法中的局部变量

在<CATALINA-HOME>/work目录下,会发现对应目标组件的Servlet类未生成对应的class文件:

【Java.Web】JSP —— 语法基础 —— 包含include_第3张图片



当客户端首次请求访问源组件include_source.jsp时,JSP容器按照以下流程响应客户请求:

  • 解析include_source.jsp并把它翻译为Servlet源文件,include_source.jsp中的<jsp:include page="include_destination.jsp" />被翻译成如下程序代码:

org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "include_destination.jsp", out, false);

  • 把Servlet源文件编译为Servlet类。
  • 初始化与include_source.jsp对应的Servlet,再运行它的服务方法。
  • 当Servlet容器执行上面生成的include方法时,会解析include_destination.jsp。
  • 如果没有语法错误,那么把include_destination.jsp翻译为Servlet源文件,再编译Servlet源文件。假定无编译错误,将生成Servlet类,再初始化该Servlet并调用它的服务方法。

  • 当Servlet容器执行完源JSP组件的include方法后,继续执行源JSP组件后面的代码。

由此可见,动态包含发生在运行JSP源组件阶段,动态包含的目标租金啊可以为HTML文件,JSP文件,或者为Servlet。如股票目标组件为JSP,Servlet容器会在运行JSP源组件的过程中,运行与JSP目标组件对应的Servlet的服务方法。

JSP目标组件生成的响应结果被包含到JSP源组件的响应结果中



<jsp:include>标签还有一个flush属性,可选值为true和false,如果flush属性为true,就表示源组件在包含目标组件之前,先把已经生成的响应正文提交给客户;flush属性默认为false。

将上面的动态包含语句改为:

<jsp:include page="include_destination.jsp" flush="true" />


再次在浏览器中请求访问该JSP,则浏览器显示为:


而生成的错误将被写到容器的log中。



将目标JSP组件改为:

<p>
    Output is from include_destination.jsp<br/>
    <%--
    var = <%= var %><br/>
    --%>
    
    username = <%= request.getAttribute("username") %><br/>
</p>

再次访问,浏览器显示为:

【Java.Web】JSP —— 语法基础 —— 包含include_第4张图片

无错误产生。



混合使用静态包含和动态包含

静态包含通常用来包含不会发生变化的网页内容;而动态包含通常用来包含会发生变化的网页内容。


目标组件路径值的区别:

  • 在动态包含中,我们可以通过表达式<%=detinationjsppath_variable%>指定page的值,如:

<jsp:include page="<%=bodyfile%>" />


  • 而对于include指令,如果使用类似的方法,Servlet容器会把字符串“<%=bodyfile%>”的字面内容直接理解为一个目标组件的URL,而且由于找不到相应的目标组件,会导致一个错误:

<%@ include file="<%=bodyfile%>" %>






你可能感兴趣的:(java,Web)