??xml version="1.0" encoding="utf-8" standalone="yes"?>久久96国产精品久久99软件,91一区一区三区,精品一区二区在线视频http://www.aygfsteel.com/machilansing/category/14204.htmlLansing--Coding 不是? zh-cnTue, 27 Feb 2007 08:50:35 GMTTue, 27 Feb 2007 08:50:35 GMT60Java虚拟机简?/title><link>http://www.aygfsteel.com/machilansing/archive/2007/01/18/94630.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 18 Jan 2007 06:27:00 GMT</pubDate><guid>http://www.aygfsteel.com/machilansing/archive/2007/01/18/94630.html</guid><wfw:comment>http://www.aygfsteel.com/machilansing/comments/94630.html</wfw:comment><comments>http://www.aygfsteel.com/machilansing/archive/2007/01/18/94630.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.aygfsteel.com/machilansing/comments/commentRss/94630.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/machilansing/services/trackbacks/94630.html</trackback:ping><description><![CDATA[Java虚拟?br /><p>一、什么是Java虚拟?/p><br /><p>Java虚拟机是一个想象中的机?在实际的计算Z通过软g模拟来实现。Java虚拟机有自己惌中的g,如处理器、堆栈、寄存器{?q具有相应的指opȝ?/p><br /><p>1.Z么要使用Java虚拟?/p><br /><p>Java语言的一个非帔R要的特点是与^台的无关性。而用Java虚拟机是实现q一特点的关键。一般的高语言如果要在不同的^Cq行,臛_需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同^Cq行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体^台相关的信息,使得Java语言~译E序只需生成在Java虚拟Zq行的目标代?字节?,可以在多种q_上不加修改地q行。Java虚拟机在执行字节码时,把字节码解释成具体^C的机器指令执行?/p><br /><p>2.谁需要了解Java虚拟?/p><br /><p>Java虚拟机是Java语言底层实现的基,对Java语言感兴的人都应对Java虚拟机有个大概的了解。这有助于理解Java语言的一些性质,也有助于使用Java语言。对于要在特定^C实现Java虚拟机的软g人员,Java语言的编译器作者以及要用硬件芯片实现Java虚拟机的人来?则必Lȝ解Java虚拟机的规范。另?如果你想扩展Java语言,或是把其它语a~译成Java语言的字节码,你也需要深入地了解Java虚拟机?/p><br /><p>3.Java虚拟机支持的数据cd</p><br /><p>Java虚拟机支持Java语言的基本数据类型如?</p><br /><p>byte://1字节有符h数的补码 <br />short://2字节有符h数的补码 <br />int://4字节有符h数的补码 <br />long://8字节有符h数的补码 <br />float://4字节IEEE754单精度QҎ <br />double://8字节IEEE754双精度QҎ <br />char://2字节无符号Unicode字符</p><br /><p>几乎所有的Javacd查都是在~译时完成的。上面列出的原始数据cd的数据在Java执行时不需要用g标记。操作这些原始数据类型数据的字节?指o)本n已l指Z操作数的数据cd,例如iadd、ladd、fadd和dadd指o都是把两个数相加,其操作数cd别是int、long、float和double。虚拟机没有lboolean(布尔)cd讄单独的指令。boolean型的数据是由integer指o,包括integerq回来处理的。boolean型的数组则是用byte数组来处理的。虚拟机使用IEEE754格式的QҎ。不支持IEEE格式的较旧的计算?在运行Java数D程序时,可能会非常慢?/p><br /><p>虚拟机支持的其它数据cd包括: <br />object//对一个Javaobject(对象)?字节引用 <br />returnAddress//4字节,用于jsr/ret/jsr-w/ret-w指o <br />?Java数组被当作object处理?/p><br /><p>虚拟机的规范对于object内部的结构没有Q何特D的要求。在Sun公司的实C,对object的引用是一个句?其中包含一Ҏ?一个指针指向该object的方法表,另一个指向该object的数据。用Java虚拟机的字节码表C的E序应该遵守cd规定。Java虚拟机的实现应拒l执行违反了cd规定的字节码E序。Java虚拟机由于字节码定义的限制似乎只能运行于32位地址I间的机器上。但是可以创Z个Java虚拟?它自动地把字节码转换?4位的形式。从Java虚拟机支持的数据cd可以看出,JavaҎ据类型的内部格式q行了严D?q样使得各种Java虚拟机的实现Ҏ据的解释是相同的,从而保证了Java的与q_无关性和?<br />UL性?/p><br /><p>二、Java虚拟Zpȝ?/p><br /><p>Java虚拟机由五个部分l成:一l指令集、一l寄存器、一个栈、一个无用单元收集堆(Garbage-collected-heap)、一个方法区域。这五部分是Java虚拟机的逻辑成䆾,不依赖Q何实现技术或l织方式,但它们的功能必须在真实机器上以某U方式实现?/p><br /><p>1.Java指o?/p><br /><p>Java虚拟机支持大U?48个字节码。每个字节码执行一U基本的CPUq算,例如,把一个整数加到寄存器,子程序{Uȝ。Java指o集相当于JavaE序的汇~语a?<br />Java指o集中的指令包含一个单字节的操作符,用于指定要执行的操作,q有0个或多个操作?提供操作所需的参数或数据。许多指令没有操作数,仅由一个单字节的操作符构成?/p><br /><p>虚拟机的内层循环的执行过E如? </p><br /><p>do{ <br />取一个操作符字节; <br />Ҏ操作W的值执行一个动? <br />}while(E序未结?</p><br /><p>׃指opȝ的简单?使得虚拟机执行的q程十分?从而有利于提高执行的效率。指令中操作数的数量和大是由操作符军_的。如果操作数比一个字节大,那么它存储的序是高位字节优先。例?一?6位的参数存放时占用两个字?其gؓ:</p><br /><p>W一个字?256+W二个字节字节码指o一般只是字节对齐的。指令tabltch和lookup是例?在这两条指o内部要求强制?字节边界寚w?/p><br /><p>2.寄存?/p><br /><p>Java虚拟机的寄存器用于保存机器的q行状?与微处理器中的某些专用寄存器cM?/p><br /><p>Java虚拟机的寄存器有四种: <br />pc:JavaE序计数器?<br />optop:指向操作数栈端的指针?<br />frame:指向当前执行Ҏ的执行环境的指针?<br />vars:指向当前执行Ҏ的局部变量区W一个变量的指针?/p><br /><p>Java虚拟?/p><br /><p>Java虚拟机是栈式?它不定义或用寄存器来传递或接受参数,其目的是Z保证指o集的z性和实现时的高效?特别是对于寄存器数目不多的处理器)?<br />所有寄存器都是32位的?/p><br /><p>3.?/p><br /><p>Java虚拟机的栈有三个区域:局部变量区、运行环境区、操作数区?/p><br /><p>(1)局部变量区 每个JavaҎ使用一个固定大的局部变量集。它们按照与vars寄存器的字偏U量来寻址。局部变量都?2位的。长整数和双_ֺ点数占据了两个局部变量的I间,却按照第一个局部变量的索引来寻址?例如,一个具有烦引n的局部变?如果是一个双_ֺ点?那么它实际占据了索引n和n+1所代表的存储空间?虚拟范ƈ不要求在局部变量中?4位的值是64位对齐的。虚拟机提供了把局部变量中的D载到操作数栈的指?也提供了把操作数栈中的值写入局部变量的指o?/p><br /><p>(2)q行环境区 在运行环境中包含的信息用于动态链?正常的方法返回以及异怼播?/p><br /><p>·动态链?<br />q行环境包括Ҏ向当前类和当前方法的解释器符可的指?用于支持Ҏ代码的动态链接。方法的class文g代码在引用要调用的方法和要访问的变量时用符受动态链接把W号形式的方法调用翻译成实际Ҏ调用,装蝲必要的类以解释还没有定义的符?q把变量讉K译成与q些变量q行时的存储l构相应的偏Ud址。动态链接方法和变量使得Ҏ中用的其它cȝ变化不会影响到本E序的代码?/p><br /><p>·正常的方法返?br />如果当前Ҏ正常地结束了,在执行了一条具有正类型的q回指o?调用的方法会得到一个返回倹{执行环境在正常q回的情况下用于恢复调用者的寄存?q把调用者的E序计数器增加一个恰当的数?以蟩q已执行q的Ҏ调用指o,然后在调用者的执行环境中l执行下厅R?/p><br /><p>·异常和错误传?br />异常情况在Java中被UCError(错误)或Exception(异常),是Throwablecȝ子类,在程序中的原因是:①动态链接错,如无法找到所需的class文g。②q行旉,如对一个空指针的引?/p><br /><p>·E序使用了throw语句?br />当异常发生时,Java虚拟机采取如下措?<br />·查与当前Ҏ相联pȝcatch子句表。每个catch子句包含其有效指令范?能够处理的异常类?以及处理异常的代码块地址?br />·与异常相匚w的catch子句应该W合下面的条?造成异常的指令在其指令范围之?发生的异常类型是其能处理的异常类型的子类型。如果找C匚w的catch子句,那么pȝ转移到指定的异常处理块处执行;如果没有扑ֈ异常处理?重复L匚w的catch子句的过E?直到当前Ҏ的所有嵌套的catch子句都被查过?br />·׃虚拟ZW一个匹配的catch子句处l执?所以catch子句表中的顺序是很重要的。因为Java代码是结构化?因此d以把某个Ҏ的所有的异常处理器都按序排列C个表?对Q意可能的E序计数器的?都可以用U性的序扑ֈ合适的异常处理?以处理在该程序计数器g发生的异常情c?br />·如果找不到匹配的catch子句,那么当前Ҏ得到一?未截获异?的结果ƈq回到当前方法的调用?好像异常刚刚在其调用者中发生一栗如果在调用者中仍然没有扑ֈ相应的异常处理块,那么q种错误传播被l箋下去。如果错误被传播到最层,那么pȝ调用一个缺省的异常处理块?<br />(3)操作数栈区 机器指o只从操作数栈中取操作?对它们进行操?q把l果q回到栈中。选择栈结构的原因?在只有少量寄存器或非通用寄存器的机器(如Intel486)?也能够高效地模拟虚拟机的行ؓ。操作数栈是32位的。它用于l方法传递参?q从Ҏ接收l果,也用于支持操作的参数,q保存操作的l果。例?iadd指o两个整数相加。相加的两个整数应该是操作数栈顶的两个字。这两个字是由先前的指o压进堆栈的。这两个整数从堆栈弹出、相?q把l果压回到操作数栈中?/p><br /><p>每个原始数据cd都有专门的指令对它们q行必须的操作。每个操作数在栈中需要一个存储位|?除了long和double?它们需要两个位|。操作数只能被适用于其cd的操作符所操作。例?压入两个intcd的数,如果把它们当作是一个longcd的数则是非法的。在Sun的虚拟机实现?q个限制由字节码验证器强制实行。但?有少数操?操作Wdupe和swap),用于对运行时数据行操作时是不考虑cd的?/p><br /><p>4.无用单元攉?/p><br /><p>Java的堆是一个运行时数据?cȝ实例(对象)从中分配I间。Java语言h无用单元攉能力:它不l程序员昑ּ释放对象的能力。Java不规定具体用的无用单元攉法,可以Ҏpȝ的需求用各U各L法?/p><br /><p>5.Ҏ?/p><br /><p>ҎZ传统语言中的~译后代码或是Unixq程中的正文D늱伹{它保存Ҏ代码(~译后的java代码)和符可。在当前的Java实现?Ҏ代码不包括在无用单元攉堆中,但计划在来的版本中实现。每个类文g包含了一个JavacL一个Java界面的编译后的代码。可以说cL件是Java语言的执行代码文件。ؓ了保证类文g的^台无x?Java虚拟范中对类文g的格式也作了详细的说明。其具体l节请参考Sun公司的Java虚拟范?/p><img src ="http://www.aygfsteel.com/machilansing/aggbug/94630.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/machilansing/" target="_blank">Lansing</a> 2007-01-18 14:27 <a href="http://www.aygfsteel.com/machilansing/archive/2007/01/18/94630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 创徏.exeE序http://www.aygfsteel.com/machilansing/archive/2007/01/18/94628.htmlLansingLansingThu, 18 Jan 2007 06:21:00 GMThttp://www.aygfsteel.com/machilansing/archive/2007/01/18/94628.htmlhttp://www.aygfsteel.com/machilansing/comments/94628.htmlhttp://www.aygfsteel.com/machilansing/archive/2007/01/18/94628.html#Feedback0http://www.aygfsteel.com/machilansing/comments/commentRss/94628.htmlhttp://www.aygfsteel.com/machilansing/services/trackbacks/94628.html  
  W三方工?/b>
  一U方法是使用W三方商业工h免费工具?Java 应用E序打包Z个可执行文g?br />  
  下面是h格和Ҏ都不同的两个工P但是?Web 上还有其它几个第三方工具可以免费下蝲?br />  
  http://www.bysoft.se/sureshot/exej/
  http://www.duckware.com/jexepack/
  使用商业安装E序QinstallerQ?br />  InstallAnywhere 是一个常用的安装E序Q它管理应用程序的安装q程Qƈ应用程序打包ؓ可执行程序?br />  
  使用 .jar
  除了以上Ҏ之外Q还可以应用程序打包ؓ一个可执行?.jar 文gQ而不是一?.exe 文g。在q篇文章中我不详细介绍q种ҎQ你可以在这里找C个非常棒的在U教E?br />  
  你需要做的最重要的一件事是指定在 .jar 文g中哪个类是应用程序的入口炏V例如,对你的应用程序来说就是具有一?public static void main(String[] args) Ҏ的引导类。可以在 .jar 表示文g?Main-Class 头部信息中提供这些信息。这个头部信息的通用形式为:Main-Class: classnameQ其?classname 是应用程序的入口点的cdU?br />  
  使用 Java Webstart
  Java Webstart 是标?Java q行时环境(JREQ的隐藏的宝物,自从版本 1.3 开始,JRE 包含了 Java Webstart。它是一个简单但功能强大且灵zȝ应用程序部|到Mq_的方法?br />  
  Webstart 允许应用E序的用户从他们的浏览器、电子邮件或桌面启动和管理应用程序。Java Webstart 的一个主要优Ҏ一旦应用程序被安装Q在每次启动它时Q它都将会检查用h否在q行最新版本的应用E序。如果不是,应用E序通过|络装蝲新版本到桌面然后执行Q因此解决了软g传播问题?br />  
  如果你的应用E序已经有很多用L话,q一点就其重要。还有很重要的一ҎQ它能够查用L本地桌面环境Qƈ能保证他们安装了正确?JRE 版本来运行你的应用程序?br />  
  Java Webstart 本n有一pd文章Q所以我你访?Java Webstart Web 站点查看更多文档和教E?br />  
  l束?/b>
  前两U方法可能会满你对q个问题的需要,但是我强烈徏议你仔细看一?Java Webstart。它?Java 标准的一部分Qƈ且能够在所有^C一致工作。我比较喜欢q个应用E序打包Ҏ?

Lansing 2007-01-18 14:21 发表评论
]]>
Log4j基本使用Ҏhttp://www.aygfsteel.com/machilansing/archive/2006/08/22/65068.htmlLansingLansingTue, 22 Aug 2006 06:28:00 GMThttp://www.aygfsteel.com/machilansing/archive/2006/08/22/65068.htmlhttp://www.aygfsteel.com/machilansing/comments/65068.htmlhttp://www.aygfsteel.com/machilansing/archive/2006/08/22/65068.html#Feedback0http://www.aygfsteel.com/machilansing/comments/commentRss/65068.htmlhttp://www.aygfsteel.com/machilansing/services/trackbacks/65068.html  一、定义配|文?/strong>

  其实您也可以完全不用配|文Ӟ而是在代码中配置Log4j环境。但是,使用配置文g您的应用E序更加灉|。Log4j支持两种配置文g格式Q一U是XML格式的文Ӟ一U是JavaҎ文Ӟ?|。下面我们介l用JavaҎ文件做为配|文件的ҎQ?/p>

  1.配置根LoggerQ其语法为:

  log4j.rootLogger = [ level ] , appenderName, appenderName, ?

  其中Qlevel 是日志记录的优先U,分ؓOFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的别。Log4j只用四个别,优先U从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的U别Q您可以控制到应用程序中相应U别的日志信息的开兟뀂比如在q里定义了INFOU别Q则应用E序中所有DEBUGU别的日志信息将不被打印出来?appenderName是指定日志信息输出到哪个地斏V您可以同时指定多个输出目的地?

  2.配置日志信息输出目的地AppenderQ其语法为:

  log4j.appender.appenderName = fully.qualified.name.of.appender.class
  log4j.appender.appenderName.option1 = value1
  ?
  log4j.appender.appenderName.option = valueN

  其中QLog4j提供的appender有以下几U:
  org.apache.log4j.ConsoleAppenderQ控制台Q,
  org.apache.log4j.FileAppenderQ文ӞQ?
  org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文ӞQ?br />  org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文ӞQ?
  org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)

  3.配置日志信息的格式(布局Q,其语法ؓQ?/p>

  log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
  log4j.appender.appenderName.layout.option1 = value1
  ?
  log4j.appender.appenderName.layout.option = valueN

  其中QLog4j提供的layout有以下几U:
  org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q,
  org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q,
  org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q,
  org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)

  Log4J采用cMC语言中的printf函数的打印格式格式化日志信息Q打印参数如下: %m 输出代码中指定的消息

  %p 输出优先U,即DEBUGQINFOQWARNQERRORQFATAL
  %r 输出自应用启动到输出该log信息耗费的毫U数
  %c 输出所属的cȝQ通常是所在类的全?
  %t 输出产生该日志事件的U程?
  %n 输出一个回车换行符QWindowsq_为“\r\n”,Unixq_为“\n?
  %d 输出日志旉点的日期或时_默认格式为ISO8601Q也可以在其后指定格式,比如Q?d{yyy MMM dd HH:mm:ss,SSS}Q输出类|2002q?0?8?22Q?0Q?8Q?21
  %l 输出日志事g的发生位|,包括cȝ名、发生的U程Q以及在代码中的行数。D例:Testlog4.main(TestLog4.java:10)

  二、在代码中用Log4j

  1.得到记录?/p>

  使用Log4jQ第一步就是获取日志记录器Q这个记录器负责控制日志信息。其语法为:

  public static Logger getLogger( String name)

  通过指定的名字获得记录器Q如果必要的话,则ؓq个名字创徏一个新的记录器。Name一般取本类的名字,比如Q?

  static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

  2.d配置文g

  当获得了日志记录器之后,W二步将配置Log4j环境Q其语法为:

  BasicConfigurator.configure ()Q?自动快速地使用~省Log4j环境?br />  PropertyConfigurator.configure ( String configFilename) Q读取用Java的特性文件编写的配置文g?br />  DOMConfigurator.configure ( String filename ) Q读取XML形式的配|文件?/p>

  3.插入记录信息Q格式化日志信息Q?/p>

  当上两个必要步骤执行完毕Q您可以轻村֜使用不同优先U别的日志记录语句插入到您想记录日志的Q何地方,其语法如下:

  Logger.debug ( Object message ) ;
  Logger.info ( Object message ) ;
  Logger.warn ( Object message ) ;
  Logger.error ( Object message ) ;



