??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲美女精品久久久,亚洲色婷婷综合开心网,亚洲av成人一区二区三区观看在线 http://m.tkk7.com/killvin/category/8034.htmlzh-cnThu, 01 Mar 2007 18:28:06 GMTThu, 01 Mar 2007 18:28:06 GMT60IE览器的两大问题(l?http://m.tkk7.com/killvin/archive/2006/07/02/56203.htmlkillvinkillvinSun, 02 Jul 2006 13:53:00 GMThttp://m.tkk7.com/killvin/archive/2006/07/02/56203.html在上一的文章中,比较仔细的分析了IE对于Cookie处理q程中出现的问题Q既然存在问题就要想办法解决Q而问题的关键在于IE没有能够"老实"的报告用户对于Cookie的设|问?br />
IE
GET /mail HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)
Host: mail.google.com
Connection: Keep-Alive
Cookie: gmailchat=killvin.liu@gmail.com/519974 ; PREF=ID=d68c481e542af276:NW=1:TM=1151742225:LM=1151742225:S=2qbdhg0_z3i-OAbW; SID=DQAAAG8AAACEdcjD2IZMNqZVatDbD62X8_U18oJuTVQc9XZUJi7MgCkM8sggJ8M5npZ35GXjdalT2o8QWPUve04tepy61MPv4v_EpILafg3JdIf8AFjD91aMT0tI5gb763FouV3e_2-C364HDO5Qzb4P4gjjgpHC

Firefox
GET /mail HTTP/1.1
Host: mail.google.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

我们可以注意刎ͼ如果用户关闭了浏览器的Cookie选项Q在Firefox中对于新的请求是包含Cookie的信息的Q然而IE却恰恰相反!q也q接用IE览一些网站所D的Cookie校验p|问题Q比如即使用户在使用q程中突然关闭CookieQ依然可以自q讉K|站的各Ҏ务)Q进一步,如果某个|站是读取依靠Cookie中的信息来验证用?其是那U保存客户信息的提示)Q即使这个用L开或者关闭窗口,M一个后来的人都可以L的浏览这个用LU有信息Q这是Cookie的最大的问题所在,当然q是另外的话题,不属于本ơ讨论的范畴Q这一ơ要说的?/font> 如何避免IE览器下Q用户关闭Cookie的问题?br />
有一个思\Q经q测试我们发现IE览器只是在首次面h的时候才会去dCookie的|所以,Z避免IE览器关闭Cookie的问题,可以在用戯求某个链接的时候,先将用户的Cookie存放在某处,q清I此时所有的Cookie|再次的请求页面,而这样做的目的就是强qIEd盘上的CookieQ如果此时用户关闭了CookieQ就不会在请求的头信息中看到Cookie信息Q如果没有关闭Cookie,可以放心的原先的Cookie写回Reponse对象?br />

只是不知道Google的网站是否也是按照这个思\去解x问题的?



killvin 2006-07-02 21:53 发表评论
]]>
IE览器的两大问题http://m.tkk7.com/killvin/archive/2006/07/01/56096.htmlkillvinkillvinSat, 01 Jul 2006 07:53:00 GMThttp://m.tkk7.com/killvin/archive/2006/07/01/56096.html IE在处理COOKIE斚w的问?br />
1。即使你提高了浏览器的隐U登讎ͼ在第一ơ打开H口的时候,你获取不CQ何的Cookies对象Q很昄的结果)Q然而当你再ơ刷新本面的,Cookie此时会奇q般的出玎ͼ而在Firefox览器中按照以上的步骤,是不会出现这L情况的?br />
2。不仅如此,你还可以透过Action的处理,多次的往Cookie中增加Cookie的数量(当然在Action中你依然可以自由的获取到Cookieq个数组Qƈ且不为空Q,然而让人匪h思的是在Cookie的存攄录下你是扑֯不到M的蛛丝马q的。而在Firefox没有出现以上的情c?br />
Q解?br />1。在首次q入面时查询客L的CookieQ如果不存在则警告用Pq要求再ơ的登陆?br />2。在用户登陆后,如果更改了浏览器的隐U别,对于Firefox标准的浏览器Q此时肯定不会再扑ֈCookie数组对象了,你需要做的仅仅只是将面调{到登陆窗口;而在IE下就非常的麻烦了甚至无法解决Q因Z依然可以讉K到原来的Cookie数组|Q比如,用IE在CSDN登陆后提高隐U别,你依然可以登陆到其他的服务区域)此时没有什么好的办法,不过Google解决了这L问题Q只是不知道如何解决的?/strong>


IE在处理Frame标记的问?br />1。如果你在某个页面中嵌入了Frame标签Qƈ且希望与q个嵌入的页面共享某些存攑֜Session中的数据Q此时你需要将外部的sessionId传入到frame标记的页面中。然而在IE中你可能q不能完全的享受q样的逻辑Q原因在于IE对于嵌入的页面不会自动的传递sessionIdQ也怽y可以Q也怸行,也就是说完全是在IE?掌控"之下。而在Firefox没有出现q样的情c?br />
Q解?br />为嵌入的面中所有的链接增加sessionId参数?br />

最好的办法是Q说服客户用标准的览器Firefox!



killvin 2006-07-01 15:53 发表评论
]]>
从ActionErrorsq渡到ActionMessageshttp://m.tkk7.com/killvin/archive/2006/06/27/55429.htmlkillvinkillvinTue, 27 Jun 2006 15:02:00 GMThttp://m.tkk7.com/killvin/archive/2006/06/27/55429.html 在Struts中我们经常这样@环的打印Message
<logic:messagesPresent message="true">
  <html:messages id="msg" message="true">
    <div class="success">
      <bean:write name="msg"/>
    </div><br/>
  </html:messages>
</logic:messagesPresent>

查阅struts tag的文档我们看C关于messagesPresent的message属性注释如?br />

message

By default the tag will retrieve the request scope bean it will iterate over from the Globals.ERROR_KEY constant string, but if this attribute is set to 'true' the request scope bean will be retrieved from the Globals.MESSAGE_KEY constant string. Also if this is set to 'true', any value assigned to the name attribute will be ignored


也就是说在将message讄为trueӞ会去request中寻找Globals.MESSAGE_KEY所代表的beanQ然而我们在具体的Action使用ActionMessagescȝ时候往往是这L
ActionMessages messages = getErrors(request);
messages.add(ActionMessages.GLOBAL_MESSAGE , new ActionMessage(key , value0));
saveMessages(request,messages);

而往往困扰人的在于ؓ什么要lmessages中放入名UCؓ"ActionMessages.GLOBAL_MESSAGE"的ActionMessage对象Q而且q需要再ơ的调用saveErrors(request,messages)ҎQ?/strong>

首先要说明的是你为ActionMessage起Q何的名称都没有关p,因ؓActionMessages本nl持着一个HashMapQ而参数property是q个HashMap中的key|如果不存在则会徏立相应的key,q将需要保存的ActionMessage对象存入到这个key所对应的List中?br />    public void add(String property, ActionMessage message) {

        ActionMessageItem item = (ActionMessageItem) messages.get(property);
        List list = null;

        if (item == null) {
            list = new ArrayList();
            item = new ActionMessageItem(list, iCount++, property);

            messages.put(property, item);
        } else {
            list = item.getList();
        }

        list.add(message);

    }

至于Z么一定要调用saveMessages(request,messages)Q看看它具体的实现逻辑清楚了
    protected void saveMessages(
        HttpServletRequest request,
        ActionMessages messages) {

        // Remove any messages attribute if none are required
        if ((messages == null) || messages.isEmpty()) {
            request.removeAttribute(Globals.MESSAGE_KEY);
            return;
        }

        // Save the messages we need
        request.setAttribute(Globals.MESSAGE_KEY, messages);
    }

再对比前面介l的messagesPresent标签的用,是不是就清楚了呢Q原来它是将ActionMessages对象保存在request中,q且名称是Globals.ERROR_KEYQ从而ؓtag的顺利解析铺q了道\。当然按理你可以选择这L对象攄在Q何的scope中,但Action只是提供了request , session两种ScopeQ不qpage , application不经怋用,可以理解Q但不提供相应的l构׃太好了)

至于messagesPresent标签是如何在scope中寻找ActionMessages对象

org.apache.struts.taglib.logic.MessagesPresentTag
    protected boolean condition(boolean desired) throws JspException {
        ActionMessages am = null;

        String key = name;
        if (message != null && "true".equalsIgnoreCase(message)){
           key = Globals.MESSAGE_KEY;
        }

        try {
            am = TagUtils.getInstance().getActionMessages(pageContext, key);
           
        } catch (JspException e) {
            TagUtils.getInstance().saveException(pageContext, e);
            throw e;
        }

        Iterator iterator = (property == null) ? am.get() : am.get(property);

        return (iterator.hasNext() == desired);

    }

