积少成多

垃圾堆

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  29 Posts :: 1 Stories :: 5 Comments :: 0 Trackbacks

#

Flex Builder 3 正式版,发布于中国时间 2008 年 2 月 25 日;

下载地址一:
http://download.macromedia.com/pub/flex/flex_builder/FB3_win.exe
大小: 424 MB ;未进行压缩的 Flex Builder 3 安装文件
不用注册登录,可以直接下载。

下载地址二:

http://trials.adobe.com/Applications/.../FB3_WWEJ.exe
大小: 385.84 MB ; 已经压缩的 Flex Builder 3 安装文件
需要注册登录,才可下载。

Flex builder 3.0注册码(已经试过的,可用的):

1377-4168-2018-0771-2432-1495

1377-4760-3354-0772-2773-8996

1377-4165-2080-7265-7813-8901

1377-4964-5021-8182-2399-8235

Flex builder 中要进行调试,就必须安装含debug的flash player版本。下载链接地址:

Adobe Flash Player 9 — Debugger Versions (aka debug players or content debuggers) for Flex and Flash Developers

12/3/2007 Updated debugger versions of Flash Player 9 (aka debug players or content debuggers) are available for Flex Builder 2 users and Flash CS3 Professional users. These new players are version 9.0.r115.

Download the Windows Flash Player 9 ActiveX control content debugger (for IE) (EXE, 1.59 MB)

Download the Windows Flash Player 9 Plugin content debugger (for Netscape-compatible browsers) (EXE, 1.56 MB)

Download the Windows Flash Player 9 Projector content debugger (EXE, 3.69 MB)

Download the Macintosh Flash Player 9 Plugin content debugger (Intel-based Macs) (DMG, 5.35 MB)

Download the Macintosh Flash Player 9 Plugin content debugger (PowerPC-based Macs) (DMG, 2.41 MB)

Download the Macintosh Flash Player 9 Projector content debugger (ZIP, 4.81 MB)

12/3/2007 Updated Linux debugger versions (aka debug players or content debuggers) of Flash Player 9 are now available. Additionally, the Linux standalone player (projector) is available for developers who wish to publish projectors on Linux operating systems.

Download the Linux debugger and standalone players (TAR.GZ, 9.29 MB)

posted @ 2011-06-28 22:46 思无 阅读(352) | 评论 (0)编辑 收藏

项目中,浏览器和服务器之间长时间没有交互,会被超时,但是用户只有在下次尝试连接的时候才会知道已经超时了。总结了一下当前这个项目针对这个问题是怎么做的。
在即将超时的时候,提醒用户,之后通过ajax 发送空消息给服务器以防止服务器将session无效。
下面是核心的代码:

var previousSmSession = null;
var times = 0;
var timer = setInterval("checkSmSession()"60 * 3000);
var maxTimes = 9;