Lansing 2006-08-22 14:28 发表评论
]]>
扚w处理JDBC语句提高处理速度http://www.aygfsteel.com/machilansing/archive/2006/08/22/64956.htmlLansingLansingTue, 22 Aug 2006 01:24:00 GMThttp://www.aygfsteel.com/machilansing/archive/2006/08/22/64956.htmlhttp://www.aygfsteel.com/machilansing/comments/64956.htmlhttp://www.aygfsteel.com/machilansing/archive/2006/08/22/64956.html#Feedback0http://www.aygfsteel.com/machilansing/comments/commentRss/64956.htmlhttp://www.aygfsteel.com/machilansing/services/trackbacks/64956.html 扚w处理JDBC语句提高处理速度

作者:佚名    来自Q未?/p>

  有时候JDBCq行得不够快Q这使得有些E序员用数据库相关的存储过E。作Z个替代方案,可以试试使用Statement 的批量处理特性看看能否同时执行所有的SQL以提高速度?

  存储q程的最单的形式是包含一pdSQL语句的过E,这些语句放在一起便于在同一个地方管理也可以提高速度。Statement cd以包含一pdSQL语句Q因此允许在同一个数据库事务执行所有的那些语句而不是执行对数据库的一pd调用?

  使用扚w处理功能涉及下面的两个方法:
  · addBatch(String) Ҏ
  · executeBatchҎ

  如果你正在用Statement 那么addBatch Ҏ可以接受一个通常的SQL语句Q或者如果你在用PreparedStatement Q那么也可以什么都不向它增加。executeBatch Ҏ执行那些SQL语句q返回一个int值的数组Q这个数l包含每个语句媄响的数据的行数。如果将一个SELECT语句或者其他返回一个ResultSet的SQL语句攑օ扚w处理中就会导致一个SQLException异常?

  关于java.sql.Statement 的简单范例可以是Q?

  Statement stmt = conn.createStatement();
  stmt.insert("DELETE FROM Users");
  stmt.insert("INSERT INTO Users VALUES("rod", 37, "circle")");
  stmt.insert("INSERT INTO Users VALUES("jane", 33, "triangle")");
  stmt.insert("INSERT INTO Users VALUES("freddy", 29, "square")");
  int[] counts = stmt.executeBatch();

  PreparedStatement 有些不同Q它只能处理一部分SQL语法Q但是可以有很多参数Q因此重写上面的范例的一部分可以得C面的l果Q?

  // 注意q里没有DELETE语句
  PreparedStatement stmt = conn.prepareStatement("INSERT INTO Users VALUES(?,?,?)");

  User[ ] users = ...;
  for(int i=0; i<users.length; i++) {
   stmt.setInt(1, users[i].getName());
   stmt.setInt(2, users[i].getAge());
   stmt.setInt(3, users[i].getShape());
   stmt.addBatch( );
  }
  int[ ] counts = stmt.executeBatch();

  如果你不知道你的语句要运行多次Q那么这是一个很好的处理SQL代码的方法。在不用批量处理的情况下,如果d50个用P那么性能有影响Q如果某个h写了一个脚本添加一万个用户Q程序可能变得很p糕。添加批处理功能可以帮助提高性能Q而且在后面的那种情况下代码的可读性也更好?/p>