org.apache.struts.taglib.TagUtils
   public ActionErrors getActionErrors(PageContext pageContext, String paramName)
            throws JspException {

        ActionErrors errors = new ActionErrors();

        Object value = pageContext.findAttribute(paramName);
        if (value != null) {
            try {
                if (value instanceof String) {
                    errors.add(
                            ActionMessages.GLOBAL_MESSAGE,
                            new ActionMessage((String) value));

                } else if (value instanceof String[]) {
                    String keys[] = (String[]) value;
                    for (int i = 0; i < keys.length; i++) {
                        errors.add(
                                ActionMessages.GLOBAL_MESSAGE,
                                new ActionMessage(keys[i]));
                    }

                } else if (value instanceof ActionErrors) {
                    errors = (ActionErrors) value;

                } else {
                    throw new JspException(
                            messages.getMessage(
                                    "actionErrors.errors",
                                    value.getClass().getName()));
                }

            } catch (JspException e) {
                throw e;

            } catch (Exception e) {
                log.debug(e, e);
            }
        }
        return errors;
    }

PageContext中的findAttribute会帮你在scope中寻扑֐UCؓGlobals.MESSAGE_KEY的ActionMessage对象?br />

注意
虽然Struts已经声明Q不推荐使用ActionErrors & ActionError对象Q但在一些遗留的pȝ中,依然q是可以看到其媄子,所以如果你的系l不q属于这L两种混合pȝQ有以下的几U方法可以参?br />
1。两ơ调用messagesPresentQ如?br /><!-- Print ActionErrors Object -->
<logic:messagesPresent>
  <html:messages id="msg" message="true">
    <div class="success">
      <bean:write name="msg"/>
    </div><br/>
  </html:messages>
</logic:messagesPresent>

<!-- Print ActionMessages Object -->
<logic:messagesPresent message="true">
  <html:messages id="msg" message="true">
    <div class="success">
      <bean:write name="msg"/>
    </div><br/>
  </html:messages>
</logic:messagesPresent>

2.分别使用<html:messages> <html:errors>标签Q当然在老系l中需要调用Action的saveErrorsҎQ而在新的应用中要调用saveMessagesҎ?/font>

3.更换所有的ActionErrors为ActionMessages,q将所有调用saveErrors的地Ҏ换成saveMessagesQƈ?lt;html:errors>标签相应的更换成<html:messages message="true"> Q?推荐Q?/font>

 



killvin 2006-06-27 23:02 发表评论
]]>
Java到底能干什么?http://m.tkk7.com/killvin/archive/2006/03/29/38034.htmlkillvinkillvinWed, 29 Mar 2006 05:49:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/29/38034.html
[深入的思考] Z么要采用javaq个q_Q?/p>


从开发项目的cd角度看javaq_

ZB/Sl构的系l,在这个方向上的竞争是Ȁ烈的Q有专注于此的LAMPQLinux + Apache + Mysql + PhpQ?也有刚刚兴v的RailsQRuby FrameworksQ甚xL快速开发的ASP.NET;当然了java在这个领域里的MVC框架数都C完,比如Struts . Webwork{,然而即便是如此Q选择java作ؓ开发的理由也是不充分的Q因为在q个梯队里java多排名最后?/p>

ZC/Sl构的系l,在这个方面java昄没有考虑周到Q面对VB 、DELPHI、vcq些个如g虎的快速开发IDEQJAVA实在是显得异常的淡薄Q即使你扑ֈ了一个可以匹敌这些个ide的工P面对W三方的lg又会成ؓ一大障,所以java在这个方面又一ơ的输了?/p>


从java所的特性角度看javaq_

java的重Ҏ业务逻辑Q(我以前也是如此坚信不U)可是谁有能够说别的语a不注重业务逻辑呢,业务逻辑只是一个抽象的概念Qjava只是依靠ejb提出了业务组件而已Q其他的语言在实C务逻辑的时候也可以包装成POJO的Ş式,看来q个观点也是p|的?/p>

java的是跨^台的优势Q这可以理解为初U的、商业的、忽悠h的词汇,面对众多动态语a如PythonQ在若干q_上的表现Qjava又如何来自己q方面的优势呢?p|

java支持分布式应用的目Q可W的a论,分布式根本不是值得炫耀的资本,在java之前的c/s目中何不是分布式的应用呢Q失?/p>


既然没有了这些个优势Q我们看看java到底q剩下些什么?对了其实是应用服务器!然而看qJ2EE WITHOUT EJB的读者肯定知道Spring所希望辑ֈ的目的,也就是脱d用服务器概念上的J2EE体系实现Q既然在作者的眼里APPLICATION SERVER只不q是一个忽悠h的词汇,那么M目都选择java作ؓ开发的依据昄是自找苦吃Q?br />

那么什么情况下攚w择java作ؓ开发的q_呢?
<1> 如果你真的遇C大型的系l开发Q务,恭喜你,你终于可以看到分布式对象、集的优势了?br /><2> 客户是一个java的忠实fans或者是sun、ibm的金牌合作伙伴之cȝQ选择java是不得已的,但记住ƈ不能证明java是最好的实现方式
<3> 如果你只惛_心业务逻辑的实玎ͼ对于事务、缓存、查扄服务的实现没有兴的话,倒是不妨考虑采用ejb的Ş式,当然前提是你不愿意在L合适的替代品的情况下?br /><4> 如果目q切的寻找某U框架的支持Q选择java是对的Q你有众多优U的、免费的、可扩展的、天才的框架可以选择Q更多的时候你是出于尴的境地Q因ZQ何一个都让你心动、而这L选择往往是最痛苦、和快乐的?/p>


正确的选择
<1>
条g: 如果目仅仅只是一个小型的|站pȝ
选择: LAMP、Rails

<2>
条g: 目规模中等
q且目的时间比较紧Q?br />目可以架构在windows的系l之上,
选择: .Net  / Delphi

<3>
条g: 大型的系l,有支持分布式对象、集的要求Q或者SUN / IBM的金牌合作伙?; 惌L某种优秀的框架来解决问题
选择: java是不二的选择Q可是我想问一下,在现实中你能遇到q样的项目吗Q?/p>

所以,从实际的角度出发Q我们面对的99Q可能都是一些符合条?Q?的系l,而选择java实在是得不偿q。最后以一DCode Complete中的话来作ؓl束?/p>

每个E序员都有很多的工具Q但q不存在M一个能够适用于所有工作的工具Q因地制宜的选择正确工具是成有效~程的程序员的关键?/strong>



killvin 2006-03-29 13:49 发表评论
]]>
JUnit 4 抢先?/title><link>http://m.tkk7.com/killvin/archive/2006/03/05/33687.html</link><dc:creator>killvin</dc:creator><author>killvin</author><pubDate>Sun, 05 Mar 2006 05:10:00 GMT</pubDate><guid>http://m.tkk7.com/killvin/archive/2006/03/05/33687.html</guid><description><![CDATA[不错的文?A ><BR>http://www-128.ibm.com/developerworks/cn/java/j-junit4.html<BR></A><BR> <BLOCKQUOTE>JUnit ?Java?语言<I>事实上的</I> 标准单元试库。JUnit 4 是该库三q以来最具里E碑意义的一ơ发布。它的新Ҏ主要是通过采用 Java 5 中的标记QannotationQ而不是利用子cR反或命名机制来识别测试,从而简化测试。在本文中,执着的代码测试h?Elliotte Harold ?JUnit 4 ZQ详l介l了如何在自q工作中用这个新框架。注意,本文假设读者具?JUnit 的用经验?/BLOCKQUOTE> <P>JUnit ?Kent Beck ?Erich Gamma 开发,几乎毫无疑问是迄今所开发的最重要的第三方 Java 库。正?Martin Fowler 所_“在软g开发领域,从来没有如此少的代码vC如此重要的作用”。JUnit 引导q促q了试的盛行。由?JUnitQJava 代码变得更健壮,更可靠,bug 也比以前更少。JUnitQ它本n的灵感来?Smalltalk ?SUnitQ衍生了许多 xUnit 工具Q将单元试的优势应用于各种语言。nUnit (.NET)、pyUnit (Python)、CppUnit (C++)、dUnit (Delphi) 以及其他工具Q媄响了各种q_和语a上的E序员的试工作?/P> <P>然而,JUnit 仅仅是一个工兯已。真正的优势来自?JUnit 所采用的思想和技术,而不是框架本w。单元测试、测试先行的~程和测试驱动的开发ƈ非都要在 JUnit 中实玎ͼM比较 GUI 的编E都必须?Swing 来完成。JUnit 本n的最后一ơ更新差不多是三q以前了。尽它被证明比大多数框架更健壮、更持久Q但是也发现?bugQ而更重要的是QJava 不断在发展。Java 语言现在支持泛型、枚举、可变长度参数列表和注释Q这些特性ؓ可重用的框架设计带来了新的可能?/P> <P>JUnit 的停滞不前ƈ没有被那些想要废弃它的程序员所打|。挑战者包?Bill Venners ?Artima SuiteRunner 以及 Cedric Beust ?TestNG {。这些库有一些可圈可点的Ҏ,但是都没有达?JUnit 的知名度和市场占有䆾额。它们都没有在诸?Ant、Maven ?Eclipse 之类的品中hq泛的开即用支持。所?Beck ?Gamma 着手开发了一个新版本?JUnitQ它利用 Java 5 的新Ҏ(其是注释)的优势,使得单元试比v用最初的 JUnit 来说更加单。用 Beck 的话来说Q“JUnit 4 的主题是通过q一步简?JUnitQ鼓励更多的开发h员编写更多的试。”JUnit 4 管保持了与现有 JUnit 3.8 试套g的向后兼容,但是它仍然承诺是?JUnit 1.0 以来 Java 单元试斚w最重大的改q?/P> <P><B>注意Q?/B>该框架的改进是相当前沿的。尽?JUnit 4 的大轮廓很清晎ͼ但是其细节仍然可以改变。这意味着本文是对 JUnit 4 抢先看,而不是它的最l效果?/P><img src ="http://m.tkk7.com/killvin/aggbug/33687.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killvin/" target="_blank">killvin</a> 2006-03-05 13:10 <a href="http://m.tkk7.com/killvin/archive/2006/03/05/33687.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2EEI竟是什么? http://m.tkk7.com/killvin/archive/2006/03/02/33308.htmlkillvinkillvinThu, 02 Mar 2006 12:59:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33308.html
J2EEQ一斚w有着一套相当庞大的标准体系和数个不同版本,另一斚wQ由于市Z应用服务器品U多P各家开发商使用的术语又不尽相同Q因此,围绕着J2EEQ常常有不少被h误解的地斏V本文将深入探讨J2EEI竟是什么,它到底能做什么?
什么是J2EEQ?
在试囄J2EE 下一个明的定义之前Q我们首先要了解J2EE q不单地只是一门语a、一U工h一套服务?

