JSP中的include 机制

来源:互联网 发布:mac os server 知乎 编辑:程序博客网 时间:2024/05/14 18:05
本文是新的 JSP 最佳实践系列文章的第一部分,它介绍了 JavaServer Pages include 机制。请跟随 Java 编程专家 Brett McLaughlin 学习如何使用 include 将静态的头文件和脚注文件加入您的网站或 Web 应用程序页面中。 
欢迎阅读 Java 专区中最新的最佳实践系列文章。如果您看过先前的系列文章,那么您会知道最佳实践旨在让您快速了解各种 Java 技术的有用方面。这一系列的最佳实践专门讨论 JavaServer Pages(JSP)技术,它是核心 J2EE 技术之一。 

简而言之,JSP 技术是在 Java 平台上构建 Web 页面或 Web 应用程序接口的工具。JSP 技术允许我们做如下事情:动态响应请求数据、显示复杂的 XML 和 HTML 以及创建生动有趣、动态驱动的网站。在本系列中,您将学习一些用 JSP 技术构建网站的基础知识。我将为您介绍最常用的 JSP 机制,通过这些机制,您将了解基本的 Web 开发技术,如制作模板、操作动态内容、图像托管、创建实用程序代码库等。 

本文是这一系列文章的第一篇,在本文中,我们将集中讨论 JSP include 机制,该机制允许我们“拉”入本地 HTML 页面的内容。我们将首先介绍有关 Web 页面 include 发展的一些背景知识,尤其是框架和服务器端 include 的使用。然后,我将向您演示如何使用 JSP include 机制将统一的头文件和脚注文件添加到 Web 页面或 Web 应用程序屏幕。 

· JSP 最佳实践系列 

本系列文章并不打算完整地介绍 JSP 技术,也不打算作为如何构建特殊类型应用程序的指南。相反,系列文章中的每个部分都集中讨论用 JSP 技术编程的某一个方面,将它分成很小的片段。有关 JSP 技术的更广泛介绍或者对如何将它用于特殊结果的更深入研究,请参阅参考资料部分。 
您将需要什么 
本系列文章中的所有最佳实践都基于 JavaServer Pages 技术。要运行任何一种实践,需要在本地机器或测试服务器上设置符合 JSP 的 Web 容器,如 Apache Tomcat。您还需要使用文本编辑器或 IDE 编写 JSP 页面代码。请参阅参考资料,获取 Tomcat 和与 JSP 兼容的 Web 容器和 IDE 的清单的链接。 

· 更好的外观 

为 Web 页面创建一致的设计和布局是确保获得专业化外观的最容易方法之一。您或许看过足够多的网站,知道单个站点中的大部分页面都共用统一的页面头、页面尾以及某种类型的导航栏。在设计良好的站点上,这些元素将在每个页面上呈现相同的布局、内容和功能,而主面板(通常称为内容窗格)会随着每个视图而变化。 

以前,这种布局几乎完全由框架和框架集实现。每段静态内容被放置在一个框架中,而页面的主体内容被放置在中间框架中。框架的麻烦就是不同的浏览器常常会以不同方式显示它们,使它们的外观不一致。使用框架从内部页面链接外部站点则比想像的更加困难。原本是想允许用户在不离开站点的情况下查看外部内容,但结果往往不一致。用户最终看到的是整个站点被挤进小得多的框架中,更糟的是,您的站点最终会嵌套在另一个站点框架中。这种混乱驱使 Web 设计者寻找一种更佳的解决方案。服务器端 include(server-side include,SSI)就是一种。 

· 服务器端 include 

不久前,SSI 还是用于创建共享内容的最受欢迎的选项之一。简单的 SSI 伪指令允许您创建包含另一个页面内容(如头和脚注文件)的页面,如清单 1 中所示。 

· 清单 1. 正使用的 SSI 