Lansing 2006-08-22 09:24 发表评论
]]>
Apache Avalon?/title><link>http://www.aygfsteel.com/machilansing/archive/2006/08/18/64430.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Fri, 18 Aug 2006 12:14:00 GMT</pubDate><guid>http://www.aygfsteel.com/machilansing/archive/2006/08/18/64430.html</guid><wfw:comment>http://www.aygfsteel.com/machilansing/comments/64430.html</wfw:comment><comments>http://www.aygfsteel.com/machilansing/archive/2006/08/18/64430.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/machilansing/comments/commentRss/64430.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/machilansing/services/trackbacks/64430.html</trackback:ping><description><![CDATA[     摘要: Avalon的简要历史以及创建它所有的设计原则概述 事情是从Apache JServ目开始的。Stefano Mazzocchi和其它协助开发Apache JServ的h员认识到目中所用到的一些模式很通用Q以用于创Z个服务器框架??999q??7日,星期三(在JServ ...  <a href='http://www.aygfsteel.com/machilansing/archive/2006/08/18/64430.html'>阅读全文</a><img src ="http://www.aygfsteel.com/machilansing/aggbug/64430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/machilansing/" target="_blank">Lansing</a> 2006-08-18 20:14 <a href="http://www.aygfsteel.com/machilansing/archive/2006/08/18/64430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>析J2EE?NETq_优劣http://www.aygfsteel.com/machilansing/archive/2006/08/17/64196.htmlLansingLansingThu, 17 Aug 2006 11:45:00 GMThttp://www.aygfsteel.com/machilansing/archive/2006/08/17/64196.htmlhttp://www.aygfsteel.com/machilansing/comments/64196.htmlhttp://www.aygfsteel.com/machilansing/archive/2006/08/17/64196.html#Feedback0http://www.aygfsteel.com/machilansing/comments/commentRss/64196.htmlhttp://www.aygfsteel.com/machilansing/services/trackbacks/64196.html一.技术概?

在表现Ş式上QJ2EE是一l规范,?NET更象是一l品。但它们的目的都是ؓ了企业应用提供分布式的,高可靠性的解决Ҏ.它们在架构上有着很多的相g处,下表是一个简单对?

J2EE .NET

通信协议 Remote Method Invocation over Internet InterOrb Protocol (RMI/IIOP)QXML

~程语言 Java C#QVB.NETQCOBOL

q行时环?Java Virtual Machine (JVM) Common Language Runtime (CLR)

胖客L Java Swing Windows Forms

目录服务 Java Naming and Directory Interface (JNDI) Active Directory Services Interface (ADSI)

数据讉K Java Database Connection (JDBC) QJava Connectors ADO.NET

异步消息处理 Java Message Service (JMS) Microsoft Message Queue

表示层技?ServletsQ?Java Server Page(JSP) ASP.NET

中间层组件模?EJBQJavaBean COM+QCOM

安全讉K JAAS COM+ Security

Call Context

事物处理 Java Transaction Server (JTS) Microsoft Distributed Transaction Coordinator (MS-DTC)

开发工?WebGain Visual Café

Borland JBuilder