· J2EE——Java 2 q_企业?
单地_J2EE是一个标准中间g体系l构Q旨在简化和规范多层分布式企业应用系l的开发和部v。J2EEҎ的实施可显著地提高系l的可移植性、安全性、可伸羃性、负载^衡和可重用性?

J2EE技术出C前,几家主要的中间g开发商的品各自ؓ阵,彼此之间~Z兼容性,可移植性差Q难以实C操作Q没有一个被普遍认可的行业标准。J2EE的出现标志着中间件技术在l历了多q的不断摸烦和经验ȝ后,正逐步走向成熟?

J2EE的核心是一l规范和指南Q定义了一个用Java语言开发多层分布式企业应用pȝ的标准^台。开发h员在q些规范和指南的基础上开发企业应用Q同时由J2EE供应商确保不同的J2EEq_之间的兼Ҏ。由于基于规范的各J2EEq_之间h良好的兼Ҏ, 因此J2EE应用pȝ可以部v在不同的应用服务器上Q无需或只需q行量的代码修攏V?


· J2EE视点
下面我们从几个不同的侧面来考察J2EEQ以期读者能对J2EE有个更全面清晰的印象?

Q?QJ2EEQ多层、分布式中间件语?
采用多层分布式应用模型,J2EE应用开发划分ؓ多个不同的层Qƈ在每一个层上定义组件。各个应用组件根据他们所在的层分布在同一个或不同的服务器上,共同l成Zlg的多层分布式pȝ。典型的J2EE四层l构包括客户层、表C逻辑层(Web层)、商业逻辑层和企业信息pȝ层?

有了J2EEQ分布式pȝ的开发变得简单了Q部|的速度也可以加快。J2EElg的分布与服务器环境无养I所有的资源都可通过分布式目录进行访问。这意味着开发h员不再需要ؓlg和资源的分布问题耗费_֊Q从而可以有更多的时间专注于业务逻辑的实玎ͼ提高开发效率?

Q?QJ2EEQ企业应用pȝ开发^?
J2EE本n是一个标准,一个ؓ企业分布式应用的开发提供的标准q_。而J2EE的实施,则具体表Cؓ诸如BEA Web logic或IBM Web sphere之类的特定Web服务器品。利用J2EE应用-~程模型开发的企业应用pȝQ可以部|在不同厂商生的、但怺兼容的J2EE 应用服务器上?

目前Q市ZZJ2EE的Web服务器品U繁多,性能特点各有千秋Q每家厂商的产品都有_ֿ设计的独C处。但与品个性无关的是,所有的J2EE应用服务器都Z业应用pȝ的开发和部v提供了一个共同的基础?