<![CDATA[ 
<html> 
<head> 
<title>Simple SSI test</title> 
</head> 
<body> 
This content is statically in the main HTML file.<br /> 
<!--#include virtual="included.html" --> 
</body> 
</html> 
]]> 

我们不久将使用该文件来做一个练习。目前,您应该将它另存为 test-ssi.shtml。在大多数设置中,SSI 文件必须以 .

shtml 结尾,这让 Web 服务器知道将它们解析为 SSI 伪指令。清单 2 显示了名为 included.html 的包含文件的内容。 

· 清单 2. 包含的内容 

<![CDATA[ 
This content is in another file, included.html 
]]> 

当请求 test-ssi.shtml 时,您将看到该文件的内容以及 included.html 的内容。您可以在任何支持 SSI 的 Web 容器(如 Apache Tomcat,请参阅参考资料)上查看这些文件。 

从用户角度看,SSI 与框架相比有重大改进,因为在单个文件和从其它被包含文件引进内容的文件之间没有显而易见的差别。不利方面就是 SSI 需要一种特定的服务器设置,而 Java 开发人员常常无法使用这种设置。另外,SSI 通常要求被包含内容是静态的,尽管在后面的版本中加入了动态内容包含。 

对于在网站或 Web 应用程序中包含不同类型的内容来说,SSI 是可行的解决方案,但它们不是 Java 开发人员的最佳选择。这不仅因为 JavaServer Pages 技术是替代 SSI 的全 Java 技术,还因为这两种技术不太容易结合在一起。JSP 页以扩展名 .jsp 结尾,这表示要使 SSI 伪指令起作用,必须更改 SSI 配置以解析 JSP 文件(给每个 JSP 页解析增加开销),或者更改 JSP 配置以将 .shtml 扩展名作为 JSP 页处理(这是一个坏主意)。对于 Java 开发人员来说,JSP 技术是最好的内容管理解决方案,幸运的是,其 include 机制很容易掌握。 

· JSP include 

JSP include 伪指令与其 SSI 对等伪指令极其相似。清单 3 显示了清单 1 所示的 SSI 伪指令的 JSP 对等伪指令。任何支持 JSP 的 Web 容器都将处理该 JSP 页的显示(同样,请参阅参考资料一节,以获得链接)。应该将该文件另存为 test-include.jsp。 

· 清单 3. JSP include 伪指令 

<![CDATA[ 
<%@ page language="java" contentType="text/html" %> 
<html> 
<head> 
<title>JSP include element test</title> 
</head> 
<body> 
This content is statically in the main JSP file.<br /> 
<%@ include file="included.html" %> 
</body> 
</html> 
]]> 

include 伪指令使将统一的头文件和脚注文件合并到您的站点变得非常容易。清单 4 显示了具有几个被包含文件的主索引页。 

· 清单 4. 主索引页的 JSP include 伪指令 

<![CDATA[ 
<%@ page language="java" contentType="text/html" %> 
<html> 
<head> 
<title>newInstance.com</title> 
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> 
<link href="/styles/default.css" rel="stylesheet" type="text/css" /> 
</head> 

<body> 
<%@ include file="header.jsp" %> 
<%@ include file="navigation.jsp" %> 
<%@ include file="bookshelf.jsp" %> 
<%@ include file="/mt-blogs/index.jsp" %> 
<%@ include file="footer.jsp" %> 

</body> 
</html> 
]]> 

通过查看代码,您将了解有关如何使用 JSP include 的各种方法。您还应该试验一下该代码,让自己掌握其工作原理。 

· 添加动态内容 

