jsp最佳实践系列文章(IBM技术文库)

  今天前面两篇介绍jsp的日记实际均源自Java“知名人士”Brett McLaughlin 介绍jsp应用的系列文章,这里把网址收集在这里,有空的时候可以好好的来欣赏一下。顺便练习一下英语阅读能力。

  网址:http://www-128.ibm.com/developerworks/views/java/libraryview.jsp?search_by=JSP%20best%20practices:

  我的前两篇引用这里面文章的日记的地址:

  1、http://www.learndiary.com/disDiaryContentAction.do?goalID=1140

  2、http://www.learndiary.com/disDiaryContentAction.do?goalID=1141

问题:中“flush”的作用?缓冲区?

  这是一篇介绍用 jsp:include 控制动态内容的文章,但是,我对其中的“flush”参数的作用不清楚?以后可以慢慢解决。

 

  用 jsp:include 控制动态内容

 

  JSP 最佳实践:用 jsp:include 控制动态内容 英文原文

用于构建动态网站的简单 JSP 标记

级别:初级

Brett McLaughlin(brett@oreilly.com)

作家,O'Reilly and Associates

2003 年 7 月

本文是 Java“知情人士”Brett McLaughlin 继第一篇 JSP 最佳实践文章后的后续文章,在文中,作者向您演示了如何扩展 JSP 技术中用于动态内容的包含功能。了解静态 include 伪指令和动态 jsp:include 元素之间的差异,搞清楚如何混合搭配这二者以获取最优性能。

在新的 JSP 最佳实践系列的前一篇文章中,您了解了如何使用 JSP include 伪指令将诸如页眉、页脚和导航组件之类的静态内容包含到 Web 页面中。和服务器端包含一样,JSP include 伪指令允许某个页面从另一个页面提取内容或数据。清单 1 重温了 include 伪指令。

清单 1. 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>

]]>

您需要什么

本系列中的所有最佳实践都基于 JavaServer Pages 技术。要运行其中的任何最佳实践,都需要在您的本地机器或测试服务器上安装符合 JSP 技术的 Web 容器。您还需要使用文本编辑器或 IDE 来对 JSP 页面编码。

虽然 include 非常适于将静态内容并入 Web 页面,但对于动态内容却不尽如人意。我们在前一篇文章中在试图重新装入高速缓存文件时发现了这一问题。与大多数页眉文件及页脚文件不同,动态内容变化频繁,必须时刻更新。我们将首先扼要地重述一下 include 伪指令的局限性,然后我将向您演示如何用 jsp:include 标记来扩展 JSP 的包含能力。

高速缓存问题

JSP include 伪指令的不足之处有一个是:它会导致 Web 浏览器高速缓存所有页面。在处理诸如页脚、版权声明或一组静态链接之类的静态组件时,这是有意义的。这些文件不会改变,因此没有理由让 JSP 解释器不断地重新轮询其中的数据。凡是可能的地方,都应该实现高速缓存,因为它改善了应用程序的性能。

JSP 测试和开发

在构建 Web 应用程序或网站时,可能需要大量更新页眉、页脚和导航链接。仅仅为了看到对所包含文件所做的更改,而被迫不断地关闭浏览器或清除其高速缓存,这可能是件痛苦的事情。另一方面,为了结束开发周期,而不得不彻底检查一遍并修改数百个使用了 include 伪指令的页面,这也是一件痛苦的事情。我的建议是,在测试期间禁用浏览器高速缓存。在大多数情形下,这样做能够彻底解决问题。也有极少数情形,这样做并不奏效,这时可以在浏览器或服务器上不断地重新启动 Web 容器来确保不进行高速缓存。

但是,有时侯,进行高速缓存会得不偿失。如果提入的内容来自使用动态数据(如 Weblog 或数据库驱动的 JSP 文件)的程序,甚至如果所包含的内容是经常变化的 HTML(如时间戳记),那么每当装入 Web 页面时,都需要显示这些文件或程序的最新版本。遗憾的是,JSP include 伪指令并不具备这一功能。在测试和开发周期(请参阅侧栏“JSP 测试和开发”)中,在浏览器中禁用高速缓存通常能够解决这一问题。但是,对于实际使用的应用程序而言,性能是任何设计决策过程中的一项重要因素,禁用高速缓存并不是一种可行的长远之计。更好的解决方案是使用 jsp:include 标记。

jsp:include 标记

jsp:include 只不过是一个不同于 include 的伪指令而已。jsp:include 的优点在于:它总是会检查所含文件中的变化。过一会儿我们将研究这一新标记的工作方式。但首先看一下两种 include 各自的代码,以便能够看到二者之间的异同。

清单 2 显示了一个简单页面,它使用了原始的 JSP include 伪指令。

清单 2. 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>

]]>

清单 3 是同一个页面,只不过这里转成使用 jsp:include 标记。

清单 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 />

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

</body>

</html>

]]>

您应该注意这两种代码类型之间的两大区别。首先,jsp:include 元素不使用属于 include 伪指令的 %@ 语法。实际上,jsp 前缀让 JSP 编译器知道:它应该寻找标准 JSP 标记集中的元素。其次,指定要包含的文件的属性从 file 变成了 page。如果愿意,可以自己测试一下新标记的结果。只需更改上一篇文章(请参阅参考资料)中 included.html 文件的内容,然后重新装入浏览器页面,就会立即看到新内容。

flush 属性

您可能已注意到 jsp:include 代码示例中的 flush 属性。顾名思义,flush 指示在读入包含内容之前是否清空任何现有的缓冲区。JSP 1.1 中需要 flush 属性,因此,如果代码中不用它,会得到一个错误。但是,在 JSP 1.2 中,flush 属性缺省为 false。由于清空大多数时候不是一个重要的问题,因此,我的建议是:对于 JSP 1.1,将 flush 设置为 true;而对于 JSP 1.2 及更高版本,将其设置为关闭。

jsp:include 是如何工作的

如果您有点爱刨根问底,那么可能十分想知道 jsp:include 标记的行为为什么与 include 伪指令不同。道理其实十分简单:jsp:include 包含的是所包含 URI 的响应,而不是 URI 本身。这意味着:对所指出的 URI 进行解释,因而包含的是生成的响应。如果页面是 HTML,那么将得到一点也没有变化的 HTML。但是,如果是 Perl 脚本、Java servlet 或者 CGI 程序,那么得到的将是从该程序解释而得的结果。虽然页面通常就是 HTML,但实际程序恰好是达到目的的手段。而且,由于每次请求页面的时候都会进行解释,因此从来不会象使用 include 伪指令时那样高速缓存结果。虽然这只是很小的变动,但它却导致了您所见到的行为中的全部差异。

一种混合搭配的解决方案

include 伪指令在某些网站上有其用武之地。例如,如果站点包含一些(如果有变化,也很少)几乎没有变化的页眉、页脚和导航文件,那么基本的 include 伪指令是这些组件的最佳选项。由于 include 伪指令采用了高速缓存,因此只需放入包含文件一次,其内容就会被高速缓存,其结果会是极大地提高了站点的性能。

然而,对于现在许多 Web 应用程序或站点而言,地毯式的高速缓存并不能解决问题。虽然页眉和页脚可能是静态的,但是不可能整个站点都是静态的。例如,从数据库提取导航链接是很常见的,并且许多基于 JSP 技术的站点还从其它站点或应用程序上的动态 JSP 页面提取内容。如果正在处理动态内容,那么需要采用 jsp:include 来处理该内容。

当然,最好的解决方案是经常把这两种方法混合搭配使用,将每种构造用到最恰当的地方。清单 4 是混合搭配包含解决方案的一个示例。

清单 4. 混合搭配解决方案

<![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>

<jsp:include page="header.jsp" flush="true">

<jsp:param name="pageTitle" value="newInstance.com"/>

<jsp:param name="pageSlogan" value=" " />

</jsp:include>

<%@ include file="/navigation.jsp" %>

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

<jsp:include page="/mt-blogs/index.jsp" flush="true" />

<%@ include file="/footer.jsp" %>

</body>

</html>

]]>