Q?QJ2EEQ电子化应用开发模?
J2EE应用很容易发布到Web、掌上电脑或Ud电话{手持设备上。换a之,应用lg可以很轻村֜实现电子化。J2EE的应?~程模型保证lg在向不同cd的客LULq程中,商业逻辑和后端系l保持不变?

此外QJ2EEq_的其他主要优点还有:自动负蝲q、可伸羃、容错和h故障排除{功能。部|在J2EE环境中的lg自动获得上q特性,而不必增加额外的代码开销?

J2EE所有这些特性对于需要构建全天候网l门L企业来说昑־ؓ重要?

Q?QJ2EEQWeb应用服务器上q泛采用的标?
可以_J2EE是首个获得业界广泛认可和采纳的中间g标准。目前几乎所有的一Web应用服务器,如BEA的Web logic、IBM的Web sphere、HP的应用服务器、Sun的iPlanet和Macromedia的Jrun{,都是ZJ2EE的。迄今ؓ止,q没有哪个其他标准能获得如此众多的中间g供应商的一致支持?

而且Q有了J2EEQ企业的应用开发对于某个特定的开发商或应用服务供应商的依赖性更。应用组件只要符合J2EE规范Q完全可以部|在不同的应用服务器上。ؓ了确保不同厂商的J2EE应用服务器的兼容性和一致性,Sun公司发布了J2EE兼容性测试包?

· J2EEI竟是什?
xQ我们可以试着用一句话来概括J2EEQ那是QJ2EE是一个中间g基础架构Q有了它Q开发者只需要集中精力编写代码来表达企业应用的商业逻辑和表C逻辑Q至于其他系l问题,如内存管理,多线E,资源分布和垃圾收集等Q都由J2EE自动完成?

J2EE如何应对挑战Q?
在这一部分里,我们探讨J2EE是如何应对企业开发过E中所面的问题,以及如何Z业未来发展之需要提供空间?

· 独立于硬仉|和操作pȝ
J2EEq行在Java虚拟机(JVMQ上Q利用Java本n的跨q_Ҏ,独立于硬仉|和操作pȝ。Javaq行环境QJREQ——JVM的可安装版本加上其他一些重要组件——几乎可以运行于所有的g/OSl合。因此,通过采用JavaQJ2EE使企业免于高昂的g讑֤和操作系l的再投资,保护已有的IT资源。在很多情况下,J2EEq可以直接运行在EIS服务器环境中Q从而节U网l带宽,提高性能?


· 坚持面向对象的设计原?
作ؓ一门完全面向对象的语言QJava几乎支持所有的面向对象的程序设计特征。面向对象和Zlg的设计原则构成了J2EE应用~程模型的基?

J2EE多层l构的每一层都有多U组件模型。因此,开发h员所要做的就是ؓ应用目选择适当的组件模型组合,灉|地开发和装配lgQ这样不仅有助于提高应用pȝ的可扩展性,q能有效地提高开发速度Q羃短开发周期。此外,ZJ2EE的应用还hl构良好Q模块化Q灵zd高度可重用性等优点?

· 灉|性、可UL性和互操作?
利用Java的跨q_Ҏ,J2EElg可以很方便地ULC同的应用服务器环境中。这意味着企业不必再拘泥于单一的开发^台?

J2EE的应用系l可以部|在不同的应用服务器上,在全异构环境下,J2EElg仍可彼此协同工作。这一特征使得装配应用lg首次获得I前的互操作性。例如,安装在IBM Websphere环境下的EJBQ一斚w可以直接与Websphere环境下的CICS直接交互Q另一斚w也可以通过安装在别处的BEA Weblogic 服务器上的EJBq行讉K?

· L的企业信息系l集?
J2EE技术出台后不久Q很快就JDBC?JMS?JCA{一Ҏ准纳归自w体pM下,q大大简化了企业信息pȝ整合的工作量Q方便企业将诸如legacy systemQ早期投资系l)QERP和数据库{多个不同的信息pȝq行无缝集成?

׃几乎所有的关系型数据库pȝ都支持JDBCQ因此只需借助必要的JDBC驱动E序QJ2EE应用可以和所有主数据库pȝq行通信。类似的Q目前业界正冒出一批基于Javaq接器体pL准的EI适配器,也用于提供各clegacy system和ERP/CRM的无~集成?

· 引进面向服务的体pȝ?
随着Web服务以及SOAP{开放标准的出现Q企业异构系l之间的互操作性成为可能。J2EEQ作Z个可扩展q_Q很自然需要加入Web服务Ҏ。ؓ此,Sun公司发布了一整套UCؓ“JAX包”的APIQ支持从XML语法分析、XMLl定、SOAP消息发送、注册表查寻、XML RPC到XML消息传递等所有各UWeb服务需求?

虽然J2EEq_的出现早于Web服务技术,但它的可扩展能力使它能很好地适应技术的最新发展。我们有理由怿Q在未来QJ2EE引入更多的技术进步而不会动摇它的核心框架和应用-~程模型?

l束?
作ؓ一个被业界q泛采用的中间g标准QJ2EE是开发可伸羃的、具有负载^衡能力的多层分布式跨q_企业应用的理惛_^台。J2EE的首要Q务在于提供一个标准中间g基础架构Q由该基架构负责处理企业开发中所涉及的所有系l问题Q从而得开发h员可以集中精力重视商业逻辑的设计和应用的表C,提高开发工作的效率?

J2EE有效地满了行业需求,提供独立于操作系l的开发环境。基于J2EE的应用系l灵zM易于UL和重用,可运行在不同厂家的Web服务器上。更为重要的是,J2EE是一个开放体p,完全有能力适应未来技术的q步和发展?


killvin 2006-03-02 20:59 发表评论
]]>
Entity Bean vs Hibernate Pojo http://m.tkk7.com/killvin/archive/2006/03/02/33307.htmlkillvinkillvinThu, 02 Mar 2006 12:58:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33307.html该文转自guty

O-R Mapping

J2EE的标准是CMP Entity BeanQ而实际应用中受到诟病最多的也是它。我们化了整整半q时间研ICMP2.0的开发方法,目前ȝ能够代码量减少?0%Qƈ且有希望减少?90%。我曄很满现有的成WQ但是当我真正地阅读了hibernate后,对CMP2.0的信心彻底动摇了?

hibernate臛_比CMP2.0有以下优点:
1. 兼容性?规范一模一P实现各有不同Q这是CMP的现状。用W三方O-R Mapping工具可以解决q个问题?
2. 保护智力投资。在了解了Orion, Weblogic, JBoss的CMP实现后,我不愿意再去学习Websphere 或者Resin的实C?
3. 性能?
a. local v.s. remoteQ?hibernate、JDO、Castor都是本地调用QCMP2.0虽然也有Local接口Q但是Web层还是需要通过Remote接口讉KEJB层的数据,序列化、网l调用、创建大量的对象Q都是性能降低的原因?
b. transactionQJ2EE提出了一个全新的事务模型Qmethod-based descriptor)Q对E序员的开发确实是个“简化”,记得一本教E徏议所有的EJBҎ都用Required。但q样的结果是什么?性能极度降低Q互锁!没有办法Q我们只有再去调节各个方法的Transaction属性,然后又出?新的互锁...
新的事务模型是不成功的。它试图化问题,却引入了更ؓ严重的问题。各家厂商的Transaction实现也不相同,有的支持Optimistic LockQ有的在VM中同步Entity对象Q又是兼Ҏ的一大敌?
hibernate没有试图创造一个更新的模式Q相反,它沿用了传统数据库的Transaction~程模式Q在对J2EE的Transaction伤透脑{后看到它,真是十分亲切Q感觉自q实在~程Q而不是碰q气填代码了?
4. 动态Query?
Entity Bean很难实现动态QueryQ这是因为它Z代码自动生成技术,xl的执行代码是在部v~译时生成的。hibernate则有Ҏ的改变,它基?reflection机制Q运行时动态Query是很自然的事。另外,hibernate几乎支持所有的SQL语法Q传l数据库可以做的它就可以做?
5. 发展速度?
I have a dream, 有一天Entity Bean会变得很好。但臛_目前来看QEntity Bean是一个不完善的品,它是大公司政L争和妥协的品,而且习惯性将一些问题“无限期搁置”,典型的例子就是QueryQ之所以不提其他问题,是因为其他都是Entity Bean的致命伤Q)Q?
形成强烈反差的是Qhibernate的核心程序员只有一人,但它改进的速度是Entity Bean无法企及的?
6. l承和多态?
OO语言的精华在Entity Beanq里是行不通的Q我曄自我安慰Entity Bean看做一个“内存中的数据表”,才找C一点^衡?
但当我看到hibernateӞ又开始不q了?

另外QCMP2.0也有一些缺Ҏ可以弥补的?
1. 代码l护?
大量的接口文件和配置文gQ开发和l护的工作量很大?
解决途径Q采用xdoclet,可以自动产生众多的接口和配置文gQ甚至facade, delegate{高U模式?

臛_目前来看Qhibernate的缺ҎQ?
1. 代码l护
hibernate提供了自动生成mapping文g“框架”的工具Q但q需要手工调节。而这cd发,能想到的最x式就是xdoclet的(代码+注释Q的模式了。幸好,hibernate的程序员已经向xdoclet目增加了hibernate的模块。现在需要的是等待xdoclet的下一?release?

l论Q?
hibernate臛_从文档上越了Entity Bean很多Q我要学习hibernate?

以下是robbin的观?/STRONG>

如果说不使用Session Facade模式的话Q我认ؓEBq是一个很有意义的的东西,因ؓEB是唯一直接支持跨RMI的持久化Ҏ。但是由于EB的效率和减少跨RMI的网l调用的原因QEB已经完全被封装到SB的后面,EB的分布式调用的功能,EB的安全验证功能,EB的容器事务功能完全被前面的SBl做了,l果EB只剩下了唯一的ORM功能了,单就ORMq一Ҏ说EB实在是一个非帔R常糟p的东西。那么EBq有什么功能值得我非ȝ它不可呢Q?

?Session Bean + DAO + Hibernate 来取?Session Bean + Entity BeanQ不但能够极大降低Y件设计难度,软g开发难度,软g调试隑ֺ和Y仉|难度,而且q可以提高允许效率,降低g要求?

不要把EB直接拿来和Hibernate做比较,两者不是一个范畴的东西Q而应该整体比较两U方案:
Session Bean + DAO + Hibernate
Session Bean + Entity Bean
我找不出来第二方案有哪怕一Ҏ面能够比W一Ҏ好的?

CMP可以使用CMR来表C多表之间通过外键兌的关pR但是你仍然会遇到即使没有键兌的表仍然需要连接查询的情况Q这是一个非常普遍的现象?

如果是HibernateQ可以在HSQL里面定义outer joinQBMP也可以写JDBCQ而CMP没有M办法来解册问题Q除非你把需要的q接查询都定义ؓCMRQ但那样的话Q凡是有需要连接查询,或者有键关联的表都必须打在一个包里面。你如果不打在一个jar包里面,如果能够建立CMRQ不是我x在一个jar里面Q而是不得不放在一个jar里面。基本上CMPq是非常W拙的?

CMP的另一大缺Ҏ不能动态SQLQguty已经提到了,一个SQLp定义一个EJBFinderҎQ在~译的时候就定M。在实际应用中,l常会遇C定查询条g的查询,比如说用户在面上用下拉列表来选择查询的条Ӟ用户既有可能什么限制条仉不选,也有可能选择某几个条件。这时候你怎么办?假设有n个查询条Ӟ你要?C1n + C2n + C3n +...+ Cnn(C是组合公式的W合Qn是下标,1...n是上?个EJBFinderҎ才行Q很恐怖吧?

其实JDBC的PrepareStatement也不能很好的解决q个问题Q因为它是按?Q?q样的次序来set参数的。用Statement是肯定不行的Q会严重影响数据库,甚至会导致数据库down?我的实际l验)。但是Hibernatep决的不错Q因为它可以按照 :name q样的Ş式来讑֮SQL中的PlaceholderQ这样set参数可以按照参数名UC递,因ؓơ序不是ȝQ在E序里面很ҎҎ用户选择的查询条Ӟ动态的产生SQLQ动态的set参数了?

CMP2.0q有一个大问题是不支持order byQ当然你可以在Java里面对取出来的集合排序,但是速度和数据库里面排好序速度不在一个数量了。Hibernate不但可以order byQ还可以group byQhavingQ子查询Q真是没有办法比下去了?

其实对于动态SQL和排序问题,特定的App Server也可以做Q但那不是CMP2.0的规范Ş了,所以ؓ了可UL性,也不敢随便去用?

在项目开发时Q?开发和q行效率以及灉|性是非常重要的指标。由于Entity Bean天生是一U粗_度的用方式,q就必定使它在装载的时候有较长的响应时_也不能自如的支持懒装入的方式Q用成l粒度会使程序变得复杂,以及q程调用l粒度的entity bean是一U非常可怕的行ؓ, 太慢?

Hibernate正好满开发和q行效率以及灉|性,说来说去Q它可以U做一个OO化的JDBC, q样大家׃会对Hibernate产生误解及恐惧心理。它支持_细两种_度方式Q运用v来灵z自如,前提是你必知道如何用,一个entity bean 实现要NU重复的Ҏ, such as ejbRemove,ejbstore,ejb...., 光类也有一大堆Q象Home Interface, Romote Interface..., Primary class if necessary. Hibernate只需要一个就行了?

CMP在进行O/R Mapping斚w只是做了最基础的工作而已Q完全用CMP做数据层Q会发现你在把数据库应该做的工作全部都搬到App Server里面来重新实C遍,有这必要吗?

CMP是把EJBQL写死?SPAN style="COLOR: #ffa34f">ejb
-jar.xml里面的,所以n个条件就需?c0n+c1n+...cnn )2的nơ方个EJBFinderҎQ简直没有办法说?

JDBC实现PrepareStatement的动态SQL构造不是不能够Q而是非常ȝQ需要写一个非帔R常大的if elseif else嵌套的判断?

Hibernate实现h特别单,Q其实OJB也实CPrepareStatement的动态SQL构造)q本wƈ不复杂,但是需要你多写些代码而已Q由于CMP把EJBQL写死在配|文仉面了Q你q选择的余地都没有?/SPAN>



killvin 2006-03-02 20:58 发表评论
]]>
Aaron Johnson对Class.forName()的解释! http://m.tkk7.com/killvin/archive/2006/03/02/33305.htmlkillvinkillvinThu, 02 Mar 2006 12:57:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33305.htmlA reader asked a question via a comment a couple months ago that I didn't really have an answer for (and had always kind of wondered the same thing). In the original post (which showed how to use JDBC with ColdFusion), I used the following snippet of code:

Class.forName("jdbc.DriverXYZ");
Connection con = DriverManager.getConnection(url,
  "myLogin", "myPassword");

and the reader wanted to know what the Class.forName(..) method did. The most common answer you'll hear is that it loads the database driver, which, while technically true, is shallow. Where does it get loaded? How does it happen? And why?

To answer the question I started with the JavaDoc for the Class.forName() method. According to the documentation, the method:

... attempts to locate, load, and link the class or interface
I wasn't perfectly clear on what "locate, load, and link" meant, so I did a little digging through the Java Language Specification. According to chapter 12 of the JLS:
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler, and constructing, from that binary form, a Class object to represent the class or interface.
Next, again according to the JLS, it must be transformed from it's binary representation to something the Java virtual machine can use, this process is called linking. Finally, the class is initialized, which is the process that executes the static initializer and the initializers for static fields declared in the class.

So then back to the original problem, when Class.forName() is called with an argument like this:

Class.forName("org.gjt.mm.mysql.Driver");

the classloader attempts to load and link the Driver class in the "org.gjt.mm.mysql" package and if successful, the static initializer is run. The MySQL Driver (download the source code) static initializer looks like this:

static {
  try {
    java.sql.DriverManager.registerDriver(new Driver());
  } catch (SQLException E) {
    throw new RuntimeException("Can't register driver!");
  }
}

So it calls a static method in the java.sql.DriverManager class which apparently registers a copy of itself when it loads.

So now I understand the where and the how, what about why? To understand the why you have to look at the next line in the initial code example:

Connection con = DriverManager.getConnection(url,
  "myLogin", "myPassword");

The DriverManager class (view DriverManager source here) returns a database connection given a JDBC URL string, a username and a password. In order to create that connection, the DriverManager class has to know which database driver you want to use. It does that by iterating over the array (internally a Vector) of drivers that have registered with it (ie: the registerDriver(Driver driver) method illustrated above) and calls the acceptsURL(url)) method on each driver in the array, effectively asking the driver to tell it whether or not it can handle the JDBC URL.