IBM VisualAge {?

(W三Ҏ供,规范本n没有定义) Visual Studio.NET

J2EEq_的构?

EJB - J2EE 中间层,完成商业逻辑Q?

JAAS - J2EE 处理认证和授权的API;

Java Connectors - J2EE 用于q接异种数据源的APIQ对上层来讲是透明?

JSPQ?Java Servlets - J2EE的表C层技术,用于生成用户界面;

Java Virtual Machine - Java 语言q行环境Q?

JDBC - J2EE数据库访问;

JMS - J2EE的异步消息队列;

JNDI - J2EE的名字查找APIQ独立于目录服务器;

JTS - J2EE用于处理交易的APIQ?

RMI/IIOP - J2EE的分布式对象的通讯APIQ提供了和CORBA交互的能力?

.NETq_构成

.NET Framework - .NET应用q行的基Q?

IL (Intermediary Language) - 所有的.NET语言首先被编译成该中间语aQ然后在CLR中运行;

SOAP - 用于服务讉K的工业标准;

DCOM - lg间通信协议Q?

MS-DTC - 用来?NETq_上用两阶段提交协议来处理分布式交易Q?

CLR - .NET应用的运行时环境Q?

COM+ - .NET的中间层模型Q用于构建商务逻辑Q?

ADO.NET - .NET Ҏ据访问的API?

此外.NETq_q包括其他一些品象Application Center ServerQBizTalk Server QNLBS (Network Load Balancing Service)QCommerce ServerQEnterprise ServersQHIS (Host Integration Server)QISAS (Internet Security and Acceleration Server)用来提供象防火墙Q安全访问,B2B交易Q负载^衡等服务.J2EE规范本n没有定义q些服务Q但可通过选择W三方品来满cM的要求?

?技术比?

1.一 vs ?

一U语avs多种语言Q一个^台vs多个q_.q似乎是大家最喜于z|乐道的话题,也似乎是所有问题的焦点?

两种q_L的开发语aJava和C#在架构上有着惊h的相|虚拟机技术,Z沙箱的安全模型,分层的命名空_垃圾回收{。所以从W一眼看上去QC#直就是Java的克隆。但微Yq不q样认ؓQ微软的说明是:“它集成了C++Q?JavaQModula 2QC和Smalltalk{多U语a的精华,对它们共同的核心思想象深度面向对?deep object-orientation)Q对象简?(object-simplification){都一一做了参考。”一斚wQC#的大多数关键字来源于C++Q它在书写上有别于Java。但另一斚wQC#的严格的cd转换{概念却明显来自于Java(当然Q它的原始类型的定义更严|q且据微软声U没有媄响到效率.)Q其在内涵上有克隆之嫌.但即是JavaQ其有些Ҏ也和Smalltalk颇有渊源.所以评价一U开发语a的优劣不仅是看其外在的表现Ş式,更重要的是其实实在在的功?作ؓ一U新语言QC#加入了基于XML的标讎ͼ可以被编译器用来直接生成文档QC#的另一个特?一站式软g(one-stop-shopping software)了自解释( self-describing) 的编码方式,卛_文gQIDL(Interface Definition Language)QGUID和其他复杂的接口无需再被引用.也即是C#QVB.NET{代码片断可以Q意的被加入到其他语言?q无疑在多种语言混合~程的模式中是一ơ飞跃,但是Q其隄护性也是不a而喻的?

微Y?NET的^台提供了象C#QVB.NETQCOBOL{多U开发语aQC#是新的,而其他的每一U语a都是在原有的基础上改造而来.q是微Y煞费苦心q且也是不得以的要ؓ习惯于这些语a的程序员Z条便捷之?但是Q这些语a的改造与其说是整容到不如说是一ơ开膛破肚的大手?首先是观念变了,BasicQCobol{语a先天的缺面向对象的内涵Q现在却变成了面向对象的语言Q这׃是要求其传统的程序员仅仅熟悉一些额外的关键字那么简单的问题?Z面向对象的Y件分析设计开发测试是完全不同于基于传l过E性语a的质变,所以这一q程的{变对传统E序员来讲也是一个痛苦和漫长的过E?在传l程序员面前Q微软看似提供了丰富多采的解x法,但对于实际问题而言Q却怕是有些力不从心.所以一个简单的办法?直接使用C#.对于独立软g开发商来讲Q其转换成本不容忽视.其次Q在一个Y仉目中使用多种语言Q开发商必须同时拥有多种语言专家和多个独立的难以互相支援的开发小l,无疑的,q也使其软g的维护的成本已非U性的曲线增长.多样性是双韧剑,实施旉仔细斟酌.

跨^台是J2EE的最大卖点,也是至今为止q绊住微软的栅栏.当开发商完成了符合J2EE规范的Y件时Q其客户可以依据其喜好和实力来选择不同应用服务?从基于open source的免费Y件到高端满B2B需求的商业套g来搭qq_.但是׃J2EE的规范还不完善,各个J2EE服务器的提供商ؓ了其提供其各自理解的完整的功能Q不得不d一些额外的Ҏ?q就使得使用了这些特别功能的应用软gQ绑定到了特定的应用服务器上.随着J2EE规范的发展,q种差别会逐渐减小.

微Y的跨q_解决Ҏ是Web servicesQ它解决的是异种q_上不同应用之间的q通性问?从技术角度讲Q它除了以XMLZ质之外没有什么新?但它的重要意义在?它是微Yq样一个重量选手所推出的,前景不容视.构造和使用 Web services 的过E较为简?

服务提供者用他所选择的语a构造服?

服务提供者用WSDL(the Web Services Description Language)来定义该服务;

服务提供者在UDDI (Universal DescriptionQ?DiscoveryQ?and Integration )中注册该服务;

使用者的应用E序?UDDI中查扑ַ注册服务;

使用者的应用E序通过 SOAP (the Simple Object Access Protocol )来调用服?(SOAP使用HTTP来传递基于XML现Ş式的参数)

正如我们所讨论? Web services解决的是异构q_上服务连通性的问题Q但在现实中所更迫切需要的是如何在异构的^C构造具有可扩展性,高可靠性,高可用性,故障冗余Q错误恢复能力的企业应用.~少q一点,从结构上Ԍ.NETq_q远未完?

2.中间?

Zlg的Y件开发技术可以在较高的别上实现软g复用Q加快企业Y件开发的q程.在J2EE构架中, JavaBean和EJB(Enterprise JavaBeans) 被用来完成事物逻辑.其中EJB?JavaBean 有着cM的模型,但它被用来创建分布式的企业应?它定义服务器端组件的模型Q具有以下一些特?

生存期模型;

讉K模型Q?

安全模型Q?

事物处理模型Q?

会话处理模型Q?

数据装模型Q?

部v模型

Ҏq些模型Q简单的~码可完成复杂的功能?

在微软的.NETq_中,旧的COM ?COM+的组件模型被新的lg模型所代替。增加了象基于沙q安全模型和垃圑֛收等功能.q且实现了多重接口承,扩展的元数据和新的代理模型等.旧有的COM和COM+lg也可被映到新的q行环境中?

lg所qͼ两众架构在基于组件的中间层的设计上各有千U,对于创徏分布式的Q复杂的Q高效的Q高可靠性的的应用程序都有着_的能力?

3.表示?

两种架构都同时支持胖客户端和瘦客L.即C/S模式和B/S模式.对于C/S模式QJ2EE提供了替代Java AWT的Java SwingQ同时作为可视化lg的JavaBean也可用来构造系l。对于B/Sl构的表C层QJ2EE使用 servlet QJSP(Java Server Page) QHMTLQWMLQXML{工h实现?

微Y的胖客户端技术则?Windows Forms代替了MFC.它们L作用相同Q在l构?Windows Forms 被插入到.NET的运行时框架(runtime framework)和组件模?(component model)?在瘦客户模型中, ASP.NET代替了旧有的ASP?HMTLQ?WML QXML作ؓ表示层。在 ASP.NET 中,C#QVB.NET{语a的代码片断可被自由引?ASP.NET 面被首先{换成中介语言( Intermediary Language)Q然后再?中介语言及时~译?just-in-time IL compiler)~译Q最后运行于公共语言q行环境中,q且 ASP.NET 提供了页面的~冲Q所以,其运行速度要远q快于ASP?

大体上,两种架构所使用的表C层的技术非常类|虽在l节上各有所长,但M功能当在伯仲之间?

4.数据讉K

J2EE ?.Net 已不同的形式支持数据的访问。JDBC和ADO一样和所q接的数据库无关Qƈ且通过q接Q命令语句和l果集来Ҏ据进行操?所以属于中间层ơ的 API.更高一U的数据装和数据管理是通过实体EJB (entity EJB)来完成的.Z容器理的实体EJB使开发更快捷Q管理更方便.事实上,׃实体EJB的load()和store()Ҏ的同步机Ӟ大大缓解因q发而数据库生的瓉.也可以采用不属于J2EE规范的第三方数据讉K工具Q象WebGain?TopLink?

而微软的.NET的数据访问工具则由基于XML的ADO.NET代替了基于COMlg的ADO.M以XML出的数据源都可以作ؓ ADO.NET 的数据源.相应的结果集升为数据集 (DataSets)Q命令语句则升为数据集命o(DataSetCommands).从Ş式来看,微Y的ADO.NET更新潮和旉一些,ZXML的特性其可以处理极其丰富的数据源,q且Q因其构架在HTTP协议之上Q易于穿透防火墙Q沟通更Z?但由于XML本n的基于标记的Ҏ,很明N制了在有大数据量和有网l瓶颈的应用中的使用.而J2EE的数据访问规则则昑־略有单薄Q但同时却更单,更有?q且通过对应用程序有效的层次的设计,对于数据库和ZXML的数据源的访问,也是可以无缝的整合的?

?整体评h

在微软还没有以和Javaq_相对抗的产品的时候,微Y所乐于做是大声的宣?"write onceQ?debug everywhere"。而它的对手则更乐于这栯价它:"微Y开始也喜欢JavaQ他们喜Ƣ它的方式是让它dQ他们当然也憎恨它,他们甚至憎恨每一个以J开头的单词?但是现在QŞ式不同了Q微软有了以自豪的.NET他们可以已他们自己所喜好的方式来对J2EE?NET来做各种比较。最热闹的应该算是微软出C的W三方对.NET Pet Shop和J2EE?Pet Store的综合比较了.有兴的读者可以到MSDNQwww.onjava.comQIBM开发者原地等|站看到相关评论?

J2EE .NET

易用?** ***

扩展能力 *** **

多^台支?**** *

多语a支持 * ****

可靠?*** ***

性能 *** ***

可管理?*** ***

重用?**** **

负蝲q *** ***

开放标?***** *

׃业而言Q内部众多系l的整合、系l的延展性、安全性是更需要注意的议题Q而这些都是J2EE的优势,也是微Y的不_?在效率方面,J2EE阵营d通过g的效能增加来弥补软g的不?开放标准,功能强大Q易于移植这些都是J2EE的卖炏V但让h奇怪的是IBM的WebSphere和BEA的WebLogic在J2EE市场占了大半壁江山,而作则制定者的SUN却在做壁上观?

微Y实提供了从桌面的办公YӞ开发工P到后台服务器数据库的全方位的产品?但统一q_的用者可能要牺牲跨^台的好处Qƈ也有可能由此p无穷无尽的锁定在微Y的许可证的汪z中.更简单,更快P更高效是微Y的目标,随着时代的发展,我们也许会看到更完美的技术解x案?



Lansing 2006-08-17 19:45 发表评论
]]>
创徏Web应用和Struts框架的配|文?/title><link>http://www.aygfsteel.com/machilansing/archive/2006/08/17/64195.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 11:43:00 GMT</pubDate><guid>http://www.aygfsteel.com/machilansing/archive/2006/08/17/64195.html</guid><wfw:comment>http://www.aygfsteel.com/machilansing/comments/64195.html</wfw:comment><comments>http://www.aygfsteel.com/machilansing/archive/2006/08/17/64195.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/machilansing/comments/commentRss/64195.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/machilansing/services/trackbacks/64195.html</trackback:ping><description><![CDATA[ <p> <b>创徏Web应用的配|文?/b> </p> <p>对于Struts应用Q它的配|文件web.xml应该对ActionServletc进行配|,此外Q还应该声明Web应用所使用的Struts标签库,本例中声明用了三个标签? Struts Bean、Struts HTML和Struts Logic标签库。例E?为web.xml的源代码?/p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6">例程1 web.xml<br /><br /><?xml version="1.0" encoding="UTF-8"?><br /><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"<br />"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"><br /><br />< web-app ><br /><br />< display-name > <br />HelloApp Struts Application<br /></display-name ><br /><br /><!-- Standard Action Servlet Configuration --><br /><br />< servlet ><br /><br />< servlet-name > action </servlet-name ><br /><br />< servlet-class > <br />org.apache.struts.action.ActionServlet<br />< /servlet-class > <br /><br />< init-param > <br />< param-name> config< /param-name > <br />< param-value><br />/WEB-INF/struts-config.xml<br /></param-value ><br /></init-param ><br /><br />< load-on-startup>2</load-on-startup ><br /><br /></servlet><br /><br /><!-- Standard Action Servlet Mapping --><br /><br />< servlet-mapping><br /><br />< servlet-name > action</servlet-name><br /><br />< url-pattern>*.do</url-pattern><br /><br /></servlet-mapping><br /><br /><!-- The Usual Welcome File List --><br /><br />< welcome-file-list><br /><br />< welcome-file > hello.jsp</welcome-file><br /><br /></welcome-file-list><br /><br /><!-- Struts Tag Library Descriptors --><br /><br />< taglib ><br /><br />< taglib-uri ><br />/WEB-INF/struts-bean.tld<br /></taglib-uri><br /><br />< taglib-location><br />/WEB-INF/struts-bean.tld<br /></taglib-location><br /><br /></taglib><br /><br />< taglib ><br /><br />< taglib-uri ><br />/WEB-INF/struts-html.tld<br /></taglib-uri ><br /><br />< taglib-location ><br />/WEB-INF/struts-html.tld<br /></taglib-location ><br /><br /></taglib ><br /><br />< taglib ><br /><br />< taglib-uri ><br />/WEB-INF/struts-logic.tld<br /></taglib-uri ><br /><br />< taglib-location ><br />/WEB-INF/struts-logic.tld<br /></taglib-location ><br /><br /></taglib ><br /><br /></web-app ></td> </tr> </tbody> </table> <center> </center> <p> <b>创徏Struts框架的配|文?/b> </p> <p>正如前面提及的,Struts框架允许把应用划分成多个lgQ提高开发速度。而Struts框架的配|文件struts-config.xml可以把这些组件组装v来,军_如何使用它们。例E?是helloapp应用的struts-config.xml文g的源代码?/p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>例程2 struts-config.xml<br /><?xml version="1.0" encoding="ISO-8859-1" ?><br /><!DOCTYPE struts-config<br /> PUBLIC"-//Apache Software Foundation<br />//DTD Struts Configuration 1.1//EN"<br /> "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"><br /><br /><!--This is the Struts configuration file <br />for the "Hello!" sample application--><br />< struts-config><br /><!-- ===== Form Bean Definitions ====== --><br />< form-beans><br />< form-bean name="HelloForm" type="hello.HelloForm"/><br /></form-beans><br /><!-- ====== Action Mapping Definitions ====== --><br /> < action-mappings><br /> <!-- Say Hello! --><br /> < action path="/HelloWorld" <br /> type="hello.HelloAction"<br /> name="HelloForm"<br /> scope="request"<br /> validate="true"<br /> input="/hello.jsp"<br />><br />< forward name="SayHello" path="/hello.jsp" /><br /></action ><br /></action-mappings ><br /><!-- ===== Message Resources Definitions ===== --><br />< message-resources parameter="hello.application"/><br /></struts-config ></pre> </td> </tr> </tbody> </table> <br /> <br />以上代码对helloapp应用的HelloForm、HelloAction和消息资源文件进行了配置Q首先通过<form-bean>元素配置了一个ActionForm BeanQ名叫HelloFormQ它对应的类为hello.HelloFormQ?br /><br /><form-bean name="HelloForm" type="hello.HelloForm" /><br /><br />接着通过元素配置了一个Actionlg:  <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre>< action<br /> path = "/HelloWorld"<br /> type ="hello.HelloAction"<br /> name = "HelloForm"<br /> scope = "request"<br /> validate = "true"<br /> input = "/hello.jsp"<br />><br />< forward name="SayHello" path="/hello.jsp" /><br /></action ></pre></td></tr></tbody></table><p><action>元素的path属性指定请求访问Action的\径,type属性指定Action的完整类名,name属性指定需要传递给Action的ActionForm BeanQscope属性指定ActionForm Bean的存放范_validate属性指定是否执行表单验证,input属性指定当表单验证p|时的转发路径?action>元素q包含一?forward>子元素,它定义了一个请求{发\径?br /><br />本例中的 <action>元素配置了HelloActionlgQ对应的cMؓhello.HelloActionQ请求访问\径ؓ"HelloWorld"Q当Actionc被调用ӞStruts框架应该把已l包含表单数据的HelloForm Bean传给它。HelloForm Bean存放在request范围内,q且在调用ActioncM前,应该q行表单验证。如果表单验证失败,h被转发到接收用戯入的|页hello.jspQ让用户U正错误?/action></forward></action></action></p><p>struts-config.xml文g最后通过元素定义了一个Resource BundleQ元素的parameter属性指定Resource Bundle使用的消息资源文件。本例中parameter属性ؓ"hello.application"Q表明消息资源文件名?application.properties"Q它的存放\径ؓWEB-INF/classes/hello/application.properties?/p></form-bean><img src ="http://www.aygfsteel.com/machilansing/aggbug/64195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/machilansing/" target="_blank">Lansing</a> 2006-08-17 19:43 <a href="http://www.aygfsteel.com/machilansing/archive/2006/08/17/64195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts框架技术在J2EE中的研究和应?/title><link>http://www.aygfsteel.com/machilansing/archive/2006/08/17/Struts.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 11:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/machilansing/archive/2006/08/17/Struts.html</guid><wfw:comment>http://www.aygfsteel.com/machilansing/comments/64193.html</wfw:comment><comments>http://www.aygfsteel.com/machilansing/archive/2006/08/17/Struts.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/machilansing/comments/commentRss/64193.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/machilansing/services/trackbacks/64193.html</trackback:ping><description><![CDATA[ <p> <span id="wmqeeuq" class="top11"> <strong>J2EE?/strong> </span> </p> <p> <span id="wmqeeuq" class="top11"> <strong> <br /> <br /> </strong>J2EE是一个开攄、基于标准的q_Q可以开发、部|和理N层结构的、面向Web的、以服务器ؓ中心的企业应用Q它是利用Java 2 q_来简化与多企业解决Ҏ的开发、部|和理相关的诸多复杂问题的应用体系l构?br /><br />J2EEq_采用一个多层次分布式的应用模式。这意味着应用逻辑Ҏ功能被划分成lgQ组成J2EE应用的不同应用组件安装在不同的服务器上,q种划分是根据应用组件属于多层次J2EE环境中的哪一个层ơ来军_的。如?所C,J2EE应用可以׃或四个层ơ组成,J2EE多层ơ应用一般被认ؓ是三层应用,因ؓ它们是被分布在三个不同的地点Q客L机器、J2EE服务器和数据库或后端的传l系l服务器。三层架构应用是Ҏ准的客户?服务器应用架构的一U扩展, 卛_客户端应用和后台存储之间增加一个多U程应用服务器?<br /><br /></span> </p> <center> <img style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid" src="http://java.ccidnet.com/col/attachment/2006/4/663945.gif" /> </center> <p> <br /> <br />J2EE体系包括JSP、Servlet、EJB、WEB SERVICE{多Ҏ术。这些技术的出现l电子商务时代的WEB应用开发提供了一个非常有竞争力的选择。怎样把这些技术组合v来,形成一个适应目需要的E_架构是项目开发过E中一个非帔R要的步骤?br /><br />一个成功的软g需要有一个成功的架构Q但软g架构的徏立是一个复杂而又持箋改进的过E,软g开发者们不可能对每个不同的项目做不同的架构,而L量重用以前的架构,或开发出量通用的架构方案,Struts是行的基于J2EE的架构方案之一Q其他常用的ZJ2EE的架构方案还有Turbine、RealMothods{。本文主要探讨Struts框架技术的应用?br /><br /><b>J2EE应用E序架构的发?/b><br /><br />在J2EE应用E序架构的发展\E中Q主要经历了两个大的阶段Q?br /><br />1、Model 1<br /><br />在JSP面中结合业务逻辑、服务器端处理程序和HTMLQ在JSP面中同时实现显C、业务逻辑和流E控Ӟ从而快速的完成Web应用开发。这U模型的不之处Q?Q不利于应用扩展和更新?Q业务逻辑和表C逻辑混合在JSP面中没有进行抽象和分离Q不利于应用pȝ业务的重用和改动?br /><br />2、Model 2<br /><br />表示的是ZMVC模式的框架。根据Model 2Qservlet 处理数据存取和导航流Q?JSP处理表现。Model 2 使Java 工程师和HTML设计者分别工作于它们所擅长和负责的部分。Model 2应用的一部分发生改变q不强求其他部分也跟着发生改变。HTML 开发h员可以改变程序的外观和感觉,q不需要改变后端servlet的工作方式。把应用逻辑、处理过E和昄逻辑分成不同的组件实现。I补了Model1的不?br /><br /><strong>Struts框架技?/strong><br /><br />Struts 框架是ZModel 2 的架构,也就是基于MVC模式的框架技术。它是一个免费的开源的WEB层的应用框架,h很高的可配置性,和有一个不断增长的Ҏ列表。一个前端控制组Ӟ一pd动作c,动作映射Q处理XML的实用工LQ服务器端java bean 的自动填充,支持验证的WEB 表单Q国际化支持Q生成HTMLQ实现表现逻辑和模板组成了struts的灵。图2昄了Strutslg是如何一起工作的?br /><br /></p> <center> <img style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid" src="http://java.ccidnet.com/col/attachment/2006/4/663947.gif" /> </center> <p> <br /> <br />Struts 的ActionServlet 控制D。其他Struts c,比如Action, 用来讉K业务逻辑cR当 ActionServlet 从容器接收到一个请求,它用URI (或者\径“path? 来决定哪个Action 用来处理请求。一?Action可以校验输入Qƈ且访问业务层以从数据库或其他数据服务中检索信息?br /><br />为校验输入或者用输入来更新数据库, Action 需要知道什么被提交上来。ƈ不是强制每个Action 从请求中抓取q些|而是?ActionServlet 输入绑定到JavaBean中。输?bean是Struts ActionForm ccȝ子类。ActionServlet 通过查找h的\径可以决定用哪个ActionFormQAction 也是通过同样的方法选取的。每个Action都必MHTTP 响应q行应答?通常, Struts Action q不自行加工响应信息Q而是请求{发到其他资源Q比如JSP 面。Struts 提供一个ActionForward c,用来一个页面的路径存储为逻辑名称。当完成业务逻辑后,Action 选择q向Servletq回一个ActionForward。Servlet 然后使用存储在ActionForward 对象中的路径来调用页面完成响应?br /><br />Struts 这些细节都l定在一个ActionMapping 对象中。每个ActionMapping 相对于一个特定的路径。当某个路径被请求时QServlet 查询ActionMapping 对象。ActionMapping对象告诉servlet哪个Actions?ActionForms ?ActionForwards 被使用?br /><br />所有这些细节,关于ActionQ?ActionFormQ?ActionForwardQ?ActionMappingQ以及其他一些东西,都在struts-config.xml 文g中定义?ActionServlet 在启动时dq个配置文gQƈ创徏一个配|对象数据库。在q行ӞStruts 应用Ҏ的是文g创徏的配|对象,而不是文件本w?br /><br /><b>ZStruts框架的应用设计实?/b><br /><br />本文以“面向铸造行业的|络化制造ASPq_开发”项目中的Y件租用模块ؓ例,来说明如何设计基于Struts框架的Web应用。在该模块中Q用户合法登陆网站后Q可以根据需要选择所要租用的软gcd及Y件中的功能模块,认信息提交服务器后Q用户将收到pȝl予的登陆密码,用户卛_登陆|站Q在U用租用YӞ实行业务托管?br /><br />Ҏ目需求分?定该系l必d备的性能?1)良好的交互?工作内容中有相当大的部分是hZ?q就要求pȝ的交互性要强?)较好的可扩展?工作的内容和形式h多变?要求pȝh良好的可扩展性?)良好的可l护?pȝ投入使用?主要是由理员承担系l维护的工作,l护人员不定期变?q就要求pȝ的可l护性强?)h较好的跨q_?用户可能使用各种不同的操作系l?而且Z适应今后可能的变?pȝ应具有较好的跨^台性。基于以上四?在开发Y件租用模块时,采用J2EE~程环境,q相应采用了专ؓJ2EE定制的Struts框架?br /><br />做基于Struts框架的项目开?关键是要有一个好的整体模?计划好系l中包括哪几个模?每个模块各需要什么样的FormBean、JavaBean,各种处理l果都通过哪些JSP面来展?同时配置好struts-config.xml文g。本pȝ的设计模型如?所C?br /><br /></p> <center> <img style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid" src="http://java.ccidnet.com/col/attachment/2006/4/663949.gif" /> </center> <p> <br /> <br />ActionServlet接受所有的HTTPh,然后Ҏ配置文g的内?军_请求映到哪一个Action对象,本系l中有两个Action对象,分别对应着登陆q程软g(LogonAction)和系l反馈密?MailAction)?br /><br />LogonAction首先会验证用h否已l登?如果没有d则重定向到登录页?Logon.jsp),验证通过后根据请求参数决定下一步的处理,如果用户q没有选择U用软gQ则转到软g介绍U用界面QQuery.jspQ,选择需要租用的软g或Y件的某些模块Q提交信息后QMailAction使服务器向用h交密码,用户接收到密码后Q登陆运行Y件?br /><br />如果用户登陆软g成功Q则通过配置文gstruts-config.xml中的ActionForwardQ通过GetInfo对象把该用户U用的Y件信息读取道FormBean中,然后调用JSP面昄Bean里的数据。如果是保存数据信息,则调SaveInfo对象FormBean里保持的信息存入数据库;如果是修改信?则调ModifyInfo对象FormBean里保持的修改后的信息存入数据库;如果是删除数据信?则调用DeleteInfo对象FormBean里保持的信息从数据库中删除?br /><br />l过q样设计的系l?用户界面和数据处理已l完全分?再加上在JSP面中用了自定义标?佉K面中没有了Java的脚本代?q样Web界面的设计和后端E序的编写就有了清晰的界U?便于开发团队的分工,q且l护h也很方便?br /><br /><b>l束?/b><br /><br />Struts是一U非怼U的基于J2EE的MVC应用框架,虽然从正式发布到现在也只有两q多的时?但它已经来多地运用于企业q_之上,许多大型|站已成功地应用了Struts框架。本文在ȝ了Struts框架技术及其工作原理的基础上,l合“面向铸造行业的|络化制造ASPq_开发”项目,提出了在U租用模块的设计思\,qؓ今后更好的应用采用Struts框架提供了参考?/p> <img src ="http://www.aygfsteel.com/machilansing/aggbug/64193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/machilansing/" target="_blank">Lansing</a> 2006-08-17 19:36 <a href="http://www.aygfsteel.com/machilansing/archive/2006/08/17/Struts.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java多线E-QBusyFlag或Lockhttp://www.aygfsteel.com/machilansing/archive/2006/08/17/BusyFlag_Lock.htmlLansingLansingThu, 17 Aug 2006 11:30:00 GMThttp://www.aygfsteel.com/machilansing/archive/2006/08/17/BusyFlag_Lock.htmlhttp://www.aygfsteel.com/machilansing/comments/64190.htmlhttp://www.aygfsteel.com/machilansing/archive/2006/08/17/BusyFlag_Lock.html#Feedback0http://www.aygfsteel.com/machilansing/comments/commentRss/64190.htmlhttp://www.aygfsteel.com/machilansing/services/trackbacks/64190.htmlJava语言内置了synchronized关键字用于对多线E进行同步,大大方便了Java中多U程E序的编写。但是仅仅用synchronized关键字还不能满对多U程q行同步的所有需要。大家知道,synchronized仅仅能够Ҏ法或者代码块q行同步Q如果我们一个应用需要跨多个方法进行同步,synchroinzed׃能胜M。在C++中有很多同步机制Q比如信号量、互斥体、届区{。在Java中也可以在synchronized语言Ҏ的基础上,在更高层ơ构L同步工具Q以方便我们的用?br />    当前Q广Z用的是由Doug Lea~写的一个Java中同步的工具包,可以在这儿了解更多这个包的详l情况:
    http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
    该工具包已经作ؓJSR166正处于JCP的控制下Q即作为JDK1.5的正式组成部分。本文ƈ不打详l剖析这个工具包Q而是对多U同步机制的一个介l,同时l出q类同步机制的实例实玎ͼqƈ不是工业U的实现。但其中会参考Doug Lea的这个同步包中的工业U实现的一些代码片断?br />    本例中还沿用上篇中的Accountc,不过我们q儿~写一个新的ATMcL模拟自动提款机,通过一个ATMTester的类Q生?0个ATMU程Q同时对John账户q行查询、提Ƒ֒存款操作。Accountcd了一些改动,以便适应本篇的需要:

  1. import  java.util.HashMap;
  2. import  java.util.Map;
  3. class  Account {
  4.     String name;
  5.     //float amount;
  6.     
  7.     //使用一个Map模拟持久存储
  8.     static Map storage = new HashMap();
  9.     static {
  10.         storage.put("John"new Float(1000.0f));
  11.         storage.put("Mike"new Float(800.0f));
  12.     }    
  13.     
  14.     
  15.     public Account(String name) {
  16.         //System.out.println("new account:" + name);
  17.         this.name = name;
  18.         //this.amount = ((Float)storage.get(name)).floatValue();
  19.     }
  20.     public synchronized void deposit(float amt) {
  21.         float amount = ((Float)storage.get(name)).floatValue();
  22.         storage.put(name, new Float(amount + amt));
  23.     }
  24.     public synchronized void withdraw(float amt) throws InsufficientBalanceException {
  25.         float amount = ((Float)storage.get(name)).floatValue();
  26.         if (amount >= amt)
  27.             amount -= amt;
  28.         else 
  29.             throw new InsufficientBalanceException();
  30.                 
  31.         storage.put(name, new Float(amount));
  32.     }
  33.     public float getBalance() {
  34.         float amount = ((Float)storage.get(name)).floatValue();
  35.         return amount;
  36.     }
  37. }