上面的代码显示了前一篇文章中的示例索引页面。导航链接和页脚是静态内容,一年最多更改一次。对于这些文件,我使用了 include 伪指令。内容窗格包含 Weblog 和“bookshelf”组件,它们是动态生成的。这两个组件需要一直更新,因此对它们,我使用了 jsp:include 标记。header.jsp 文件有点奇怪。这个组件是从另一个本质上是静态的 JSP 页面提取的。但是,正如您将注意到的那样,它从包含页提取页“标语”,然后将它显示出来。要处理这一共享信息,我们必须向页眉文件传入参数。而要处理那些参数,就必须使用 jsp:include 元素。

如果您想了解有关那些参数的内容,请放心,后续文章不久就将能满足您的需要。在下一篇文章中,我将解释 JSP 参数以及它们是如何与 JavaBeans 组件交互的。届时,我们网上见。

 

jsp页面间传递参数(转自网络)

  我想在几个jsp页面间接力传递一个LinkedList参数,这个参数在经过不同的页面时会发生变化。我在网络上发现了实现这种应用的两种方法,特地把它贴在这里备忘:

  第一种方法,使用jsp内置的Session对象来传递:(转自:http://www.7880.com/Info/Article-4616cf60.html)

JSP学习笔记(六)-----在多个JSP页面之间传递参数【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2005-02-20 人气:4084 出处:CSDN

 

1.       怎么在多个JSP页面之间进行参数传递?需要使用JSP的内置作用域对象session。利用它的两个方法setAttribute(),getAttribute()

2.       下面的这个实例实现了把第一个JSP页面的参数传递给第三个页面的功能

3.       代码如下:1.jsp

<html>

       <form method=get action=2.jsp>

       what's your name<input type=text name=username>

       <input type=submit value=submit>

       </form>

</html>

 

4.       2.jsp

<html>

      

       <form method=post action="3.jsp?pass=11">

       <%

              String name=request.getParameter("username");

              session.setAttribute("username",name);

       %>

       Your name is:<%=request.getParameter("username")%>

       <br>what's your hobby<input type=text name=hobby>

       <input type=submit value=submit>

       </form>

</html>

 

5.       3.jsp

<html>

       your name is:<%=session.getAttribute("username")%>

       <br>

       your hobby is:<%=request.getParameter("hobby")%>

       <br>

       your password is:<%=request.getParameter("pass")%>

       <br>

       </form>

</html>

   第二种方法,利用JavaBean和JSP技术在Web页面中保存和传递数据,(转自:http://www.cnblogs.com/bjzhanghao/archive/2004/08/07/30950.html)

[翻译]JavaBean组件与JSP技术结合

Web架构师Brett McLaughlin向我们展示了怎样利用JavaBean和JSP技术在Web页面中保存和传递数据,以及如何设计可以得到更大的灵活性。

到目前为止,在JSP最佳实践系列里,我们已经讨论了相当一部分基础知识。在前面的两个章节里,你应该学会了如何使用JSP的include机制将网站以外的内容包含在页面或应用程序里。共有两种不同类型的include:静态的include命令和动态的jsp:include标记。

同时,我们还没有涉及到在父页面(在我们的例子中是网站的首页)和被包含内容之间的通信问题。而实际上这种情况是非常普遍的。当你开始建立一个真正的网站或者web应用程序时,通常你会需要这样的通讯机制,举个例子,你的网站可能会在首页产生一些标题一类的小段文字,这些文字要出现在页眉或页脚页面中。在这一部分里,你将学到如何在页面间传递数据,以及如何在被包含的页面中使用这些数据。

注:这部分的全部例子都基于JavaServer Pages技术,为了能运行它们,你需要建立一个JSP兼容的web容器,在你本地计算机或某个用于测试的服务器上都可以。同时,你还要有一个文本编辑器或者集成环境来编写你的JSP页面。

用于保存数据的JavaBean

让我们假想这样的一个网站,在这个网站里每个页面有一小句“口号”(例如“书:装满知识的容器”或者“唱片:值得一听”)和一个标题。父页面(有时也被称作主页面)决定了每一页的口号,但真正产生html输出这个口号的是页眉页面,它是被包含的。要实现这个目的,父页面必须能够把口号传递给页眉页面,页眉页面得到这个口号,将它以页面标题的形式输出。

首先我们需要某种对象来保存被传递的数据,恰好(这并非偶然)JavaBean组件就是这样一个合适的选择,它与JSP技术配合得天衣无缝,简单的使用取值方法和赋值方法就可以控制你要的数据。稍有java编程经验的读者可能已经想到,get()就是一个取值方法,因为它读取数据;而set()是一个赋值方法,因为它改变数据。

列表1展示了我们所需要的一个JavaBean的代码,PageHeaderinfo包含了网站页眉信息。

<![CDATA[

package com.newInstance.site.beans;

import java.io.Serializable;

public class PageHeaderInfo implements Serializable {

     /** The title of the page */

     private String pageTitle;

     /** The slogan of the page */

     private String pageSlogan;

     public String getPageTitle() {

       return pageTitle;

     }

     public void setPageTitle(String pageTitle) {

       this.pageTitle = pageTitle;

     }

     public String getPageSlogan() {

       return pageSlogan;

     }

     public void setPageSlogan(String pageSlogan) {

       this.pageSlogan = pageSlogan;

     }

}

]]>

作为第一个练习,将这个文件保存为PageHeaderInfo.java并编译它。接下来,把得到的class文件PageHeaderInfo.class放在你的web应用程序的WEB-INF/classes目录下。请确保目录包含了包的结构,例如:

$<TOMCAT-ROOT>/webapps/$<WEB-APP-NAME>/WEB-INF/classes/com/newInstance/  site/beans/PageHeaderInfo.class

你可以使用类似这样的路径安排web应用程序中用到的类。按以上步骤做到这里,下面就可以向PageHeaderInfo里存入数据然后在不同的JSP页面中获取了。

传递已保存的数据

在我们的网站里,页眉页面包含向不同页面传递不同口号的代码。查看前面的章节就会发现,页眉页面(header.jsp)是通过jsp:include标记被包含的文件。列表2展示了网站首页如何通过标记把数据传递给header.jsp文件。

<![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>

<jsp:include page="header.jsp" flush="true">

     <jsp:param name="pageTitle" value="newInstance.com"/>

     <jsp:param name="pageSlogan"

       value="Java and XML :: Turning theory into practice" />

</jsp:include>

<%@ include file="/navigation.jsp" %>

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

<jsp:include page="/mt-blogs/index.jsp" flush="true" />

<%@ include file="/footer.jsp" %>

</body>

</html>

]]>

可以看出,标题是被传递过去作为口号的。

你可能已经注意到了,在你建立页面的时候,不一定需要JavaBean组件实际存在。我总是先写好JavaBean,有一个很好的理由:JSP参数名必须与JavaBean属性名匹配,先完成JavaBean可以保证你在编写JSP页面时使用合适的参数名称。

获得数据

当你完成了JSP参数和JavaBean属性的编码,一旦数据被传递给header.jsp,这个页面就可以开始获取数据了。列表3展示了header.jsp页面。它的大部分内容是html,请注意里面的JSP脚本,在你研究过这些代码后我会在后面向你解释。

<![CDATA[

<!-- Begin header section -->

<%@ page language="java" contentType="text/html" %>

<jsp:useBean id="pageHeaderInfo"

class="com.newInstance.site.beans.PageHeaderInfo">

     <jsp:setProperty name="pageHeaderInfo" property="*" />

</jsp:useBean>

<table width="100%" border="0" cellspacing="0" cellpadding="0">

     <tr>

       <td width="91" height="50" align="right" valign="top"

           bgcolor="#330066"><font color="#FFFFFF"><img

           src="/images/header-lions.gif"

           width="90" height="60"></font></td>

       <td colspan="3" align="left" valign="top"

           bgcolor="#000000"><table width="100%" height="60" border="0"

           cellpadding="0" cellspacing="0">

           <tr>

             <td width="261" rowspan="2"><img

               src="/images/header-title.gif" width="261" height="60"></td>

             <td class="pagetitle" width="249" height="55" align="right"

               valign="bottom"><jsp:getProperty name="pageHeaderInfo"

               property="pageSlogan"/></td>

             <td width="10" height="55"> </td>

           </tr>

           <tr>

             <td height="5"><img src="/images/spacer.gif" width="1"

               height="5"></td>

             <td height="5"><img src="/images/spacer.gif" width="1"

               height="5"></td>

           </tr>

         </table></td>

       <td width="141" bgcolor="#000000">

         <font color="#FFFFFF"> </font>

       </td>

     </tr>

<!-- End header section -->

]]>

第一行代码标识了该页面为一个JSP页面,然后通过jsp:useBean标记声明需要访问PageHeaderInfo这个JavaBean,id属性为这个bean指定了一个名称,通过该名称可以在JSP页面中使用bean;class属性指定了JavaBean类的全名。相邻的jsp:setProperty标记说明了JavaBean(通过id属性标识)的所有属性都以请求数据赋值,也就是说,为这个bean里的每个属性(例如pagetitle和pageslogan)寻找名称对应的请求参数来赋值。这些请求参数可以来自客户端的浏览器,也可以来自包含这一页的其他JSP页面。在这种情况下,唯一的请求数据是由父页面创建的。对于我们的网站,首页(index.jsp)发送pagetitle和pageslogan,其值分别为“newinstance.com”和“Java and XML: Turning theory into practice”。

一旦bean的属性被赋值后,页面就可以使用这些数据了。对于header.jsp,在后面的代码里可以看到,通过jsp:getProperty标记使用了这些数据。Jsp;getProperty标记通过name参数标识从哪个对象取数据,通过property参数标识取对象的哪一个属性。取得的数据值自动插入到页面的输出,也就是输出到父页面里,从而得到一个无缝的、动态的页面口号,在JSP页面间传递数据就是这么简单!你可以为一个JSP页面增加任意多的bean,每一个bean都可以有任意多的属性,足以应付任何复杂的请求数据。

处理需求变化

改变是软件开发者最大的烦恼,你写好了你的bean,在JSP页面里也写好了使用它们的代码,这时web应用程序的需求似乎不可避免的会发生变化。如果这个改变要求更多的属性(大多数情况都是如此),你不得不改写你的JavaBean源代码,重新编译它,还要确定JSP页面能够正确访问新生成的bean类。有些情况下,你可以不必对bean进行处理,如果保存或获取属性页面不再使用了(也就是说,即使那个页面还在站点的目录里,但你不再使用该页面),这时你可以不用去管原来的代码即可。实际上,我就遇到过这种情况!

我的个人网站的页眉页面header.jsp用于生成html的头部,以前有一段时间里,这一页向我的其他页面头部里的title标记里插入一个标题,后来我做了修改,在header.jsp里不再使用页面标题了。但我并没有从PageHeaderInfo里把pageTitle移除;实际上,我甚至在大部分JSP页面里连jsp:param标记都没有移除,这个标记的作用本来是为页面设置标题的。我认为花这些工夫不值得,因为我确信保留这些数据不会带来任何坏的影响(也许某一天我还会重新用到呢!)。因此,如果你遇到同样的情况,不用浪费时间了--有处理这些琐事的时间不如用来为你的web应用程序增加些新的、有趣的、实用的功能。

下一次

当你熟练掌握了在JSP页面间传递数据的方法后,试着自己写一些有用的JavaBean并且看看能不能把它们用在你的站点里。通过和这些bean的接触,还有jsp:useBean、jsp:param以及jsp:get/setProperty的使用,你应该能够做出一些很酷的功能了!在下次的最佳实践里,我将向你展示使用JSP向站点增加外部内容的方法,JSTL标记和我们熟悉的include标记差不多,它使得JSP更灵活和更高效。在这之前,请用功准备,到时再见!

(这篇文章是一年前翻译的,当时想找翻译的活做,也是未果。请参考英文原文。)

posted on 2004-08-07 10:40 八进制 阅读(935) 评论(1)  编辑 收藏 收藏至365Key

 

get some basic knowledge about rss from rss.sina

 ?什么是RSS???2004年最热门的互联网词汇之一:RSS 2005年1月03日 (http://wm23.com/resource/R01/Internet_1005.htm)

 ?RSS利于发布什么样的内容 2005年3月11日(http://www.donews.net/walaqi/archive/2005/03/11/298648.aspx)

 ?利用RSS进行项目沟通 2005年3月16日(http://blog.csdn.net/wangchinaking/archive/2005/03/16/321270.aspx)

 ?深度:中国RSS现状调查 2005年1月13日(http://www.ccw.com.cn/news2/look/htm2005/20050113_09EL8.htm)

 ?主流Blog程序 2005年2月08日(http://www.blogchina.com/new/display/64629.html)

 ?RSS列表 2005年3月16日(http://www.donews.net/sogoo/archive/2005/03/16/303272.aspx)

  There are several questions give me strong impression:

  1.Rss is the trend of the content exchanging,although this maybe impact ad business(by this reason,some website don't provide rss service.)

  2.Rss can make people avoid the garbage information from the internet,such as spam,harmful information,ad information;

  3.迪斯尼 has build a inner knowledge sharing platform successfully with Blog and Rss technique,this is a successful example in this area-(knowledage sharing),the successful example is very rare now.

(转帖)用JSTL实现JSP应用程序快速开发 作者

转帖者注:由于本站留言板只有管理员才能查看,且没有明确的说明这个限制。致使hard在留言板中提交的这篇文章不能被大家看见,真是对不起。我会在留言板上明确标明这个限制。以后的留言板也许会作一些改进。

以下是hard提交文章的正文。

标题: 用JSTL实现JSP应用程序快速开发  作者: hard  创建时间: 2005-09-03 11:03:27  删除 

内容

在这篇文章中,我将为大家介绍一种基于JSP且灵活有趣的技术,那就是JSTL.JSTL全称为Java Server Pages Standard Tag Library.虽然JSP已经变的非常流行,但JSTL在基于SQL数据库的简单、快速的前后台开发中还是没有被广泛的应用。一旦你了解了JSTL,你就会了解到它的优点,并发现在你作为程序员的日常工作中,它已经被应用到了很多方面。我这里假设你已经熟悉HTML,能理解基本的SQL语句,和Jsp的基础知识。因为下面的内容要涉及到这些知识。

  JSTL是一个已经被标准化的标记库集合,她支持迭代、条件、XML文档的解析,国际化,和利用SQL与数据库交互的功能。起初,JSTL规范一直由JCP(Java Community process program)组织下的JSR #52 发展完善,"JCP肩负着Java 技术发展的重任"--官方网站这样评价。JCP作为一个开放性的组织,他同时吸收正式的会员和非正式会员.JCP对于Java技术规范的形成与发展发挥了重要的主导作用。JSTL主要包括四个基本部分的标记库:Core,XML,国际化,和对SQL的支持。由于这篇文章的主要是以其中的SQL部分的应用来快速了解JSTL,所以我们这篇文章只介绍了 Core和SQl标签库的一些基本功能。

  这项技术简单而且功能强大,足以和PHP、ColdFusion一较高下.他在拓展Java的应用领域方面有足够的能力,这些领域不只包括大型的可再升级的Web应用程序,对于仅拥有简单主页的Web程序一样没问题。这允许你在建立站点的时候可以避免那些经常考虑的XML的集成和与数据库的连接。正如我刚才提到的一样,JSTL的关键点就是简单易用。还有,那就是JSTL是基于JSP构建的, 他允许我们使用所有的Java技术,这一点我们有必要记住。

  开始之前,我们需要弄清楚怎样才能运行JSTL.由于是基于JSP技术的,所以我们运行它就需要一个能够编译JSP的容器,这里我们使用免费的JSP容器:TOMCAT(http://jakarta.apache.org/tomcat/index.html).至于如何安装这个产品已经超出了本文所讲述的范围。毫无疑问,这个软件产品现在已经很普及了,而且关于如何安装的文档资料也是很多。这里假设您已经安装并成功配置了这个容器,你只需再安装JSTL运行所需文件即可,它可以从这里下载http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html你不需要真正的安装它,只需要将其中的.JAR文件包含到你的应用程序的WEB-INF/lib目录下即可,稍后我会具体说到该怎么做.

  因为我们要在一个支持标准SQL的数据库上运行程序,你需要在你的电脑上安装有一个数据库。数据库的类型有许多种,这里我选择了MySql。我之所以选择他的原因在于首先,我们需要展示JSTL对于构造简单快速的应用程序领域所起的作用,同时能和一直在这个领域处于主导地位的PHP+MySql有所比较;第二点那就是MySql是可以免费下载并包含有一个针对JAVA的JDBC驱动.总之,为了使用下面的例子,你需要下载一个MYSQL服务器(http://www.mysql.com/products/mysql/index.html; MySql Connector/J JDBC驱动程序http://www.mysql.com/products/connector-j/index.html;还有就是MySql control center http://www.mysql.com/products/connector-j/index.html),这个产品可以让你非常容易的操作管理Mysql数据库文件。全部下载完成后,你需要安装mysql和mysql Control Center。另外还有就是mysql的JDBC驱动需要放到你的web应用程序中的/Web-INF/lib目录中。

  在创建程序代码之前,你需要创建并填写数据库表。关于这方面的主题文章也相当广泛,具体如何操作超出了本文的范围。这里我推荐给你我们上面提及的一个可视化的管理工具 MySQL Control Center.你可以用他来创建一个用来运行程序的测试用户,数据库以及创建一个测试表,并填写若干记录。关于登陆名及密码 数据库名称这些配置环境参数,你应该记住他们,稍后需要应用到我们的代码中。

  现在,你就可以准备创建自己的第一个JSTL应用程序了它需要我们做下面一些事情:

  整个实例程序代码包括两个文件Hello.jsp和 Continue.jsp

  Hello.jsp文件允许你输入数据库名称、登陆名称、登陆密码、数据库表名。Continue.jsp:接受Hello.jsp中的数据信息并且连接数据库,并对数据库中的表执行一个Select请求.

  下面是这个系统所有的代码文件,我将逐一进行解释。这些代码相当简单,对于代码的结构,我相信你即使没有我的解释你也能理解的.

1: <!-- Hello.jsp -->

2: <html>

3: <head>

4: <title>Hello</title>

5: </head>

6: <body bgcolor="#ffffff">

7: <h1>Please, enter all necessary information and click OK.</h1>

8: <form method="post" action="Continue.jsp">

9: <br>Your login to database:

<input type="text" name="login" size="15">

10: <br>Your password to database:

<input type="password" name="password" size="15">

11: <br>Your database name:

<input type="text" name="database" size="15">

12: <br>Your database table:

<input type="text" name="table" size="15">

13: <br><br><input type="submit" name="submit" value=" OK ">

14: </form>

15: </body>

16: </html>

  (请注意文本左侧的数字只是为你提供一些标记信息,你不需要将他们输入到你的代码文件中。)

  上面就是所有Hello.jsp的源代码,很惊奇吧,他仅仅是纯粹的HTML代码,就这么简单,我想应该没有注释的必要了.我之所以将这些代码片段包含进文章中就是为了展示一下JSTL集成到那些需要快速扩充额外功能的HTML站点中是多么的简单.让我再为你展示一下Continue.jsp的全部代码,看过之后,你就会对 JSTL有些了解了。

1: <!-- Continue.jsp -->

2: <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

3: <@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %>

4: <c:set var="h" value="localhost"/>

5: <c:set var="l" value="${param.login}"/>

6: <c:set var="p" value="${param.password}"/>

7: <c:set var="d" value="${param.database}"/>

8: <c:set var="t" value="${param.table}"/>

9: <html>

10: <head>

11: <title>Continue</title>

12: </head>

13: <body bgcolor="#ffffff">

14: <sql:setDataSource driver="com.mysql.jdbc.Driver"

url="jdbc:mysql://${l}/${d}?user=${u}&password=${p}"/>

15: <sql:query var="result">

16: SELECT * FROM <c:out value="${t}"/>

17: </sql:query>

18: <c:forEach var="row" items="${result.rowsByIndex}">

19: <c:out value="${row[0]}"/> <br>

20: </c:forEach>

21: </body>

22: </html>

(请注意文本左侧的数字只是为你提供一些标记信息,你不需要将他们输入到你的代码文件中。)

  这就是我们所有的代码了,是不是非常不错?现在我门来解释一下上面这些代码的作用。

  行1 是 HTML 的注释说明。

  行2--3 这些 JSP 标签是为了引用外部的 标签库,更确切的说这里是引用了JSTL库中的 Core 和SQL标签库部分。我们为他们都设置了前缀名称,以便于我们通过这些前缀名称访问被引入的标签库中的功能方法。

  行4---8正如 Hello.jsp 真正运行的样子,他将请求continue.jsp,Continue.jsp获得请求后就需要得到并解析来自Hello.jsp的若干变量,我们使用了这样的方式${param.YOUR_VAR}。在第4行<c:set标签,将变量${h}设置为 "localhost",第五行变量${l}将获取我们在 Hello.jsp中的login文本域中输入的信息,第6,7,8行的变量将分别获得来自Hello.jsp中用户所输入的密码,数据库名称,数据表名称。

  行9--13是一些我经常用来常见HTML网页头的简单的HTML标签,马上,重要的功能马上要到了。

  行14,我们试图用我们先前获得的mysql驱动程序(com.mysql.jdbc.Driver)建立数据库连接,在URL中,我们指明数据库连接所需要的参数,象数据库名称,主机名称,登陆名及登陆密码。依此,我们可以用其它任何的JDBC驱动程序连接其相对的数据库。如果我们需要连接其他的SQL数据库,只需更改这个 URL就够了。

  行15--17 这里我们执行了一个Select 查询,请特别注意第16行,我们使用了另一个JSTL功能函数<c:out 用来输出我们所获取的数据表名称,这里我们同样可以使用其他的SQL命令,比如说 INSERT,DELETE,等等。要执行这些没有返回值的查询请求,你就需要使用<sql:update JSTL功能函数了。他可以直接执行他们就象<SQL:query一样,只是执行它是不需要特别指定结果变量来存储语句执行返回的结果。

  行18--20 既然我们执行了上面的SELECT查询语句,我们就应该把他的返回结果显示出来。<c:forEach 就是JSTL 中一个具有迭代功能的函数,执行它时,我们通过${result.rowsByIndex}将返回的每一个数据行信息返回给变量${row},紧接着在第19行, 我们通过<c:out value="${row[0]}"/>显示返回的每个数据行的第一个数据列中的值。只要你的数据表中包含的字段,你都可以通过改变变量 ${row}中的数字大小来对请求表中的任意一个字段中的值对他们进行访问。

  行21--22是HTML 页脚

  在你亲自创建JSTL应用程序过程中,可能你还没有发现它有多么的强大,但你应该能够意识到JSTL的功能函数的简单和高效性,试想有了JSTL,整合出一个基于SQL的新闻专栏是何等的快速,集成你现有的web站点是何等的容易。

  很好,我们的代码很容易理解的,即使一个非专业程序员的话,打个比方就算是一个设计师也能够读懂它,理解它,还可能进行部分的修改,起码是页面布局上的修改。

  正如我们开始的时候所提到的,为了使我们的JSTL代码正常的运行,我们需要安装Mysql Connector/J 中的JAR 文件,当然还有 JSTL。因为我们使用了Tomcat这个JSp 容器,你需要在Tomcat的文件目录Webapps下创建你自己的文件夹,将你的Hello.jsp 、Continue.jsp文件放在你创建的文件目录中,在你创建的目录中你还要创建一个叫做WEB-INF 的文件夹,将你的配置文件Web.xml放在里面,web.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app

PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app />

  接下来我们还需要在WEB-INF下创建一个叫做lib的子目,并将下列文件放进去:

jstl.jar

saxpath.jar

standard.jar

mysql-connector-java-3.0.9-stable-bin.jar (注意,这个名称依据你的Mysql Connector/J版本不同可能会有所变化)

  所有的这些信息您能够在JSTL或Tomcat手册中查阅的到,如果你想理解他们具体是如何运行而又为什么这么运行你就应该研读一下这些手册。不过为了帮助你快速的掌握JSTL的基本操作,相关的知识我已经作了介绍。

  如果你使用的是其他的Jsp 容器,那么就需要你阅读他们相关的手册资料。

  罗罗索索这么多,我还想再说明一点,这篇文章只是对JSTL技术的基本的介绍,并不是完全手册。JSTL中包含有许多功能丰富的函数用法来帮助你以简捷快速的方式完成你的Jsp开发,我建议大家读一些有关JSTL功能以及它如何与JavaBeans协同工作的更详细的文档资料,到最终你可能会发现他就是你期待已久的开发平台。通过阅读本篇文章,你应该已经能够创建一些简单的基于SQL 数据库的前后台应用了。

 

敬请作者关注:学习日记使用方法

非常感谢lian的热心支持,敬请关注学习日记使用方法:

一)、数据结构:http://www.learndiary.com/aboutMe.html

     采用的结构:目标-->评论目标,目标-->日记,日记-->评论日记

二)、使用方法:http://www.learndiary.com/help.html

    1>在"您的目标"链接页面中点击"添加新目标",订立自己想要实现的目标。(强烈建议订立自己的目标前先检索一下,看是否别人已经订了类似的目标,这样你就可以加入这个目标,形成朝这个目标前进的集体效应。)

2>在"所有目标"链接页面中点击"加入",添加别人订立而自己也想要实现的目标。

3>在上述两个页面中都可以对目标进行评论,以目标为中心写日记,对日记进行评论。

4>在"您的目标"链接页面中点击"改变目标状态"下的选择菜单可以对自己的所有目标进行管理。

5>在您发写帖子时请尽量写出你撰写内容所引用的资源,以便大家共享。

比如:您的两个目标可以分别归类到:

目标“学习Hibernate (11篇) ”http://www.learndiary.com/disGoalContentAction.do?goalID=401

像这样:http://www.learndiary.com/disDiaryContentAction.do?goalID=1101

目标:“一起学习Struts(MVC) (19篇)”http://www.learndiary.com/disGoalContentAction.do?goalID=167

像这样:http://www.learndiary.com/disDiaryContentAction.do?goalID=1102

再次感谢lian的热心支持,新版的学习日记会对使用方法作出程序流程上的显而易见的提示。

(转贴)实际项目中的StrutsPlugIn插件扩展 作者: l

作者:冰莲如水

本文讲述Struts应用在实际项目中的插件类开发技术。在我们的learndiaryV1.0项目中已经有了很好的应用。通过对它的讲解,我们可以了解在应用开发中这一技术的实做经验。首先说明Struts插件扩展技术的特点:

Struts框架的一大优势在于它允许开发人员根据实际需要来扩展框架,定制客户化的功能。

Struts1.1框架提供了动态插入和加载组件的功能,这种组件被称为Struts插件。Struts插件实际上就是一个Java类,它在Struts应用启动时Struts框架调用每个插件的init()方法进行初始化,在插件的初始化阶段可以完成一些初始化的操作,如建立数据库连接,和远程系统建立连接,在当前的应用范围内加入插件类自身的实例等。在应用关闭时Struts框架会调用每个插件的 destroy()方法,destroy()方法可以用来完成释放资源的任务,如关闭数据库连接,断开与远程的连接等。任何作为插件的Java类都应该实现org.apache.struts.action.PlugIn接口。PlugIn接口包括两个方法:

       public interface PlugIn {

        /**

        *当struts应用启动时,下面的方法将被调用执行

        */

        public void init(ActionServlet servlet, ApplicationConfig config)

              throws ServletException;

       /**

       *当struts应用关闭时,将调用下面的方法,以释放资源。

       */

        public void destroy();

       } 

相关资源

 

相关评论

标题: 实际项目中的StrutsPlugIn插件扩展  作者: lian  创建时间: 2005-08-30 16:03:36  最近更新: 2005-08-30 16:03:36  编辑  删除 

内容

我们在learndiaryV1.0这个项目中使用了Struts框架的PlugIn插件扩展来实现ServiceFactory类。ServiceFactory为应用中的业务逻辑工厂类,它将提供创建各种业务逻辑类实例的方法,我们是通过对业务逻辑类实例的方法调用最终实现后台的商业逻辑及业务数据的检索和持久化的。关于持久层的存取更新请参阅《Hibernate 存取及批量更新删除》这一章节。ServiceFactory 工厂类实现了 Struts 的 PlugIn 接口并在 Struts 的配置文件struts-config中对其进行了配置描述,使其在Struts系统启动时自动被加载。而在 ServiceFactory 工厂类所覆盖的 PlugIn 的 init() 方法中,此工厂类将其自身加入到应用的 ServletContext 实例当中去。在具体的项目中,因为ServiceFactory 工厂类已经被启动并加载,在加载的过程中init() 方法又将ServiceFactory 工厂类自身的实例加入到ServletContext当中,我们便可以通过servlet.getServletContext().getAttribute(Constants.SERVICE_FACTORY_KEY)这样的方法对此ServiceFactory工厂类进行引用。通常我们也可以在struts-config文件中的ServiceFactory工厂类插件配置项<plug-in>中加入插件类的启动参数<set-property>,在当前的应用中我们没有采用这样的方式。听上去可能会糊里糊途的,我们还是从代码中找到灵感吧! 

相关资源 

标题: 实际项目中的StrutsPlugIn插件扩展  作者: lian  创建时间: 2005-08-30 16:04:34  最近更新: 2005-08-30 16:04:34  编辑  删除 

内容

首先我们构建出你的ServiceFactory类所要去实现的接口类,这有利于实现商业应用的面向接口的编程,这是一种良好的JAVA开发规范。在今后的开发环节当中我们还会遇到类似的开发案例。

  

        package com.learndiary.website.services;

import java.lang.IllegalAccessException;

import java.lang.ClassNotFoundException;

import java.lang.InstantiationException;

/**

 * 业务逻辑工厂的接口

 * 应用程序开发后期将会扩充此工厂接口,

 * 设置各种createService()方法,

 * 返回均为此业务逻辑方法的接口。

 */

public interface IServiceFactory {

public IBusinessService createService() throws ClassNotFoundException,

IllegalAccessException,InstantiationException;

public IUserService createUserService(String serviceName) throws ClassNotFoundException,

IllegalAccessException,InstantiationException;

public IUserService createUserService() throws ClassNotFoundException,

    IllegalAccessException,InstantiationException;

public void destroy();

}

你会发现上面的代码中所有方法返回的实例都定义为业务逻辑接口形式,如IBusinessService createService() 。在各类的IBusinessService接口中我们定义了这一类业务逻辑接口所要实现的方法。例如IUserService接口为我们定义了如下的一些方法。 

相关资源 

标题: 实际项目中的StrutsPlugIn插件扩展  作者: lian  创建时间: 2005-08-30 16:05:43  最近更新: 2005-08-30 16:05:43  编辑  删除 

内容

      public interface IUserService extends IBusinessService{

public User saveUser (User user) throws BusinessException;

public User findUserById(Long id) throws BusinessException;

public User findUserByName(String name) throws BusinessException;

public User findUserByEmail(String email) throws BusinessException;

public User findUserByPassword(String name, String password) throws BusinessException ;

public void saveOrUpdateUser(User user) throws BusinessException;

public List getUsers() throws BusinessException;

public int getAllUserNum() throws BusinessException;

}

此外IServiceFactory接口的定义中还存在着IUserService createUserService()的重载形式IUserService createUserService(String serviceName),这是为了方便大家对于这一应用形式的重构和扩展。

ServiceFactory的具体实现类如下:

  package com.learndiary.website.services;

import javax.servlet.ServletException;

import java.lang.InstantiationException;

import java.lang.IllegalAccessException;

import org.apache.struts.action.ActionServlet;

import org.apache.struts.action.PlugIn;

import org.apache.struts.config.ModuleConfig;

import com.learndiary.website.Constants;

import net.sf.hibernate.*;

import net.sf.hibernate.cfg.Configuration;

/**

 *业务逻辑工厂,ServiceFactory工厂类实现了struts 的PlugIn接口,

 *使其将在系统启动时,自动被加载;在工厂类所覆盖的PlugIn的init()方法中,

 *此工厂类将其自身加入到应用的ServletContext实例当中去。

 */

public class ServiceFactory implements IServiceFactory,PlugIn {

    

//由init()方法中传入ActionServlet实例

private ActionServlet servlet =null;

private String serviceClassname = "com.learndiary.website.services.ORMService";

/*

* 创建业务逻辑实例的模板

*/

public IBusinessService createService() throws ClassNotFoundException,

IllegalAccessException, InstantiationException {

IBusinessService serInstance =

(IBusinessService)Class.forName(serviceClassname).newInstance();

serInstance.setServletContext(servlet.getServletContext());

return serInstance;

}

/*

* 根据给定的服务类名,创建服务类的对象。

* 以接口IBusinessService型式返回。

*/

public IUserService createUserService(String serviceName) throws ClassNotFoundException,

IllegalAccessException, InstantiationException{

IUserService serInstance=

(IUserService)Class.forName(serviceName).newInstance();

serInstance.setServletContext(servlet.getServletContext());

return serInstance;

}

public IUserService createUserService() throws ClassNotFoundException,

    IllegalAccessException,InstantiationException{

IUserService serInstance = new UserService();

serInstance.setServletContext(servlet.getServletContext());

return serInstance;

}

public void destroy() {

}

/*

* 扩展Struts PlugIn接口的 init()方法

* Struts框架会在启动系统时,自动加载扩展了PlugIn接口的组件。

* 并调用此组件中的init()方法,对其进行初始化。

*

*/

public void init(ActionServlet svt, ModuleConfig conf)

throws ServletException {

this.servlet = svt;

/*

* 此处,利用组件初始化时,将本工厂实例保存于当前的ServletContext中。

* 此后,我们便可以在应用当中,调用此工厂实例。即调用ServiceFactory。

*/

servlet.getServletContext().setAttribute(Constants.SERVICE_FACTORY_KEY,this);

}



相关资源 

标题: 实际项目中的StrutsPlugIn插件扩展  作者: lian  创建时间: 2005-08-30 16:07:10  最近更新: 2005-08-30 16:07:10  编辑  删除 

内容

其中的public IBusinessService createService() throws ClassNotFoundException,

IllegalAccessException, InstantiationException {

IBusinessService serInstance =

(IBusinessService)Class.forName(serviceClassname).newInstance();

serInstance.setServletContext(servlet.getServletContext());

return serInstance;

}

为构建业务逻辑实现类的模板。业务逻辑实现类的具体的实例采用IBusinessService serInstance =

(IBusinessService)Class.forName(serviceClassname).newInstance();

的方式构建。关于具体的业务逻辑实现类是怎么样实现业务功能的,将在后续的章节中介绍。

在你的应用中加入了以上ServiceFactory工厂类之后,我们要把它作为Struts应用的插件加入到Struts配置文件当中, Struts框架在启动时将根据插件类相关的配置信息来初始化插件。与插件对应的配置元素为 <plug-in>,在struts-config.xml中对ServiceFactory插件类进行的如下配置:

  

  <plug-in className="com.learndiary.website.services.ServiceFactory">

  </plug-in>

根据Struts 配置文件的DTD 定义,在Struts配置文件中, <plug-in>元素必须位于其他配置元素的后面,此外,如果在配置文件中布署了多个插件, Struts框架将按照它们在配置文件中的先后顺序来依次初始化它们。

合理的使用好Struts的插件类扩展,将使我们的应用更加健壮,功能上具有良好的可扩展性和可移植性。在本文中也许存有疏漏错误之处,请开发员朋友们不吝恩教,吾人当励行而改之!

以上代码均为开源社区learndiary.com 1.0版本下测试通过的实际应用代码,你可以联系作者取得相关原码文件。

联系本文作者:QQ 284508610 

(转贴)Hibernate 存取及批量更新删除 作者: lian

            Hibernate 存取及批量更新删除

作者:冰莲如水

Hibernate是介于JAVA应用逻辑层与数据库层之间的一类开源的ORM中间件。ORM(即Object-Relation Mapping)从字面意义上讲就是对象-关系映射,ORM模式指的是在单个组件中负责所有实体域对象的持久化。其重点就在于把实体域对象通过一定规则上的映射机制,转化为数据库中所对应的记录,即持久化。为了更好的理解持久化,我们可以回想一下,以前所用到的通过JDBC API来对实体域对象实现的持久化。例如:

    Connetion con = null;

    PreparedStatement stmt = null;

     try{

        con = getConnection();

        con.setAutoCommit(false);

        stmt = con.prepareStatement(“insert into customers (ID, NAME, AGE) values (?,?,?)”);

        stmt.setLong(1, new Long(1));

        stmt.setString(2, new String(“ping”));

        stmt.setInt(3, new Integer(20));

        stmt.execute();

       }catch(SQLException sqlex){

           con.rollback();

         }catch(Exception e){

         …… }

        finally{

           try{

              stmt.close();

              con.close();

           }catch(Exception ex){

             …….

            }

          }

        }

 

相关资源

 

相关评论

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 01:57:52  最近更新: 2005-08-30 01:57:52  编辑  删除 

内容

     在上面的JDBC持久化模式中,业务逻辑层的过程域对象中业务逻辑和数据访问代码是混杂在一起的,并未能完全实现面向对象的编程思路,且程序结构不清晰,当关系数据模型发生变更时,软件的维护难度会大幅增加。而且这种模式中的SQL语句如果存在语法错误,在编译时是不能检查出来的,增加了调试程序时的难度。

    Hibernate的出现,将在业务逻辑层与数据库层之间再次构建出一个持久化层。Hibernate作为ORM中间件,封装了数据访问细节,我们只要通过Hibernate提供的对象-关系映射服务 ,便可在程序中实现域对象到关系数据的保存,或从数据库提取业务数据并转化为实体对象形式。

    对于要被持久化的JAVA对象,它在内存中的生命周期是从new语句创建了这个对象时开始,当不再有任何引用变量引用它时,这个对象的生命中期就将结束,所占用的内存将被JVM的垃圾回收器(GC)回收。 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 01:58:57  最近更新: 2005-08-30 01:58:57  编辑  删除 

内容

  对于Hibernate所要操作的持久化对象,在它的生命周期中,可处于三种状态:

? 临时状态(transient): 用new语句新建的对象,还没有被持久化,此时它不处于任何的Hibernate 的Session之中。处于临时状态的JAVA对象被称为临时对象。

? 持久化状态(persistent):这类对象已经被持久化,已处于(被加入)Session的缓存中。处于持久化状态的JAVA对象被称为持久华对象。

? 游离状态(detached):已经被持久化,但不再处于Session(被扔出或是Session自行关闭了)的缓存当中。处于游离状态的JAVA对象被称为游离对象。

Session接口是Hibernate向应用程序提供的操作数据库的最主要的接口,它提供了基本的面向对象的保存,更新,删除和查询方法。它由SessionFactory工厂类创建。 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 01:59:40  最近更新: 2005-08-30 01:59:40  编辑  删除 

内容

* Session 的save()方法:

    save()方法使一个临时对象转变为持久化对象。例如:

         Customer customer = new Customer();

         customer.setId( new Long(9));

         customer.setName(“Tom”);

         Session session = sessionFactory.openSession();

         Transaction tx = session.beginTransaction();

         Session.save(customer);

         tx.commit();

         session.close();

  Session 的save()方法所要注意的问题,1.在实际的对象持久化保存中,新建对象的ID应在此对象的类的映射文件中设置其生成方式,无需在程序中再对ID进行赋值。

例如以上的Customer类的映射文件Customer.hbm.xml中对ID生成方式的设置:

      <id name=”id” column=”ID”>

         <generator class=”increment”/>

      </id>

如果希望由应用程序来为新的对象指定ID,可以调用save()的另一个重载方法:

      save( customer, new Long(1));

   但此种方法在程序中不推荐使用。

2.在应用程序中不应该把持久化对象或游离对象传给save()方法。

 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:00:47  最近更新: 2005-08-30 02:00:47  编辑  删除 

内容

* Session 的update()方法

     update()方法使一个游离对象转变为持久化对象。以下代码在session1中保存一个 Customer 对象,然后在session2中更新这个 Customer对象:

     Customer customer = new Customer();

     customer.setName(“Tom”);

     Session session1 = sessionFactory.openSession();

     Transaction tx1 = session1.beginTransaction();

     session1.save(customer);

     tx1.commit();

     session1.close(); // 此时Customer对象变为游离对象,因为session1已经关闭。

      

     Session session2 = sessionFactory.openSession();

     Transaction tx2 = session2.beginTransaction();

     costomer.setName(“Linda”); //在与session2关联之前修改Customer对象的属性,

                            //这不是必须的一步,你也可以不修改,或修改更多属性。

     session2.update(customer); //在session2中加载 customer游离对象,并使其再次转为

                           //持久化对象。

     customer.setName(“Jack”); //在与session2关联之后再次修改了Customer对象的属性,

     tx2.commit();

     session2.close(); 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:01:52  最近更新: 2005-08-30 02:01:52  编辑  删除 

内容

在上面的例子中,customer先是被session1持久化后,session1关闭,customer变成

游离对象,再次与session2关联后,customer又变成持久对象。其中我们不厌其烦的修改Customer对象的属性,为了要证明当Customer对象与新的session2关联以后,修改了其属性,并不需要再次执行session2.save(customer),Session在清理缓存时,会根据最近一次的更新组装成update语句并执行数据库更新。

* Session的saveOrUpdate()方法

  saveOrUpdate()方法同时包含了save() 和update()方法的功能。如果传入的参数是临时对象,就调用save()方法;如果传入的是游离对象,就调用update()方法;如果传入的参数是持久化对象,就直接返回。以下的示例程序中,customer起初为游离对象, anotherCustomer起初为临时对象,session2的saveOrUpdate()方法分别将它们变为持久化对象:

     ……

Session session2 = sessionFactory.openSession();

Transaction tx2 = session2.beginTransaction();

Customer anotherCustomer = new Customer(); // anotherCustomer为临时对象

anotherCustomer.setName(“Tom”);

session2.saveOrUpdate(customer); //使customer游离对象被session2关联

session2.saveOrUpdate(anotherCustomer); //使anotherCustomer临时对象被session2关联

tx2.commit();

session2.close(); 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:02:34  最近更新: 2005-08-30 02:02:34  编辑  删除 

内容

* Session 的load()和 get()方法

    load()和 get()方法都能根据给定的OID从数据库中加载一个持久化对象,这两个方法的区别在于:当数据库中不存在与对象的OID相同的记录时,load()方法抛出net.sf.hibernate.ObjectNotFoundException异常,而get()方法返回null。示例如下:

    Session session1 = sessionFactory.openSession();

    Transaction tx1 = session1.beginTransaction();

    Customer a = (Customer)session1.load(Customer.class, new Long(1));

    Customer b= (Customer)session1.get(Customer.class. new Long(2));

   

    tx1.commit();

    session1.close();

    当执行了session1.load(Customer.class, new Long(1))这样的代码以后,就把OID为1的Customer对象载到session1的缓存里。我们可以在tx1.commit()执行之前对加载后的Customer对象a进行属性的修改。这些修改并不会马上被执行,而是在Session清理缓存时,会根据持久化对象的属性变化来同步更新数据库。

 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:03:27  最近更新: 2005-08-30 02:03:27  编辑  删除 

内容

*Session 的delete()方法

   delete()方法用于从数据库中删除与Java对象对应的记录。如果传入的参数是持久化对象,Session就计划执行一个delete语句。如果传入的参数是游离对象,先使游离对象被Session关联,使它变为持久化对象,然后计划执行一个delete语句。而真正的删除语句的执行是在Session清理缓存时。示例代码如下,首先加载了一个持久化对象,然后通过delete()方法将它删除。

     Session session1 = sessionFactory.openSession();

     Transaction tx1 = session1.beginTransaction();

     //加载一个持久化对象,因为Session 的get()和load()方法返回的永远是持久化对象。

     Customer customer = (Customer)session1.get(Customer.class, new Long(1));

     session1.delete(customer);

session1.close();

如果customer是游离对象时,下面的代码显示将此游离对象删除:

Session session2 = sessionFactory.openSession();

Transaction tx2 = session2.beginTransaction();

//在删除前,此游离对象customer先与session2关联,成为持久对象,然后将计划

//执行对其删除的SQL语句

session2.delete(customer);

tx2.commit();

session2.close();

 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:04:17  最近更新: 2005-08-30 02:04:17  编辑  删除 

内容

关于Hibernate的批量检索,批量更新和批量删除,所执行的操作并不尽遵循相同的规律。这一点使目前的Hibernate2.0还显得有些不够规格化和强健。但以后的版本中,期望其可以突破这几个屏障。

   首先说明批量查询,我们已经了解到,Session 的load(), get() , find() 方法都可实现对业务数据的查询,其中load()会因所要查询的对象类的映射文件(比如Customer.hbm.xml文件)中设置的检索策略,而实现立即检索或延迟检索。get()方法和find()方法却不受这种控制,它们总是会执行立即检索。那么象load()这样的方法,当其被设置为使用延迟检索时,它会返回什么样的实例呢?当使用延迟检索时返回为这一对象的代理类实例,代理类实例也有一个标志性的OID, 但没有被实例化,其所有属性为默认初始值或为空。关于延迟检索和对象类的映射方式,这里不做多余解释。提到检索,load() 和get()方法都是用指定了OID的方式检索并返回一个与数据库中记录相对应的实例对象。如Customer customer = (Customer)session.get(Customer.class, new Long(1)) 将会返回一个Customer实例对象customer. 而 find()可以实现批量的检索,其返回类型为List的对象集合。例如:

     List customerList = session.find( “from Customer as c”);

注意,其中的”from Customer as c” 为HQL查询语句, Customer 并不是象普通的SQL语句中对表名的引用那样可以对大小写不敏感,这里的查询是基于对象类的,Customer为待查询的对象类,你要写正确你的类名,c是你为这个类在这里所取的别名。Hibernate是通过你对Customer这个对象类的映射文件Customer.hbm.xml中的设置得知此对象类与哪一个表对应。它可能正是对应了CUSTOMERS这个表。那么Hibernate又如何知道你所用的对象类与表的映射,到底是哪一个数据库中的表呢?这个对数据库名的映射是在Hibernate的配置文件hibernate.cfg.xml文件中给出的。相关的一些问题请查阅Hibernate的配置和映射章节。 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:05:00  最近更新: 2005-08-30 02:05:00  编辑  删除 

内容

    以上的session.find( “from Customer as c”)方法,Hibernate最终会执行这样的SQL语句执行数据库的查询(立即检索方式):

    select * from CUSTOMERS ;

或者你也可以按如下的方式进行查询:

    List customerList = session.find(“from Customer as c where c.age > 24”);

最终Hibernate所执行的SQL语句为:

     select * from CUSTOMERS where AGE > 24 ;

如果担心一次检出Customer类对象的量会过大,可以在Customer.hbm.xml文件中设置一次批量检索的检出量batch-size:

    <class name=”mypack.Customer” table=”CUSTOMERS” batch-size=”4”>

对于一对一,一对多的关联也存在着集合(set. list ,bag, map)的延迟检索或立即检索,对于这种关联集合的检索,也存在着批量检索的设置,如在类的映射文件中的一对多的关联集合set中设置延迟检索时的批量检索尺寸:

   <class name=”mypack.customer” table=”CUSTOMERS”>

      ……..

      <set name=”topics” inverse=”true” lazy=”true” batch-size=”3”>

       …..

      </set>

   </class>

对于这类检索本文不做过多解释。有兴趣的读者可参阅Hibernate的关联映射与检索类型。

关于批量删除,可以采用Session 的delete()方法的重载形式,以HQL语句作为参数执行批量的删除:

    session.delete(“from Customer c where c.age > 24”) ;

  但是Hibernate最终并不会为我们构建这样的SQL并执行:

      select * from CUSTOMERS where AGE > 24 ;

  Session 的delete()方法首先通过以下select 语句把所有附合查询条件的Customer对象加载到内存中:select * from CUSTOMERS where AGE > 24 ;

  然后再逐一执行对这些对象的删除工作:

        delect from CUSTOMERS where ID = 1;

        delect from CUSTOMERS where ID = 2;

        delect from CUSTOMERS where ID = 3;

        …….

        delect from CUSTOMERS where ID = 10000; 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:06:15  最近更新: 2005-08-30 02:06:15  编辑  删除 

内容

 这有可能造成对一万条数据的加载和逐一删除。如此将会严重消耗内存,影响系统性能。此时最佳的方案又回到了使用JDBC API执行批量的删除工作。在此我们暂不举其实例。

下面探讨在Hibernate中的批量更新。Hibernate中Session的update()方法的各种重载形式,一次都只能更新一个对象,那么我们可不可以使用Session 的find()方法先检索出要更新的所有的对象,再用轮询的方法逐一对其进更新呢?比如:

     Session session = sessionFactory.openSession();

     Transaction tx = session.beginTransaction();

     Iterator customers = session.find(“from Customer c where c.age >24”) .iterator() ;

     while(customers.hasNext()){

        Customer customer = (Customer)customers.next();

        customer.setAge(customer.getAge() + 1);

        session.flush();

        session.evict(customer);

     }

    tx.commit();

    session.close();

 以上的程序只是实现了批量检索并更新对象的目的,依旧没有注意内存的占用及系统的性能问题。我们还是回到原始却又是最有效的方法,使用JDBC API来实现业务数据的批量更新。幸好Hibernate只是对JDBC进行了轻量的封装,我们在程序中依旧可以引用JDBC API:

    …….

    tx = session.beginTransaction();

    Connection con = session.connection(); //取得当前session使用的数据库连接

    PreparedStatement stmt = con.prepareStatement(“update CUSTOMERS set AGE=AGE + 1 ” + “where AGE >24”);

    stmt.executeUpdate();

    tx.commit(); 

相关资源 

标题: Hibernate 存取及批量更新删除  作者: lian  创建时间: 2005-08-30 02:06:54  最近更新: 2005-08-30 02:06:54  编辑  删除 

内容

如果你使用的底层的数据库(如Oracle)支持存储过程,也可以通过存储过程来执行批量更新。Oracle中的存储过程的设置参考如下:

       create or replace procedure batchUpdateCustomer(p_age in number) as

         begin

            update CUSTOMERS set AGE = AGE + 1 where AGE > p_age ;

         end;

   上面的存储过程中的参数p_age代表一个数值型的传入参数,表示客户的年龄。我想你用它甚至可以查出一个上千年的老妖 :)

    在我们的应用程序中可以对这个存储过程进行如下的调用:

         ……..

tx = session.beginTransaction();

         Connection con = session.connection();

         String procedure = “ {call batchUpdateCustomer(?)}”;

         CallableStatement cstmt = con.prepareCall(procedure);

         cstmt.setInt(1, 24);

         cstmt.executeUpdate();

         tx.commit();

与此类同,Hibernate的批量删除也可以采用程序中调用JDBC API的方式,进行操作。你可以把上面的存储过程改一下,试着去执行它。

总结:Hibernate让我们在面对复杂多变的业务数据时,真正的体验到了面向对象编程的快意高效,但同时它自已也知道自身的不足之处在哪里,给我们留下了充分的空间去选择最适合的开发模式,而Hibernate为我们提供了对这些常规开发模式的支持。也许有一天,国人也能参与到这样经典的大型开源组件的设计当中去,做出我们引领时带的开源品牌,一同努力吧!这的确需要大部分人的努力和奉献。 

(转贴)Struts的多模块设计

Struts的多模块设计

Struts在1.1以后的版本引入了模块(Module)的概念,克服了1.0的并行开发所遇到的问题。但是模板的规划往往又是比较麻烦,如果不注意,可能适得其反,影响你的开发速度。下面我们看看如何去规划一个对模块的Struts项目。

首先我们需要建立一个web的项目,接下来就要进行目录规划。如下图:

(http://www.learndiary.com/pictures/j_struts_module.gif)

 

1 首先确定项目的模块,如此项目中包含两个模块:mFirst和mSecond,当然还有缺省模板。

2 本例子中考虑到使用XDoclet自动生成Struts配置和校验文件,所以有些特殊性。在WEB-INF下建立两个目录mFirst和mSecond,用于模块配置文件的存放。同时建立merge目录,并包含相应的模块目录,主要存放XDoclet生成Struts配置文件所需要的合并文件。模板的java源码和测试代码也分别存放,这样便于管理。为了包含某些不允许从浏览器端直接访问的jsp文件,我们在WEB-INF下同时建立webpages目录,该目录下同时包含模块目录,主要存放各个模块的受限文件。

3 本例中为了集成方便,所有编译后的代码均存在同一目录下(WEB-INF\classes),编译后的测试代码同样存在同一目录下。

4 经过以上的设置,为XDoclet生成配置文件提供了方便,我们的原则是同一个模块只有一个配置文件(struts-config.xml)和校验文件(validation.xml)。

 

 

5 接下来我们只需在web.xml中进行模块声明即可,其他信息请参考struts的sample。

<init-param>

<param-name>config</param-name>

<param-value>WEB-INF/struts-config.xml</param-value>

</init-param>

<init-param>

<param-name>config/mFirst</param-name>

<param-value>WEB-INF/mFirst/struts-config.xml</param-value>

</init-param>

<init-param>

<param-name>config/mSecond</param-name>

<param-value>WEB-INF/mSecond/struts-config.xml</param-value>

</init-param>

6 完成这些信息以后,我们要注意一些事情:

struts-config.xml文件中的Controller声明,由于我们将模板的jsp文件隐藏到WEB-INF目录下,而不是在根目录下直接建立模板目录,所以必须设置forwardPattern,详细信息请参考Struts文档。请在每个模块的struts-config.xml文件中添加以下代码,在本例中为:

<controller forwardPattern="/WEB-INF/webpages/$M$P"/>

在每个模块的properties资源文件中可能都有配置Struts默认的出错信息,因为这些模块都是独立的。

7 接下来就是模块的之间的切换问题,因为在现时过程必须需要解决的问题。其实很简单,如果你想使用项目下绝对路径(包含模块目录信息),只需将forward的contextRelative属性值设置为true即可,这样模块之间切换也很容易实现。

<forward contextRelative="true" name="success"

path="/mSecond/second.do" redirect="false"/>

8 接下来就是你的代码啦,可能你要在编码中适当地考虑到项目模块之间的关系。

总结:多模块设计不太难,但是你也的考虑周全点,这样会给你的开发带来方便。在IntelliJ IDEA下,虽然在模块比较多的情况下目录很乱,通过设置excluded,让你的目录更整洁,这样就可以关注你的模块。在有些情况下,取消excluded,这样你有可以把握项目全局。

 

posted on 2005-08-17 09:03 风太少 阅读(34) 评论(0)  编辑 收藏