So there you have it. Class.forName explained.



killvin 2006-03-02 20:57 发表评论
]]>
Java基础问题Qjava.lang.String - intern() http://m.tkk7.com/killvin/archive/2006/03/02/33304.htmlkillvinkillvinThu, 02 Mar 2006 12:56:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33304.html原文: http://forum.javaeye.com/viewtopic.php?t=17912


搂主的问题问的含含糊p?flyjiel出了非常详l的解释Q?BR>不过是没有解释String实例化的Ҏ斚w以及Intern()Ҏ的含?BR>
-------
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
java代码:
String str ;

q样声明str它只支是一个对象的referenceQ不会生实际的对象。如果没有初始化strQ编译时便会发生错误?
java代码:
String str1=new String("test");
String str2 = "test";

str1是一个新的对象。new关键字的意思就是创建某个新的对象。而str2是一个对象的引用。 它们的内容相同,但内存地址是不一L?java中对象的引用存在Stack(?中,而对象由Heap(?分配I间?

3、引?=变量?  不一?
java代码:

  public class TestString {
public static void main(String[] args) {
String s1 = "test";
String s2 = new String("test");
if (s1 == s2)
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
if (s1.equals(s2))
System.out.println("s1 equals s2");
else System.out.println("s1 not equals s2");
}
}

我们?s2 ?new 操作W创建程序输出:s1 != s2 s1 equals s2.
java代码:

s2 = s2.intern();

在你加上q句话后Q上面的E序输入Qs1 == s2 s1 equals s2

而String a = "test" ; String b = "test" ; a == b 会返回true; q里a="test"时创Z个在栈中的reference, b=test时jvm发现栈中已存在名?test"的字W串Q直接引用。结论:String 是个对象Q要Ҏ两个不同的String对象的值是否相同明昄要用?equals() q个Ҏ. ?= 比较的是内存地址的倹{?

4、private final String a = "test", q个a属于帔RQ存攑֜帔R存储I间(CS)中?

5、徏议你看看<<深入出java虚拟?gt;>一书?

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



ȝ

1. 在学习JAVA的时候就知道Q=比较的是内存地址.而equals比较的是内存地址对应的|Q可是还是有很多的h问来问去的,真不知道他们JAVA的基评是怎么学的Q!Q?BR>
2. JAVA所有的对象都是存放在堆中的!你获取的"对象"仅仅只是对象的引用而已

3. String是比较特D的对象Q特D在
3.1 > String a = new String("test") Q此时你是在堆中实例化了一个字W串对象
3.2 > String b = "test"Q此时JVM会先d中寻找这L对象Q如果有p回此对象的引用;如果没有重新实例化一个这L对象Q基于这L一个过E所以JAVA要求String不可以更改值的?BR>
3.3 >intern()Ҏ是试图完成q样的一个寻找过E?BR>When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

q里有一份详l的参考资料:

关于Java栈与堆的思?http://www.javafan.net/article/20051123115654293.html




killvin 2006-03-02 20:56 发表评论
]]>
Java Nested class http://m.tkk7.com/killvin/archive/2006/03/02/33303.htmlkillvinkillvinThu, 02 Mar 2006 12:55:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33303.htmlURL : http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

|上的一些关于内部类的概忉|不完整的Q还是看看SUN的文档上的标准答案?BR>...

Like other members, a nested class can be declared static (or not). A static nested class is called just that: a static nested class. A nonstatic nested class is called an inner class.

Q?Nested class分ؓ静态Static nested class 的和非静态的 inner class, 在SUN的眼里只有Nested ClassQ!


As with static methods and variables, which we call class methods and variables, a static nested class is associated with its enclosing class. And like class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class ?it can use them only through an object reference.

Q?静态的Static nested class是不可以直接调用它的外部cenclosing class的,但是可以通过外部cȝ引用来调用,像你在一个类中写了mainҎ一栗?BR>...

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's instance variables and methods. Also, because an inner class is associated with an instance, it cannot define any static members itself.

Q非静态类inner class 可以自由的引用外部类的属性和ҎQ但是它与一个实例绑定在了以Ӟ不可以定义静态的属性、方法(q点不是很理解,可能需要看JVM的类实现Q?BR>
...
class EnclosingClass {
...
class InnerClass {
...
}
}


The interesting feature about the relationship between these two classes is not that InnerClass is syntactically defined within EnclosingClass. Rather, it's that an instance of InnerClass can exist only within an instance of EnclosingClass and that it has direct access to the instance variables and methods of its enclosing instance. The next figure illustrates this idea.


Q图形化的嵌入类与外部类的关p?/DIV>

killvin 2006-03-02 20:55 发表评论
]]>
Difference requestDispatcher.forward and response.sendRedirect. http://m.tkk7.com/killvin/archive/2006/03/02/33301.htmlkillvinkillvinThu, 02 Mar 2006 12:54:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33301.html引言
在用response的过E中l常会遇到蟩转页面的事情Q这个时候有两种情况供你选择
1。就是调?BR>ServletContext.getRequestDispatcher(java.lang.String).forward(request ,
response) ;
2。就是调用response.setRedirect(),可是q两个方法有什么不同呢Q?BR>

看看TSS上关于这个问题的解释Q?BR>Difference request.forward() and response.sendRedirect .
Posted by: Kapil Israni on August 24, 2000 in response to Message #2253 1
replies in this thread
i suppose u r talking bout requestDispatcher.forward() here.

well basically both method calls redirect u to new resource/page/servlet.

