`
Aether
  • 浏览: 13932 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

JSP拾遗(五)——jsp文件包含指令

    博客分类:
  • Java
阅读更多

<%@include file=”fileName” %> <jsp:include flush="true" page="fileName"> 

 

    看到很多教程已经面试中都对jsp中的两个文件包含指令比较纠结,这里就特别对这两个指令做一个比较直观的对比。

   

    参数指定:filename不带路径时默认为当前页目录,如果设置目录,则需以应用的根目录设置地址。jsp:include中的参数flush必须为true,因为在jsp1.1false是一个无效的设定值。

   

下面示例,先看一下<%@include %>的处理方式:修改MyJsp.jsp,内容如下:

<html>
  <body>
    This is my first JSP! <br/>
    <%
    	String test ="This is a test value!";
    %>
    
    Here is include a jsp file, named include.jsp.<br/>
    <%@ include file="include.jsp" %>
  </body>
</html>


新建一个include.jsp,内容如下:

 

<!-- start of include.jsp -->
<html>
  <body>
    This is the include jsp.<br/>
    Here will print the String "test" if it's existing. </br>
    test = <%= test%>
  </body>
</html>
<!-- end of include.jsp --> 

 

浏览器上刷新MyJsp.jsp页面。我们可以看到,页面输出结果为:

This is my first JSP! 
Here is include a jsp file, named include.jsp.
This is the include jsp.
Here will print the String "test" if it's existing. 
test = This is a test value!

 

由结果可以看出,Myjsp.jsp中不仅输出了include.jsp文件中的内容,而且include.jsp中程序代码也共用了MyJsp.jsp中所定义的字符串test打开work下的源文件目录,我们可以发现,目录下面并没有include_jsp.java文件。打开MyJsp_jsp.java文件:

 

 

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class MyJsp_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static java.util.Vector _jspx_dependants;

  static {
    _jspx_dependants = new java.util.Vector(1);
    _jspx_dependants.add("/include.jsp");
  }

  public java.util.List getDependants() {
    return _jspx_dependants;
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("<html>\r\n");
      out.write("  <body>\r\n");
      out.write("    This is my first JSP! <br/>\r\n");
      out.write("    ");

    	String test ="This is a test value!";
    
      out.write("\r\n");
      out.write("    \r\n");
      out.write("    Here is include a jsp file, named include.jsp.<br/>\r\n");
      out.write("    ");
      out.write("<!-- start of include.jsp -->\r\n");
      out.write("<html>\r\n");
      out.write("  <body>\r\n");
      out.write("    This is the include jsp.<br/>\r\n");
      out.write("    Here will print the String \"test\" if it's existing. </br>\r\n");
      out.write("    test = ");
      out.print( test);
      out.write("\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
      out.write("<!-- end of include.jsp -->");
      out.write("\r\n");
      out.write("  </body>\r\n");
      out.write("</html>");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          out.clearBuffer();
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

 

java代码中可以看到,include.jsp中的内容被直接插入到MyJsp.jsp中输出,这个操作过程相当于直接把include.jsp的内容复制到MyJsp.jsp的相应位置,因此include.jsp可以和MyJsp.jsp直接共享所有的对象,和在同一个页面中编码一样。这里应该注意的是,include.jsp中的代码是始终包含在MyJsp.jsp中的,即使把<%@ include %>放在MyJsp.jsp的最末一行,在生成的java文件中,include的内容也将包含在一个_jspService()方法中。因此include.jsp中对公共对象的设置都会对Myjsp.jsp产生影响,特别是当include.jsp中调用response.getOutputStream()输出并关闭输出流后,如果不重新打开输出流,将会引起OutputStream is already closedIO异常。

 

 

MyJsp.jsp中的包含更改成jsp:include:

 

<html>
  <body>
    This is my first JSP! <br/>
    <%
    	String test ="This is a test value!";
    %>
    
    Here is include a jsp file, named include.jsp.<br/>
    <jsp:include flush="true" page="include.jsp" %>
  </body>
</html>

 

再次刷新MyJsp.jsp页面,结果显示如下: 

This is my first JSP! 
Here is include a jsp file, named include.jsp.

 

Include.jsp的内容并没有显示出来,查看tomcat控制台我们可以看到,有异常报出: 

2009-7-12 18:47:45 org.apache.jasper.compiler.Compiler generateClass
严重: Error compiling file: /D:/Program/Java/Tomcat5/work/Catalina/localhost/test//org/apache/jsp\include_jsp.java     [javac] Compiling 1 source file

D:\Program\Java\Tomcat5\work\Catalina\localhost\test\org\apache\jsp\include_jsp.java:48: 找不到符号
符号: 变量 test
位置: 类 org.apache.jsp.include_jsp
      out.print( test);
                 ^
1 错误

  

 

    这里提示test变量未定义。打开work下源代码目录,我们可以查找到include_jsp.java文件,但找不到include_jsp.class文件,因此在编译时出现了异常。很显然,用jsp:include时,所包含的jsp文件不能共用调用者的对象,并且本身就会编译成java类。

 

查看MyJsp_jsp.java文件,我们发现,这里关于include.jsp的调用,只有一句代码

 

 

 

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

 

很明显,jsp:include只调用一个工具方法来显示被包含文件的显示结果。两者的代码互不影响(当然,有三个对象还是传递了过去,你可以在include.jsp中改变这几个对象的属性值),因此include.jsp中的异常并不会影响到MyJsp.jsp文件的正常显示。

 

介于jsp:include并不能与调用者共享自定义的对象,当调用者需要向被包含页面传入参数时,需要使用<param >标签来传入参数,并在被包含页用request.getParameter()方法来获取。将MyJsp.jsp修改一下: 

<html>
  <body>
    This is my first JSP! <br/>
    <%
    	String test ="This is a test value!";
    %>
    
    Here is include a jsp file, named include.jsp.<br/>
    <jsp:include flush="true" page="include.jsp">
    	<jsp:param name="test" value="<%=test %>"></jsp:param>
    </jsp:include>
  </body>
</html>

 

include.jsp更改为:

<!-- start of include.jsp -->
<html>
  <body>
    This is the include jsp.<br/>
    Here will print the String "test" if it's existing. </br>
    test = <%= request.getParameter("test")%>
  </body>
</html>
<!-- end of include.jsp -->

  

    刷新MyJsp.jsp,页面即正常显示了。Html: 

This is my first JSP! 
Here is include a jsp file, named include.jsp.
This is the include jsp.
Here will print the String "test" if it's existing. 
test = This is a test value

综合上面比较可以看出,<%@ include %>包含文件时,相当于直接把被包含的文件的内容插入到包含页里面,因此被包含页的每次更新,就会导致所有包含页的全部重新编译,而被包含页并不会主动被编译,可以称之为jsp编译指令。而<jsp:include>则相当于直接调用被包含页的输出结果,被包含页的任意更新并不会导致包含页重新编译,可以称之为jsp运行时调用。这也引出了一个几乎所有教程中都会提到的一个结论:在包含不会经常修改到页面时,应使用<%@include %>,在包含经常修改到的页面时,应使用jsp:include。这里的修改指的是文件本身的修改,在实际系统应用中,网站的前台页面因样式等原因修改的几率比较大,因此应该使用jsp:include,那些以html静态页和jsp动态页来区分使用哪个include的方式,显然是错误的。

分享到:
评论
1 楼 Aether 2009-07-12  
Here is include a jsp file!
This is the include jsp!
大家BS我的烂E文吧

相关推荐

Global site tag (gtag.js) - Google Analytics