JSP静态包含和动态包含的区别

 

1、什么是包含?

  包含就是Servlet容器将其他Web组件(Jsp、Servlet、Html),将生成的结果包含到自己的结果中。

 

2、为什么需要包含?

  Servlet对象是由Servlet容器创建,Servlet对象的Service()方法是由servlet容器调用,Servlet之间是不允许相互调用的(Servlet API 2.1以前版本可以)。但又是我们不得不通过多个Servlet组件处理任务,同时方便代码维护管理,提高开发效率。这样就可以需要Servlet转发和包含的技术支持。

 

3、Jsp页面包含的三种方式

(a)、include指令

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


(b)、include标签
    语法一:
    <jsp:include page="被包含主组件的绝对URL或相对URL"/>
    
    语法二:
    <jsp:includepage="login.jsp">
        <jsp:param name="name" value="userName"/>
        <jsp:param name="password" value="userPassword"/>
    </jsp:include>


(c)、JSTL标签(不介绍)

    <c:import url="http://www.sina.com/index.html"/>

 

4、包含类型

包含主要分为静态包含和动态包含,include指令用于静态包含、include标签用于动态包含。无论是静态包含还是动态包含,源组件和被包含的目标组件都共享请求范围内的共享数据。

  • 头部Jsp代码
<%request.setAttribute("name","LaoYe"); %>
<%request.setAttribute("age","20"); %>

这是头部 header<b>.jsp</b> 的内容<hr/>
  • 主页Jsp代码
<!DOCTYPE HTML>
<html>
  <head>
    <title>首页</title>
  </head>
  <body>
        //静态包含
        <%@ include file="header.jsp" %>
  		
    	这是首页index.jsp内容<br/>
    	
    	Name = ${name}
    	age = ${age}
    	sex = ${sex}
    	
        //动态包含
    	<jsp:include page="footer.jsp"/>
  </body>
</html>
  • 底部Jsp代码
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>底部</title>
  </head>
  <body>
    	<hr/>这是底部foot<b>.jsp</b>的内容
    	<%request.setAttribute("sex","男"); %>
  </body>
</html>
  • 最终结果

从结果我们可以看出sex的值我在footer.jsp设置了request域的sex值为男,但是最终的输出却为空的字符串,这是因为footer.jsp在最后动态包含时,程序从上往下执行时还未执行到这里,所以无法获取到sex的值。例如将上面的index.jsp稍作修改之后,得到如下结果。

<!DOCTYPE HTML>
<html>
  <head>
    <title>首页</title>
  </head>
  <body>
  		
    	这是首页index.jsp内容<br/>
    	
    	Name = ${name}	<br/>
    	age = ${age}	<br/>
    	sex = ${sex}
    	
    	<%@ include file="header.jsp" %>
    	<jsp:include page="footer.jsp"/>
  </body>
</html>

最终的结果如下所以,可以看出所有的值均为空字符,所以在包含时我们应该注意一下请求参数的位置

 

5、编译过程

运行Servlet容器之后访问页面,Servlet容器会将Jsp源代码编译成Servlet源文件,然后再把它编译成Servlet类。我们打开文件之后可以看到,include指令的静态包含完全的嵌入到了index.jsp页面中,而include标签的动态包含则通过调用JspRuntimeLibrary.include(request, response, "footer.jsp", out, false)方法来解析footer.jsp,如果没有语法错误,则会吧footer.jsp翻译成Servlet源文件,然后再编译Servlet源文件。

 

在Tomcat的Servlet源文件和Servlet类的文件目录中,存在如下文件

 

(a)、静态包含

文件中唯独没有header_jsp.java和header_jsp.class文件,再看上一张图可以发现。静态包含发生在解析JSP源组件阶段,被包含的目标文件中的内容被原封不动的添加到了JSP源组件中,Servlet容器然后再对JSP源组件进行翻译和编译。

注意:静态包含的目标组件可以为HTML文件或JSP文件,但不允许为Servlet。如果目标组件为JSP文件,那么该JSP文件可以访问再源组件定义的局部变量,因为实际上,JSP源组件和JSP目标组件对应同一个Servlet(即Servlet不能包含另一个Servlet,他们之间只存在调用关系,而不存在包含关系。静态包含中的源组件和目标组件都在同一个Servlet中)。