the difference between the two is that sendRedirect always sends a header
back to the client/browser. this header then contains the
resource(page/servlet) which u wanted to be redirected. the browser uses
this header to make another fresh request. thus sendRedirect has a overhead
as to the extra remort trip being incurred. its like any other Http request
being generated by ur browser. the advantage is that u can point to any
resource(whether on the same domain or some other domain). for eg if
sendRedirect was called at www.mydomain.com then it can also be used to
redirect a call to a resource on www.theserverside.com.

where as in case of forward() call, the above is not true. resources from
the server, where the fwd. call was made, can only be requested for. but
the major diff between the two is that forward just routes the request to
the new resources which u specify in ur forward call. that means this route
is made by the servlet engine at the server level only. no headers r sent
to the browser which makes this very eficient. also the request and
response objects remain the same both from where the forward call was made
and the resource which was called.

i hope i have hit ur question right.


killvin 2006-03-02 20:54 发表评论
]]>
初识Java内部c?http://m.tkk7.com/killvin/archive/2006/03/02/33302.htmlkillvinkillvinThu, 02 Mar 2006 12:54:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33302.html    提vJava内部c(Inner ClassQ可能很多h不太熟悉Q实际上cM的概念在C++里也有,那就是嵌套类QNested ClassQ,关于q两者的区别与联p,在下文中会有Ҏ。内部类从表面上看,是在类中又定义了一个类Q下文会看到Q内部类可以在很多地方定义)Q而实际上q没有那么简单,乍看上去内部cM乎有些多余,它的用处对于初学者来说可能ƈ不是那么显著Q但是随着对它的深入了解,你会发现Java的设计者在内部cn上的是用心良苦。学会用内部类Q是掌握Java高~程的一部分Q它可以让你更优雅地设计你的E序l构。下面从以下几个斚w来介l:
    ·W一ơ见?BR>public interface Contents {
    int value();
}
public interface Destination {
    String readLabel();
}
public class Goods {
    private class Content implements Contents {
        private int i = 11;
        public int value() {
            return i;
        }
    }
    protected class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
            label = whereTo;
        }
        public String readLabel() {
            return label;
        }
    }
    public Destination dest(String s) {
        return new GDestination(s);
    }
    public Contents cont() {
        return new Content();
    }
}
class TestGoods {
    public static void main(String[] args) {
        Goods p = new Goods();
        Contents c = p.cont();
        Destination d = p.dest("Beijing");
    }
}
    在这个例子里cContent和GDestination被定义在了类Goods内部Qƈ且分别有着protected和private修饰W来控制讉KU别。Content代表着Goods的内容,而GDestination代表着Goods的目的地。它们分别实C两个接口Content和Destination。在后面的mainҎ里,直接?Contents c和Destination dq行操作Q你甚至q这两个内部cȝ名字都没有看见!q样Q内部类的第一个好处就体现出来了——隐藏你不想让别人知道的操作Q也卛_装性?
    同时Q我们也发现了在外部cM用范围之外得到内部类对象的第一个方法,那就是利用其外部cȝҎ创徏q返回。上例中的cont()和dest()Ҏ是q么做的。那么还有没有别的方法呢Q当然有Q其语法格式如下Q?BR>    outerObject=new outerClass(Constructor Parameters);
    outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);
    注意在创建非静态内部类对象Ӟ一定要先创v相应的外部类对象。至于原因,也就引出了我们下一个话题—?BR>    ·非静态内部类对象有着指向其外部类对象的引?BR>    对刚才的例子E作修改Q?BR>public class Goods {
    private valueRate=2;
    private class Content implements Contents {
        private int i = 11*valueRate;
        public int value() {
            return i;
        }
    }
    protected class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
            label = whereTo;
        }
        public String readLabel() {
            return label;
        }
    }
    public Destination dest(String s) {
        return new GDestination(s);
    }
    public Contents cont() {
        return new Content();
    }
}
    修改的部分用蓝色昄了。在q里我们lGoodscd加了一个private成员变量valueRateQ意义是货物的h值系敎ͼ在内部类Content的方法value()计算价值时把它乘上。我们发玎ͼvalue()可以讉KvalueRateQ这也是内部cȝW二个好处——一个内部类对象可以讉K创徏它的外部cd象的内容Q甚臛_括私有变量!q是一个非常有用的Ҏ,为我们在设计时提供了更多的思\和捷径。要惛_现这个功能,内部cd象就必须有指向外部类对象的引用。Java~译器在创徏内部cd象时Q隐式的把其外部cd象的引用也传了进dƈ一直保存着。这样就使得内部cd象始l可以访问其外部cd象,同时q也是ؓ什么在外部cM用范围之外向要创建内部类对象必须先创建其外部cd象的原因?BR>    有h会问Q如果内部类里的一个成员变量与外部cȝ一个成员变量同名,也即外部cȝ同名成员变量被屏蔽了Q怎么办?没事QJava里用如下格式表达外部cȝ引用Q?BR>outerClass.this
    有了它,我们׃怕这U屏蔽的情况了?BR>    ·静态内部类
    和普通的cMP内部cM可以有静态的。不q和非静态内部类相比Q区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套cd相像了,Java内部cMC++嵌套cL大的不同在于是否有指向外部的引用这一点上Q当然从设计的角度以及以它一些细节来讲还有区别?BR>    除此之外Q在M非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类Q内部类的嵌套可以不止一层)。不q静态内部类中却可以拥有q一切。这也算是两者的W二个区别吧?BR>    ·局部内部类
    是的QJava内部cM可以是局部的Q它可以定义在一个方法甚至一个代码块之内?BR>public class Goods1 {
     public Destination dest(String s) {
          class GDestination implements Destination {
               private String label;
               private GDestination(String whereTo) {
                    label = whereTo;
               }
               public String readLabel() { return label; }
          }
          return new GDestination(s);
     }
     public static void main(String[] args) {
          Goods1 g= new Goods1();
          Destination d = g.dest("Beijing");
     }
}
    上面是q样一个例子。在Ҏdest中我们定义了一个内部类Q最后由q个Ҏq回q个内部cȝ对象。如果我们在用一个内部类的时候仅需要创建它的一个对象ƈ创给外部Q就可以q样做。当Ӟ定义在方法中的内部类可以使设计多样化Q用途绝不仅仅在q一炏V?BR>    下面有一个更怪的例子Q?BR>public class Goods2{
     private void internalTracking(boolean b) {
          if(b) {
               class TrackingSlip {
                    private String id;
                    TrackingSlip(String s) {
                         id = s;
                    }
                    String getSlip() { return id; }
               }
               TrackingSlip ts = new TrackingSlip("slip");
               String s = ts.getSlip();
          }
     }
     public void track() { internalTracking(true); }
     public static void main(String[] args) {
          Goods2 g= new Goods2();
          g.track();
     }
}
    你不能在if之外创徏q个内部cȝ对象Q因已经出了它的作用域。不q在~译的时候,内部cTrackingSlip和其他类一样同时被~译Q只不过它由它自q作用域,出了这个范围就无效Q除此之外它和其他内部类q没有区别?BR>    ·匿名内部c?
    java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一P当你只需要创Z个类的对象而且用不上它的名字时Q用内部类可以使代码看上去z清楚。它的语法规则是q样的:
    new interfacename(){......}; ?new superclassname(){......};
    下面接着前面l箋举例子:
public class Goods3 {
     public Contents cont(){
          return new Contents(){
               private int i = 11;
               public int value() {
                    return i;
               }
          };
     }
}
    q里Ҏcont()使用匿名内部cȝ接返回了一个实C接口Contents的类的对象,看上ȝ十分简z?BR>    在java的事件处理的匿名适配器中Q匿名内部类被大量的使用。例如在惛_闭窗口时加上q样一句代码:
frame.addWindowListener(new WindowAdapter(){
     public void windowClosing(WindowEvent e){
          System.exit(0);
     }
});
    有一炚w要注意的是,匿名内部cȝ于没有名字,所以它没有构造函敎ͼ但是如果q个匿名内部cȝ承了一个只含有带参数构造函数的父类Q创建它的时候必d上这些参敎ͼq在实现的过E中使用super关键字调用相应的内容Q。如果你惌初始化它的成员变量,有下面几U方法:
    1.如果是在一个方法的匿名内部c,可以利用q个Ҏ传进你想要的参数Q不q记住,q些参数必须被声明ؓfinal?
    2.匿名内部类攚w成有名字的局部内部类Q这样它可以拥有构造函C?
    3.在这个匿名内部类中用初始化代码块?
    ·Z么需要内部类Q?
    java内部cL什么好处?Z么需要内部类Q?BR>    首先举一个简单的例子Q如果你惛_C个接口,但是q个接口中的一个方法和你构想的q个cM的一个方法的名称Q参数相同,你应该怎么办?q时候,你可以徏一个内部类实现q个接口。由于内部类对外部类的所有内定w是可讉K的,所以这样做可以完成所有你直接实现q个接口的功能?BR>    不过你可能要质疑Q更改一下方法的不就行了吗?
    的确Q以此作计内部类的理由,实在没有说服力?BR>    真正的原因是q样的,java中的内部cd接口加在一P可以的解军_被C++E序员抱怨java中存在的一个问题——没有多l承。实际上QC++的多l承设计h很复杂,而java通过内部cd上接口,可以很好的实现多l承的效果?BR>