在新的AccountcMQ我们采用一个HashMap来存储̎户信息。Account由ATMc通过logind后用:

  1. public  class ATM {
  2.     Account acc;
  3.     
  4.     //作ؓ演示Q省略了密码验证
  5.     public boolean login(String name) {
  6.         if (acc != null)
  7.             throw new IllegalArgumentException("Already logged in!");
  8.         acc = new Account(name);
  9.         return true;
  10.     }
  11.     
  12.     public void deposit(float amt) {
  13.         acc.deposit(amt);
  14.     }
  15.     
  16.     public void withdraw(float amt) throws InsufficientBalanceException  {
  17.             acc.withdraw(amt);
  18.     }
  19.     
  20.     public float getBalance() {
  21.         return acc.getBalance();
  22.     }
  23.     
  24.     public void logout () {
  25.         acc = null;
  26.     }
  27.     
  28. }
  29. 下面是ATMTesterQ在ATMTester中首先生成了10个ATM实例Q然后启?0个线E,同时dJohn的̎P先查询余额,然后Q再提取余额?0Q,然后再存入等额的ƾ(以维持最l的余额的不变)。按照我们的预想Q应该不会发生金额不的问题。首先看代码Q?br />

    1. public  class ATMTester {
    2.     private static final int NUM_OF_ATM = 10;
    3.     public static void main(String[] args) {
    4.         ATMTester tester = new ATMTester();
    5.         
    6.         final Thread thread[] = new Thread[NUM_OF_ATM];
    7.         final ATM atm[] = new ATM[NUM_OF_ATM];
    8.         for (int i=0; i
    9.             atm[i] = new ATM();
    10.             thread[i] = new Thread(tester.new Runner(atm[i]));
    11.             thread[i].start();
    12.         }    
    13.         
    14.     }
    15.     
    16.     class Runner implements Runnable {
    17.         ATM atm;
    18.         
    19.         Runner(ATM atm) {
    20.             this.atm = atm;
    21.         }
    22.         
    23.         public void run() {
    24.             atm.login("John");
    25.             //查询余额
    26.             float bal = atm.getBalance();
    27.             try {
    28.                 Thread.sleep(1); //模拟Z查询到取ƾ之间的间隔
    29.             } catch (InterruptedException e) {
    30.                 // ignore it
    31.             } 
    32.             
    33.             try {
    34.                 System.out.println("Your balance is:" + bal);
    35.                 System.out.println("withdraw:" + bal * 0.8f);
    36.                 atm.withdraw(bal * 0.8f);
    37.                 System.out.println("deposit:" + bal * 0.8f);
    38.                 atm.deposit(bal * 0.8f);
    39.             } catch (InsufficientBalanceException e1) {
    40.                 System.out.println("余额不Q?);
    41.             } finally {
    42.                                     atm.logout();
    43.                            }
    44.         }
    45.     }
    46. }


    q行ATMTesterQ结果如下(每次q行l果都有所差异Q:

    Your balance is:1000.0
    withdraw:800.0
    deposit:800.0
    Your balance is:1000.0
    Your balance is:1000.0
    withdraw:800.0
    withdraw:800.0
    余额不Q?br />Your balance is:200.0
    Your balance is:200.0
    Your balance is:200.0
    余额不Q?br />Your balance is:200.0
    Your balance is:200.0
    Your balance is:200.0
    Your balance is:200.0
    withdraw:160.0
    withdraw:160.0
    withdraw:160.0
    withdraw:160.0
    withdraw:160.0
    withdraw:160.0
    withdraw:160.0
    deposit:160.0
    余额不Q?br />余额不Q?br />余额不Q?br />余额不Q?br />余额不Q?br />余额不Q?br />
    Z么会出现q样的情况?因ؓ我们q儿是多个ATM同时对同一账户q行操作Q比如一个ATM查询Z余额?000Q第二个ATM也查询出了余?000Q然后两者都期望提取?00Q那么只有第1个用戯够成功提出,因ؓ在第1个提?00后,账户真实的余额就只有200了,而第二个用户仍认Z额ؓ1000。这个问题是׃多个ATM同时对同一个̎戯行操作所不可避免产生的后果。要解决q个问题Q就必须限制同一个̎户在某一时刻Q只能由一个ATMq行操作。如何才能做到这一点?直接通过synchronized关键字可以吗Q非帔R憾!因ؓ我们现在需要对整个Account的多个方法进行同步,q是跨越多个Ҏ的,而synchronized仅能Ҏ法或者代码块q行同步。在下一我们将通过~写一个锁对象辑ֈq个目的?

我们首先开发一个BusyFlag的类Q类gC++中的Simaphore?br />

  1. public  class BusyFlag {
  2.     protected Thread busyflag = null;
  3.     protected int busycount = 0;
  4.     
  5.     public synchronized void getBusyFlag() {
  6.         while (tryGetBusyFlag() == false) {
  7.             try {
  8.                 wait();
  9.             } catch (Exception e) {}            
  10.         }
  11.     }
  12.     
  13.     private synchronized boolean tryGetBusyFlag() {
  14.         if (busyflag == null) {
  15.             busyflag = Thread.currentThread();
  16.             busycount = 1;
  17.             return true;
  18.         }
  19.         
  20.         if (busyflag == Thread.currentThread()) {
  21.             busycount++;
  22.             return true;
  23.         }
  24.         return false;        
  25.     }
  26.     
  27.     public synchronized void freeBusyFlag() {
  28.         if(getOwner()== Thread.currentThread()) {
  29.             busycount--;
  30.             if(busycount==0) {
  31.                 busyflag = null;
  32.                                      notify();
  33.                             }
  34.         }
  35.     }
  36.     
  37.     public synchronized Thread getOwner() {
  38.         return busyflag;
  39.     }
  40. }


注:参考Scott Oaks & Henry Wong《Java Thread?br />
BusyFlag?个公开ҎQgetBusyFlag, freeBusyFlag, getOwnerQ分别用于获取忙标志、释攑ֿ标志和获取当前占用忙标志的线E。用这个BusyFlag也非常地单,只需要在需要锁定的地方Q调用BusyFlag的getBusyFlag()Q在寚w定的资源使用完毕Ӟ再调用改BusyFlag的freeBusyFlag()卛_。下面我们开始改造上中的Account和ATMc,q应用BusyFlag工具cM得同时只有一个线E能够访问同一个̎L目标得以实现。首先,要改造Accountc,在Account中内|了一个BusyFlag对象Qƈ通过此标志对象对Accountq行锁定和解锁:

  1. import  java.util.Collections;
  2. import  java.util.HashMap;
  3. import  java.util.Map;
  4. class  Account {
  5.     String name;
  6.     //float amount;
  7.     
  8.     BusyFlag flag = new BusyFlag();
  9.     
  10.     //使用一个Map模拟持久存储
  11.     static Map storage = new HashMap();
  12.     static {
  13.         storage.put("John"new Float(1000.0f));
  14.         storage.put("Mike"new Float(800.0f));
  15.     }
  16.     
  17.     static Map accounts = Collections.synchronizedMap(new HashMap());    
  18.     
  19.     
  20.     private Account(String name) {
  21.         this.name = name;
  22.         //this.amount = ((Float)storage.get(name)).floatValue();
  23.     }
  24.     
  25.     public synchronized static Account getAccount (String name) {
  26.         if (accounts.get(name) == null)
  27.             accounts.put(name, new Account(name));
  28.         return (Account) accounts.get(name);
  29.     }
  30.     public synchronized void deposit(float amt) {
  31.         float amount = ((Float)storage.get(name)).floatValue();
  32.         storage.put(name, new Float(amount + amt));
  33.     }
  34.     public synchronized void withdraw(float amt) throws InsufficientBalanceException {
  35.         float amount = ((Float)storage.get(name)).floatValue();
  36.         if (amount >= amt)
  37.             amount -= amt;
  38.         else 
  39.             throw new InsufficientBalanceException();
  40.                 
  41.         storage.put(name, new Float(amount));
  42.     }
  43.     public float getBalance() {
  44.         float amount = ((Float)storage.get(name)).floatValue();
  45.         return amount;
  46.     }
  47.     
  48.     public void lock() {
  49.         flag.getBusyFlag();
  50.     }
  51.     
  52.     public void unlock() {
  53.         flag.freeBusyFlag();
  54.     }
  55. }

新的Account提供了两个用于锁定的ҎQlock()和unlock()Q供Account对象的客L在需要时锁定Account和解锁AccountQAccount通过委托lBusyFlag来提供这个机制。另外,大家也发CQ新的Account中提供了对Account对象的缓存,同时去除了public的构造方法,改ؓ使用一个静态工厂方法供用户获取Account的实例,q样做也是有必要的,因ؓ我们希望所有的ATM机同时只能有一个能够对同一个Accountq行操作Q我们在Account上的锁定是对一个特定Account对象q行加锁Q如果多个ATM同时实例化多个同一个user的Account对象Q那么仍然可以同时操作同一个̎戗所以,要用这U机制就必须保证Account对象在系l中的唯一性,所以,q儿使用一个Account的缓存,q将Account的构造方法变为私有的。你也可以说Q通过在Accountc锁上进行同步,卛_Account中的BusyFlag对象声明为static的,但这样就使同时只能有一台ATM行操作了。这P在一台ATM机在操作Ӟ全市其它的所有的ATM机都必须{待?br />另外必须注意的一ҎQAccount中的getAccount()Ҏ必须同步Q否则,有可能生成多个Account对象Q因为可能多个线E同时到达这个方法,q监到accounts中没有“John”的Account实例Q从而实例化多个John的Account实例。s

ATMcd需作少量改动,在loginҎ中锁定AccountQ在logoutҎ中解锁:

  1. public  class ATM {
  2.     Account acc;
  3.     
  4.     //作ؓ演示Q省略了密码验证
  5.     public synchronized boolean login(String name) {
  6.         if (acc != null)
  7.             throw new IllegalArgumentException("Already logged in!");
  8.         acc = Account.getAccount(name);
  9.         acc.lock();
  10.         return true;
  11.     }
  12.     
  13.     public void deposit(float amt) {
  14.         acc.deposit(amt);
  15.     }
  16.     
  17.     public void withdraw(float amt) throws InsufficientBalanceException  {
  18.             acc.withdraw(amt);
  19.     }
  20.     
  21.     public float getBalance() {
  22.         return acc.getBalance();
  23.     }
  24.     
  25.     public synchronized void logout () {
  26.         acc.unlock();
  27.         acc = null;
  28.     }
  29.     
  30. }



ATMTestercM需要做M修改卛_同样q行Q同时保证同一个Account同时只能׃个ATMq行操作。解决了上篇提到的多个ATM同时对同一个Accountq行操作造成的问题?br />
在最新的Doug Lea的util.concurrent工具包中Q现处于JSR166Q提供了cM的ƈ发实用类QReentrantLockQ它实现了java .util.concurrent.locks.Lock接口Q将在JDK1.5中发布)Q它的作用也cM于我们这儿的BusyFlagQ实现机制、用方法也怼。但q是一个工业强度的可重入锁的实现类。在ReentrantLock的API文档中有它的使用CZQ?br />

  1.      Lock l = ...; 
  2.      l.lock();
  3.      try {
  4.          // access the resource protected by this lock
  5.      } finally {
  6.          l.unlock();
  7.      }


Lansing 2006-08-17 19:30 发表评论
]]>
Java企业应用QHibernate实战全解http://www.aygfsteel.com/machilansing/archive/2006/08/17/Java_Hibernate.htmlLansingLansingThu, 17 Aug 2006 11:26:00 GMThttp://www.aygfsteel.com/machilansing/archive/2006/08/17/Java_Hibernate.htmlhttp://www.aygfsteel.com/machilansing/comments/64189.htmlhttp://www.aygfsteel.com/machilansing/archive/2006/08/17/Java_Hibernate.html#Feedback0http://www.aygfsteel.com/machilansing/comments/commentRss/64189.htmlhttp://www.aygfsteel.com/machilansing/services/trackbacks/64189.html   Hibernate是一个中间层Q它的目的是把数据库中的关系通过一定的规则映射成ؓ对象Q让Java开发h员不用太多的考虑底层数据库的问题Q只需要像通常情况下管理对象一L理数据。在关系数据库仍持l占据市场的情况下,它很可观。在数据持久化领域,即便是轻量的方案也会是复杂饶舌的,也许如同周杰伦的音乐一样不知所云。在学习它之前,最好先回想一下以前进行数据库开发中遇到的问题和不便Q想想ؓ什么需要一个持久化层,才能知道很多操作的目的是什么,以及Z么要q么qԌ在这个问题上我不惛_更多的叙qͼ因ؓ“长久以来……”这L句式通常longQ不好意思,打不出来Q长Q会Ҏ的键盘和热情造成很大的磨损。如果让我写一本书Q那么我会乐意去叙述什么是数据持久化,它有什么好处等{。废话少_来了?/font>

   首先需要配|环境,下蝲Hibernate 2.1(www.hibernate.org)Q把lib下的*.jard到classpathQ你的数据库JDBC驱动E序也应该在classpath中。打开hibernate.propertiesQ针对你使用的数据库Q配|相应的信息Q比如我使用的是MS SQL ServerQ配|如下:

 ## MS SQL Server

 hibernate.dialect net.sf.hibernate.dialect.SQLServerDialect
 hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver
 hibernate.connection.url jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=zizz
 hibernate.connection.username sa
 hibernate.connection.password

   其中很大部分是已l写好的Q只需要取掉注释即可,我自己只是修改了数据库名U、帐受密码。徏立一个名为zizz的数据库备用?/font>

   然后把这个文件拷贝到你的应用的根目录下?/font>

   我们谈论了很多次映射Q应该首先来看看q个映射是如何完成的。假设一个最单的应用Q写一个功能最单一的留a板,设计的数据有留言的编受留a者名U、留a内容Q还有留a旉。够简单吧Q换做是你打怎么qԌ我猜你要首先建立一个数据库表格Q名字也许叫做guestbook。NoQ这不是面向对象的方式,不妨首先从对象的角度来考虑。我们当然希望每一条留a都以对象的方式呈玎ͼ每个对象应该h的属性有Qid、author、content、time。偷个懒Q没有画UML。下面这个类应该是很Ҏ理解的:

 //GuestBook.java
 package org.bromon.zizz;

 import java.util.*;

 public class GuestBook
 {
 private int id;
 private String author;
 private String content;
 private Calendar time;

 private void setId(int id)
 {
  this.id=id;
 }
 public int getId()
 {
  return(id);
 }

 public void setAuthor(String author)
 {
  this.author=author;
 }
 public String getAuthro()
 {
  return(author);
 }

 public void setContent(String content)
 {
  this.content=content;
 }
 public String getContent()
 {
  return(content);
 }

 public void setTime(Calendar time)
 {
  this.time=time;
 }
 public Calendar getTime()
 {
  return(time);
 }
 }


   基本上是最单的Bean了,如果觉得困难的话Q请你先回火星等我?/p>

   需要注意的是setIdҎ被指定ؓprivateQ这是因为我希望用这个字D做主键Q它最好由pȝ自动生成Q所以不应该qh指定Q这个方法专为Hibernate准备Q所以是U有的?/p>

   如何把这个类与数据库映射hQ看看Hibernate的魔法,使用一个XML文g来描qͼ它应该被命名为GuestBook.hbm.xmlQ?/p>

 &lt ?xml version="1.0"? &gt
 &lt !DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt

 &lt hibernate-mapping package="org.bromon.zizz" &gt
    &lt class name="GuestBook" table=”guestbook" lazy="true" &gt
        &lt id name="id" type="integer" unsaved-value="null" &gt
   &lt column name="id" sql-type="int" not-null="true"/ &gt
   &lt generator class="identity"/ &gt
  &lt /id &gt
       
  &lt property name="author" column="author" not-null="true" unique="false"/ &gt
 &lt property name="content" column="content" not-null="true"/ &gt
  &lt property name="time" column="time" not-null="true"/ &gt
    &lt /class &gt
 &lt /hibernate-mapping &gt

 虽然有点陌生Q但是很易读Q仔l琢一下?/p>

 下面来编写我们的应用Q它的功能是插入数据Q?/p>

 //Operate.java
 package org.bromon.zizz;
 import net.sf.hibernate.*;
 import net.sf.hibernate.cfg.*;
 import net.sf.hibernate.tool.hbm2ddl.*;
 import java.util.*;

 public class Operate
 {
 public static void main(String args[])
 {
  try
  {
   Configuration cfg=new Configuration().addClass(GuestBook.class);
   SessionFactory sessions=cfg.buildSessionFactory();
   new SchemaExport(cfg).create(true,true);
   Session session=sessions.openSession();
  
   GuestBook gb=new GuestBook();
   gb.setAuthor(“Bromon?;
   gb.setContent(“留a的内容?;
   gb.setTime(Calendar.getInstance());
  
   Transaction ts=session.beginTransaction();
   session.save(gb);
   ts.commit();
   session.close();
  }catch(Exception e)
  {
   System.out.println(e);
  }
 }
 }
   ~译吧:javac –d . *.java
   执行一下:java org.bromon.zizz.Operate

 到数据库里面看看Q表格已l徏立好了,q且数据也已l保存。如果把

 new SchemaExport().create(true,true);

 注释掉,那么pȝ不会创徏表格Q而只是在已有的表gd新的记录Q当Ӟ如果表格不存在的话,会生异常?/p>

 你已l看CHibernate奇法?%Q它_的复杂强大,可以让你应付复杂的应用?br />

one-to-one关系
 在绝大多数系l当中不可能只存在一个数据表|否则p背了关系数据库的初衷。表与表的关pL较复杂,可以分ؓ几种情况Q?

 ?一对一兌(one to one)
 ?一对多兌(one to many)
 ?多对一兌(many to one)
 ?多对多关?many to many)

 按顺序来讌Ӏ假设一个一对一兌的例子是Q?br /> 表格Qperson
 id ~号Q主键)
 name 姓名
 email email地址

 表格Qspouse
 id ~号Q外键)
 name 姓名

 personq个表保存用户信息,而spouse保存用户配偶的信息。在一般情况下一个h只有一个配Ӟq很适合我们一对一的情c如果你对婚外恋感兴的话,我们可以在一对多和多对一的关联中讨论q个问题Q也许还可以在多对多中^_^Q禽?Q?/font>

 OKQ下面设计POJOQ?br /> Personq个c非常简单:

 /*
 * Created on 2004-4-19
 */
 package org.bromon.zizz;

 /**
 * @author Bromon
 */
 public class Person
 {
 private int id;
 private String name;
 private String email;

 public void setId(int id)
 {
  this.id=id;
 }
 public int getId()
 {
  return(id);
 }

 public void setName(String name)
 {
  this.name=name;
 }
 public String getName()
 {
  return(name);
 }

 public void setEmail(String email)
 {
  this.email=email;
 }
 public String getEmail()
 {
  return(email);
 }
 }


 然后~写它的映射规则Q这个应该能够理解了Q?br /> &lt ?xml version="1.0"? &gt
 &lt !DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
 "' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt 

 &lt hibernate-mapping package="org.bromon.zizz" &gt
 &lt class name="Person" table="person" lazy="true" &gt
 &lt id name="id" type="integer" unsaved-value="null" &gt
 &lt column name="id" sql-type="int" not-null="true"/ &gt
 &lt generator class="identity"/ &gt
 &lt /id &gt

 &lt property name="name" column="name" not-null="true" unique="false"/ &gt
 &lt property name="email" column="email" not-null="false"/ &gt
 &lt /class &gt
 &lt /hibernate-mapping &gt

 so easy是不是?一切都按部q。下面是Sousec:

 /*
 * Created on 2004-4-20
 */
 package org.bromon.zizz;

 /**
 * @author Bromon
 */
 public class Spouse
 {
 private int id;
 private String name;
 private Person person;

 public void setId(int id)
 {
  this.id=id;
 }
 public int getId()
 {
  return(id);
 }

 public void setName(String name)
 {
  this.name=name;
 }
 public String getName()
 {
  return(name);
 }

 public void setPerson(Person person)
 {
  this.person=person;
 }
 public Person getPerson()
 {
  return(person);
 }
 }


 注意里面的域person。它的映文Ӟ

 &lt ?xml version="1.0"? &gt
 &lt !DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
 "' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt 

 &lt hibernate-mapping package="org.bromon.zizz" &gt
 &lt class name="Spouse" table="spouse" lazy="true" &gt
 &lt id name="id" type="integer" unsaved-value="null" &gt
 &lt column name="id" sql-type="int" not-null="true"/ &gt
 &lt generator class="foreign" &gt
 &lt param name="property" &gtperson&lt /param &gt
 &lt /generator &gt
 &lt /id &gt

 &lt property name="name" column="name" not-null="true" unique="false"/ &gt
 &lt one-to-one name="person" class="Person" cascade="all" constrained="true" / &gt
 &lt /class &gt
 &lt /hibernate-mapping &gt

 q里指明了id的generator是一个外键,和person相关联。然后指定一个one-to-one关系Q不隄解是不是QHibernate的确很符合我们的思维习惯。需要提醒的是,q种兌关系是单向的QPersonq不需要去指定Spouse?/p>

 下面来操作这两个c:

 /*
 * Created on 2004-4-20
 */
 package org.bromon.zizz;
 import net.sf.hibernate.*;
 import net.sf.hibernate.cfg.*;
 import net.sf.hibernate.tool.hbm2ddl.*;
 /**
 * @author Bromon
 */
 public class OperateSpouse
 {
 public static void main(String args[])
 {
  try
  {
   Configuration cfg=new Configuration().addClass(Spouse.class);
   cfg.addClass(Person.class);
   SessionFactory factory=cfg.buildSessionFactory();
   new SchemaExport(cfg).create(true,true);
   Session session=factory.openSession();
 
   Person person=new Person();
   person.setName("bromon");
   person.setEmail("bromon@163.com");
 
   Spouse spouse=new Spouse();
   spouse.setName("who");
   spouse.setPerson(person);
  
   Transaction ts=session.beginTransaction();
   session.save(person);
   session.save(spouse);
   ts.commit();
   session.close();
  }catch(Exception e)
  {
   System.out.println(e);
  }
 }
 }


 q个例子和第一中的例子非常相伹{OKQ执行一下,然后看看zizz数据库,搞掂?br />

Many-to-One关系

 很明显一对多或者多对一关系是关pL据库中非常常见的现象Q下面通过父亲-儿子的例子来演示一对多关系Q多对一关系是类似的Q不q在我们的这个例子中不宜采用Q否则会带来伦理学上的问题?

 首先定义Childc:
 /*
  * Created on 2004-5-8
  */
 package org.bromon.zizz;

 /**
  * @author Bromon
  */
 public class Child
 {
  private int id;
  private String name;
  private int fatherId;
  private Person father;

  public Child(){}
 
  /**
   * @return
   */
  public Person getFather()
  {
   return father;
  }

  /**
   * @return
   */
  public int getFatherId()
  {
   return fatherId;
  }

  /**
   * @return
   */
  public int getId()
  {
   return id;
  }

  /**
   * @return
   */
  public String getName()
  {
   return name;
  }

  /**
   * @param person
   */
  public void setFather(Person p)
  {
   father = p;
  }

  /**
   * @param i
   */
  public void setFatherId(int i)
  {
   fatherId = i;
  }

  /**
   * @param i
   */
  public void setId(int i)
  {
   id = i;
  }

  /**
   * @param string
   */
  public void setName(String string)
  {
   name = string;
  }

 }

 q里的fatherId是外键,兌person表的id字段?/font>

 下面是映文件Child.hbm.xmlQ?br /> &lt ?xml version="1.0"? &gt
 &lt !DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt 

 &lt hibernate-mapping package="org.bromon.zizz" &gt
  &lt class name="Child" table="child" lazy="true" &gt
   &lt id name="id" type="integer" unsaved-value="null" &gt
    &lt column name="id" sql-type="int" not-null="true"/ &gt
    &lt generator class="identity"/ &gt
   &lt /id &gt
       
   &lt property name="name" column="name" not-null="true" unique="false"/ &gt
   &lt many-to-one name="father" column="fatherid" / &gt
      
  &lt /class &gt
 &lt /hibernate-mapping &gt
 需要注意的是fatherIdq没有做Z个property被映,而是在many-to-one声明中用?/font>

 需要对Person..java做修改,d以下代码Q?/font>

 import java.util.*;

 private Set children=new HashSet();
 /**
 * @return
 */
 public Set getChildren()
 {
  return children;
 }
 /**
 * @param set
 */
 public void setChildren(Set set)
 {
  children = set;
 }

 然后修改Person.hbm.xmlQ对d的代码做映射Q?/font>

 &lt set name="books" lazy="true" inverse="true" cascade="all"  &gt
  &lt key column="fatherid"/ &gt
  &lt one-to-many class="Child" / &gt
 &lt /set &gt

 q里的key column是child表的外键Qinverse需要指定ؓtrue?/font>

 下面做操作一下,功能是查询person表中id=1的记录,作ؓ孩的父Ԍ然后lchild表添加一条新记录?/font>

 /*
  * Created on 2004-5-8
  */
 package org.bromon.zizz;
 import net.sf.hibernate.*;
 import net.sf.hibernate.cfg.*;
 import net.sf.hibernate.tool.hbm2ddl.*;
 /**
  * @author Bromon
  */
 public class OperateChild
 {
  /**
   * @param args
   */
  public static void main(String args[])
  {
   try
   {
    Configuration cfg = new Configuration().addClass(Person.class);
    cfg.addClass(Child.class);
    SessionFactory sessions = cfg.buildSessionFactory();
    new SchemaExport(cfg).create(true, true);
    Session session = sessions.openSession();
   
    Child c=new Child();
   
    /*Query q=session.createQuery("from org.bromon.zizz.Person as p where p.id=1");
    Person p=(Person)q.list().get(0);*/
   
    Person p=(Person)session.find("from org.bromon.zizz.Person as p where p.id=?",new Integer(1),Hibernate.INTEGER).get(0);
    System.out.println(p.getName());
    c.setName("andy");
    c.setFather(p);
   
    Transaction ts = session.beginTransaction();
    session.save(c);
    ts.commit();
    session.close();
   } catch (Exception e)
   {
    System.out.println(e);
   }
  }
 }

 被注释掉的部分是HQL的另外一U查询方法。在q个例子中可以看出对象的查询非常ҎQ不需要自己再d装数据,修改和删除对象也很容易:

 //得到一个对?br /> Query q=session.createQuery("from org.bromon.zizz.Person as p where p.id=1");
 Person p=(Person)q.list().get(0);

 //修改数据
 p.setName(“Mr Smith?;

 //保存数据
 session.save(p);
 session.flush();

 //删除数据
 session.delete(p);
 session.flush();



Lansing 2006-08-17 19:26 发表评论
]]>
Oracle 10g TO_DATE() ora-01830 领悟共勉http://www.aygfsteel.com/machilansing/archive/2006/08/10/62857.htmlLansingLansingThu, 10 Aug 2006 13:03:00 GMThttp://www.aygfsteel.com/machilansing/archive/2006/08/10/62857.htmlhttp://www.aygfsteel.com/machilansing/comments/62857.htmlhttp://www.aygfsteel.com/machilansing/archive/2006/08/10/62857.html#Feedback0http://www.aygfsteel.com/machilansing/comments/commentRss/62857.htmlhttp://www.aygfsteel.com/machilansing/services/trackbacks/62857.html今天?DRM中报错ora-01830