在静态包含时,我们应该要注意的一点是,Java代码片段里面不能重复出现相同的变量,否则程序将报错。

错误提示:

 

(b)、动态包含

当客户端首次请求访问index.jsp时,Tomcat解析index.jsp并将它翻译为Servlet源文件。index.jsp中的include标签被翻译为org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "footer.jsp", out, false)。当Servlet容器执行JspRuntimeLibrary.include(...)方法时,会解析index.jsp。如语法无误,则将footer.jsp翻译为Servlet源文件,在编译Servlet源文件。假定无编译错误,将生成Servlet类,再初始化该Servlet并调用它的服务方法。

当容器执行完JspRuntimeLibrary.include(...)方法后,继续执行index.jsp代表的Servlet的服务方法中的后续代码。

  • index.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML>
<html>
  <head>
    <title>首页</title>
  </head>
  <body>
  	<%System.out.println("header_jsp.java编译前");%>
  	<jsp:include page="header.jsp"/>
  	<%System.out.println("header_jsp.java编译后");%>
  </body>
</html>
  • header.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>底部</title>
  </head>
  <body>
	<%System.out.println("header_jsp.java编译中");%>
  </body>
</html>
  • 最终输出结果

  

 

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

在我们实际应用中,很少说一个页面只用静态包含或只用动态包含的。而是根基实际情况,对页眉页脚、导航栏之类的静态内容我们就用静态包含,对数据库实时查询、时间戳等动态内容我们就用动态包含。具体情况,具体使用,动静结合,灵活搭配。

 

7、总结

1、<%@include file="xxx.jsp"%>为jsp中的编译指令,其文件的包含是发生在jsp向servlet转换的时期,而<jsp:include page="xxx.jsp">是jsp中的动作指令,其文件的包含是发生在编译时期,也就是将java文件编译为class文件的时期 

2、使用静态包含只会产生一个class文件,而动态包含产生多个class文件 

3、使用静态包含,包含页面和被包含页面的request对象为同一对象,因为静态包含只是将被包含的页面的内容复制到包含的页面中去;而动态包含包含页面和被包含页面不是同一个页面,被包含的页面的request对象可以取到的参数范围要相对大些,不仅可以取到传递到包含页面的参数,同样也能取得在包含页面向下传递的参数

4、静态包含一般用于加载进页面显示后就再也不变的东西,比如页眉、背景、标题等等。静态包含不会检查所含文件的变化,把文件包含进来后,被包含文件的修改变化是不会影响已被包含进来的内容的。因为,静态包含发生在编译阶段。比如:a.jsp中使用了语句 <%@ include file="b.jsp"%>,把b.jsp包含了进来,那么在编译a.jsp文件时,会直接把b.jsp文件的内容全部内嵌到a.jsp文件中包含b的语句的位置。然后运行a,显示a页面。也就是说,静态include是先把被包含文件的内容全部复制内嵌到包含文件中,再进行编译运行的。也正是因为要把b包含进a,所以b中的变量等不能与a重复,否则会报错。

动态包含用于加载经常变化的、要求显示最新版本内容的东西,比如提交时间戳:用户打开博客编辑页面时,有一个时间加载进来了。用户编写完博客,点击提交时,就应该使用/显示提交瞬间的时间而不是打开编辑页面时的那个时间。所以这里要用的就是最新时间。由上面我们知道,静态include是先包含进来,再编译,运行并传回浏览器显示的,所以不能满足我们要求某些部分使用最新内容的要求。那么,我们就要用到动态include。

动态include与静态include的最大不同在于:包含文件与被包含文件都是先编译执行,再包含。二者的编译阶段是相互独立的,只有在包含文件的include语句处把被包含文件的执行结果包含进来。换言之,包含文件先编译,执行。执行到了include语句的时候才触发被包含文件的编译、执行,并实时把结果包含进来。从而达到获取最新的被包含内容的目的。同样使用a.jsp包含b.jsp的例子:加入a.jsp中动态include了b.jsp。现在,a先编译成servlet类文件,然后运行,当运行到包含b的语句处,引起b的编译,运行,并把b的运行servlet运行结果包含进a。最后a顺利运行完毕,把a的servlet类运行结果输出到浏览器显示。

 综上所述,我们可以一句话辨析静态include与动态include的区别:静态include是编译阶段的代码拼接,动态include是编译后的servlet的运行结果的拼接。

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值