killvin 2006-03-02 20:54 发表评论
]]>
Java关键? transient | strictfp | volatile http://m.tkk7.com/killvin/archive/2006/03/02/33300.htmlkillvinkillvinThu, 02 Mar 2006 12:53:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33300.htmlJava Language Keywords

Here's a list of keywords in the Java language. These words are reserved ?you cannot use any of these words as names in your programs. true, false, and null are not keywords but they are reserved words, so you cannot use them as names in your programs either.

abstract    |   continue    |   for    |    new     |   switch
assert***  |   default     |   goto*     |   package     |   synchronized
boolean    |   do     |   if     |   private     |   this
break         |   double     |   implements    |   protected    |   throw
byte            |   else     |   import     |   public  throws
case          |   enum****    |   instanceof    |   return     |   transient 
catch         |   extends     |   int     |   short     |   try
char           |   final     |   interface    |   static     |   void
class         |   finally     |   long     |   strictfp**    |   volatile
const*       |   float     |   native     |   super     |   while


*   not used
**   added in 1.2
***   added in 1.4 
****   added in 5.0                                    

 

Key: strictfp**

使用对象Q类、方?/P>

自Java2以来QJava语言增加了一个关键字strictfpQ虽然这个关键字在大多数场合比较用Q但是还是有必要了解一下?/P>

strictfp的意思是FP-strictQ也是说精Q点的意思。在Java虚拟行Q点运时Q如果没有指定strictfp关键字时QJava的编译器以及q行环境在对点q算的表辑ּ是采取一U近g我行我素的行为来完成q些操作Q以致于得到的结果往往无法令你满意。而一旦用了strictfp来声明一个类、接口或者方法时Q那么所声明的范围内Java的编译器以及q行环境会完全依照Q点规范IEEE-754来执行。因此如果你惌你的点q算更加_Q而且不会因ؓ不同的硬件^台所执行的结果不一致的话,那就L关键字strictfp?/P>

你可以将一个类、接口以及方法声明ؓstrictfpQ但是不允许Ҏ口中的方法以及构造函数声明strictfp关键字,例如下面的代码:

1. 合法的用关键字strictfp

strictfp interface A {}

public strictfp class FpDemo1 {
    strictfp void f() {}
}

2. 错误的用方?/P>

interface A {
    strictfp void f();
}

public class FpDemo2 {
    strictfp FpDemo2() {}
}

一旦用了关键字strictfp来声明某个类、接口或者方法时Q那么在q个关键字所声明的范围内所有Q点运都是精的Q符合IEEE-754规范的。例如一个类被声明ؓstrictfpQ那么该cM所有的Ҏ都是strictfp的?/P>

 

Keys: volatile

使用对象Q字D?BR>
介绍Q因为异步线E可以访问字D,所以有些优化操作是一定不能作用在字段上的。volatile有时

可以代替synchronized?BR>

 

KeysQ?FONT face="Courier New">transient

  使用对象Q字D?/P>

  介绍Q字D不是对象持久状态的一部分Q不应该把字D和对象一起串赗?/P>

killvin 2006-03-02 20:53 发表评论
]]>
Java异常框架设计一 http://m.tkk7.com/killvin/archive/2006/03/02/33299.htmlkillvinkillvinThu, 02 Mar 2006 12:50:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33299.html引言

 记得当初参与某公司的ERP目中,接触q异常框架这个概念,可是gq没有感觉到当时技术经理提个概늚意义Q而且他也对这个概念似乎很"保守"Q虽然按照他的思\L行,但没有理解的概念再实施v来的时候L觉得?别扭"Q而如今面对自p设计咚咚了,不得不重新审视异常这个概念,JAVA异常的介l文章在|络上非常的,而对于如何构件J2EE的异常处理框架更昄E,于是׃使自己写下了q样的文章?/P>

 本文只是自己的一些愚见,希望和大家相互学习。Email:Killvin@hotmail.com

概念

什么是异常Q?/P>

异常QexceptionQ应该是异常事gQexceptional eventQ的~写?BR>异常定义Q异常是一个在E序执行期间发生的事Ӟ它中断正在执行的E序的正常的指o?BR>当在一个方法中发生错误的时候,q个Ҏ创徏一个对象,q且把它传递给q行时系l。这个对象被叫做异常对象Q它包含了有关错误的信息Q这些信息包括错误的cd和在E序发生错误时的状态。创Z个错误对象ƈ把它传递给q行时系l被叫做抛出异常?BR>一个方法抛出异常后Q运行时pȝ׃试着查找一些方法来处理它。这些处理异常的可能的方法的集合是被整理在一LҎ列表Q这些方法能够被发生错误的方法调用。这个方法列表被叫做堆栈调用Qcall stackQ?/P>

q行时系l搜d含能够处理异常的代码块的Ҏ所h的堆栈。这个代码块叫做异常处理器,搜寻首先从发生的Ҏ开始,然后依次按着调用Ҏ的倒序索调用堆栈。当扑ֈ一个相应的处理器时Q运行时pȝ把异常传递给q个处理器。一个异常处理器要适当地考o抛出的异常对象的cd和异常处理器所处理的异常的cd是否匚w。异常被捕获以后Q异常处理器关闭。如果运行时pȝ搜寻了这个方法的所有的调用堆栈Q而没有找到相应的异常处理器?/P>

 

怎么设计异常框架