把sql语句输出作了以下的实验,发现是时间多了一?0

后来的办法是先把q个旉转成to_charQ再转成to_date

SQL> select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss') from dual;

select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss') from dual

ORA-01830: 日期格式囄在{换整个输入字W串之前l束

SQL> select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:sssss') from dual;

select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:sssss') from dual

ORA-01836: 时与日中的U发生冲H?/font>

SQL> select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss.sssss') from dual;

select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss.sssss') from dual

ORA-01836: 时与日中的U发生冲H?/font>

SQL> select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ff') from dual;

select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ff') from dual

ORA-01821: 日期格式无法识别

------------------------------------------------------------------

必须保证传入的字W串和要转换的格式精匹?/font>

SQL> SELECT TO_DATE('11-10-1996-13:51:21','DD/MM/YYYY-HH24') A FROM dual;

ERROR:
ORA-01830: date format picture ends before converting entire input string.

SQL> SELECT TO_DATE('11-10-1996-13:51:21','DD/MM/YYYY-HH24:MI:SS') B FROM dual;
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
以上是{载的
后来我是q么做的哈:

SELECT中将其他表的日期TO_CHAR下,然后再将值在INSERT时TO_DATE!
具体的做法如下:

SELECT TO_CHAR(parameter,'YYYY-MM-DD HH24:MI:SS') AS TIME
FROM TABLE_NAME_1;

...
...

INSERT INTO TABLE_NAME_2
(COLUME_NAME_1)
VALUE (TO_DATE('"+TIME+"','YYYY-MM-DD HH24:MI:SS'));

然后OK了,呵呵Q看来要学的q真多!



Lansing 2006-08-10 21:03 发表评论
]]>
վ֩ģ壺 Ͽ| ԭ| ϰ| | | | ϲ| ĵ| | | | | | ͨ| | | | | ʡ| | ˮ| | | | Ž| | | | ľ| ̨| | ƶ| | ʡ| ij| | ɽ| | | | Ҫ|