除了如头、脚注和导航文件之类的静态内容外,清单 4 还包括对 Weblog(/mt-blogs/index.jsp)的调用,这涉及动态内容的主题。如同 SSI include 伪指令那样,当 JSP include 机制应用于动态内容时会出现问题。可以通过使用 JSP include 伪指令来引入动态内容,但将无法获得对该内容的更改。这是因为 Web 容器将被包含文件作为原始(包含)页面的一部分读取。容器将结果高速缓存为单个文件,而不是多个 JSP 组件。因为 Web 容器不会针对更改去轮询被包含文件,所以它不会知道有任何更改发生,它将自动显示高速缓存的页面而不是刷新的页面。要了解它的工作原理,我们将做一个简单的练习。首先,将已保存的 included.html 页面更新为清单 5 中所示的那样。 

· 清单 5. 修改包含的内容 

<![CDATA[ 
This content is in another file, included.html. 
<br /> 
Some new content... 
]]> 

接下来,保存这些更改,导航至 test-include.jsp 文件,刷新浏览器。您将注意到浏览器中没有显示 included.html 中的新内容。被包含文件的内容在更改发生之前就被高速缓存了,所以它不会显示出来。如果您的站点包含动态内容或可能被频繁修改的内容,那么这会是一个问题。幸运的是,有一个变通方法。在下一个部分中,我将向您演示如何使用 <jsp:include> 标记将动态内容加入 Web 页面。在此之前,请参考参考资料一节并试验这里提供的代码,我将在网上与您再见。 

可以自动跳转到出错页面的servlet/jsp框架

jsp有一个指令可以定义jsp的错误页面,并在此jsp页面出错时跳转到该页面输出出错日志。如下的例子:

<%@ page errorPage="errorPage.jsp" %>errorPage.jsp的代码如下所示:.....<%@ page isErrorPage="ue" %>....//输出出错日志<%= exception.getMessage() %> 

但是,这只能在jsp页面层控制。在J2EE的实现中,很多的情况是jsp往往只作为页面显示,与业务相关的数据库操作都是在后台的servlet执行,处理完毕之后再跳转某个jsp显示页面。这种设置框架,实现了MVC结构,使得整个系统的维护难度大大降低。 

实际的工作中,尽管系统采用了以上的设置框架,但由J2EE开发人员水平以及编程的习惯都有可能不通,经常会遇到开发人员在servlet中对有可能报错的地方处理不恰当。最常见的一种情况是,catch一个Exception e,然后仅仅调用e.printStackTrace()。这样造成的后果非常严重。一旦有Exception发生,web页面会出现白屏,我们可以从两方面来看: 

(1)如果是使用的用户。他往往会不知所措,并且有可能还不知道有错误发生,继续使用系统,但这时候的系统已经出错了,在错误的基础上继续业务流程,往往会造成更多系统级别的错误。 

(2)如果是开发人员。用户反映了这个出错,但是不知道出错原因。只能说出现要白屏。开发人员需要调试抓错的话,非得到应用服务器的输入端查看出错日志,定位可能出错的原因,再进行排错。 

在此,我介绍一种有效的servlet出错处理机制,这种机制将所有Exception的出错内容抛出到web页面,让使用用户立即有错误发生,并可以及时将该出错内容提交给开发人员定位出错原因。 

其实,这种机制非常简单。思路是定义一个抽象的BaseServlet基类,它继承HttpServlet。 

并增加一个抽象的 
absact public void doWorkFlow(HttpServletRequest request,HttpServletResponse response)的方法,这个方法是所有BaseServlet子类都必须且仅需实现的方法。BaseServlet基类当然要实现service方法 -- 

public final void service(HttpServletRequest request,HttpServletResponse response)。它的代码片断如下: 

public final void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { y{ //在执行doWorkFlow()之前,你可以在此处理是否有权限处理等问题 ....... doWorkFlow(); }catch(Exception e){ SingWriter out = new SingWriter(); e.printStackTrace(new PrintWriter(out)); request.setAtibute("err_msg", out.toSing()); RequestDispatcher rd = this.getServletContext().getRequestDispatcher("errorServlet.jsp"); rd.forward(request,response); }} 
errorServlet.jsp非常简单。代码片断如下: 

....//输出出错日志<%= request.getAtibute("err_msg") %>