M的异帔R是Throwablec(Z不是接口Q?Q,q且在它之下包含两个字类Error / ExceptionQ而Error仅在当在Java虚拟Z发生动态连接失败或其它的定位失败的时候,Java虚拟机抛Z个Error对象。典型的易程序不捕获或抛出Errors对象Q你可能永远不会遇到需要实例化Error的应用,那就让我们关心一下Exception

Exception中比较重要的是RuntimeExceptionQ运行时异常Q当然这个名字是存在争议的,因ؓM的异帔R只会发生在运行时Q,Z么说q个cL很重要的呢?因ؓ它直接关pd你的异常框架的设计,仔细看RuntimeException

A method is not required to declare in its throws clause any subclasses of RuntimeException that might be thrown during the execution of the method but not caught.

Q可能在执行Ҏ期间抛出但未被捕L RuntimeException 的Q何子c都无需?throws 子句中进行声明?

也就是说你的应用应该不去“关心”(说不兛_是不服责ȝQ但只是你不应该试图实例化它的字c)RuntimeExceptionQ就如同你不应该兛_Error的生与处理一PRuntimeException描述的是E序的错误引h的,因该q序负担这个责任!Q?lt;B>从责任这个角度看Error属于JVM需要负担的责Q;RuntimeException是程序应该负担的责Q;checked exception 是具体应用负担的责Q</B>Q?/P>

那就有h会问Q那我该兛_什么!{案是除了Error与RuntimeExceptionQ其他剩下的异常都是你需要关心的Q而这些异常类l称为Checked Exception,至于Error与RuntimeException则被l称为Unchecked Exception.


异常的概念就q些了,即你在|络上搜索也׃q如此,是不是感觉到有点清晰又有Ҏp?那么怎么该如何在q样单薄而模p的概念下设计J2EE的异常框架呢Q?/P>


解决ҎQJ2EE异常框架

我们拿一个模拟的例子来说明异常框架的设计q程Q比如我们要对外提供doBusiness()q个业务Ҏ

public void doBusiness() throws xxxBusinessException

当客L调用q样的方法的时候应该这样处理异常(包括处理RuntimeException , checked exceptionQ?BR><B>CQ无论如何我们都不希望或者确切的说是不应该将RuntimeExceptionq样的异常暴露给客户的,因ؓ他们没有解决q个问题的责任!</B>
我们暂时Struts中的某个Action看作时客LQ其中doExecute(....)要调用doBusiness()q个Ҏ

public void doAction(......)
{
 try
 {

  xxx.doBusiness();
 }
 catch(Exception e)
 {
   if(e instanceof RuntimeException) 
   {
    // catch runtime exception
    // 你可以在q里捕获到的RuntimeException
    // 异帔R知l某个负责此E序的程序员Q让他知道他
    // 自己犯了多么低的错误!


   }else
   {
    //checked exception such as xxxBusinessException
    //这L异常暴露l客hC?nbsp;   

   }

 }
}

我们可以q样设计xxxBusinessException

public class xxxBusinessException extends ApplicationException
{
    public xxxBusinessException(String s){
        super(s);

};

import java.io.PrintStream;
import java.io.PrintWriter;
public class ApplicationException extends Exception {
       /** A wrapped Throwable */
       protected Throwable cause;
       public ApplicationException() {
           super("Error occurred in application.");
       }
       public ApplicationException(String message)  {
           super(message);
       }
       public ApplicationException(String message, Throwable cause)  {
           super(message);
           this.cause = cause;
       }
       // Created to match the JDK 1.4 Throwable method.
       public Throwable initCause(Throwable cause)  {
           this.cause = cause;
           return cause;
       }
       public String getMessage() {
           // Get this exception's message.
           String msg = super.getMessage();
           Throwable parent = this;
           Throwable child;
           // Look for nested exceptions.
           while((child = getNestedException(parent)) != null) {
               // Get the child's message.
               String msg2 = child.getMessage();
               // If we found a message for the child exception,
               // we append it.
               if (msg2 != null) {
                   if (msg != null) {
                       msg += ": " + msg2;
                   } else {
                       msg = msg2;
                   }
               }
               // Any nested ApplicationException will append its own
               // children, so we need to break out of here.
               if (child instanceof ApplicationException) {
                   break;
               }
               parent = child;
           }
           // Return the completed message.
           return msg;
       }
       public void printStackTrace() {
           // Print the stack trace for this exception.
           super.printStackTrace();
           Throwable parent = this;
           Throwable child;
           // Print the stack trace for each nested exception.
           while((child = getNestedException(parent)) != null) {
               if (child != null) {
                   System.err.print("Caused by: ");
                   child.printStackTrace();
                   if (child instanceof ApplicationException) {
                       break;
                   }
                   parent = child;
               }
           }
       }
       public void printStackTrace(PrintStream s) {
           // Print the stack trace for this exception.
           super.printStackTrace(s);
           Throwable parent = this;
           Throwable child;
           // Print the stack trace for each nested exception.
           while((child = getNestedException(parent)) != null) {
               if (child != null) {
                   s.print("Caused by: ");
                   child.printStackTrace(s);
                   if (child instanceof ApplicationException) {
                       break;
                   }
                   parent = child;
               }
           }
       }
       public void printStackTrace(PrintWriter w) {
           // Print the stack trace for this exception.
           super.printStackTrace(w);
           Throwable parent = this;
           Throwable child;
           // Print the stack trace for each nested exception.
           while((child = getNestedException(parent)) != null) {
               if (child != null) {
                   w.print("Caused by: ");
                   child.printStackTrace(w);
                   if (child instanceof ApplicationException) {
                       break;
                   }
                   parent = child;
               }
           }
       }
       public Throwable getCause()  {
           return cause;
       }
}

?聪明"的读者肯定要问我那doBusiness()q个业务Ҏ该如何包装异常呢Q?/P>

 public void doBusiness() throw xxxBusinessException
 {
   try
   {
     execute1(); // if it throw exception1

     exexute2(); // if it throw exception 2

     .... .....

   }
   catch (exception1 e1)
   {
    throw new xxxBusinessException(e1);
   }
   catch(exception2 e2)
   {
    throw new xxxBusinessException(e2);
   }
   ........
 }

 也可以这?/P>

 public void doBusiness() throw xxxBusinessException
 {
   try
   {
     execute1(); // if it throw exception1

     exexute2(); // if it throw exception 2

     .... .....

   }
   catch (Exception e)
   {
    // 注意很多应用在这里根本不判断异常的类型而一股脑的采?BR>    // throw new xxxBusinessException(e);
    // 而这样带来的问题是xxxBusinessException"吞掉?RuntimeException
    // 从而将checked excption 与unchecked exception混在了一P

    // 其实xxxBusinessException属于checked excpetion Q它Ҏ不应该也不能够理睬RuntimeException
    if(! e instanceof RuntimeException) throw new xxxBusinessException(e);
   }
 }


ȝ
 1。JAVA的异常分Zc? checked exception & unchecked excpetion
 2。应用开发中产生的异帔R应该集成自Exception 但都属于checked excpetioncd
 3。应用中的每一层在包装q传递异常的时候要qo掉RuntimeExceptionQ?BR> 4。从责Qq个角度看Error属于JVM需要负担的责Q;RuntimeException是程序应该负担的责Q;checked exception 是具体应用负担的责Q
 5。无论如何我们都不希望或者确切的说是不应该将RuntimeExceptionq样的异常暴露给客户的,因ؓ他们没有解决q个问题的责任!



killvin 2006-03-02 20:50 发表评论
]]>
Java内部c?如何在内部类中返回外部类对象 http://m.tkk7.com/killvin/archive/2006/03/02/33298.htmlkillvinkillvinThu, 02 Mar 2006 12:49:00 GMThttp://m.tkk7.com/killvin/archive/2006/03/02/33298.htmlNasted Class 的介l,误见参?/P>

今天讨论的不是不是内部类的概念,而是具体使用的一个场景-如何在内部类中返回外部对?/P>

看一D代?/P>

import java.util.LinkedList;
import java.util.List;


public class OuterClass
{

 private List listeners = new LinkedList();

 public void addListeners(IListener listener)
 {
  this.listeners.add(listener);
 }


 private OuterClass outer = this;  Q?Q?BR> private class InnterClass
 {
  public void publish()
  {
   //事件发布出?Q?Q?BR>   for(int i=0;i < listeners.size();i++)
   {
    IListener listener = (IListener) listeners.get(i);
    listener.receiveEvent(outer);
   }

  }
 }


 public void execute()
 {
  InnterClass in = new InnterClass(); Q?Q?BR>  in.publish();
 }
}

public interface IListener
{

public void receiveEvent(OuterClass obj);
}

你可能觉得这个例子很别扭Q在哪里让你觉得隑֏呢?其实问题的关键就在于接口IListener的定义,q里需要给receiveEventҎ传递的参数是外部对象!Q别Ȁ动,下面我会说明需要传递的一个场景)

场景

在一个GUIpȝ中,我们要在LWorkSpaceQWorkSpace实现了IListener接口Q上产生一颗树Q但树中的每个节点的产生Q绘图)是我们不知道的算法,pȝ只ؓ我们提供了一些绘囄接口Qƈq回元素的句柄!看来我们需?包装"一下这个绘囄句柄BrushQ其实我把它叫做W刷Q因为它只知道如??出图像来Q就q点本事Q)q对外提供节?STRONG>Nodeq样一个通用的类?/P>

此时Node与Brush的关pd很微妙了Q不q我们可以抛开q些外表Q看到Node与Brush其实是外部cM内部cȝ关系Q-W一步完成了Q确定了两者的关系

然而,事情没有q么单,Nodecdd理一些事Ӟ而这些事件理所当然只有Brush能够看懂Q而NodeҎ不知道这L事g处理q程Q现在有两个办法Q办法一Q让Node实现Brush所有的事gQ办法二Q把Brushq回回去Q让它来处理自己的事Ӟ看来办法二是个好LQ因为我可以不关心事件的U类Q-W二步完成了Q确定了事g处理的责?/STRONG>

q没完呢Q你肯定不希?STRONG>LWorkSpace面对的是l图的句?/STRONG>Brushq样的对象,相反你只希望WokSpace只知道Node的存在!IListener接口中receiveEventҎ的参数定义ؓOuterClass q此而来Q-W三步完成:接口的定?/STRONG>

public interface IListener
{

public void receiveEvent(OuterClass obj);
}

 既然说清楚了q个问题Q应该比较清楚了吧?Q那改如何实现这样一个蹩脚而有无可奈何的设计呢Q让我们回忆一下内部类Q内部类拥有讉K外部cȝҎ与属性的权限

 private OuterClass outer = this;  Q?q个对外部类的引用就是ؓ内部cȝ讉K准备?/STRONG>

 private class InnterClass
 {
  public void publish()
  {
   //事件发布出?nbsp;

   for(int i=0;i < listeners.size();i++)
   {
    IListener listener = (IListener) listeners.get(i);
    listener.receiveEvent(outer);  Q?nbsp;q里不可以返回thisQ因为this代表的是内部c自?BR>   }
  }

 

 

参?/P>

Java Nested class   http://blog.csdn.net/Killvin/archive/2006/01/10/574983.aspx

初识Java内部c?    http://blog.csdn.net/killvin/archive/2006/01/10/574991.aspx



killvin 2006-03-02 20:49 发表评论
]]>
վ֩ģ壺 ҹڵ| 99þþƷѾƷ| ַѹۿ | ¼ҳ| 㽶ѾƷƵ| һ| ŮߵƵѹۿڵ| վƵ| ް鵺̳| 99Ƶۿ| һ| AVַ߹ۿ| Ʒһ| ޸avվ| ɬɬѹۿƷ | ձѵӰһ| AVרӰ| Ʒۺ| þþþþþѿ| H߲߹ۿH| Ļav޿| ޳avƬ롿| A| AëƬþ| ŷ޹պƷ| һѸ߹ۿ| AVרAV鶹Ѿ | ޾Ʒa߹ۿapp| ѹվ߹ۿ15 | ޵һվ| һëƬѹۿ| ޾ǧ˾ղ| ۺݾ| ƷרëƬ| ɫַ| 1134Ʒ| СƵ߹ۿ| ձһѿ| ŷһ| ¸Ļ| ĻƷþ|