<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-57  評論-202  文章-17  trackbacks-0
     
          在JDK1.3版本中引入了Dynamic Proxy的代理機制,通過實現java.lang.reflect.InvocationHandler接口,可以實現攔截需要改寫的方法。下面是一個簡單范例。
          有下面一個接口TestInterface和它的一個實現TestImpl:

    package sample.proxy;

    /**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2005</p>
     *
     * <p>Company: </p>
     *
     * @author George Hill
     * @version 1.0
     
    */


    public interface TestInterface {

      
    public String print();

    }


    package sample.proxy;

    /**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2005</p>
     *
     * <p>Company: </p>
     *
     * @author George Hill
     * @version 1.0
     
    */


    public class TestImpl implements TestInterface {
      
      
    public String print() {
        
    return "Hello, it's from TestImpl class";
      }

      
    }


          下面攔截print方法,調用自己的實現,這需要實現java.lang.reflect.InvocationHandler接口。

    package sample.proxy;

    import java.lang.reflect.
    *;

    /**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2005</p>
     *
     * <p>Company: </p>
     *
     * @author George Hill
     * @version 1.0
     
    */


    public class TestHandler implements InvocationHandler {
      
      TestInterface test;
      
      
    /**
       * 將動態代理綁定到指定的TestInterface
       * @param test TestInterface
       * @return TestInterface 綁定代理后的TestInterface
       
    */

      
    public TestInterface bind(TestInterface test) {
        
    this.test = test;
        
        TestInterface proxyTest 
    = (TestInterface) Proxy.newProxyInstance(
          test.getClass().getClassLoader(), test.getClass().getInterfaces(), 
    this);
        
        
    return proxyTest;
      }

      
      
    /**
       * 方法調用攔截器,攔截print方法
       * @param proxy Object
       * @param method Method
       * @param args Object[]
       * @return Object
       * @throws Throwable
       
    */

      
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
    // 如果調用的是print方法,則替換掉
        if ("print".equals(method.getName())) {
          
    return "HaHa, It's come from TestHandler";
        }
     else {
          
    return method.invoke(this.test, args);
        }

      }

      
    }


          下面是測試用例:

    package sample.test;

    import junit.framework.
    *;

    import sample.proxy.
    *;

    /**
     * <p>Title: </p> 
     * 
     * <p>Description: </p> 
     * 
     * <p>Copyright: Copyright (c) 2005</p> 
     * 
     * <p>Company: </p>
     * 
     * @author George Hill
     * @version 1.0
     
    */


    public class TestDynamicProxy extends TestCase {
      
      
    private TestInterface test = null;

      
    protected void setUp() throws Exception {
        super.setUp();
        TestHandler handler 
    = new TestHandler();
        
    // 用handler去生成實例
        test = handler.bind(new TestImpl());
      }


      
    protected void tearDown() throws Exception {
        test 
    = null;
        super.tearDown();
      }


      
    public void testPrint() {
        System.
    out.println(test.print());
      }


    }


          運行測試用例,可以看到輸出的是“HaHa, It's come from TestHandler”。
    posted @ 2005-05-24 17:47 小米 閱讀(3500) | 評論 (3)編輯 收藏
          昨天,終于收到了等待已久的《深入淺出Hibernate》一書,到現在已經看了40多頁,感覺很不錯,以前的一些問題在看了作者的剖析后,豁然開朗! 作者看來下了很大功夫去寫這本書,真正做到了深入淺出。我評價此書為,向大家推薦這本書。
          另外還買了一本《精通Spring》和《Java線程編程》,呵呵,看來有一段時間忙看書了。
    posted @ 2005-05-24 17:30 小米 閱讀(594) | 評論 (1)編輯 收藏
          在工作中,經常需要寫充值這樣的功能,這個功能無非是要做下面四件事:
          1. 判斷是否可以充值;
          2. 將充值卡的余額減去充值金額;
          3. 將用戶的余額加上充值金額;
          4. 寫日志。
          在實際的應用中,還是有不少地方需要考慮的,主要有以下幾個方面:
          1. 這四步中,后面三步都涉及到數據庫的操作,所以必須在一個事務中完成;
          2. 后面三步的執行順序是需要考慮的,我覺得比較好的順序是這樣的:
             a. 寫日志;
             b. 將充值卡的余額減去充值金額;
             c. 將用戶的余額加上充值金額。
          由于寫日志操作是不涉及到金額的,即使失敗了,對系統也沒有什么很大的影響,所以我放在第一步執行。至于是先給用戶增加金額還是先減去充值卡的金額,似乎誰先誰后都沒有什么關系。不過,其實有一個微妙的地方,如果先給用戶加上余額而不幸在減去充值卡的余額時出錯,甚至很不幸數據庫也出了問題,沒有回滾事務。那么就等于用戶平白無故的多了錢,用戶當然很高興,也許會投訴,也許不會投訴(是我肯定不投訴,高興都來不及呢)。如果是相反的情況,那么用戶必然投訴,也就可以發現系統的問題。所以我覺得應該先減去充值卡的余額。
          3. 在執行更改充值卡的余額時,必須要在數據庫中進行加減操作,而且要在數據庫中再檢查一遍充值卡的余額是否足夠。執行的SQL語句類似下面:
          UPDATE card SET card_balance=card_balance-? WHERE card_number=? AND card_balance>=?
          由于現在大部分的系統都是多進程或者多線程的,有可能在你提交之前,有其它的進程或者線程更新了數據庫中的記錄,所以如果不在數據庫中進行加減操作,不再檢查一遍余額是否充足,會給系統帶來隱患。
    posted @ 2005-05-20 18:19 小米 閱讀(507) | 評論 (0)編輯 收藏
         摘要:       使用Jakarta Commons Pool可以根據需要快速的實現自己的對象池,只需要實現PoolableObjectFactory或者KeyedPoolableObjectFactory接口。KeyedPoolableObjectFactory和PoolableObjectFactory的不同之處在于KeyedPoolabl...  閱讀全文
    posted @ 2005-05-20 14:08 小米 閱讀(4095) | 評論 (0)編輯 收藏
          續上一篇隨筆,struts1.2的源代碼和struts1.1的源代碼有些不同,struts1.1的eoncode方法是用的RequestUtils.encodeURL(String s)處理的,指定用UTF-8進行encoding。所以我的修改有些不同。
          從struts的網站上下載1.1的源代碼:http://apache.justdn.org/jakarta/struts/source/jakarta-struts-1.1-src.zip,解壓到本地目錄。打開文件jakarta-struts-1.1-src\src\share\org\apache\struts\taglib\bean\WriteTag.java,新增一個布爾屬性encode,表示是否需要用UTF-8編碼輸出字符串。代碼片斷如下:

        /**
         * The encode flag for the value.
         * Added by George Hill, 05/19/2005
         
    */

        
    protected boolean encode = false;
        
        
    public boolean isEncode() {
            
    return (this.encode);
        }

        
        
    public void setEncode(boolean encode) {
            
    this.encode = encode;
        }

          修改方法formatValue,把這段:


            
    // Return String object as is.
            if ( value instanceof java.lang.String ) {
                    
    return (String)value;
            }
     else {

            }


          替換成:


            
    // Return String object as is.
            if ( value instanceof java.lang.String ) {
                
    if (encode)
                    
    return RequestUtils.encodeURL((String)value);
                
    else
                    
    return (String)value;
            }
     else {

            }


          保存修改后的文件。然后需要修改文件jakarta-struts-1.1-src\doc\userGuide\struts-bean.xml。這個文件在ant編譯時會變成strtus-bean.tld文件。在tag write后面增加一個attribute,如下所示:


        
    <attribute>
          
    <name>encode</name>
          
    <required>false</required>
          
    <rtexprvalue>true</rtexprvalue>
          
    <info>
          
    <p>Added by George Hill, specifies the value need UTF-8 encode or not.</p>
          
    </info>
          
    <default>false</default>
        
    </attribute>

          然后修改一下ant的編譯配置文件build.xml,這一部分和上一篇的隨筆類似,請參考上篇隨筆:<<用URLEncoder輸出<bean:write />的值>>。
          運行ant,編譯后的jar文件保存在jakarta-struts-1.1-src\target\library目錄中,把原來的struts.jar和struts-bean.tld文件替換掉,就可以用自定義的<bean:write /> tag了。
    posted @ 2005-05-20 11:52 小米 閱讀(1045) | 評論 (0)編輯 收藏
          我在JSP頁面中,當處理<a href></a>時,經常不用<html:link/>的方式處理,而是用下面這樣的方式處理:
          <a href="foo.do?param1=<bean:write name="n1" property="p1"/>&param2=<bean:write name="n2" property="p2"/>">Test</a>
          這樣在處理多個參數時,就不需要先放到一個Collection中。按照<html:link/>的多個參數的處理方法去做,有時確實是很繁瑣。不過這樣帶來一個新的問題,在處理中文參數值時,這樣就行不通了。用request.getParameter("param1")獲取的中文,在中文的個數為奇數個時,就會顯示不正確。例如“三個字”在getParameter中獲取的值是“三個?”。
          這個問題是由于<bean:write />沒有用URLEncoder的encode方法處理值,因為<bean:write />主要是用來在頁面上顯示bean的信息,并不是用在鏈接中當作參數的值。這個問題可以通過給<bean:write />增加新的屬性來解決。
          從Struts的網站上下載Struts 1.2.4的源代碼:http://apache.freelamp.com/struts/source/jakarta-struts-1.2.4-src.zip
          解壓到本地目錄,然后修改文件jakarta-struts-1.2.4-src\src\share\org\apache\struts\taglib\bean\WriteTag.java。新增一個屬性charset,表示需要用什么編碼進行編碼。代碼片斷如下:

        /**
         * Added by George Hill, the string value charset to encoding.
         * 05/19/2005
         
    */

        
    protected String charset = null;

        
    public String getCharset() {
            
    return (this.charset);
        }


        
    public void setCharset(String charset) {
            
    this.charset = charset;
        }

          修改方法formatValue,把這段


            
    if (value instanceof java.lang.String) {
                    
    return (String) value;
            }
     else {

            }


          替換為:


            
    if (value instanceof java.lang.String) {
                
    if (charset != null && charset.length() != 0)
                    
    return TagUtils.getInstance().encodeURL((String) value, charset);
                
    else
                    
    return (String) value;
            }
     else {

            }


          保存修改后的文件。然后需要修改文件jakarta-struts-1.2.4-src\doc\userGuide\struts-bean.xml。這個文件在ant編譯時會變成strtus-bean.tld文件。在tag write后面增加一個attribute,如下所示:


      
    <tag>
        
    <name>write</name>

        
    <attribute>
          
    <name>charset</name>
          
    <required>false</required>
          
    <rtexprvalue>true</rtexprvalue>
          
    <info>
          
    <p>Added by George Hill, use this charset to encoding the value.</p>
          
    </info>
        
    </attribute>

      
    </tag>

          然后修改一下ant的編譯配置文件build.xml,有幾個部分需要修改:
          1.屬性catalina.home需要修改成你安裝的tomcat的目錄;
          2.compile.classpath需要修改,把jar文件的路徑指向正確;
          3.prepare.library taget部分的copy,把相關的jar文件的路徑指向正確。
          運行ant,編譯后的jar文件保存在jakarta-struts-1.2.4-src\target\library目錄中,把原來的struts.jar和struts-bean.tld文件替換掉,就可以用自定義的<bean:write /> tag了。如果不寫charset屬性,那么和原來的<bean:write />處理是一樣的。
          這樣,類似于下面的鏈接地址:
          <a href="foo.do?param1=<bean:write name="n1" property="p1"/>&param2=<bean:write name="n2" property="p2"/>">Test</a>
          就可以修改成:
          <a href="foo.do?param1=<bean:write name="n1" property="p1" charset="UTF-8"/>&param2=<bean:write name="n2" property="p2" charset="UTF-8"/>">Test</a>
          在request.getParameter("param1")中將會獲得正確的中文值。
          對于struts 1.1,程序又稍微有些不同。我將在下一篇隨筆中介紹。
    posted @ 2005-05-20 00:50 小米 閱讀(2092) | 評論 (5)編輯 收藏
          等了好多天,總于等到了。在China-pub和第二書店都有售。地址:
          http://www.china-pub.com/computers/common/info.asp?id=24500
          http://www.dearbook.com.cn/book/viewbook.aspx?pno=TS0028982
          期待快遞公司快點送過來!
    posted @ 2005-05-18 18:21 小米 閱讀(397) | 評論 (0)編輯 收藏
          下面是我的一個簡單的網絡服務器端的程序,程序的流程是監聽ACCEPT事件,然后往客戶端輸出一串字符串。是不是很簡單。

    package sample.nio;

    import java.io.
    *;
    import java.net.
    *;
    import java.nio.channels.
    *;
    import java.util.
    *;

    /**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2005</p>
     *
     * <p>Company: </p>
     *
     * @author George Hill
     * @version 1.0
     
    */


    public class Server {

      
    private int port;

      
    public Server(int port) {
        
    this.port = port;
      }


      
    public void startServer() throws IOException {
        
    // 創建ServerSocketChannel并且綁定到指定的端口
        ServerSocketChannel ssc = ServerSocketChannel.open();
        InetSocketAddress address 
    = new InetSocketAddress(InetAddress.getLocalHost(), port);
        ssc.socket().bind(address);
        ssc.configureBlocking(
    false);

        
    // 創建Selector,并且注冊ACCEPT事件
        Selector selector = Selector.open();
        SelectionKey skey 
    = ssc.register(selector, SelectionKey.OP_ACCEPT);

        boolean stop 
    = false;
        
    int n = 0;

        System.
    out.println("Server Start");

        
    // 輪詢
        while (!stop) {
          
    // 獲取Selector返回的時間值
          n = selector.select();

          
    // 當傳回的值大于0事,讀時間發生了
          if (n > 0{
            Set 
    set = selector.selectedKeys();
            Iterator it 
    = set.iterator();

            
    while (it.hasNext()) {
              skey 
    = (SelectionKey) it.next();
              it.remove();

              
    if (skey.isAcceptable()) {
                
    // 從channel()中取得剛剛注冊的Channel
                Socket socket = ((ServerSocketChannel) skey.channel()).accept().socket();

                PrintWriter writer 
    = new PrintWriter(socket.getOutputStream(), true);

                
    // 將"Hello, World"寫入
                writer.write("Hello, World!\n");

                
    // 睡眠3秒
                try {
                  Thread.sleep(
    3000);
                }
     catch (InterruptedException ie) {
                }


                
    // 將"EXIT"寫入Buffer
                writer.write("EXIT");

                
    // 退出程序
                writer.close();
                
    // stop = true;
              }

            }

          }

        }


        ssc.close();
        System.
    out.println("Server Stop");
      }


      
    public static void main(String[] args) throws Exception {
        Server server 
    = new Server(5000);
        server.startServer();
      }

    }

    posted @ 2005-05-18 12:21 小米 閱讀(729) | 評論 (0)編輯 收藏
         摘要:       最近在做有關Socket的程序,寫了兩個客戶端程序,第一個客戶端程序如下:  1package sample.nio; 2 3import java.io.IOException; 4import java.net.*; 5import&nb...  閱讀全文
    posted @ 2005-05-18 12:18 小米 閱讀(3890) | 評論 (1)編輯 收藏

          從JDK1.4開始,SUN提供了JCE包,可以實現多種加密算法。下面是我的一個用JCE進行DES加密解密的程序:

    package sample;

    import java.security.
    *;
    import javax.crypto.
    *;

    /**
     * <p>Title: </p>
     *
     * <p>Description: </p>
     *
     * <p>Copyright: Copyright (c) 2005</p>
     *
     * <p>Company: </p>
     *
     * @author George Hill
     * @version 1.0
     
    */


    public class Test {
      
      
    // 加密使用的Key
      private SecretKey key;
      
      
    // 加密算法,JCE可用DES,DESede和Blowfish
      private static final String algorithm = "DES";
      
      
    public Test() throws NoSuchAlgorithmException {
        KeyGenerator generator 
    = KeyGenerator.getInstance(algorithm);
        key 
    = generator.generateKey();
      }

      
      
    /**
       * 利用DES算法加密
       * @param s String 需要加密的字符串
       * @return String 加密后的字符串
       * @throws Exception
       
    */

      
    public String encryptData(String s) throws Exception {
        Cipher c 
    = Cipher.getInstance(algorithm);
        c.init(Cipher.ENCRYPT_MODE, key);

        
    return new String(c.doFinal(s.getBytes()));
      }

      
      
    /**
       * 利用DES算法解密
       * @param s String 需要解密的字符串
       * @return String 解密后的字符串
       * @throws Exception
       
    */

      
    public String decryptData(String s) throws Exception {
        Cipher c 
    = Cipher.getInstance(algorithm);
        c.init(Cipher.DECRYPT_MODE, key);

        
    return new String(c.doFinal(s.getBytes()));
      }

      
      
    /**
       * 測試程序
       * @param args String[]
       * @throws Exception
       
    */

      
    public static void main(String[] args) throws Exception {
        String s 
    = "Hello";
        Test test 
    = new Test();
        String encrypt 
    = test.encryptData(s);
        System.
    out.println(encrypt);
        String decrypt 
    = test.decryptData(encrypt);
        System.
    out.println(decrypt);
      }

    }



          在實際的使用中,往往需要對加密后的byte數組進行轉換,可以自己實現轉換,或者用一些第三方的API。
    posted @ 2005-05-18 11:55 小米 閱讀(2630) | 評論 (4)編輯 收藏
    僅列出標題
    共6頁: 上一頁 1 2 3 4 5 6 下一頁 
    主站蜘蛛池模板: 亚洲一区无码中文字幕乱码| 亚洲爆乳精品无码一区二区| A在线观看免费网站大全| 亚洲综合激情五月丁香六月| 中文字幕日韩亚洲| 亚洲成年轻人电影网站www | 一级毛片视频免费观看| 亚洲国产精品无码久久一线| 美女视频黄a视频全免费| 午夜不卡AV免费| 亚洲国产午夜电影在线入口| 亚洲熟伦熟女新五十路熟妇| 亚洲视频免费一区| 一边摸一边桶一边脱免费视频 | 亚洲视频在线免费看| 视频一区在线免费观看| 久久精品国产亚洲AV高清热 | 亚洲人AV在线无码影院观看| 亚洲精品无码不卡在线播放HE| 国产精品视频永久免费播放| 中文字幕av无码不卡免费| 亚洲一区二区三区播放在线| 亚洲精品国偷自产在线| 日韩免费观看一级毛片看看| 免费A级毛片无码专区| 内射少妇36P亚洲区| 精品国产亚洲男女在线线电影 | 国产精品观看在线亚洲人成网| 亚洲男人的天堂在线播放| 免费人成年轻人电影| 青苹果乐园免费高清在线| 久久久久成人片免费观看蜜芽 | 在线免费观看韩国a视频| 无码区日韩特区永久免费系列 | 国产精品亚洲w码日韩中文| 拍拍拍又黄又爽无挡视频免费| 日韩内射激情视频在线播放免费| 一级毛片免费全部播放| 亚洲Aⅴ在线无码播放毛片一线天| 精品亚洲麻豆1区2区3区| 亚洲国产精品无码久久一区二区|