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

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

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

    176142998

      BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
      116 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

    #

    官網(wǎng)地址
    http://www.oracle.com/technetwork/cn/middleware/ias/downloads/wls-main-091116-zhs.html


    各個(gè)版本的都有,以下列舉出來(lái)9.2的

    Oracle WebLogic Server 9.2 MP3版本

    http://download.oracle.com/otn/bea/weblogic/server923_win32.exe.zip

    http://download.oracle.com/otn/bea/weblogic/server923_linux32.bin.zip

    http://download.oracle.com/otn/bea/weblogic/server923_solaris32.bin.zip

     

    Oracle WebLogic Server 9.2 MP4版本

     

    http://download.oracle.com/otn/bea/weblogic/server924_win32.zip

     

    http://download.oracle.com/otn/bea/weblogic/server924_linux32.zip

    http://download.oracle.com/otn/bea/weblogic/server924_solaris32.zip

     

    Oracle WebLogic Server 10.0 MP2 版本

    http://download.oracle.com/otn/bea/weblogic/V16484-01.zip

    posted @ 2012-04-12 09:54 飛飛 閱讀(1034) | 評(píng)論 (0)編輯 收藏



    linux-geum:/etc/init.d # more start_oracle.sh
    #this script is used to start the oracle

    su - oracle -c "/opt/oracle/product/10g/bin/dbstart"

    su - oracle -c "/opt/oracle/product/10g/bin/lsnrctl start"


    ln -s /etc/init.d/start_oracle.sh  /etc/rc.d/rc2.d/S16start_oracle
    ln -s /etc/init.d/start_oracle.sh  /etc/rc.d/rc3.d/S16start_oracle
    ln -s /etc/init.d/start_oracle.sh  /etc/rc.d/rc5.d/S16start_oracle

    linux-geum:/etc/init.d # more stop_oracle.sh
    #this script is used to stop the oracle

    su - oracle -c "/opt/oracle/product/10g/bin/lsnrctl stop"

    su - oracle -c "/opt/oracle/product/10g/bin/bin/dbshut"


    ln -s /etc/init.d/stop_oracle.sh  /etc/rc.d/rc2.d/S16stop_oracle
    ln -s /etc/init.d/stop_oracle.sh  /etc/rc.d/rc3.d/S16stop_oracle
    ln -s /etc/init.d/stop_oracle.sh  /etc/rc.d/rc5.d/S16stop_oracle

    posted @ 2012-04-06 17:35 飛飛 閱讀(693) | 評(píng)論 (0)編輯 收藏

    在/etc/init.d 下新建after.local或者編輯after.local文件,

    文件內(nèi)容
    /usr/local/bin/memcached -d -m 512 -u root -l 192.168.1.106 -p 11211 -c 1024 -P /tmp/memcached.pid
    posted @ 2012-04-06 17:33 飛飛 閱讀(551) | 評(píng)論 (0)編輯 收藏

    1、主要實(shí)現(xiàn)用戶(hù)在進(jìn)行某項(xiàng)操作時(shí),多數(shù)據(jù)庫(kù)的更新、插入和刪除詳細(xì)信息。記錄操作時(shí)的請(qǐng)求信息。
    2、在進(jìn)入Controller時(shí),生成一個(gè)事物ID,在這個(gè)Controller中進(jìn)行的所有DAO操作都綁定該事物ID。并進(jìn)行記錄日志信息。


    package com.centralsoft.filter;

    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.regex.Pattern;

    import net.sf.json.JSONObject;

    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Component;

    import com.centralsoft.cache.CacheService;
    import com.centralsoft.cache.annotations.Cache;
    import com.centralsoft.cache.entity.MemCacheKey;
    import com.centralsoft.entity.SysLogDetail;
    import com.centralsoft.manager.pub.ThreadBean;
    import com.centralsoft.manager.pub.ThreadId;
    import com.centralsoft.pub.dao.SysLogDAO;
    import com.centralsoft.webservice.pub.DateSHA;

    /**
     * DAO層AOP攔截器,實(shí)現(xiàn)記錄用戶(hù)操作過(guò)的所有方法和參數(shù),并實(shí)現(xiàn)DAO層緩存
     *
     * @author Administrator
     *
     */
    @Aspect
    @Component
    public class AspectAutoDAOBean {

     @Autowired
     @Qualifier("CacheService")
     private CacheService memcache;

     @Autowired
     @Qualifier("SysLogDAO")
     private SysLogDAO SysLogDAO;

     @Around("execution(* com.centralsoft.*.dao.Zr*DAO.*(..))")
     public Object before(ProceedingJoinPoint joinPoint) throws Throwable {
      // 獲取請(qǐng)求事務(wù)ID信息
      ThreadId threadId = new ThreadBean().getThreadId();
      // 調(diào)用方法名稱(chēng)
      String methodName = joinPoint.getSignature().getName();
      // 調(diào)用參數(shù)
      Object[] args = joinPoint.getArgs();
      Object object = null;

      // 數(shù)據(jù)庫(kù)更新操作日志
      if (Pattern.matches("(save|insert|add|delete|remove|del|update)[\\S]*",
        methodName)) {
       if (threadId != null && threadId.getTransactionalId() != null) {
        // 獲取執(zhí)行請(qǐng)求事務(wù)ID
        String transactionalId = threadId.getTransactionalId();
        // 獲取執(zhí)行請(qǐng)求用戶(hù)ID
        String userId = threadId.getUserId();
        SysLogDetail sysLogDetail = new SysLogDetail();
        sysLogDetail.setXh(transactionalId);
        sysLogDetail.setUserId(userId);
        sysLogDetail.setMethod(methodName);
        JSONObject msg = new JSONObject();
        // 處理參數(shù)
        for (Object temp : args) {
         // 獲取參數(shù)類(lèi)型,不同參數(shù)類(lèi)型數(shù)據(jù)處理不一樣
         Class<? extends Object> paramClazz = temp.getClass();
         String classType = paramClazz.getName();
         if (classType.equals("java.lang.String")) {
          msg.put("key", temp);
         } else if (classType.equals("java.util.HashMap")) {
          msg.putAll((HashMap<?, ?>) temp);
         } else if (classType.startsWith("com.")) {
          try {
           Field[] f = paramClazz.getDeclaredFields();
           for (Field field : f) {
            String fieldName = field.getName();
            field.setAccessible(true);
            msg.put(fieldName, field.get(temp));
           }
          } catch (SecurityException e) {
           e.printStackTrace();
          } catch (IllegalArgumentException e) {
           e.printStackTrace();
          }
         }
        }
        sysLogDetail.setMsg(msg.toString());
        // 記錄DAO數(shù)據(jù)庫(kù)操作日志
        SysLogDAO.insertSysLogDetail(sysLogDetail);
       }
       // 執(zhí)行數(shù)據(jù)庫(kù)操作
       object = joinPoint.proceed();

       // 數(shù)據(jù)庫(kù)查詢(xún)緩存
      } else if (Pattern.matches("(query|load|get|select|read)[\\S]*",
        methodName)) {
       // DAO層緩存注解
       MemCacheKey cacheKey = new MemCacheKey();
       // 獲取cache注解屬性
       Cache cache = null;
       // 獲取請(qǐng)求方法
       Class<?> cls = joinPoint.getTarget().getClass();
       // 獲取class中的所有方法
       Method[] methods = cls.getMethods();
       for (Method m : methods) {
        // 獲取執(zhí)行方法前的注解信息。
        if (m.getName().equals(methodName)) {
         cache = m.getAnnotation(Cache.class);
         break;
        }
       }

       if (cache != null) {
        // 獲取memcacheKey,并進(jìn)行MD5加密
        cacheKey = memcacheKey(cache, args);
        // 判斷緩存服務(wù)器是否存在該可以值
        if (memcache.exist(cacheKey.getMemcacheKey())) {
         object = memcache.get(cacheKey.getMemcacheKey());
        } else {
         // 執(zhí)行數(shù)據(jù)庫(kù)操作
         object = joinPoint.proceed();
         // 將數(shù)據(jù)存放進(jìn)緩存
         if (cacheKey.getMemcacheKey() != null) {
          memcache.put(cacheKey.getMemcacheKey(),
            object == null ? "" : object, new Date(cacheKey
              .getTime()));
         }
        }
       } else {
        // 執(zhí)行數(shù)據(jù)庫(kù)操作
        object = joinPoint.proceed();
       }
      } else {
       // 執(zhí)行數(shù)據(jù)庫(kù)操作
       object = joinPoint.proceed();
      }

      return object;

     }

     /**
      * 獲取根據(jù)注解中的key獲取memcache的含參數(shù)key值
      *
      * @param cache
      * @param parameterObject
      * @return
      * @author fei.zhao 2011-10-10
      */
     @SuppressWarnings("unchecked")
     private static MemCacheKey memcacheKey(Cache cache, Object[] args) {
      MemCacheKey tempKey = new MemCacheKey();
      String key = "";
      boolean flag = true;
      StringBuilder keyBuilder = new StringBuilder(32);
      // 獲取注解中的key值
      String cacheKey = cache.key();
      Object[] cacheArgs = cacheKey.split("\\.");

      // 設(shè)置請(qǐng)求參數(shù)在args[]中的序號(hào)
      // key參數(shù)進(jìn)行循環(huán)遍歷
      for (Object s : cacheArgs) {
       // 判斷是否是格式$,$...
       if (s.toString().startsWith("$")) {
        // 獲取參數(shù)名稱(chēng)
        String type = s.toString().substring(1);
        // 獲取參數(shù)值
        Object temp = args[0];
        // 獲取參數(shù)類(lèi)型,不同參數(shù)類(lèi)型數(shù)據(jù)處理不一樣
        Class<? extends Object> paramClazz = temp.getClass();
        String classType = paramClazz.getName();
        if (classType.equals("java.lang.String")) {
         keyBuilder.append(temp);
        } else if (classType.equals("java.util.HashMap")) {
         keyBuilder.append(((HashMap) temp).get(type));
        } else if (classType.startsWith("com.")) {
         try {
          Field f = paramClazz.getDeclaredField(type);// 實(shí)體中字段
          f.setAccessible(true);// 允許訪(fǎng)問(wèn)私有字段
          keyBuilder.append(f.get(temp));
         } catch (SecurityException e) {
          flag = false;
          e.printStackTrace();
         } catch (NoSuchFieldException e) {
          flag = false;
          e.printStackTrace();
         } catch (IllegalArgumentException e) {
          flag = false;
          e.printStackTrace();
         } catch (IllegalAccessException e) {
          flag = false;
          e.printStackTrace();
         }
        }
       } else {
        keyBuilder.append(s);
       }
       // 每個(gè)參數(shù)后面添加 “.”號(hào)分隔
       keyBuilder.append(".");
      }
      if (args.length == 3) {
       keyBuilder.append(args[1] + ".").append(args[2]);
      }
      if (flag == true) {
       key = keyBuilder.toString();
       tempKey.setMemcacheKey(DateSHA.shaEncrypt(key));
       tempKey.setTime(cache.time());
      }
      return tempKey;
     }
    }

    posted @ 2011-11-07 19:48 飛飛 閱讀(7758) | 評(píng)論 (0)編輯 收藏

    一般的情況下我們都是使用IE或者Navigator瀏覽器來(lái)訪(fǎng)問(wèn)一個(gè)WEB服務(wù)器,用來(lái)瀏覽頁(yè)面查看信息或者提交一些數(shù)據(jù)等等。所訪(fǎng)問(wèn)的這些頁(yè)面有的僅僅是一些普通的頁(yè)面,有的需要用戶(hù)登錄后方可使用,或者需要認(rèn)證以及是一些通過(guò)加密方式傳輸,例如HTTPS。目前我們使用的瀏覽器處理這些情況都不會(huì)構(gòu)成問(wèn)題。不過(guò)你可能在某些時(shí)候需要通過(guò)程序來(lái)訪(fǎng)問(wèn)這樣的一些頁(yè)面,比如從別人的網(wǎng)頁(yè)中“偷”一些數(shù)據(jù);利用某些站點(diǎn)提供的頁(yè)面來(lái)完成某種功能,例如說(shuō)我們想知道某個(gè)手機(jī)號(hào)碼的歸屬地而我們自己又沒(méi)有這樣的數(shù)據(jù),因此只好借助其他公司已有的網(wǎng)站來(lái)完成這個(gè)功能,這個(gè)時(shí)候我們需要向網(wǎng)頁(yè)提交手機(jī)號(hào)碼并從返回的頁(yè)面中解析出我們想要的數(shù)據(jù)來(lái)。如果對(duì)方僅僅是一個(gè)很簡(jiǎn)單的頁(yè)面,那我們的程序會(huì)很簡(jiǎn)單,本文也就沒(méi)有必要大張旗鼓的在這里浪費(fèi)口舌。但是考慮到一些服務(wù)授權(quán)的問(wèn)題,很多公司提供的頁(yè)面往往并不是可以通過(guò)一個(gè)簡(jiǎn)單的URL就可以訪(fǎng)問(wèn)的,而必須經(jīng)過(guò)注冊(cè)然后登錄后方可使用提供服務(wù)的頁(yè)面,這個(gè)時(shí)候就涉及到COOKIE問(wèn)題的處理。我們知道目前流行的***頁(yè)技術(shù)例如ASP、JSP無(wú)不是通過(guò)COOKIE來(lái)處理會(huì)話(huà)信息的。為了使我們的程序能使用別人所提供的服務(wù)頁(yè)面,就要求程序首先登錄后再訪(fǎng)問(wèn)服務(wù)頁(yè)面,這過(guò)程就需要自行處理cookie,想想當(dāng)你用java.net.HttpURLConnection來(lái)完成這些功能時(shí)是多么恐怖的事情啊!況且這僅僅是我們所說(shuō)的頑固的WEB服務(wù)器中的一個(gè)很常見(jiàn)的“頑固”!再有如通過(guò)HTTP來(lái)上傳文件呢?不需要頭疼,這些問(wèn)題有了“它”就很容易解決了!

    我們不可能列舉所有可能的頑固,我們會(huì)針對(duì)幾種最常見(jiàn)的問(wèn)題進(jìn)行處理。當(dāng)然了,正如前面說(shuō)到的,如果我們自己使用java.net.HttpURLConnection來(lái)搞定這些問(wèn)題是很恐怖的事情,因此在開(kāi)始之前我們先要介紹一下一個(gè)開(kāi)放源碼的項(xiàng)目,這個(gè)項(xiàng)目就是Apache開(kāi)源組織中的httpclient,它隸屬于Jakarta的commons項(xiàng)目,目前的版本是2.0RC2。commons下本來(lái)已經(jīng)有一個(gè)net的子項(xiàng)目,但是又把httpclient單獨(dú)提出來(lái),可見(jiàn)http服務(wù)器的訪(fǎng)問(wèn)絕非易事。

    Commons-httpclient項(xiàng)目就是專(zhuān)門(mén)設(shè)計(jì)來(lái)簡(jiǎn)化HTTP客戶(hù)端與服務(wù)器進(jìn)行各種通訊編程。通過(guò)它可以讓原來(lái)很頭疼的事情現(xiàn)在輕松的解決,例如你不再管是HTTP或者HTTPS的通訊方式,告訴它你想使用HTTPS方式,剩下的事情交給httpclient替你完成。本文會(huì)針對(duì)我們?cè)诰帉?xiě)HTTP客戶(hù)端程序時(shí)經(jīng)常碰到的幾個(gè)問(wèn)題進(jìn)行分別介紹如何使用httpclient來(lái)解決它們,為了讓讀者更快的熟悉這個(gè)項(xiàng)目我們最開(kāi)始先給出一個(gè)簡(jiǎn)單的例子來(lái)讀取一個(gè)網(wǎng)頁(yè)的內(nèi)容,然后循序漸進(jìn)解決掉前進(jìn)中的所形侍狻?/font>

    1. 讀取網(wǎng)頁(yè)(HTTP/HTTPS)內(nèi)容

    下面是我們給出的一個(gè)簡(jiǎn)單的例子用來(lái)訪(fǎng)問(wèn)某個(gè)頁(yè)面

    /*

     * Created on 2003-12-14 by Liudong

     */

    package http.demo;

     

    import java.io.IOException;

     

    import org.apache.commons.httpclient.*;

    import org.apache.commons.httpclient.methods.*;

    /**

     * 最簡(jiǎn)單的HTTP客戶(hù)端,用來(lái)演示通過(guò)GET或者POST方式訪(fǎng)問(wèn)某個(gè)頁(yè)面

     * @author Liudong

     */

    public class SimpleClient {

     

        public static void main(String[] args) throws IOException

        {

            HttpClient client = new HttpClient();   

            //設(shè)置代理服務(wù)器地址和端口    

            //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);

            //使用GET方法,如果服務(wù)器需要通過(guò)HTTPS連接,那只需要將下面URL中的http換成https

            HttpMethod method = new GetMethod("http://java.sun.com");

            //使用POST方法

            //HttpMethod method = new PostMethod("http://java.sun.com");

            client.executeMethod(method);

            //打印服務(wù)器返回的狀態(tài)

            System.out.println(method.getStatusLine());

            //打印返回的信息

            System.out.println(method.getResponseBodyAsString());

            //釋放連接

            method.releaseConnection();

        }
    }

     

    在這個(gè)例子中首先創(chuàng)建一個(gè)HTTP客戶(hù)端(HttpClient)的實(shí)例,然后選擇提交的方法是GET或者POST,最后在HttpClient實(shí)例上執(zhí)行提交的方法,最后從所選擇的提交方法中讀取服務(wù)器反饋回來(lái)的結(jié)果。這就是使用HttpClient的基本流程。其實(shí)用一行代碼也就可以搞定整個(gè)請(qǐng)求的過(guò)程,非常的簡(jiǎn)單!


    2. 以GET或者POST方式向網(wǎng)頁(yè)提交參數(shù)

    其實(shí)前面一個(gè)最簡(jiǎn)單的示例中我們已經(jīng)介紹了如何使用GET或者POST方式來(lái)請(qǐng)求一個(gè)頁(yè)面,本小節(jié)與之不同的是多了提交時(shí)設(shè)定頁(yè)面所需的參數(shù),我們知道如果是GET的請(qǐng)求方式,那么所有參數(shù)都直接放到頁(yè)面的URL后面用問(wèn)號(hào)與頁(yè)面地址隔開(kāi),每個(gè)參數(shù)用&隔開(kāi),例如:http://java.sun.com?name=liudong&mobile=123456,但是當(dāng)使用POST方法時(shí)就會(huì)稍微有一點(diǎn)點(diǎn)麻煩。本小節(jié)的例子演示向如何查詢(xún)手機(jī)號(hào)碼所在的城市,代碼如下:

     

    /*

     * Created on 2003-12-7 by Liudong

     */

    package http.demo;

     

    import java.io.IOException;

     

    import org.apache.commons.httpclient.*;

    import org.apache.commons.httpclient.methods.*;

    /**

     * 提交參數(shù)演示

     * 該程序連接到一個(gè)用于查詢(xún)手機(jī)號(hào)碼所屬地的頁(yè)面

     * 以便查詢(xún)號(hào)碼段1330227所在的省份以及城市

     * @author Liudong

     */

    public class SimpleHttpClient {

     

        public static void main(String[] args) throws IOException

        {

            HttpClient client = new HttpClient();

            client.getHostConfiguration().setHost("www.imobile.com.cn", 80, "http");

     

            HttpMethod method = getPostMethod();//使用POST方式提交數(shù)據(jù)

            client.executeMethod(method);

           //打印服務(wù)器返回的狀態(tài)

            System.out.println(method.getStatusLine());

            //打印結(jié)果頁(yè)面

            String response =

               new String(method.getResponseBodyAsString().getBytes("8859_1"));

           //打印返回的信息

            System.out.println(response);

            method.releaseConnection();

        }

        /**

         * 使用GET方式提交數(shù)據(jù)

         * @return

         */

        private static HttpMethod getGetMethod(){

            return new GetMethod("/simcard.php?simcard=1330227");

        }

        /**

         * 使用POST方式提交數(shù)據(jù)

         * @return

         */

        private static HttpMethod getPostMethod(){

            PostMethod post = new PostMethod("/simcard.php");

            NameValuePair simcard = new NameValuePair("simcard","1330227");

            post.setRequestBody(new NameValuePair[] { simcard});

            return post;

        }

    }

    在上面的例子中頁(yè)面http://www.imobile.com.cn/simcard.php需要一個(gè)參數(shù)是simcard,這個(gè)參數(shù)值為手機(jī)號(hào)碼段,即手機(jī)號(hào)碼的前七位,服務(wù)器會(huì)返回提交的手機(jī)號(hào)碼對(duì)應(yīng)的省份、城市以及其他詳細(xì)信息。GET的提交方法只需要在URL后加入?yún)?shù)信息,而POST則需要通過(guò)NameValuePair類(lèi)來(lái)設(shè)置參數(shù)名稱(chēng)和它所對(duì)應(yīng)的值

    3. 處理頁(yè)面重定向

    在JSP/Servlet編程中response.sendRedirect方法就是使用HTTP協(xié)議中的重定向機(jī)制。它與JSP中的<jsp:forward …>的區(qū)別在于后者是在服務(wù)器中實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn),也就是說(shuō)應(yīng)用容器加載了所要跳轉(zhuǎn)的頁(yè)面的內(nèi)容并返回給客戶(hù)端;而前者是返回一個(gè)狀態(tài)碼,這些狀態(tài)碼的可能值見(jiàn)下表,然后客戶(hù)端讀取需要跳轉(zhuǎn)到的頁(yè)面的URL并重新加載新的頁(yè)面。就是這樣一個(gè)過(guò)程,所以我們編程的時(shí)候就要通過(guò)HttpMethod.getStatusCode()方法判斷返回值是否為下表中的某個(gè)值來(lái)判斷是否需要跳轉(zhuǎn)。如果已經(jīng)確認(rèn)需要進(jìn)行頁(yè)面跳轉(zhuǎn)了,那么可以通過(guò)讀取HTTP頭中的location屬性來(lái)獲取新的地址。

    狀態(tài)碼
     對(duì)應(yīng)HttpServletResponse的常量
     詳細(xì)描述
     
    301
     SC_MOVED_PERMANENTLY
     頁(yè)面已經(jīng)永久移到另外一個(gè)新地址
     
    302
     SC_MOVED_TEMPORARILY
     頁(yè)面暫時(shí)移動(dòng)到另外一個(gè)新的地址
     
    303
     SC_SEE_OTHER
     客戶(hù)端請(qǐng)求的地址必須通過(guò)另外的URL來(lái)訪(fǎng)問(wèn)
     
    307
     SC_TEMPORARY_REDIRECT
     同SC_MOVED_TEMPORARILY
     


    下面的代碼片段演示如何處理頁(yè)面的重定向

    client.executeMethod(post);

            System.out.println(post.getStatusLine().toString());

            post.releaseConnection();

           

            //檢查是否重定向

            int statuscode = post.getStatusCode();

            if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) ||

                (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) ||

                (statuscode == HttpStatus.SC_SEE_OTHER) ||

    (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {

    //讀取新的URL地址

                Header header = post.getResponseHeader("location");

                if (header != null) {

                    String newuri = header.getValue();

                    if ((newuri == null) || (newuri.equals("")))

                        newuri = "/";

                    GetMethod redirect = new GetMethod(newuri);

                    client.executeMethod(redirect);

                    System.out.println("Redirect:"+ redirect.getStatusLine().toString());

                    redirect.releaseConnection();

                } else

                    System.out.println("Invalid redirect");

            }

    我們可以自行編寫(xiě)兩個(gè)JSP頁(yè)面,其中一個(gè)頁(yè)面用response.sendRedirect方法重定向到另外一個(gè)頁(yè)面用來(lái)測(cè)試上面的例子。

    4. 模擬輸入用戶(hù)名和口令進(jìn)行登錄

    本小節(jié)應(yīng)該說(shuō)是HTTP客戶(hù)端編程中最常碰見(jiàn)的問(wèn)題,很多網(wǎng)站的內(nèi)容都只是對(duì)注冊(cè)用戶(hù)可見(jiàn)的,這種情況下就必須要求使用正確的用戶(hù)名和口令登錄成功后,方可瀏覽到想要的頁(yè)面。因?yàn)镠TTP協(xié)議是無(wú)狀態(tài)的,也就是連接的有效期只限于當(dāng)前請(qǐng)求,請(qǐng)求內(nèi)容結(jié)束后連接就關(guān)閉了。在這種情況下為了保存用戶(hù)的登錄信息必須使用到Cookie機(jī)制。以JSP/Servlet為例,當(dāng)瀏覽器請(qǐng)求一個(gè)JSP或者是Servlet的頁(yè)面時(shí),應(yīng)用服務(wù)器會(huì)返回一個(gè)參數(shù),名為jsessionid(因不同應(yīng)用服務(wù)器而異),值是一個(gè)較長(zhǎng)的唯一字符串的Cookie,這個(gè)字符串值也就是當(dāng)前訪(fǎng)問(wèn)該站點(diǎn)的會(huì)話(huà)標(biāo)識(shí)。瀏覽器在每訪(fǎng)問(wèn)該站點(diǎn)的其他頁(yè)面時(shí)候都要帶上jsessionid這樣的Cookie信息,應(yīng)用服務(wù)器根據(jù)讀取這個(gè)會(huì)話(huà)標(biāo)識(shí)來(lái)獲取對(duì)應(yīng)的會(huì)話(huà)信息。

    對(duì)于需要用戶(hù)登錄的網(wǎng)站,一般在用戶(hù)登錄成功后會(huì)將用戶(hù)資料保存在服務(wù)器的會(huì)話(huà)中,這樣當(dāng)訪(fǎng)問(wèn)到其他的頁(yè)面時(shí)候,應(yīng)用服務(wù)器根據(jù)瀏覽器送上的Cookie中讀取當(dāng)前請(qǐng)求對(duì)應(yīng)的會(huì)話(huà)標(biāo)識(shí)以獲得對(duì)應(yīng)的會(huì)話(huà)信息,然后就可以判斷用戶(hù)資料是否存在于會(huì)話(huà)信息中,如果存在則允許訪(fǎng)問(wèn)頁(yè)面,否則跳轉(zhuǎn)到登錄頁(yè)面中要求用戶(hù)輸入帳號(hào)和口令進(jìn)行登錄。這就是一般使用JSP開(kāi)發(fā)網(wǎng)站在處理用戶(hù)登錄的比較通用的方法。

    這樣一來(lái),對(duì)于HTTP的客戶(hù)端來(lái)講,如果要訪(fǎng)問(wèn)一個(gè)受保護(hù)的頁(yè)面時(shí)就必須模擬瀏覽器所做的工作,首先就是請(qǐng)求登錄頁(yè)面,然后讀取Cookie值;再次請(qǐng)求登錄頁(yè)面并加入登錄頁(yè)所需的每個(gè)參數(shù);最后就是請(qǐng)求最終所需的頁(yè)面。當(dāng)然在除第一次請(qǐng)求外其他的請(qǐng)求都需要附帶上Cookie信息以便服務(wù)器能判斷當(dāng)前請(qǐng)求是否已經(jīng)通過(guò)驗(yàn)證。說(shuō)了這么多,可是如果你使用httpclient的話(huà),你甚至連一行代碼都無(wú)需增加,你只需要先傳遞登錄信息執(zhí)行登錄過(guò)程,然后直接訪(fǎng)問(wèn)想要的頁(yè)面,跟訪(fǎng)問(wèn)一個(gè)普通的頁(yè)面沒(méi)有任何區(qū)別,因?yàn)轭?lèi)HttpClient已經(jīng)幫你做了所有該做的事情了,太棒了!下面的例子實(shí)現(xiàn)了這樣一個(gè)訪(fǎng)問(wèn)的過(guò)程。


    /*

     * Created on 2003-12-7 by Liudong

     */

    package http.demo;

     

    import org.apache.commons.httpclient.*;

    import org.apache.commons.httpclient.cookie.*;

    import org.apache.commons.httpclient.methods.*;

     

    /**

     * 用來(lái)演示登錄表單的示例

     * @author Liudong

     */

    public class FormLoginDemo {

     

        static final String LOGON_SITE = "localhost";

        static final int    LOGON_PORT = 8080;

       

        public static void main(String[] args) throws Exception{

            HttpClient client = new HttpClient();

            client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);

          

           //模擬登錄頁(yè)面login.jsp->main.jsp

            PostMethod post = new PostMethod("/main.jsp");

            NameValuePair name = new NameValuePair("name", "ld");    

            NameValuePair pass = new NameValuePair("password", "ld");    

            post.setRequestBody(new NameValuePair[]{name,pass});

           int status = client.executeMethod(post);

            System.out.println(post.getResponseBodyAsString());

            post.releaseConnection(); 

          

           //查看cookie信息

            CookieSpec cookiespec = CookiePolicy.getDefaultSpec();

            Cookie[] cookies = cookiespec.match(LOGON_SITE, LOGON_PORT, "/", false, client.getState().getCookies());

           if (cookies.length == 0) {

               System.out.println("None");   

           } else {

               for (int i = 0; i < cookies.length; i++) {

                   System.out.println(cookies[i].toString());   

               }

           }

           //訪(fǎng)問(wèn)所需的頁(yè)面main2.jsp

            GetMethod get = new GetMethod("/main2.jsp");

            client.executeMethod(get);

            System.out.println(get.getResponseBodyAsString());

            get.releaseConnection();

        }

    }

    5. 提交XML格式參數(shù)

    提交XML格式的參數(shù)很簡(jiǎn)單,僅僅是一個(gè)提交時(shí)候的ContentType問(wèn)題,下面的例子演示從文件文件中讀取XML信息并提交給服務(wù)器的過(guò)程,該過(guò)程可以用來(lái)測(cè)試Web服務(wù)。

    import java.io.File;

    import java.io.FileInputStream;

     

    import org.apache.commons.httpclient.HttpClient;

    import org.apache.commons.httpclient.methods.EntityEnclosingMethod;

    import org.apache.commons.httpclient.methods.PostMethod;

     

    /**

     * 用來(lái)演示提交XML格式數(shù)據(jù)的例子

     */

    public class PostXMLClient {

     

        public static void main(String[] args) throws Exception {

            File input = new File(“test.xml”);

            PostMethod post = new PostMethod(“http://localhost:8080/httpclient/xml.jsp”);

            // 設(shè)置請(qǐng)求的內(nèi)容直接從文件中讀取

            post.setRequestBody(new FileInputStream(input));

           

            if (input.length() < Integer.MAX_VALUE)

                post.setRequestContentLength(input.length());

            else            post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);

           

            // 指定請(qǐng)求內(nèi)容的類(lèi)型

            post.setRequestHeader("Content-type", "text/xml; charset=GBK");

           

            HttpClient httpclient = new HttpClient();

            int result = httpclient.executeMethod(post);

            System.out.println("Response status code: " + result);

            System.out.println("Response body: ");

            System.out.println(post.getResponseBodyAsString());

            post.releaseConnection();

        }

    }

    6. 通過(guò)HTTP上傳文件

    httpclient使用了單獨(dú)的一個(gè)HttpMethod子類(lèi)來(lái)處理文件的上傳,這個(gè)類(lèi)就是MultipartPostMethod,該類(lèi)已經(jīng)封裝了文件上傳的細(xì)節(jié),我們要做的僅僅是告訴它我們要上傳文件的全路徑即可,下面的代碼片段演示如何使用這個(gè)類(lèi)。

    MultipartPostMethod filePost = new MultipartPostMethod(targetURL);

    filePost.addParameter("fileName", targetFilePath);

    HttpClient client = new HttpClient();

    //由于要上傳的文件可能比較大,因此在此設(shè)置最大的連接超時(shí)時(shí)間

    client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);

    int status = client.executeMethod(filePost);


    上面代碼中,targetFilePath即為要上傳的文件所在的路徑。

    7. 訪(fǎng)問(wèn)啟用認(rèn)證的頁(yè)面

    我們經(jīng)常會(huì)碰到這樣的頁(yè)面,當(dāng)訪(fǎng)問(wèn)它的時(shí)候會(huì)彈出一個(gè)瀏覽器的對(duì)話(huà)框要求輸入用戶(hù)名和密碼后方可,這種用戶(hù)認(rèn)證的方式不同于我們?cè)谇懊娼榻B的基于表單的用戶(hù)身份驗(yàn)證。這是HTTP的認(rèn)證策略,httpclient支持三種認(rèn)證方式包括:基本、摘要以及NTLM認(rèn)證。其中基本認(rèn)證最簡(jiǎn)單、通用但也最不安全;摘要認(rèn)證是在HTTP 1.1中加入的認(rèn)證方式,而NTLM則是微軟公司定義的而不是通用的規(guī)范,最新版本的NTLM是比摘要認(rèn)證還要安全的一種方式。

    下面例子是從httpclient的CVS服務(wù)器中下載的,它簡(jiǎn)單演示如何訪(fǎng)問(wèn)一個(gè)認(rèn)證保護(hù)的頁(yè)面:


    import org.apache.commons.httpclient.HttpClient;

    import org.apache.commons.httpclient.UsernamePasswordCredentials;

    import org.apache.commons.httpclient.methods.GetMethod;

     

    public class BasicAuthenticationExample {

        public BasicAuthenticationExample() {

        }

        public static void main(String[] args) throws Exception {

            HttpClient client = new HttpClient();

            client.getState().setCredentials(

                "www.verisign.com",

                "realm",

                new UsernamePasswordCredentials("username", "password")

            );

            GetMethod get = new GetMethod("https://www.verisign.com/products/index.html");

            get.setDoAuthentication( true );

            int status = client.executeMethod( get );

            System.out.println(status+""+ get.getResponseBodyAsString());

            get.releaseConnection();

        }

    }

    8. 多線(xiàn)程模式下使用httpclient

    多線(xiàn)程同時(shí)訪(fǎng)問(wèn)httpclient,例如同時(shí)從一個(gè)站點(diǎn)上下載多個(gè)文件。對(duì)于同一個(gè)HttpConnection同一個(gè)時(shí)間只能有一個(gè)線(xiàn)程訪(fǎng)問(wèn),為了保證多線(xiàn)程工作環(huán)境下不產(chǎn)生沖突,httpclient使用了一個(gè)多線(xiàn)程連接管理器的類(lèi):MultiThreadedHttpConnectionManager,要使用這個(gè)類(lèi)很簡(jiǎn)單,只需要在構(gòu)造HttpClient實(shí)例的時(shí)候傳入即可,代碼如下:

    MultiThreadedHttpConnectionManager connectionManager =

       new MultiThreadedHttpConnectionManager();

    HttpClient client = new HttpClient(connectionManager);

    以后盡管訪(fǎng)問(wèn)client實(shí)例即可。

    posted @ 2011-04-22 12:38 飛飛 閱讀(528) | 評(píng)論 (0)編輯 收藏


    import org.apache.commons.httpclient.methods.PostMethod;


    public class UTF8PostMethod extends PostMethod
    {
       
        public static final String ENCODE_UTF8 = "UTF-8";
       
        /**
         * 默認(rèn)構(gòu)造函數(shù)
         * @param url    地址
         */
        public UTF8PostMethod(String url)
        {
            super(url);
        }

        /* (non-Javadoc)
         * @see org.apache.commons.httpclient.methods.EntityEnclosingMethod#getRequestCharSet()
         */
        @Override
        public String getRequestCharSet()
        {
            return ENCODE_UTF8;
        }

        /* (non-Javadoc)
         * @see org.apache.commons.httpclient.HttpMethodBase#getResponseCharSet()
         */
        @Override
        public String getResponseCharSet()
        {
            return ENCODE_UTF8;
        }
    }


    package com.org.softwore;

    import org.apache.commons.httpclient.methods.GetMethod;

    public class UTF8GetMethod extends GetMethod {
     public static final String ENCODE_UTF8 = "UTF-8";

     /**
      * 默認(rèn)構(gòu)造函數(shù)
      *
      * @param url
      *            地址
      */
     public UTF8GetMethod(String url) {
      super(url);
     }

     /*
      * (non-Javadoc)
      *
      * @see
      * org.apache.commons.httpclient.methods.EntityEnclosingMethod#getRequestCharSet
      * ()
      */
     @Override
     public String getRequestCharSet() {
      return ENCODE_UTF8;
     }

     /*
      * (non-Javadoc)
      *
      * @see org.apache.commons.httpclient.HttpMethodBase#getResponseCharSet()
      */
     @Override
     public String getResponseCharSet() {
      return ENCODE_UTF8;
     }
    }




    測(cè)試使用!

    HttpMethod method = null;
            try {
                HttpClient client = new HttpClient();
                method = new UTF8PostMethod(
                        "http://.........");
                client.executeMethod(method);
                if (method.getStatusCode() == HttpStatus.SC_OK) {
                    String response = method.getResponseBodyAsString();
                    System.out.println(response);
                }

            } catch (HttpException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            } finally {
                if (method != null) {
                    method.releaseConnection();
                }
            }

    posted @ 2011-04-22 11:00 飛飛 閱讀(1068) | 評(píng)論 (0)編輯 收藏

     

    鼎鼎大名的Spring框架3.0版在12月5日由其作者之一——Juergen Hoeller先生在博客里宣告問(wèn)世,并命為里程碑版,給Spring粉絲們帶來(lái)了震撼的快感。筆者即開(kāi)“快車(chē)”拉了兩個(gè)包回來(lái),遺憾的是參考文檔至今還沒(méi)有出來(lái)(僅有API文檔),這為學(xué)習(xí)Spring 3.0帶來(lái)了非常大的困難,但沒(méi)有阻擋筆者對(duì)新產(chǎn)品的興趣。

        Spring之父Rod Johnson先生早在2003年就預(yù)言EJB將死(觀(guān)點(diǎn)頗具爭(zhēng)議),攻擊EJB之臃腫是在虐待程序員。然而EJB 3.0出來(lái)后幾乎宣判Spring死刑,但自2.0版以后Spring火爆程度已經(jīng)超過(guò)EJB,兩者的爭(zhēng)斗至今仍不停息,這也是Spring 3.0連文檔還沒(méi)有整理出來(lái)就匆匆推出的原因。當(dāng)然,Spring與EJB有很多各自獨(dú)特優(yōu)勢(shì)之處,例如EJB的分布式運(yùn)算、標(biāo)準(zhǔn)規(guī)范,Spring的IoC、AOP切面編程、偶合集成、MVC等等,取各自之長(zhǎng)在企業(yè)中應(yīng)用如虎添翼。Spring目前已經(jīng)加入了J2EE規(guī)范,J2EE世界將更加精彩......

        或許是用膩了Struts1那死板的WEB框架,才對(duì)Spring MVC愛(ài)不釋手,尤其是2.5版本以后,支持全注解配置方式,已經(jīng)使很久沒(méi)有再寫(xiě)過(guò)xml文件了。

        3.0版是完全兼容2.5,因此了解2.5版的@MVC則更容易接受。正如Arjen Poutsma小伙子在他的博客里說(shuō)的那樣,3.0時(shí)代將集中致力于表述性狀態(tài)轉(zhuǎn)移(REST,希望我沒(méi)有翻譯錯(cuò),金山詞霸翻譯為“休息”)的網(wǎng)絡(luò)服務(wù)和更容易的網(wǎng)絡(luò)編程。的確增加了更多的控制器類(lèi)型,并增強(qiáng)了SOAP/WSDL/WS這些基于分布式體系結(jié)構(gòu)。

    先回憶下2.5注解方式的@MVC,來(lái)一個(gè)示例:

    @Controller
    public class ArticleController{

      @RequestMapping("/articleView")
       public String getArticle(@RequestParam("id") String id, HttpServletRequest request){
        request.setAttribute("article", service.find(Article.class, id));
        return "articleView";
       }

    }

        ArticleController沒(méi)有實(shí)現(xiàn)任何接口,是一個(gè)最普通不過(guò)的pojo,如果瀏覽器來(lái)了articleView.do?id=xxx這個(gè)請(qǐng)求,Spring會(huì)找到getArticle()這個(gè)方法,該方法第一個(gè)參數(shù)綁定到了URL上的請(qǐng)求參數(shù),第二個(gè)是J2EE標(biāo)準(zhǔn)的request對(duì)象(可見(jiàn)Spring MVC是非侵入式的,不像變態(tài)的Struts2),事實(shí)上還可以給定HttpServletResponse,ModelMap,甚至自己的類(lèi)型,Spring都會(huì)為你將值傳入進(jìn)來(lái)。通過(guò)一個(gè)邏輯層service組件根據(jù)id參數(shù)值去底層查找Article對(duì)象,并放入request作用域中,最后返回的是面頁(yè)視圖名,這個(gè)例子中是返回到articleView.jsp中。

        上例再變通下:

    @Controller
    public class ArticleController{

      @RequestMapping("/articleView_*")
       public String getArticle(HttpServletRequest request){

        String id = StringUtil.getParam(request.getRequestURI(),"articleView_*");
        request.setAttribute("article", service.find(Article.class, id));
        return "articleView";
       }

    }

        對(duì)于articleView_aaa.do,articleView_bbbb.do,articleView_c5h8j2.do,articleView_xxx.do,這樣的請(qǐng)求都會(huì)由getArticle()這個(gè)方法來(lái)應(yīng)付,是不是很有意思?

        Spring 3.0增加了一個(gè)@ PathVariable注解來(lái)支持可變的請(qǐng)求路徑,將上面的代碼在3.0版中再變通下:

    @Controller
    public class ArticleController{

      @RequestMapping("/articleView/${id}")   //可以接受articleView/aaa.do,articleView/xxx.do...
       public String getArticle(@PathVariable String id, HttpServletRequest request){
        request.setAttribute("article", service.find(Article.class, id));
        return "articleView";
       }

    }

    再變得復(fù)雜些:

    @Controller
    public class ArticleController{

      @RequestMapping("/articleList/${pageSize}/channel/*/category/${id}")   

       public String getArticles((@PathVariable Integer pageSize, @PathVariable int id, HttpServletRequest request){
        Integer channelId = StringUtil.getParam(request.getRequestURI(),"channel/*/");
        request.setAttribute("articles", service.findScroll(Article.class, pageSize,50,"channel=? and category=?",new Object[]{channelId,id}));
        
        return "articleList";
       }

    }

        它已經(jīng)靈活到URL地址完全可以自己隨意編制。

        根據(jù)內(nèi)容協(xié)商制的視圖解析機(jī)制:

        2.5版是由@MVC控制器來(lái)決定視圖解析器,3.0版將變得更加靈活,似乎可以通過(guò)擴(kuò)展名來(lái)轉(zhuǎn)到不同的解析器中,例如請(qǐng)求一個(gè).pdf文件將是如何效果呢?3.0版都會(huì)帶來(lái)不可思議的模式。

        HTTP方法的轉(zhuǎn)換:

        先看前臺(tái)頁(yè)面一段Html代碼

    <form:form method="delete">  
    <p class="submit"><input type="submit" value="Delete Pet"/></p> 
    </form:form>

        HTTP規(guī)范中form表單只有兩種方法——POST和GET,而3.0做了一個(gè)過(guò)濾器,可以轉(zhuǎn)換這些方法至四種——GET, PUT, POST, 和 DELETE。控制器接受請(qǐng)求:

    @Controller("/deleteArticle")
    public class ArticleController{

      de style="line-height: 28px; ">@RequestMappingde>de style="line-height: 28px; ">(method = RequestMethod.DELETE)
    de>   public String deleteArticle(@PathVariable String id, HttpServletRequest request){
        service.delete(Article.class, id);
        return "message";
       }

    }
        3.0版僅在MVC子集中就增加了很多新特性,如果在IoC、AOP等等其它子集所有的變革,絕對(duì)可以稱(chēng)得上Srping創(chuàng)始人所述的里程碑版本。3.0版使用的注解列表如下:

    ? @Autowired
    ? @Component
    ? @Controller
    ? @InitBinder
    ? @ManagedAttribute
    ? @ManagedOperation
    ? @ManagedOperationParameters
    ? @ManagedOperationParameter
    ? @ManagedResource
    ? @PathVariable
    ? @PostConstruct
    ? @PreDestroy
    ? @Repository
    ? @RequestMapping
    ? @Required
    ? @Resource
    ? @Service
    ? @Transactional
        目前Spring 3版本已經(jīng)到了M2,應(yīng)該是M3完成后將推出最終正式版本,我想很快會(huì)來(lái)臨,按照Spring的創(chuàng)始人羅德.約翰遜的預(yù)言,未來(lái)J2EE應(yīng)用中Spring+Tomcat將占主導(dǎo)地位,是否引起爭(zhēng)議,筆者不敢點(diǎn)評(píng),不過(guò)Oracle收購(gòu)Sun后,Java社區(qū)將是如何,還無(wú)從知曉,似乎羅德.約翰遜對(duì)這宗收購(gòu)案也有些緊張,因?yàn)镺racle不像Sun的第一個(gè)談判者IBM那樣有過(guò)開(kāi)放技術(shù)的先例(可以回憶下IBM早期的主板總線(xiàn)開(kāi)放掀起的兼容機(jī)潮至今波濤不熄)。目前國(guó)內(nèi)對(duì)新東西消化尚慢,我到圖書(shū)城看了下,Spring 2.5的資料都很難找到。且很多企業(yè)都是抱著Struts1.x在做開(kāi)發(fā),盡管筆者這樣說(shuō)會(huì)引來(lái)很多爭(zhēng)議,但Struts1時(shí)代的滅亡只是時(shí)間問(wèn)題。Struts2雖然改進(jìn)了很多,依筆者看,與Spring MVC相比仍有諸多的不足,尤其看不慣那種變態(tài)的侵入模式,看看它把HttpServletRequest、HttpSession、HttpServletResponse等servlet標(biāo)準(zhǔn)組件干成什么樣?開(kāi)源時(shí)代,至少我不愿意接受那種變態(tài)的潛規(guī)則。

        筆者早先常用Struts1.x框架,它搭配了一套自己的ActionForm,使得編程工作量增加,雖然可以變通使用自己的Pojo,但對(duì)于沒(méi)有掌握J(rèn)2EE底層工具類(lèi)(BeanUtil)的開(kāi)發(fā)人員來(lái)說(shuō),其類(lèi)型匹配是非常復(fù)雜的事。事實(shí)上Spring MVC早在1.x版本就完全使用自己的pojo來(lái)對(duì)應(yīng)表單的填充,配上屬性編輯器,可以解決類(lèi)型轉(zhuǎn)換問(wèn)題,完全實(shí)現(xiàn)領(lǐng)域模型驅(qū)動(dòng)的設(shè)計(jì)模式。由于MVC層的控制器也是Spring容器的Bean而已,因此對(duì)整個(gè)項(xiàng)目的控制、擴(kuò)展變得非常容易。同時(shí)上文也順便點(diǎn)評(píng)了Struts2,可見(jiàn)Spring MVC在各類(lèi)MVC框架的優(yōu)勢(shì)所在。本身羅德.約翰遜先生是設(shè)計(jì)模式高手,一個(gè)優(yōu)秀的框架給我們帶來(lái)的遠(yuǎn)遠(yuǎn)不只是開(kāi)發(fā)效率,還有更先進(jìn)的開(kāi)發(fā)模式和理念...

        筆者對(duì)Spring框架研究膚淺,待日后了解掌握更多時(shí)會(huì)常在博客中述之。

    posted @ 2011-04-21 11:02 飛飛 閱讀(880) | 評(píng)論 (0)編輯 收藏

    從4個(gè)層面分析這部分實(shí)現(xiàn): 
    1. iBatis的基本實(shí)現(xiàn)
    2. 基于事務(wù)的iBatis的基本實(shí)現(xiàn)
    3. 基于事務(wù)的Spring+iBatis實(shí)現(xiàn)
    4. 基于回調(diào)方式的Spring+iBatis實(shí)現(xiàn)

    1.iBatis的基本實(shí)現(xiàn)

    iBatis通過(guò)SqlMapClient提供了一組方法用于批處理實(shí)現(xiàn):
    1. startBatch() 開(kāi)始批處理
    2. executeBatch() 執(zhí)行批處理

    代碼如下:
    Java代碼 復(fù)制代碼 收藏代碼
    1. public void create(List<Reply> replyList) {   
    2.   
    3.     try {   
    4.         // 開(kāi)始批處理   
    5.         sqlMapClient.startBatch();   
    6.   
    7.         for (Reply reply: replyList) {   
    8.             // 插入操作   
    9.             sqlMapClient.insert("Reply.create", reply);   
    10.         }   
    11.         // 執(zhí)行批處理   
    12.         sqlMapClient.executeBatch();   
    13.   
    14.     } catch (Exception e) {   
    15.         e.printStackTrace();   
    16.     }   
    17. }  

    這是基于iBatis的最基本實(shí)現(xiàn),如果你一步一步debug,你會(huì)發(fā)現(xiàn):其實(shí),數(shù)據(jù)庫(kù)已經(jīng)執(zhí)行了插入操作!
    因此,除了這兩個(gè)核心方法外,你還需要開(kāi)啟事務(wù)支持。否則,上述代碼只不過(guò)是個(gè)空架子!

    2.基于事務(wù)的iBatis的基本實(shí)現(xiàn)
    事務(wù)處理:
    1. startTransaction() 開(kāi)始事務(wù)
    2. commitTransaction() 提交事務(wù)
    3. endTransaction() 結(jié)束事務(wù)


    我們以insert操作為例,把它們結(jié)合到一起:
    Java代碼 復(fù)制代碼 收藏代碼
    1. public void create(List<Reply> replyList) {   
    2.   
    3.     try {   
    4.         // 開(kāi)始事務(wù)   
    5.         sqlMapClient.startTransaction();   
    6.         // 開(kāi)始批處理   
    7.         sqlMapClient.startBatch();   
    8.   
    9.         for (Reply reply: replyList) {   
    10.             // 插入操作   
    11.             sqlMapClient.insert("Reply.create", reply);   
    12.         }   
    13.         // 執(zhí)行批處理   
    14.         sqlMapClient.executeBatch();   
    15.   
    16.         // 提交事務(wù)   
    17.         sqlMapClient.commitTransaction();   
    18.   
    19.     } catch (Exception e) {   
    20.         e.printStackTrace();   
    21.     } finally {     
    22.              try {   
    23.             // 結(jié)束事務(wù)   
    24.             sqlMapClient.endTransaction();   
    25.                 } catch (SQLException e) {   
    26.                          e.printStackTrace();   
    27.                      }   
    28.     }     
    29. }  

    replyList是一個(gè)List,要把這個(gè)List插入到數(shù)據(jù)庫(kù),就需要經(jīng)過(guò)這三個(gè)步驟:
    1. 開(kāi)始批處理 startBatch()
    2. 插入      insert()
    3. 執(zhí)行批處理 executeBatch()

    如果要在Spring+iBatis中進(jìn)行批處理實(shí)現(xiàn),需要注意使用同一個(gè)sqlMapClient!同時(shí),將提交事務(wù)的工作交給Spring統(tǒng)一處理!

    3.基于事務(wù)的Spring+iBatis實(shí)現(xiàn)
    Java代碼 復(fù)制代碼 收藏代碼
    1. public void create(List<Reply> replyList) {   
    2.     if (!CollectionUtils.isEmpty(replyList)) {   
    3.         // 注意使用同一個(gè)SqlMapClient會(huì)話(huà)   
    4.         SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();   
    5.   
    6.         try {   
    7.             // 開(kāi)始事務(wù)   
    8.             sqlMapClient.startTransaction();   
    9.             // 開(kāi)始批處理   
    10.             sqlMapClient.startBatch();   
    11.             for (Reply reply : replyList) {   
    12.                 // 插入操作   
    13.                 sqlMapClient.insert("Reply.create", reply);   
    14.             }   
    15.   
    16.             // 執(zhí)行批處理   
    17.             sqlMapClient.executeBatch();   
    18.             // 提交事務(wù) 交給Spring統(tǒng)一控制   
    19.             // sqlMapClient.commitTransaction();   
    20.   
    21.         } catch (Exception e) {   
    22.             e.printStackTrace();   
    23.         } finally {     
    24.                  try {   
    25.                 // 結(jié)束事務(wù)   
    26.                 sqlMapClient.endTransaction();   
    27.                     } catch (SQLException e) {   
    28.                              e.printStackTrace();   
    29.                          }   
    30.         }     
    31.     }   
    32. }  

    注意使用同一個(gè)sqlMapClient:
    SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();
    如果直接sqlMapClientTemplate執(zhí)行insert()方法,將會(huì)造成異常!

    想想,還有什么問(wèn)題?其實(shí)問(wèn)題很明顯,雖然解決了批處理實(shí)現(xiàn)的問(wèn)題,卻造成了事務(wù)代碼入侵的新問(wèn)題。 這么做,有點(diǎn)惡心!
    除此之外,異常的處理也很惡心,不能夠簡(jiǎn)單的包裝為 DataAccessException 就無(wú)法被Spring當(dāng)作統(tǒng)一的數(shù)據(jù)庫(kù)操作異常做處理。


    4.基于回調(diào)方式的Spring+iBatis實(shí)現(xiàn)
    如果觀(guān)察過(guò)Spring的源代碼,你一定知道,Spring為了保持事務(wù)統(tǒng)一控制,在實(shí)現(xiàn)ORM框架時(shí)通常都采用了回調(diào)模式,從而避免了事務(wù)代碼入侵的可能!
    修改后的代碼如下:
    Java代碼 復(fù)制代碼 收藏代碼
    1. @SuppressWarnings("unchecked")   
    2. public void create(final List<Reply> replyList) {   
    3.     // 執(zhí)行回調(diào)   
    4.     sqlMapClientTemplate.execute(new SqlMapClientCallback() {   
    5.         // 實(shí)現(xiàn)回調(diào)接口   
    6.         public Object doInSqlMapClient(SqlMapExecutor executor)   
    7.                 throws SQLException {   
    8.             // 開(kāi)始批處理   
    9.             executor.startBatch();   
    10.             for (Reply reply : replyList) {   
    11.                 // 插入操作   
    12.                 executor.insert("Reply.create", reply);   
    13.   
    14.             }   
    15.             // 執(zhí)行批處理   
    16.             executor.executeBatch();   
    17.   
    18.             return null;   
    19.   
    20.         }   
    21.     });   
    22.   
    23. }  

    注意,待遍歷的參數(shù)replyList需要加入final標(biāo)識(shí)!即,待遍歷對(duì)象不能修改!
    引用
    public void create(final List<Reply> replyList)

    這樣做,就將事務(wù)處理的控制權(quán)完全交給了Spring!
    簡(jiǎn)述:
    1. SqlMapClientCallback 回調(diào)接口
    2. doInSqlMapClient(SqlMapExecutor executor) 回調(diào)實(shí)現(xiàn)方法
    3. DataAccessException 最終可能拋出的異常
    posted @ 2011-04-21 10:15 飛飛 閱讀(961) | 評(píng)論 (0)編輯 收藏

    Log4J的配置文件(Configuration File)就是用來(lái)設(shè)置記錄器的級(jí)別、存放器和布局的,它可接key=value格式的設(shè)置或xml格式的設(shè)置信息。通過(guò)配置,可以創(chuàng)建出Log4J的運(yùn)行環(huán)境。

    1. 配置文件
    Log4J配置文件的基本格式如下:

    #配置根Logger
    log4j.rootLogger  =   [ level ]   ,  appenderName1 ,  appenderName2 ,  …

    #配置日志信息輸出目的地Appender
    log4j.appender.appenderName  =  fully.qualified.name.of.appender.class
      log4j.appender.appenderName.option1  =  value1
      …
      log4j.appender.appenderName.optionN  =  valueN

    #配置日志信息的格式(布局)
    log4j.appender.appenderName.layout  =  fully.qualified.name.of.layout.class
      log4j.appender.appenderName.layout.option1  =  value1
      …
      log4j.appender.appenderName.layout.optionN  =  valueN 

    其中 [level] 是日志輸出級(jí)別,共有5級(jí):


    FATAL       0 
    ERROR      3 
    WARN       4 
    INFO         6 
    DEBUG      7
     
    Appender 為日志輸出目的地,Log4j提供的appender有以下幾種:
    org.apache.log4j.ConsoleAppender(控制臺(tái)),
    org.apache.log4j.FileAppender(文件),
    org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個(gè)日志文件),
    org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件),
    org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)
    Layout:日志輸出格式,Log4j提供的layout有以下幾種:


    org.apache.log4j.HTMLLayout(以HTML表格形式布局),
    org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
    org.apache.log4j.SimpleLayout(包含日志信息的級(jí)別和信息字符串),
    org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線(xiàn)程、類(lèi)別等等信息)

    打印參數(shù): Log4J采用類(lèi)似C語(yǔ)言中的printf函數(shù)的打印格式格式化日志信息,如下:


        %m   輸出代碼中指定的消息
      %p   輸出優(yōu)先級(jí),即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL
      %r   輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù)
      %c   輸出所屬的類(lèi)目,通常就是所在類(lèi)的全名
      %t   輸出產(chǎn)生該日志事件的線(xiàn)程名
      %n   輸出一個(gè)回車(chē)換行符,Windows平臺(tái)為“\r\n”,Unix平臺(tái)為“\n”
      %d   輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},輸出類(lèi)似:2002年10月18日  22 : 10 : 28 , 921 
      %l   輸出日志事件的發(fā)生位置,包括類(lèi)目名、發(fā)生的線(xiàn)程,以及在代碼中的行數(shù)。舉例:Testlog4.main(TestLog4.java: 10 ) 

    2. 在代碼中初始化Logger:
    1)在程序中調(diào)用BasicConfigurator.configure()方法:給根記錄器增加一個(gè)ConsoleAppender,輸出格式通過(guò)PatternLayout設(shè)為"%-4r [%t] %-5p %c %x - %m%n",還有根記錄器的默認(rèn)級(jí)別是Level.DEBUG.
    2)配置放在文件里,通過(guò)命令行參數(shù)傳遞文件名字,通過(guò)PropertyConfigurator.configure(args[x])解析并配置;
    3)配置放在文件里,通過(guò)環(huán)境變量傳遞文件名等信息,利用log4j默認(rèn)的初始化過(guò)程解析并配置;
    4)配置放在文件里,通過(guò)應(yīng)用服務(wù)器配置傳遞文件名等信息,利用一個(gè)特殊的servlet來(lái)完成配置。

    3. 為不同的 Appender 設(shè)置日志輸出級(jí)別:
    當(dāng)調(diào)試系統(tǒng)時(shí),我們往往注意的只是異常級(jí)別的日志輸出,但是通常所有級(jí)別的輸出都是放在一個(gè)文件里的,如果日志輸出的級(jí)別是BUG!?那就慢慢去找吧。
    這時(shí)我們也許會(huì)想要是能把異常信息單獨(dú)輸出到一個(gè)文件里該多好啊。當(dāng)然可以,Log4j已經(jīng)提供了這樣的功能,我們只需要在配置中修改Appender的Threshold 就能實(shí)現(xiàn),比如下面的例子:

    [配置文件]


     ### set log levels ###
    log4j.rootLogger = debug ,  stdout ,  D ,  E

    ### 輸出到控制臺(tái) ###
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n

    ### 輸出到日志文件 ###
    log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File = logs/log.log
    log4j.appender.D.Append = true
    log4j.appender.D.Threshold = DEBUG ## 輸出DEBUG級(jí)別以上的日志
    log4j.appender.D.layout = org.apache.log4j.PatternLayout
    log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

    ### 保存異常信息到單獨(dú)文件 ###
    log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File = logs/error.log ## 異常日志文件名
    log4j.appender.D.Append = true
    log4j.appender.D.Threshold = ERROR ## 只輸出ERROR級(jí)別以上的日志!!!
    log4j.appender.D.layout = org.apache.log4j.PatternLayout
    log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    [代碼中使用]


      public   class  TestLog4j   {
         public   static   void  main(String[] args)   {
            PropertyConfigurator.configure( " D:/Code/conf/log4j.properties " );
            Logger logger  =  Logger.getLogger(TestLog4j. class );
            logger.debug( " debug " );
            logger.error( " error " );
        }
    }

    運(yùn)行一下,看看異常信息是不是保存在了一個(gè)單獨(dú)的文件error.log中

    log4j.properties 使用
    一.參數(shù)意義說(shuō)明
    輸出級(jí)別的種類(lèi)
    ERROR、WARN、INFO、DEBUG
    ERROR 為嚴(yán)重錯(cuò)誤 主要是程序的錯(cuò)誤
    WARN 為一般警告,比如session丟失
    INFO 為一般要顯示的信息,比如登錄登出
    DEBUG 為程序的調(diào)試信息
    配置日志信息輸出目的地
    log4j.appender.appenderName = fully.qualified.name.of.appender.class
    1.org.apache.log4j.ConsoleAppender(控制臺(tái))
    2.org.apache.log4j.FileAppender(文件)
    3.org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個(gè)日志文件)
    4.org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件)
    5.org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)
    配置日志信息的格式
    log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
    1.org.apache.log4j.HTMLLayout(以HTML表格形式布局),
    2.org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
    3.org.apache.log4j.SimpleLayout(包含日志信息的級(jí)別和信息字符串),
    4.org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線(xiàn)程、類(lèi)別等等信息)
    控制臺(tái)選項(xiàng)
    Threshold=DEBUG:指定日志消息的輸出最低層次。
    ImmediateFlush=true:默認(rèn)值是true,意謂著所有的消息都會(huì)被立即輸出。
    Target=System.err:默認(rèn)情況下是:System.out,指定輸出控制臺(tái)
    FileAppender 選項(xiàng)
    Threshold=DEBUF:指定日志消息的輸出最低層次。
    ImmediateFlush=true:默認(rèn)值是true,意謂著所有的消息都會(huì)被立即輸出。
    File=mylog.txt:指定消息輸出到mylog.txt文件。
    Append=false:默認(rèn)值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內(nèi)容。
    RollingFileAppender 選項(xiàng)
    Threshold=DEBUG:指定日志消息的輸出最低層次。
    ImmediateFlush=true:默認(rèn)值是true,意謂著所有的消息都會(huì)被立即輸出。
    File=mylog.txt:指定消息輸出到mylog.txt文件。
    Append=false:默認(rèn)值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內(nèi)容。
    MaxFileSize=100KB: 后綴可以是KB, MB 或者是 GB. 在日志文件到達(dá)該大小時(shí),將會(huì)自動(dòng)滾動(dòng),即將原來(lái)的內(nèi)容移到mylog.log.1文件。
    MaxBackupIndex=2:指定可以產(chǎn)生的滾動(dòng)文件的最大數(shù)。
    log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
    日志信息格式中幾個(gè)符號(hào)所代表的含義:
     -X號(hào): X信息輸出時(shí)左對(duì)齊;
     %p: 輸出日志信息優(yōu)先級(jí),即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL,
     %d: 輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類(lèi)似:2002年10月18日 22:10:28,921
     %r: 輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù)
     %c: 輸出日志信息所屬的類(lèi)目,通常就是所在類(lèi)的全名
     %t: 輸出產(chǎn)生該日志事件的線(xiàn)程名
     %l: 輸出日志事件的發(fā)生位置,相當(dāng)于%C.%M(%F:%L)的組合,包括類(lèi)目名、發(fā)生的線(xiàn)程,以及在代碼中的行數(shù)。舉例:Testlog4.main (TestLog4.java:10)
     %x: 輸出和當(dāng)前線(xiàn)程相關(guān)聯(lián)的NDC(嵌套診斷環(huán)境),尤其用到像java servlets這樣的多客戶(hù)多線(xiàn)程的應(yīng)用中。
     %%: 輸出一個(gè)"%"字符
     %F: 輸出日志消息產(chǎn)生時(shí)所在的文件名稱(chēng)
     %L: 輸出代碼中的行號(hào)
     %m: 輸出代碼中指定的消息,產(chǎn)生的日志具體信息
     %n: 輸出一個(gè)回車(chē)換行符,Windows平臺(tái)為"\r\n",Unix平臺(tái)為"\n"輸出日志信息換行
     可以在%與模式字符之間加上修飾符來(lái)控制其最小寬度、最大寬度、和文本的對(duì)齊方式。如:
     1)%20c:指定輸出category的名稱(chēng),最小的寬度是20,如果category的名稱(chēng)小于20的話(huà),默認(rèn)的情況下右對(duì)齊。
     2)%-20c:指定輸出category的名稱(chēng),最小的寬度是20,如果category的名稱(chēng)小于20的話(huà),"-"號(hào)指定左對(duì)齊。
     3)%.30c:指定輸出category的名稱(chēng),最大的寬度是30,如果category的名稱(chēng)大于30的話(huà),就會(huì)將左邊多出的字符截掉,但小于30的話(huà)也不會(huì)有空格。
     4)%20.30c:如果category的名稱(chēng)小于20就補(bǔ)空格,并且右對(duì)齊,如果其名稱(chēng)長(zhǎng)于30字符,就從左邊較遠(yuǎn)輸出的字符截掉。
    二.文件配置Sample1
    log4j.rootLogger=DEBUG,A1,R
    #log4j.rootLogger=INFO,A1,R
    # ConsoleAppender 輸出
    log4j.appender.A1=org.apache.log4j.ConsoleAppender
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n
    # File 輸出 一天一個(gè)文件,輸出路徑可以定制,一般在根路徑下
    log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
    log4j.appender.R.File=blog_log.txt
    log4j.appender.R.MaxFileSize=500KB
    log4j.appender.R.MaxBackupIndex=10
    log4j.appender.R.layout=org.apache.log4j.PatternLayout
    log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n
    文件配置Sample2
    下面給出的Log4J配置文件實(shí)現(xiàn)了輸出到控制臺(tái),文件,回滾文件,發(fā)送日志郵件,輸出到數(shù)據(jù)庫(kù)日志表,自定義標(biāo)簽等全套功能。
    log4j.rootLogger=DEBUG,CONSOLE,A1,im
    #DEBUG,CONSOLE,FILE,ROLLING_FILE,MAIL,DATABASE
    log4j.addivity.org.apache=true
    ###################
    # Console Appender
    ###################
    log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    log4j.appender.Threshold=DEBUG
    log4j.appender.CONSOLE.Target=System.out
    log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
    #log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n
    #####################
    # File Appender
    #####################
    log4j.appender.FILE=org.apache.log4j.FileAppender
    log4j.appender.FILE.File=file.log
    log4j.appender.FILE.Append=false
    log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
    # Use this layout for LogFactor 5 analysis
    ########################
    # Rolling File
    ########################
    log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
    log4j.appender.ROLLING_FILE.Threshold=ERROR
    log4j.appender.ROLLING_FILE.File=rolling.log
    log4j.appender.ROLLING_FILE.Append=true
    log4j.appender.ROLLING_FILE.MaxFileSize=10KB
    log4j.appender.ROLLING_FILE.MaxBackupIndex=1
    log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
    ####################
    # Socket Appender
    ####################
    log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
    log4j.appender.SOCKET.RemoteHost=localhost
    log4j.appender.SOCKET.Port=5001
    log4j.appender.SOCKET.LocationInfo=true
    # Set up for Log Facter 5
    log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
    log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
    ########################
    # Log Factor 5 Appender
    ########################
    log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
    log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
    ########################
    # SMTP Appender
    #######################
    log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
    log4j.appender.MAIL.Threshold=FATAL
    log4j.appender.MAIL.BufferSize=10
    log4j.appender.MAIL.From=chenyl@yeqiangwei.com
    log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
    log4j.appender.MAIL.Subject=Log4J Message
    log4j.appender.MAIL.To=chenyl@yeqiangwei.com
    log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
    log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
    ########################
    # JDBC Appender
    #######################
    log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
    log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
    log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
    log4j.appender.DATABASE.user=root
    log4j.appender.DATABASE.password=
    log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
    log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
    log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
    log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
    log4j.appender.A1.File=SampleMessages.log4j
    log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
    log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
    ###################
    #自定義Appender
    ###################
    log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
    log4j.appender.im.host = mail.cybercorlin.net
    log4j.appender.im.username = username
    log4j.appender.im.password = password
    log4j.appender.im.recipient = corlin@yeqiangwei.com
    log4j.appender.im.layout=org.apache.log4j.PatternLayout
    log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
    三.高級(jí)使用
    實(shí)驗(yàn)?zāi)康模?br />  1.把FATAL級(jí)錯(cuò)誤寫(xiě)入2000NT日志
     2. WARN,ERROR,F(xiàn)ATAL級(jí)錯(cuò)誤發(fā)送email通知管理員
     3.其他級(jí)別的錯(cuò)誤直接在后臺(tái)輸出
    實(shí)驗(yàn)步驟:
     輸出到2000NT日志
     1.把Log4j壓縮包里的NTEventLogAppender.dll拷到WINNT\SYSTEM32目錄下
     2.寫(xiě)配置文件log4j.properties
    # 在2000系統(tǒng)日志輸出
     log4j.logger.NTlog=FATAL, A8
     # APPENDER A8
     log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender
     log4j.appender.A8.Source=JavaTest
     log4j.appender.A8.layout=org.apache.log4j.PatternLayout
     log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
    3.調(diào)用代碼:
     Logger logger2 = Logger.getLogger("NTlog"); //要和配置文件中設(shè)置的名字相同
     logger2.debug("debug!!!");
     logger2.info("info!!!");
     logger2.warn("warn!!!");
     logger2.error("error!!!");
     //只有這個(gè)錯(cuò)誤才會(huì)寫(xiě)入2000日志
     logger2.fatal("fatal!!!");
    發(fā)送email通知管理員:
     1. 首先下載JavaMail和JAF,
      http://java.sun.com/j2ee/ja/javamail/index.html
      http://java.sun.com/beans/glasgow/jaf.html
     在項(xiàng)目中引用mail.jar和activation.jar。
     2. 寫(xiě)配置文件
     # 將日志發(fā)送到email
     log4j.logger.MailLog=WARN,A5
     #  APPENDER A5
     log4j.appender.A5=org.apache.log4j.net.SMTPAppender
     log4j.appender.A5.BufferSize=5
     log4j.appender.A5.To=chunjie@yeqiangwei.com
     log4j.appender.A5.From=error@yeqiangwei.com
     log4j.appender.A5.Subject=ErrorLog
     log4j.appender.A5.SMTPHost=smtp.263.net
     log4j.appender.A5.layout=org.apache.log4j.PatternLayout
     log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
     3.調(diào)用代碼:
     //把日志發(fā)送到mail
     Logger logger3 = Logger.getLogger("MailLog");
     logger3.warn("warn!!!");
     logger3.error("error!!!");
     logger3.fatal("fatal!!!");
    在后臺(tái)輸出所有類(lèi)別的錯(cuò)誤:
     1. 寫(xiě)配置文件
     # 在后臺(tái)輸出
     log4j.logger.console=DEBUG, A1
     # APPENDER A1
     log4j.appender.A1=org.apache.log4j.ConsoleAppender
     log4j.appender.A1.layout=org.apache.log4j.PatternLayout
     log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
     2.調(diào)用代碼
     Logger logger1 = Logger.getLogger("console");
     logger1.debug("debug!!!");
     logger1.info("info!!!");
     logger1.warn("warn!!!");
     logger1.error("error!!!");
     logger1.fatal("fatal!!!");
    --------------------------------------------------------------------
     全部配置文件:log4j.properties
     # 在后臺(tái)輸出
     log4j.logger.console=DEBUG, A1
     # APPENDER A1
     log4j.appender.A1=org.apache.log4j.ConsoleAppender
     log4j.appender.A1.layout=org.apache.log4j.PatternLayout
     log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
    # 在2000系統(tǒng)日志輸出
     log4j.logger.NTlog=FATAL, A8
     # APPENDER A8
     log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender
     log4j.appender.A8.Source=JavaTest
     log4j.appender.A8.layout=org.apache.log4j.PatternLayout
     log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
    # 將日志發(fā)送到email
     log4j.logger.MailLog=WARN,A5
     #  APPENDER A5
     log4j.appender.A5=org.apache.log4j.net.SMTPAppender
     log4j.appender.A5.BufferSize=5
     log4j.appender.A5.To=chunjie@yeqiangwei.com
     log4j.appender.A5.From=error@yeqiangwei.com
     log4j.appender.A5.Subject=ErrorLog
     log4j.appender.A5.SMTPHost=smtp.263.net
     log4j.appender.A5.layout=org.apache.log4j.PatternLayout
     log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
    全部代碼:Log4jTest.java
     
    /*
      * 創(chuàng)建日期 2003-11-13
      */
     package edu.bcu.Bean;
     import org.apache.log4j.*;
     //import org.apache.log4j.nt.*;
     //import org.apache.log4j.net.*;
     /**
      * @author yanxu
      */
     public class Log4jTest
     {
      public static void main(String args[])
      {
       PropertyConfigurator.configure("log4j.properties");
       //在后臺(tái)輸出
       Logger logger1 = Logger.getLogger("console");
       logger1.debug("debug!!!");
       logger1.info("info!!!");
       logger1.warn("warn!!!");
       logger1.error("error!!!");
       logger1.fatal("fatal!!!");
    //在NT系統(tǒng)日志輸出
       Logger logger2 = Logger.getLogger("NTlog");
       //NTEventLogAppender nla = new NTEventLogAppender();
       logger2.debug("debug!!!");
       logger2.info("info!!!");
       logger2.warn("warn!!!");
       logger2.error("error!!!");
       //只有這個(gè)錯(cuò)誤才會(huì)寫(xiě)入2000日志
       logger2.fatal("fatal!!!");
    //把日志發(fā)送到mail
       Logger logger3 = Logger.getLogger("MailLog");
       //SMTPAppender sa = new SMTPAppender();
       logger3.warn("warn!!!");
       logger3.error("error!!!");
       logger3.fatal("fatal!!!");
      }
     }

     

    本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/azheng270/archive/2008/03/12/2173430.aspx

    posted @ 2011-04-18 14:14 飛飛 閱讀(460) | 評(píng)論 (0)編輯 收藏

    查看進(jìn)行命令: ps -ef | grep tomcat
    查看日志 tail -f logs/catalina.out
    74文件傳送跳轉(zhuǎn)文件夾 /opt/transport/
    復(fù)制文件命令 scp UserOperateServiceImpl.class 118.123.253.71:/opt/transport/
    遠(yuǎn)程連接 ssh 118.123.253.71
    結(jié)束進(jìn)程命令 kill -9 31454
    啟動(dòng)tomcat sh bin/startup.sh
    搜索日志中的內(nèi)容 grep '18923858130' interfaceLog.log*
    本地復(fù)制文件 cp -r appMarketWebApi   appMarketWebApi2000000
    刪除文件命令 rm appMarketWebApi.zip
    壓縮文件命令  zip -r AppStoreBak1108.zip AppStore
    復(fù)制文件清除.svn文件夾 xcopy appMarketWebApi1.3 11111111111 /s /i
    從現(xiàn)網(wǎng)復(fù)制文件命令 scp 10.128.100.115:/opt/transport/appMarketWebApi_1111_115.zip /opt/transport/
    查看文件占用量大命令 du -k|sort -t " " +0 -n -r|more
    查看當(dāng)前目錄文件大小 du -sh .
    tar包解壓命令 tar -xvf
    抓內(nèi)存包命令 jmap -dump:format=b,file=heap20101216.bin
    useradd -d /home -s /bin/sh   liyanhong
    passwd liyanhong 
    posted @ 2011-04-15 16:11 飛飛 閱讀(318) | 評(píng)論 (0)編輯 收藏

    僅列出標(biāo)題
    共12頁(yè): 1 2 3 4 5 6 7 8 9 下一頁(yè) Last 
    主站蜘蛛池模板: 狠狠躁狠狠爱免费视频无码| 内射干少妇亚洲69XXX| 国产精品亚洲lv粉色| 一个人免费观看视频www| 亚洲视频一区网站| 永久在线观看www免费视频| 久久精品亚洲精品国产色婷| 57pao国产成永久免费视频 | 免费一级特黄特色大片在线 | 久久免费观看国产99精品| 亚洲国产天堂久久综合网站| 日本免费大黄在线观看| 亚洲国产精品人久久| 很黄很黄的网站免费的| 亚洲无人区码一二三码区别图片 | 欧美男同gv免费网站观看| 香蕉大伊亚洲人在线观看| 免费看大美女大黄大色| 色屁屁www影院免费观看视频| 国产精品亚洲二区在线观看 | 国产成人1024精品免费| 国产aⅴ无码专区亚洲av| 无码日韩精品一区二区三区免费 | 亚洲视频欧洲视频| 日韩毛片免费无码无毒视频观看| 亚洲精品色播一区二区| xvideos亚洲永久网址| 日本亚洲欧洲免费天堂午夜看片女人员| 亚洲成人精品久久| 午夜成年女人毛片免费观看| 一级做a爰性色毛片免费| 久久久亚洲欧洲日产国码农村| 青青青国产在线观看免费网站| 婷婷国产偷v国产偷v亚洲| 亚洲国产精品久久久天堂| 18禁超污无遮挡无码免费网站国产| 无遮挡呻吟娇喘视频免费播放| 久久精品亚洲一区二区| 国产精品免费视频一区| 久久国产乱子精品免费女| 亚洲综合av一区二区三区|