function checkSmSession()
{
    
var currentSmSession = getCurrSmSession();
    
if (currentSmSession != previousSmSession) {
        previousSmSession 
= currentSmSession;
        times 
= 0;
    } 
else {
        times
++;
        
if (maxTimes == times) {
                
this.focus();
                
var currentCheckingTime = new Date();
                currentCheckingTime.setTime(currentCheckingTime.getTime() 
+ 60 * 3000);
                
var sessionWarningMsg = "Due to inactivity you will be logged out of the system at " + currentCheckingTime.toLocaleString().replace(/^.*?\d{4/,""+ ". To extend your session click OK."
                
var val = confirm(sessionWarningMsg);
                
if (val) {
                        times 
= 0;
                        refreshSessions();
                 } 
else {
                      
//  self.location = "/wps/logout.jsp"; 
                }
        }
    }
}


function getCurrSmSession() {
    
var allCookies = document.cookie.split(";");
    
    
var aCookie = null;
    
var aCookieName = "";
    
var aCookieValue = "";         
    
for (var i=0; i<allCookies.length; i++)    {
        aCookie 
= allCookies[i].split("=");
        aCookieName 
= aCookie[0].replace(/^\s+|\s+$/g, "");
        
if (smSessionName == aCookieName) {
            
if (aCookie.length > 1) {
                aCookieValue 
= unescape(aCookie[1].replace(/^\s+|\s+$/g, ""));
            }
            
break;
        }
    }
    
if (i == allCookies.length) {
        aCookieValue 
= null;
    }
    
return aCookieValue;
}

function refreshSessions () {
    
var dummyUrls = ["/home/FlexKeepAlive.jsp""/cfi/FlexKeepAlive.jsp"];
    
for (var i=0; i<dummyUrls.length; i++) {
        
var aXmlHttp = getXMLHttpObject();
        
if (null == aXmlHttp) {
            alert(
"AJAX does not work!");
            
break;    
        }
        aXmlHttp.open(
"GET", dummyUrls[i]+"?sid="+Math.random(), true);
        aXmlHttp.send(
null);
    }     
}

function getXMLHttpObject () {
    
var xmlHttpObj = null;
    
    
try {
        xmlHttpObj 
= new XMLHttpRequest();// Firefox    
    } catch (e) {
        
try {
            xmlHttpObj 
= new ActiveXObject("Msxml2.XMLHTTP");    //IE
        } catch (e) {
            xmlHttpObj 
= new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    
    
return xmlHttpObj;
}
posted @ 2011-06-28 16:22 思无 阅读(327) | 评论 (0)编辑 收藏

http://www.iteye.com/topic/72170

关于j2ee项目中异常的管理和设计。之前一直困惑于异常的处理,为什么异常分为checked和uncheck,应该遵循怎样的规则自定义异常。在j2ee项目中,处理异常需要注意什么地方。
[原文]
为什么要在J2EE项目中谈异常处理呢?可能许多java初学者都想说:“异常处理不就是try….catch…finally吗?这谁都会 啊!”。笔者在初学java时也是这样认为的。如何在一个多层的j2ee项目中定义相应的异常类?在项目中的每一层如何进行异常处理?异常何时被抛出?异 常何时被记录?异常该怎么记录?何时需要把checked Exception转化成unchecked Exception ,何时需要把unChecked Exception转化成checked Exception?异常是否应该呈现到前端页面?如何设计一个异常框架?本文将就这些问题进行探讨。
1. JAVA异常处理
在面向过程式的编程语言中,我们可以通过返回值来确定方法是否正常执行。比如在一个c语言编写的程序中,如果方法正确的执行则返回1.错误则返回0。在vb或delphi开发的应用程序中,出现错误时,我们就弹出一个消息框给用户。
通过方法的返回值我们并不能获得错误的详细信息。可能因为方法由不同的程序员编写,当同一类错误在不同的方法出现时,返回的结果和错误信息并不一致。
所以java语言采取了一个统一的异常处理机制。
什么是异常?运行时发生的可被捕获和处理的错误。
在java语言中,Exception是所有异常的父类。任何异常都扩 展于Exception类。Exception就相当于一个错误类型。如果要定义一个新的错误类型就扩展一个新的Exception子类。采用异常的好处 还在于可以精确的定位到导致程序出错的源代码位置,并获得详细的错误信息。
Java异常处理通过五个关键字来实 现,try,catch,throw ,throws, finally。具体的异常处理结构由try….catch….finally块来实现。try块存放可能出现异常的java语句,catch用来捕获发 生的异常,并对异常进行处理。Finally块用来清除程序中未释放的资源。不管理try块的代码如何返回,finally块都总是被执行。
一个典型的异常处理代码
java 代码
  1.   
  2. public String getPassword(String userId)throws DataAccessException{   
  3. String sql = “select password from userinfo where userid=’”+userId +”’”;   
  4. String password = null;   
  5. Connection con = null;   
  6. Statement s = null;   
  7. ResultSet rs = null;   
  8. try{   
  9.  con = getConnection();//获得数据连接   
  10.  s = con.createStatement();   
  11.  rs = s.executeQuery(sql);   
  12.  while(rs.next()){   
  13.     password = rs.getString(1);   
  14.  }   
  15.  rs.close();   
  16.  s.close();   
  17.      
  18. }   
  19. Catch(SqlException ex){   
  20.  throw new DataAccessException(ex);   
  21. }   
  22. finally{   
  23.  try{   
  24.       if(con != null){   
  25.         con.close();   
  26.       }   
  27.  }   
  28.    Catch(SQLException sqlEx){   
  29.      throw new DataAccessException(“关闭连接失败!”,sqlEx);   
  30.    }   
  31. }   
  32. return password;   
  33. }   
  34.    
可以看出Java的异常处理机制具有的优势:
给错误进行了统一的分类,通过扩展Exception类或其子类来实现。从而避免了相同的错误可能在不同的方法中具有不同的错误信息。在不同的方法中出现相同的错误时,只需要throw 相同的异常对象即可。
获得更为详细的错误信息。通过异常类,可以给异常更为详细,对用户更为有用的错误信息。以便于用户进行跟踪和调试程序。
把正确的返回结果与错误信息分离。降低了程序的复杂度。调用者无需要对返回结果进行更多的了解。
强制调用者进行异常处理,提高程序的质量。当一个方法声明需要抛出一个异常时,那么调用者必须使用try….catch块对异常进行处理。当然调用者也可以让异常继续往上一层抛出。
 
2. Checked 异常 还是 unChecked 异常?
Java异常分为两大类:checked 异常和unChecked 异常。所有继承java.lang.Exception 的异常都属于checked异常。所有继承java.lang.RuntimeException的异常都属于unChecked异常。
当一个方法去调用一个可能抛出checked异常的方法,必须通过try…catch块对异常进行捕获进行处理或者重新抛出。
我们看看Connection接口的createStatement()方法的声明。
public Statement createStatement() throws SQLException;
      
   SQLException是checked异常。当调用createStatement方法时,java强制调用者必须对SQLException进行捕获处理。
java 代码
  1.        public String getPassword(String userId){   
  2.        try{   
  3.        ……   
  4.               Statement s = con.createStatement();   
  5.               ……   
  6.        Catch(SQLException sqlEx){   
  7.               ……   
  8.    }   
  9. ……   
  10. }   
或者
java 代码
  1. public String getPassword(String userId)throws SQLException{   
  2.    Statement s = con.createStatement();   
  3. }  
(当然,像Connection,Satement这些资源是需要及时关闭的,这里仅是为了说明checked 异常必须强制调用者进行捕获或继续抛出)
 
unChecked异常也称为运行时异常,通常 RuntimeException都表示用户无法恢复的异常,如无法获得数据库连接,不能打开文件等。虽然用户也可以像处理checked异常一样捕获 unChecked异常。但是如果调用者并没有去捕获unChecked异常时,编译器并不会强制你那么做。
 
比如一个把字符转换为整型数值的代码如下:
 
java 代码
  1. String str = “123”;   
  2. int value = Integer.parseInt(str);  
 
parseInt的方法签名为:
java 代码
  1. public static int parseInt(String s) throws NumberFormatException  
 
当传入的参数不能转换成相应的整数时,将会抛出NumberFormatException。因为NumberFormatException扩展于RuntimeException,是unChecked异常。所以调用parseInt方法时无需要try…catch
 
因为java不强制调用者对unChecked异常进行捕获或往上抛 出。所以程序员总是喜欢抛出unChecked异常。或者当需要一个新的异常类时,总是习惯的从RuntimeException扩展。当你去调用它些方 法时,如果没有相应的catch块,编译器也总是让你通过,同时你也根本无需要去了解这个方法倒底会抛出什么异常。看起来这似乎倒是一个很好的办法,但是 这样做却是远离了java异常处理的真实意图。并且对调用你这个类的程序员带来误导,因为调用者根本不知道需要在什么情况下处理异常。而checked异 常可以明确的告诉调用者,调用这个类需要处理什么异常。如果调用者不去处理,编译器都会提示并且是无法编译通过的。当然怎么处理是由调用者自己去决定的。
 
       所以Java推荐人们在应用代码中应该使用checked异常。就像我们在上节提到运用异常的好外在于可以强制调用者必须对将会产生的异常进行处理。包括在《java Tutorial》等java官方文档中都把checked异常作为标准用法。
       使用checked异常,应意味着有许多的try…catch在你的代码中。当在编写和处理越来越多的try…catch块之后,许多人终于开始怀疑checked异常倒底是否应该作为标准用法了。
甚至连大名鼎鼎的《thinking in java》的作者Bruce Eckel也改变了他曾经的想法。Bruce Eckel甚至主张把unChecked异常作为标准用法。并发表文章,以试验checked异常是否应该从java中去掉。Bruce Eckel语:“当少量代码时,checked异常无疑是十分优雅的构思,并有助于避免了许多潜在的错误。但是经验表明,对大量代码来说结果正好相反”
关于checked异常和unChecked异常的详细讨论可以参考
 
使用checked异常会带来许多的问题。
       checked异常导致了太多的try…catch 代码
              可能有很多checked异常对开发人员来说是无法合理地进行处理的,比如 SQLException。而开发人员却不得不去进行try…catch。当开发人员对一个checked异常无法正确的处理时,通常是简单的把异常打印 出来或者是干脆什么也不干。特别是对于新手来说,过多的checked异常让他感到无所适从。
java 代码
  1.        try{   
  2.        ……   
  3.               Statement s = con.createStatement();   
  4.               ……   
  5.        Catch(SQLException sqlEx){   
  6.               sqlEx.PrintStackTrace();   
  7.    }   
  8.    或者   
  9.        try{   
  10.        ……   
  11.               Statement s = con.createStatement();   
  12.               ……   
  13.        Catch(SQLException sqlEx){   
  14.           //什么也不干   
  15. }   
 
checked异常导致了许多难以理解的代码产生
        当开发人员必须去捕获一个自己无法正确处理的checked异常,通常的是重新封装成一个新的异常后再抛出。这样做并没有为程序带来任何好处。反而使代码晚难以理解。
就像我们使用JDBC代码那样,需要处理非常多的try…catch.,真正有用的代码被包含在try…catch之内。使得理解这个方法变理困难起来
checked异常导致异常被不断的封装成另一个类异常后再抛出
java 代码
  1.         public void methodA()throws ExceptionA{   
  2.          …..          
  3.           throw new ExceptionA();        
  4. }   
  5.           
  6. public void methodB()throws ExceptionB{   
  7.    try{   
  8.       methodA();   
  9.       ……   
  10.    }catch(ExceptionA ex){   
  11.    throw new ExceptionB(ex);   
  12.    }   
  13. }   
  14.            
  15.         Public void methodC()throws ExceptinC{   
  16.        try{   
  17.          methodB();   
  18.          …   
  19.        }   
  20.        catch(ExceptionB ex){   
  21.           throw new ExceptionC(ex);   
  22.         }   
  23.     }   
我们看到异常就这样一层层无休止的被封装和重新抛出。
 
checked异常导致破坏接口方法
   一个接口上的一个方法已被多个类使用,当为这个方法额外添加一个checked异常时,那么所有调用此方法的代码都需要修改。
 
可见上面这些问题都是因为调用者无法正确的处理checked异常时而被迫去捕获和处理,被迫封装后再重新抛出。这样十分不方便,并不能带来任何好处。在这种情况下通常使用unChecked异常。
chekced异常并不是无一是处,checked异常比传统编程的错误返回值要好用得多。通过编译器来确保正确的处理异常比通过返回值判断要好得多。
如果一个异常是致命的,不可恢复的。或者调用者去捕获它没有任何益处,使用unChecked异常。
如果一个异常是可以恢复的,可以被调用者正确处理的,使用checked异常
在使用unChecked异常时,必须在在方法声明中详细的说明该方法可能会抛出的unChekced异常。由调用者自己去决定是否捕获unChecked异常
 
倒底什么时候使用checked异常,什么时候使用unChecked异常?并没有一个绝对的标准。但是笔者可以给出一些建议
当所有调用者必须处理这个异常,可以让调用者进行重试操作;或者该异常相当于该方法的第二个返回值。使用checked异常。
这个异常仅是少数比较高级的调用者才能处理,一般的调用者不能正确的处理。使用unchecked异常。有能力处理的调用者可以进行高级处理,一般调用者干脆就不处理。
这个异常是一个非常严重的错误,如数据库连接错误,文件无法打开等。或者这些异常是与外部环境相关的。不是重试可以解决的。使用unchecked异常。因为这种异常一旦出现,调用者根本无法处理。
如果不能确定时,使用unchecked异常。并详细描述可能会抛出的异常,以让调用者决定是否进行处理。
 
3. 设计一个新的异常类
在设计一个新的异常类时,首先看看是否真正的需要这个异常类。一般情况下尽量不要去设计新的异常类,而是尽量使用java中已经存在的异常类。
java 代码
  1. IllegalArgumentException, UnsupportedOperationException  
 
不管是新的异常是chekced异常还是unChecked异常。我们都必须考虑异常的嵌套问题。
java 代码
  1. public void methodA()throws ExceptionA{   
  2.          …..          
  3.           throw new ExceptionA();        
  4. }   
 
方法methodA声明会抛出ExceptionA.
 
public void methodB()throws ExceptionB
methodB声明会抛出ExceptionB,当在methodB方 法中调用methodA时,ExceptionA是无法处理的,所以ExceptionA应该继续往上抛出。一个办法是把methodB声明会抛出 ExceptionA.但这样已经改变了MethodB的方法签名。一旦改变,则所有调用methodB的方法都要进行改变。
另一个办法是把ExceptionA封装成ExceptionB,然后再抛出。如果我们不把ExceptionA封装在ExceptionB中,就丢失了根异常信息,使得无法跟踪异常的原始出处。
java 代码
  1. public void methodB()throws ExceptionB{   
  2.    try{   
  3.       methodA();   
  4.       ……   
  5.    }catch(ExceptionA ex){   
  6.      throw new ExceptionB(ex);   
  7.    }   
  8. }  
 
   如上面的代码中,ExceptionB嵌套一个ExceptionA.我们暂且把ExceptionA称为“起因异常”,因为ExceptionA导致了ExceptionB的产生。这样才不使异常信息丢失。
所以我们在定义一个新的异常类时,必须提供这样一个可以包含嵌套异常的构造函数。并有一个私有成员来保存这个“起因异常”。
java 代码
  1. public Class ExceptionB extends Exception{   
  2. private Throwable cause;   
  3.     
  4. public ExceptionB(String msg, Throwable ex){   
  5.  super(msg);   
  6.  this.cause = ex;   
  7. }   
  8.     
  9. public ExceptionB(String msg){   
  10.  super(msg);   
  11. }   
  12.     
  13. public ExceptionB(Throwable ex){   
  14.  this.cause = ex;   
  15. }   
  16. }   
当然,我们在调用printStackTrace方法时,需要把所有的“起因异常”的信息也同时打印出来。所以我们需要覆写printStackTrace方法来显示全部的异常栈跟踪。包括嵌套异常的栈跟踪。
java 代码
  1. public void printStackTrace(PrintStrean ps){   
  2. if(cause == null){   
  3.  super.printStackTrace(ps);   
  4. }else{   
  5.  ps.println(this);   
  6.  cause.printStackTrace(ps);   
  7. }   
  8. }   
 
一个完整的支持嵌套的checked异常类源码如下。我们在这里暂且把它叫做NestedException
 
java 代码
  1. public NestedException extends Exception{   
  2. private Throwable cause;   
  3. public NestedException (String msg){   
  4.  super(msg);   
  5. }   
  6.     
  7. public NestedException(String msg, Throwable ex){   
  8.  super(msg);   
  9.  This.cause = ex;   
  10. }   
  11.     
  12. public Throwable getCause(){   
  13.  return (this.cause == null ? this :this.cause);   
  14. }   
  15.     
  16. public getMessage(){   
  17.  String message = super.getMessage();   
  18.  Throwable cause = getCause();   
  19.    if(cause != null){   
  20.      message = message + “;nested Exception is ” + cause;   
  21.    }   
  22.  return message;   
  23. }   
  24. public void printStackTrace(PrintStream ps){   
  25.  if(getCause == null){   
  26.     super.printStackTrace(ps);   
  27.        
  28.  }else{   
  29.  ps.println(this);   
  30.  getCause().printStackTrace(ps);   
  31.  }   
  32. }   
  33.     
  34. public void printStackTrace(PrintWrite pw){   
  35.  if(getCause() == null){   
  36.     super.printStackTrace(pw);   
  37.  }   
  38.  else{   
  39.     pw.println(this);   
  40.     getCause().printStackTrace(pw);   
  41.  }   
  42. }   
  43. public void printStackTrace(){   
  44.  printStackTrace(System.error);   
  45. }   
  46. }   
  47.     
同样要设计一个unChecked异常类也与上面一样。只是需要继承RuntimeException。
 
 
4. 如何记录异常
作为一个大型的应用系统都需要用日志文件来记录系统的运行,以便于跟踪和记录系统的运行情况。系统发生的异常理所当然的需要记录在日志系统中。
java 代码
  1. public String getPassword(String userId)throws NoSuchUserException{   
  2. UserInfo user = userDao.queryUserById(userId);   
  3. If(user == null){   
  4.  Logger.info(“找不到该用户信息,userId=”+userId);   
  5.  throw new NoSuchUserException(“找不到该用户信息,userId=”+userId);   
  6. }   
  7. else{   
  8.  return user.getPassword();   
  9. }   
  10. }   
  11.     
  12. public void sendUserPassword(String userId)throws Exception {   
  13. UserInfo user = null;   
  14. try{   
  15.   user = getPassword(userId);   
  16.    //……..   
  17.  sendMail();   
  18.  //   
  19. }catch(NoSuchUserException ex)(   
  20.    logger.error(“找不到该用户信息:”+userId+ex);   
  21.    throw new Exception(ex);   
  22. }   
 
我们注意到,一个错误被记录了两次.在错误的起源位置我们仅是以info级别进行记录。而在sendUserPassword方法中,我们还把整个异常信息都记录了。
笔者曾看到很多项目是这样记录异常的,不管三七二一,只有遇到异常就把整个异常全部记录下。如果一个异常被不断的封装抛出多次,那么就被记录了多次。那么异常倒底该在什么地方被记录?
异常应该在最初产生的位置记录
 
如果必须捕获一个无法正确处理的异常,仅仅是把它封装成另外一种异常往上抛出。不必再次把已经被记录过的异常再次记录。
 
如果捕获到一个异常,但是这个异常是可以处理的。则无需要记录异常
 
java 代码
  1. public Date getDate(String str){   
  2.  Date applyDate = null;   
  3. SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);   
  4. try{   
  5.  applyDate = format.parse(applyDateStr);   
  6. }   
  7. catch(ParseException ex){   
  8.  //乎略,当格式错误时,返回null   
  9. }   
  10. return applyDate;   
  11. }   
 
捕获到一个未记录过的异常或外部系统异常时,应该记录异常的详细信息
java 代码
  1. try{   
  2.        ……   
  3.         String sql=”select * from userinfo”;   
  4.               Statement s = con.createStatement();   
  5.               ……   
  6.        Catch(SQLException sqlEx){   
  7.           Logger.error(“sql执行错误”+sql+sqlEx);   
  8. }   
      
   究竟在哪里记录异常信息,及怎么记录异常信息,可能是见仁见智的问题了。甚至有些系统让异常类一记录异常。当产生一个新异常对象时,异常信息就被自动记录。
java 代码
  1.   public class BusinessException extends Exception {   
  2.       private void logTrace() {   
  3.           StringBuffer buffer=new StringBuffer();   
  4.           buffer.append("Business Error in Class: ");   
  5.           buffer.append(getClassName());   
  6.           buffer.append(",method: ");   
  7.           buffer.append(getMethodName());   
  8.           buffer.append(",messsage: ");   
  9.           buffer.append(this.getMessage());   
  10.           logger.error(buffer.toString());   
  11.              
  12. }   
  13. public BusinessException(String s) {   
  14.          super(s);   
  15. race();   
  16. }   
这似乎看起来是十分美妙的,其实必然导致了异常被重复记录。同时违反了“类的职责分配原则”,是一种不好的设计。记录异常不属于异常类的行为,记录异常应 该由专门的日志系统去做。并且异常的记录信息是不断变化的。我们在记录异常同应该给更丰富些的信息。以利于我们能够根据异常信息找到问题的根源,以解决问 题。
虽然我们对记录异常讨论了很多,过多的强调这些反而使开发人员更为疑惑,一种好的方式是为系统提供一个异常处理框架。由框架来决定是否记录异常和怎么记录异常。而不是由普通程序员去决定。但是了解些还是有益的。
5. J2EE项目中的异常处理
目前,J2ee项目一般都会从逻辑上分为多层。比较经典的分为三层:表示层,业务层,集成层(包括数据库访问和外部系统的访问)。
J2ee项目有着其复杂性,J2ee项目的异常处理需要特别注意几个问题。
在分布式应用时,我们会遇到许多checked异常。所有RMI调用 (包括EJB远程接口调用)都会抛出java.rmi.RemoteException;同时RemoteException是checked异常,当我 们在业务系统中进行远程调用时,我们都需要编写大量的代码来处理这些checked异常。而一旦发生RemoteException这些checked异 常对系统是非常严重的,几乎没有任何进行重试的可能。也就是说,当出现RemoteException这些可怕的checked异常,我们没有任何重试的 必要性,却必须要编写大量的try…catch代码去处理它。一般我们都是在最底层进行RMI调用,只要有一个RMI调用,所有上层的接口都会要求抛出 RemoteException异常。因为我们处理RemoteException的方式就是把它继续往上抛。这样一来就破坏了我们业务接口。 RemoteException这些J2EE系统级的异常严重的影响了我们的业务接口。我们对系统进行分层的目的就是减少系统之间的依赖,每一层的技术改 变不至于影响到其它层。
 
java 代码
  1. //   
  2. public class UserSoaImpl implements UserSoa{   
  3.    public UserInfo getUserInfo(String userId)throws RemoteException{   
  4.       //……   
  5. 远程方法调用.   
  6.       //……   
  7.    }   
  8. }   
  9. public interface UserManager{   
  10.    public UserInfo getUserInfo(Stirng userId)throws RemoteException;   
  11. }   
 
同样JDBC访问都会抛出SQLException的checked异常。
 
为了避免系统级的checked异常对业务系统的深度侵入,我们可以为 业务方法定义一个业务系统自己的异常。针对像SQLException,RemoteException这些非常严重的异常,我们可以新定义一个 unChecked的异常,然后把SQLException,RemoteException封装成unChecked异常后抛出。
如果这个系统级的异常是要交由上一级调用者处理的,可以新定义一个checked的业务异常,然后把系统级的异常封存装成业务级的异常后再抛出。
一般地,我们需要定义一个unChecked异常,让集成层接口的所有方法都声明抛出这unChecked异常
java 代码
  1. public DataAccessException extends RuntimeException{   
  2.  ……   
  3. }   
  4. public interface UserDao{   
  5.  public String getPassword(String userId)throws DataAccessException;   
  6. }   
  7.     
  8. public class UserDaoImpl implements UserDAO{   
  9. public String getPassword(String userId)throws DataAccessException{   
  10.  String sql = “select password from userInfo where userId= ‘”+userId+”’”;   
  11. try{   
  12.     …   
  13.      //JDBC调用   
  14.      s.executeQuery(sql);   
  15.     …   
  16.    }catch(SQLException ex){   
  17.       throw new DataAccessException(“数据库查询失败”+sql,ex);   
  18.    }   
  19. }   
  20. }   
 
定义一个checked的业务异常,让业务层的接口的所有方法都声明抛出Checked异常.
 
java 代码
  1. public class BusinessException extends Exception{   
  2.  …..   
  3. }   
  4.     
  5. public interface UserManager{   
  6.    public Userinfo copyUserInfo(Userinfo user)throws BusinessException{   
  7.       Userinfo newUser = null;   
  8.       try{   
  9.         newUser = (Userinfo)user.clone();   
  10. }catch(CloneNotSupportedException ex){   
  11.  throw new BusinessException(“不支持clone方法:”+Userinfo.class.getName(),ex);   
  12. }   
  13.  }   
  14. }  
 
J2ee表示层应该是一个很薄的层,主要的功能为:获得页面请求,把页 面的参数组装成POJO对象,调用相应的业务方法,然后进行页面转发,把相应的业务数据呈现给页面。表示层需要注意一个问题,表示层需要对数据的合法性进 行校验,比如某些录入域不能为空,字符长度校验等。
J2ee从页面所有传给后台的参数都是字符型的,如果要求输入数值或日期类型的参数时,必须把字符值转换为相应的数值或日期值。
如果表示层代码校验参数不合法时,应该返回到原始页面,让用户重新录入数据,并提示相关的错误信息。
 
通常把一个从页面传来的参数转换为数值,我们可以看到这样的代码
java 代码
  1. ModeAndView handleRequest(HttpServletRequest request,HttpServletResponse response)throws Exception{   
  2.    String ageStr = request.getParameter(“age”);   
  3.    int age = Integer.parse(ageStr);   
  4.    …………   
  5.     
  6.  String birthDayStr = request.getParameter(“birthDay”);   
  7. SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);   
  8. Date birthDay = format.parse(birthDayStr);   
  9.     
  10. }   
 
上面的代码应该经常见到,但是当用户从页面录入一个不能转换为整型的字符或一个错误的日期值。
Integer.parse()方法被抛出一个 NumberFormatException的unChecked异常。但是这个异常绝对不是一个致命的异常,一般当用户在页面的录入域录入的值不合法 时,我们应该提示用户进行重新录入。但是一旦抛出unchecked异常,就没有重试的机会了。像这样的代码造成大量的异常信息显示到页面。使我们的系统 看起来非常的脆弱。
同样,SimpleDateFormat.parse()方法也会抛出ParseException的unChecked异常。
这种情况我们都应该捕获这些unChecked异常,并给提示用户重新录入。
java 代码
  1. ModeAndView handleRequest(HttpServletRequest request,HttpServletResponse response)throws Exception{   
  2.    String ageStr = request.getParameter(“age”);   
  3. String birthDayStr = request.getParameter(“birthDay”);   
  4.    int age = 0;   
  5.  Date birthDay = null;   
  6. try{   
  7. age=Integer.parse(ageStr);   
  8.    }catch(NumberFormatException ex){   
  9.      error.reject(“age”,”不是合法的整数值”);   
  10.    }   
  11.    …………   
  12.     
  13.  try{   
  14. SimpleDateFormat format = new SimpleDateFormat(“MM/dd/yyyy”);   
  15.  birthDay = format.parse(birthDayStr);   
  16. }catch(ParseException ex){   
  17.  error.reject(“birthDay”,”不是合法的日期,请录入’MM/dd/yyy’格式的日期”);   
  18. }   
  19.     
  20. }  
在表示层一定要弄清楚调用方法的是否会抛出unChecked异常,什么情况下会抛出这些异常,并作出正确的处理。
在表示层调用系统的业务方法,一般情况下是无需要捕获异常的。如果调用的业务方法抛出的异常相当于第二个返回值时,在这种情况下是需要捕获
posted @ 2011-06-27 16:02 思无 阅读(376) | 评论 (0)编辑 收藏

package hello;
public interface Hello extends java.rmi.Remote{
    String sayHello() throws java.rmi.RemoteException;
}

package hello;
import java.rmi.
*;
public class HelloClient {
    
public static void main(String args[]){
        System.setSecurityManager(new RMISecurityManager());
        try{
            Hello obj 
= (Hello)Naming.lookup("HelloServer");
            String message
=obj.sayHello();
            System.out.println(message);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

package hello;
import java.rmi.
*;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
public class HelloImpl extends UnicastRemoteObject implements Hello{
    private String name;
    
public HelloImpl(String s) throws java.rmi.RemoteException{
        super();
        name
=s;
    }
    
public String sayHello()throws RemoteException{
        
return "hello world";
    }
    
public static void main(String args[]){
        System.setSecurityManager(new RMISecurityManager());
        try{
            HelloImpl obj 
= new HelloImpl("HelloServer");
            LocateRegistry.createRegistry(
1099); 
            Naming.rebind("HelloServer", obj);
            System.out.println("HelloImpl created 
and bound in the registry to the name HelloServer");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

安全策略文件
grant {
    permission java.security.AllPermission;
    };

运行脚本:
Set CLASSPATH=%CLASSPATH%;c:\         没有空格
javac -d .. *.java                                  在hello目录下
rmic -d . hello.HelloImpl                           在hello的父目录下
java -Djava.security.policy=file:C:/java.policy hello.HelloImpl        注意安全策略文件
java -Djava.security.policy=file:/C:/java.policy hello.HelloClient     注意安全策略文件

相关资料:
http://blog.csdn.net/coolriver/archive/2004/09/10/100702.aspx
http://topic.csdn.net/t/20020310/12/566253.html
http://topic.csdn.net/u/20070426/08/b852e323-08c6-4f80-b87a-937e24af237d.html

posted @ 2011-06-13 15:18 思无 阅读(255) | 评论 (0)编辑 收藏

/**
 * 改类掩饰了如何通过java.bean的类去获知bean中的属性并调用相应的set get方法
 
*/
import java.beans.*;
import java.lang.reflect.Method;
public class JavaBeanInvoke {
    
public static void main(String args[])throws Exception{
        test1();
    }
    
    
public static void test1()throws Exception{
        Person person 
= Person.class.newInstance();
        
        BeanInfo beaninfo 
= Introspector.getBeanInfo(Person.class);
        PropertyDescriptor[] porpertydescriptors 
= beaninfo.getPropertyDescriptors();
        
for(PropertyDescriptor pd:porpertydescriptors){
            System.out.println(pd.getName());
            
if(pd.getName().endsWith("name")){
                Method setMethod
=pd.getWriteMethod();
                Method getMethod
=pd.getReadMethod();
                setMethod.invoke(person,
"ShenZiping");
                System.out.println(getMethod.invoke(person));
                
break;
            }
        }
    }
    
    
public static void test2() throws Exception{
        Person person 
= Person.class.newInstance();
        PropertyDescriptor pd 
= new PropertyDescriptor("age",Person.class);
        Method setMethod 
= pd.getWriteMethod();
        Method getMethod 
= pd.getReadMethod();
        setMethod.invoke(person, 
56);
        System.out.println(getMethod.invoke(person));
    }
}

/**
 * 代码举例了beanUtil包的普遍用法,需要apache的logging包和beanUtils包
 
*/
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.*;
public class BeanUtilsInvoke {
    
public static void main(String args[])throws Exception{
        test1();
        test2();
        test3();
        test4();
        myConvertTest();
    }
    
public static void test1()throws Exception{
        Person person 
= new Person();
        BeanUtils.copyProperty(person, 
"name""ShenZiping");
        System.out.println(
"test1"+person.getName());
    }
    
public static void test2() throws Exception{
        Person person 
= new Person();
        Map
<String, String> map = new HashMap<String, String>();
        map.put(
"name""ShenZiping");
        map.put(
"age""65");
        BeanUtils.populate(person, map);
        System.out.println(
"test2"+person.getAge());
        System.out.println(
"test2"+person.getName());
    }
    
    
public static void test3() throws Exception{
        Person p1 
= new Person();
        Person p2 
= new Person();
        p1.setAge(
98);
        p1.setName(
"ShenZiping");
        BeanUtils.copyProperties(p2, p1);
        System.out.println(
"test3"+p2.getAge());
        System.out.println(
"test3"+p2.getName());
    }
    
    
public static void test4() throws Exception{
        Person person 
= new Person();
        Man man 
= new Man();
        person.setName(
"ShenZiping");
        BeanUtils.copyProperties(man, person);
        System.out.println(
"test4"+man.getName());
    }
    
    
public static void myConvertTest(){
        ConvertUtils.register(
new Converter(){
            
public Object convert(Class clazz, Object value){
                
if(clazz==Date.class){
                    SimpleDateFormat dateFormat 
= new SimpleDateFormat("yyyy-MM-dd");
                    
try{
                        
return dateFormat.parse((String)value);
                    }
catch(ParseException e){
                        
throw new RuntimeException("invalid format");
                    }
                }
                
return null;
            }
        }, Date.
class);
        Date date 
= (Date)ConvertUtils.convert("2010-01-15",Date.class);
        System.out.println(
"myConvertTest"+date);
    }
}
posted @ 2011-06-13 12:38 思无 阅读(775) | 评论 (0)编辑 收藏

做了这么多年前台的东西,还是第一次捧起前台相关的书来看。
这次看得是Robert Hoekman的第二本书,总体感觉看下来,比较受用,重点讲了下面几个词汇。
简单,清楚,预期,反馈。
简单:界面要足够的简单,不要多,更不要无必要的“多“,要把“多“的东西隐藏起来,多指不常用的,比较“高级“的功能。
清楚:突出什么要清楚,突出什么可以通过颜色,视觉习惯等方法。
预期:用户要知道自己操作的进度,比如填写多页表单。
反馈:让用户知道自己操作的结果的提示,操作完页面需要做出反馈以提示用户操作的结果。

该书从设计用户登陆开始,中间穿插了一些网站小模块的设计,到最终用户退出系统的设计。比较完整的用31个瞬间讲述了一个用户浏览网站的过程。

给自己最大的提示,老生常谈,站在使用者的角度,方便使用者的目的,并尽可能依靠使用者的“抱怨”,改进系统的设计,提高使用者的效率。
posted @ 2011-06-09 13:30 思无 阅读(400) | 评论 (0)编辑 收藏

转自    oracle.sql.CLOB clob =null;  
    stmt 
= conn.createStatement();  
    rs 
= stmt.executeQuery(sql);  
    
if (rs.next()) {  
        System.out.println(rs.getClob(
column).getClass());  
        clob 
= (oracle.sql.CLOB) rs.getClob(column);  
        out 
= new BufferedWriter(clob.getCharacterOutputStream());  
        
in = new BufferedReader(new StringReader(data));  
    }
这个代码很奇怪,看试没有一点问题,但是,项目跑起来后,代码 
clob = (oracle.sql.CLOB) rs.getClob(column); 
都会抛出java.lang.ClassCastException: oracle.sql.CLOB异常(WEB容器使用的是TOMCAT5.5),先以为是类型转换的问题, 
System.out.println(rs.getClob(column).getClass()); 
但打印出来的是oracle.sql.clob 
后又以为是驱动的问题,把classes12.jar换成了ojdbc14.jar 
可问题还没有解决 

解决的方法: 

在网上狂找,终于找到一位高人写的一篇高水平的文章(主要是把我的问题给解决了,哈) 

是因为驱动包重复了,我理解为类重名,我使用的是tomcat数据源,哪么,$TOMCAT_HOME$\comm\lib目录下需要oracle驱动包,是给tomcat创建jndi数据源时用的,而项目中也要有oracle驱动包,是给程序编译用的,最后使用eclilpse的java build path进行外部引用,使用应用程序编译通过,但也不会把ojdbc14.jar的驱动包引入到发布目录,再试,果然解决了问题。

posted @ 2011-06-07 13:38 思无 阅读(494) | 评论 (0)编辑 收藏

Selectors

Selector Example Selects
* $("*") All elements
#id $("#lastname") The element with id=lastname
.class $(".intro") All elements with class="intro"
element $("p") All p elements
.class.class $(".intro.demo") All elements with the classes "intro" and "demo"
     
:first $("p:first") The first p element
:last $("p:last") The last p element
:even $("tr:even") All even tr elements
:odd $("tr:odd") All odd tr elements
     
:eq(index) $("ul li:eq(3)") The fourth element in a list (index starts at 0)
:gt(no) $("ul li:gt(3)") List elements with an index greater than 3
:lt(no) $("ul li:lt(3)") List elements with an index less than 3
:not(selector) $("input:not(:empty)") All input elements that are not empty
     
:header $(":header") All header elements h1, h2 ...
:animated $(":animated") All animated elements
     
:contains(text) $(":contains('W3Schools')") All elements which contains the text
:empty $(":empty") All elements with no child (elements) nodes
:hidden $("p:hidden") All hidden p elements
:visible $("table:visible") All visible tables
     
s1,s2,s3 $("th,td,.intro") All elements with matching selectors
     
[attribute] $("[href]") All elements with a href attribute
[attribute=value] $("[href='default.htm']") All elements with a href attribute value equal to "default.htm"
[attribute!=value] $("[href!='default.htm']") All elements with a href attribute value not equal to "default.htm"
[attribute$=value] $("[href$='.jpg']") All elements with a href attribute value ending with ".jpg"
     
:input $(":input") All input elements
:text $(":text") All input elements with type="text"
:password $(":password") All input elements with type="password"
:radio $(":radio") All input elements with type="radio"
:checkbox $(":checkbox") All input elements with type="checkbox"
:submit $(":submit") All input elements with type="submit"
:reset $(":reset") All input elements with type="reset"
:button $(":button") All input elements with type="button"
:image $(":image") All input elements with type="image"
:file $(":file") All input elements with type="file"
     
:enabled $(":enabled") All enabled input elements
:disabled $(":disabled") All disabled input elements
:selected $(":selected") All selected input elements
:checked $(":checked") All checked input elements


Events

Method Description
bind() Add one or more event handlers to matching elements
blur() Triggers, or binds a function to the blur event of selected elements
change() Triggers, or binds a function to the change event of selected elements
click() Triggers, or binds a function to the click event of selected elements
dblclick() Triggers, or binds a function to the dblclick event of selected elements
delegate() Add one or more event handlers to current, or future, specified child elements of the matching elements
die() Remove all event handlers added with the live() function
error() Triggers, or binds a function to the error event of selected elements
event.currentTarget The current DOM element within the event bubbling phase
event.data Contains the optional data passed to jQuery.fn.bind when the current executing handler was bound
event.isDefaultPrevented() Returns whether event.preventDefault() was called for the event object
event.isImmediatePropagationStopped() Returns whether event.stopImmediatePropagation() was called for the event object
event.isPropagationStopped() Returns whether event.stopPropagation() was called for the event object
event.pageX The mouse position relative to the left edge of the document
event.pageY The mouse position relative to the top edge of the document
event.preventDefault() Prevents the default action of the event
event.relatedTarget The other DOM element involved in the event, if any
event.result This attribute contains the last value returned by an event handler that was triggered by this event, unless the value was undefined
event.stopImmediatePropagation() Prevents other event handlers from being called
event.stopPropagation() Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event
event.target The DOM element that initiated the event
event.timeStamp This attribute returns the number of milliseconds since January 1, 1970, when the event is triggered
event.type Describes the nature of the event
event.which Which key or button was pressed for a key or button event
focus() Triggers, or binds a function to the focus event of selected elements
focusin() Binds a function to the focusin event of selected elements
focusout() Binds a function to the focusout event of selected elements
hover() Binds one or two functions to the hover event of selected elements
keydown() Triggers, or binds a function to the keydown event of selected elements
keypress() Triggers, or binds a function to the keypress event of selected elements
keyup() Triggers, or binds a function to the keyup event of selected elements
live() Add one or more event handlers to current, or future, matching elements
load() Triggers, or binds a function to the load event of selected elements
mousedown() Triggers, or binds a function to the mouse down event of selected elements
mouseenter() Triggers, or binds a function to the mouse enter event of selected elements
mouseleave() Triggers, or binds a function to the mouse leave event of selected elements
mousemove() Triggers, or binds a function to the mouse move event of selected elements
mouseout() Triggers, or binds a function to the mouse out event of selected elements
mouseover() Triggers, or binds a function to the mouse over event of selected elements
mouseup() Triggers, or binds a function to the mouse up event of selected elements
one() Add one or more event handlers to matching elements. This handler can only be triggered once per element
ready() Binds a function to the ready event of a document
(when an HTML document is ready to use)
resize() Triggers, or binds a function to the resize event of selected elements
scroll() Triggers, or binds a function to the scroll event of selected elements
select() Triggers, or binds a function to the select event of selected elements
submit() Triggers, or binds a function to the submit event of selected elements
toggle() Binds two or more functions to the toggle between for the click event for selected elements
trigger() Triggers all events bound to the selected elements
triggerHandler() Triggers all functions bound to a specified event for the selected elements
unbind() Remove an added event handler from selected elements
undelegate() Remove an event handler to selected elements, now or in the future
unload() Triggers, or binds a function to the unload event of selected elements

Effect
Method Description
animate() Performs a custom animation (of a set of CSS properties) for selected elements
clearQueue() Removes all queued functions for the selected element
delay() Sets a delay for all queued functions for the selected element
dequeue() Runs the next queued functions for the selected element
fadeIn() Gradually changes the opacity, for selected elements, from hidden to visible
fadeOut() Gradually changes the opacity, for selected elements, from visible to hidden
fadeTo() Gradually changes the opacity, for selected elements, to a specified opacity
hide() Hides selected elements
queue() Shows the queued functions for the selected element
show() Shows hidden selected elements
slideDown() Gradually changes the height, for selected elements, from hidden to visible
slideToggle() Toggles between slideUp() and slideDown() for selected elements
slideUp() Gradually changes the height, for selected elements, from visible to hidden
stop() Stops a running animation on selected elements
toggle() Toggles between hide() and show(), or custom functions, for selected elements

HTML

Method Description
addClass() Adds one or more classes (for CSS) to selected elements
after() Inserts content after selected elements
append() Inserts content at the end of (but still inside) selected elements
appendTo() Inserts content at the end of (but still inside) selected elements
attr() Sets or returns an attribute and value of selected elements
before() Inserts content before selected elements
clone() Makes a copy of selected elements
detach() Removes (but keeps a copy of) selected elements
empty() Removes all child elements and content from selected elements
hasClass() Checks if any of the selected elements have a specified class (for CSS)
html() Sets or returns the content of selected elements
insertAfter() Inserts HTML markup or elements after selected elements
insertBefore() Inserts HTML markup or elements before selected elements
prepend() Inserts content at the beginning of (but still inside) selected elements
prependTo() Inserts content at the beginning of (but still inside) selected elements
remove() Removes selected elements
removeAttr() Removes an attribute from selected elements
removeClass() Removes one or more classes (for CSS) from selected elements
replaceAll() Replaces selected elements with new content
replaceWith() Replaces selected elements with new content
text() Sets or returns the text content of selected elements
toggleClass() Toggles between adding/removing one or more classes (for CSS) from selected elements
unwrap() Removes the parent element of the selected elements
val() Sets or returns the value attribute of the selected elements (form elements)
wrap() Wraps specified HTML element(s) around each selected element
wrapAll() Wraps specified HTML element(s) around all selected elements
wrapInner() Wraps specified HTML element(s) around the content of each selected element

CSS

Method Description
addClass() Adds one or more classes to selected elements
css() Sets or returns one or more style properties for selected elements
hasClass() Checks if any of the selected elements have a specified class
height() Sets or returns the height of selected elements
offset() Sets or returns the position (relative to the document) for selected elements
offsetParent() Returns the first parent element that is positioned
position() Returns the position (relative to the parent element) of the first selected element
removeClass() Removes one or more classes from selected elements
scrollLeft() Sets or returns the horizontal position of the scrollbar for the selected elements
scrollTop() Sets or returns the vertical position of the scrollbar for the selected elements
toggleClass() Toggles between adding/removing one or more classes from selected elements
width() Sets or returns the width of selected elements

AJAX

Method Description
$.ajax() Performs an AJAX request
ajaxComplete() Specifies a function to run when the AJAX request completes
ajaxError() Specifies a function to run when the AJAX request completes with an error
ajaxSend() Specifies a function to run before the AJAX request is sent
$.ajaxSetup() Sets the default values for future AJAX requests
ajaxStart() Specifies a function to run when the first AJAX request begins
ajaxStop() Specifies a function to run when all AJAX requests have completed
ajaxSuccess() Specifies a function to run an AJAX request completes successfully
$.get() Loads data from a server using an AJAX HTTP GET request
$.getJSON() Loads JSON-encoded data from a server using a HTTP GET request
$.getScript() Loads (and executes) a JavaScript from the a server using an AJAX HTTP GET request
load() Loads data from a server and puts the returned HTML into the selected element
$.param() Creates a serialized representation of an array or object (can be used as URL query string for AJAX requests)
$.post() Loads data from a server using an AJAX HTTP POST request
serialize() Encodes a set of form elements as a string for submission
serializeArray() Encodes a set of form elements as an array of names and values

MISC

Method Description
data() Attaches data to, or gets data from, selected elements
each() Run a function for each element matched by the jQuery selector
get() Get the DOM elements matched by the selector
index() Search for a given element from among the matched elements
$.noConflict() Release jQuery's control of the $ variable
$.param() Creates a serialized representation of an array or object (can be used as URL query string for AJAX requests)
removeData() Removes a previously-stored piece of data
size() Return the number of DOM elements matched by the jQuery selector
toArray() Retrieve all the DOM elements contained in the jQuery set, as an array
posted @ 2011-05-31 16:19 思无 阅读(354) | 评论 (0)编辑 收藏

 
//被观察者接口,有添加观察者对象,唤醒所有观察者等方法申明。
public
 interface ISubject {
    
public void setName(String name);
    
public String getName();
    
public void addObserver(IObserver o);
    
public void notifyAllObserver();
}

import java.util.*;
public class Subject implements ISubject{
    
private String name;
    List
<IObserver> observers = new ArrayList<IObserver>();
    
public Subject(){}
    
    
public Subject(String name){
        
this.name=name;
    }
    
public String getName(){
        
return this.name;
    }
    
public void setName(String name){
        
this.name=name;
    }
    
public void addObserver(IObserver o){
        observers.add(o);
    }
    
public void notifyAllObserver(){
        
for(int i=0;i<observers.size();i++){
            observers.get(i).showInfo();
        }
    }
}

//观察者接口。
public interface IObserver {
    
public void showInfo();
}

public class Observer implements IObserver{
    
    
private ISubject sjtref = null;
    
    
public void setRef(ISubject sjt){
        
this.sjtref=sjt;
    }
    
public Observer(ISubject sjtref){
        
super();
        
this.sjtref=sjtref;
    }
    
public void showInfo(){
        System.out.println(
"Observering:"+sjtref.getName());
    }
}

public class ObserverMain {
    
public static void main(String args[]){
        //新建被观察对象
        ISubject subject = new Subject("Shen,Ziping");
        //新建观察者对象
        IObserver observer1 = new Observer(subject);
        //注册
        subject.addObserver(observer1);
        //唤醒观察者
        subject.notifyAllObserver();
    }
}
posted @ 2011-05-30 12:24 思无 阅读(188) | 评论 (0)编辑 收藏


public
 interface IMobilePhone {
    
public void call();
}

public class NokiaMPhone implements IMobilePhone{
    
public void call(){
    }
}

public class OppoMPhone implements IMobilePhone{
    
public void call(){
    }
}

public interface IFactory {
    
public IMobilePhone createNokiaPhone();
    
public IMobilePhone createOppoPhone();
}

public class MobilePhoneFactory implements IFactory{
    
public IMobilePhone createNokiaPhone(){
        
return new NokiaMPhone();
    }
    
public IMobilePhone createOppoPhone(){
        
return new OppoMPhone();
    }
}

public class Client {
    
public static void main(String args[]){
        IFactory factory 
= new MobilePhoneFactory();
        IMobilePhone nokia 
= factory.createNokiaPhone();
        IMobilePhone oppo 
= factory.createOppoPhone();
        nokia.call();
        oppo.call();
    }
}

就代码上而言,工厂模式和抽象工厂模式功能上是差不多的。都通过借口遍程实现了比较好的代码隔离。不同的地方在于factory类的组织。工厂模式对每一个产品均实现一个工厂。而抽象工厂在一个工厂类中建立多个方法返回多种产品。
posted @ 2011-05-27 14:21 思无 阅读(224) | 评论 (0)编辑 收藏

仅列出标题
共3页: 上一页 1 2 3 下一页