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

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

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

    176142998

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      116 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

    2012年4月12日 #

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


    各個版本的都有,以下列舉出來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 飛飛 閱讀(1027) | 評論 (0)編輯 收藏

    2012年4月6日 #



    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 飛飛 閱讀(687) | 評論 (0)編輯 收藏

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

    文件內容
    /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 飛飛 閱讀(547) | 評論 (0)編輯 收藏

    2011年11月7日 #

    1、主要實現用戶在進行某項操作時,多數據庫的更新、插入和刪除詳細信息。記錄操作時的請求信息。
    2、在進入Controller時,生成一個事物ID,在這個Controller中進行的所有DAO操作都綁定該事物ID。并進行記錄日志信息。


    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攔截器,實現記錄用戶操作過的所有方法和參數,并實現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 {
      // 獲取請求事務ID信息
      ThreadId threadId = new ThreadBean().getThreadId();
      // 調用方法名稱
      String methodName = joinPoint.getSignature().getName();
      // 調用參數
      Object[] args = joinPoint.getArgs();
      Object object = null;

      // 數據庫更新操作日志
      if (Pattern.matches("(save|insert|add|delete|remove|del|update)[\\S]*",
        methodName)) {
       if (threadId != null && threadId.getTransactionalId() != null) {
        // 獲取執行請求事務ID
        String transactionalId = threadId.getTransactionalId();
        // 獲取執行請求用戶ID
        String userId = threadId.getUserId();
        SysLogDetail sysLogDetail = new SysLogDetail();
        sysLogDetail.setXh(transactionalId);
        sysLogDetail.setUserId(userId);
        sysLogDetail.setMethod(methodName);
        JSONObject msg = new JSONObject();
        // 處理參數
        for (Object temp : args) {
         // 獲取參數類型,不同參數類型數據處理不一樣
         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數據庫操作日志
        SysLogDAO.insertSysLogDetail(sysLogDetail);
       }
       // 執行數據庫操作
       object = joinPoint.proceed();

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

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

      return object;

     }

     /**
      * 獲取根據注解中的key獲取memcache的含參數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("\\.");

      // 設置請求參數在args[]中的序號
      // key參數進行循環遍歷
      for (Object s : cacheArgs) {
       // 判斷是否是格式$,$...
       if (s.toString().startsWith("$")) {
        // 獲取參數名稱
        String type = s.toString().substring(1);
        // 獲取參數值
        Object temp = args[0];
        // 獲取參數類型,不同參數類型數據處理不一樣
        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);// 實體中字段
          f.setAccessible(true);// 允許訪問私有字段
          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);
       }
       // 每個參數后面添加 “.”號分隔
       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 飛飛 閱讀(7750) | 評論 (0)編輯 收藏

    2011年4月22日 #

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

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

    Commons-httpclient項目就是專門設計來簡化HTTP客戶端與服務器進行各種通訊編程。通過它可以讓原來很頭疼的事情現在輕松的解決,例如你不再管是HTTP或者HTTPS的通訊方式,告訴它你想使用HTTPS方式,剩下的事情交給httpclient替你完成。本文會針對我們在編寫HTTP客戶端程序時經常碰到的幾個問題進行分別介紹如何使用httpclient來解決它們,為了讓讀者更快的熟悉這個項目我們最開始先給出一個簡單的例子來讀取一個網頁的內容,然后循序漸進解決掉前進中的所形侍狻?/font>

    1. 讀取網頁(HTTP/HTTPS)內容

    下面是我們給出的一個簡單的例子用來訪問某個頁面

    /*

     * 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.*;

    /**

     * 最簡單的HTTP客戶端,用來演示通過GET或者POST方式訪問某個頁面

     * @author Liudong

     */

    public class SimpleClient {

     

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

        {

            HttpClient client = new HttpClient();   

            //設置代理服務器地址和端口    

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

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

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

            //使用POST方法

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

            client.executeMethod(method);

            //打印服務器返回的狀態

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

            //打印返回的信息

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

            //釋放連接

            method.releaseConnection();

        }
    }

     

    在這個例子中首先創建一個HTTP客戶端(HttpClient)的實例,然后選擇提交的方法是GET或者POST,最后在HttpClient實例上執行提交的方法,最后從所選擇的提交方法中讀取服務器反饋回來的結果。這就是使用HttpClient的基本流程。其實用一行代碼也就可以搞定整個請求的過程,非常的簡單!


    2. 以GET或者POST方式向網頁提交參數

    其實前面一個最簡單的示例中我們已經介紹了如何使用GET或者POST方式來請求一個頁面,本小節與之不同的是多了提交時設定頁面所需的參數,我們知道如果是GET的請求方式,那么所有參數都直接放到頁面的URL后面用問號與頁面地址隔開,每個參數用&隔開,例如:http://java.sun.com?name=liudong&mobile=123456,但是當使用POST方法時就會稍微有一點點麻煩。本小節的例子演示向如何查詢手機號碼所在的城市,代碼如下:

     

    /*

     * 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.*;

    /**

     * 提交參數演示

     * 該程序連接到一個用于查詢手機號碼所屬地的頁面

     * 以便查詢號碼段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方式提交數據

            client.executeMethod(method);

           //打印服務器返回的狀態

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

            //打印結果頁面

            String response =

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

           //打印返回的信息

            System.out.println(response);

            method.releaseConnection();

        }

        /**

         * 使用GET方式提交數據

         * @return

         */

        private static HttpMethod getGetMethod(){

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

        }

        /**

         * 使用POST方式提交數據

         * @return

         */

        private static HttpMethod getPostMethod(){

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

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

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

            return post;

        }

    }

    在上面的例子中頁面http://www.imobile.com.cn/simcard.php需要一個參數是simcard,這個參數值為手機號碼段,即手機號碼的前七位,服務器會返回提交的手機號碼對應的省份、城市以及其他詳細信息。GET的提交方法只需要在URL后加入參數信息,而POST則需要通過NameValuePair類來設置參數名稱和它所對應的值

    3. 處理頁面重定向

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

    狀態碼
     對應HttpServletResponse的常量
     詳細描述
     
    301
     SC_MOVED_PERMANENTLY
     頁面已經永久移到另外一個新地址
     
    302
     SC_MOVED_TEMPORARILY
     頁面暫時移動到另外一個新的地址
     
    303
     SC_SEE_OTHER
     客戶端請求的地址必須通過另外的URL來訪問
     
    307
     SC_TEMPORARY_REDIRECT
     同SC_MOVED_TEMPORARILY
     


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

    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");

            }

    我們可以自行編寫兩個JSP頁面,其中一個頁面用response.sendRedirect方法重定向到另外一個頁面用來測試上面的例子。

    4. 模擬輸入用戶名和口令進行登錄

    本小節應該說是HTTP客戶端編程中最常碰見的問題,很多網站的內容都只是對注冊用戶可見的,這種情況下就必須要求使用正確的用戶名和口令登錄成功后,方可瀏覽到想要的頁面。因為HTTP協議是無狀態的,也就是連接的有效期只限于當前請求,請求內容結束后連接就關閉了。在這種情況下為了保存用戶的登錄信息必須使用到Cookie機制。以JSP/Servlet為例,當瀏覽器請求一個JSP或者是Servlet的頁面時,應用服務器會返回一個參數,名為jsessionid(因不同應用服務器而異),值是一個較長的唯一字符串的Cookie,這個字符串值也就是當前訪問該站點的會話標識。瀏覽器在每訪問該站點的其他頁面時候都要帶上jsessionid這樣的Cookie信息,應用服務器根據讀取這個會話標識來獲取對應的會話信息。

    對于需要用戶登錄的網站,一般在用戶登錄成功后會將用戶資料保存在服務器的會話中,這樣當訪問到其他的頁面時候,應用服務器根據瀏覽器送上的Cookie中讀取當前請求對應的會話標識以獲得對應的會話信息,然后就可以判斷用戶資料是否存在于會話信息中,如果存在則允許訪問頁面,否則跳轉到登錄頁面中要求用戶輸入帳號和口令進行登錄。這就是一般使用JSP開發網站在處理用戶登錄的比較通用的方法。

    這樣一來,對于HTTP的客戶端來講,如果要訪問一個受保護的頁面時就必須模擬瀏覽器所做的工作,首先就是請求登錄頁面,然后讀取Cookie值;再次請求登錄頁面并加入登錄頁所需的每個參數;最后就是請求最終所需的頁面。當然在除第一次請求外其他的請求都需要附帶上Cookie信息以便服務器能判斷當前請求是否已經通過驗證。說了這么多,可是如果你使用httpclient的話,你甚至連一行代碼都無需增加,你只需要先傳遞登錄信息執行登錄過程,然后直接訪問想要的頁面,跟訪問一個普通的頁面沒有任何區別,因為類HttpClient已經幫你做了所有該做的事情了,太棒了!下面的例子實現了這樣一個訪問的過程。


    /*

     * 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.*;

     

    /**

     * 用來演示登錄表單的示例

     * @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);

          

           //模擬登錄頁面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());   

               }

           }

           //訪問所需的頁面main2.jsp

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

            client.executeMethod(get);

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

            get.releaseConnection();

        }

    }

    5. 提交XML格式參數

    提交XML格式的參數很簡單,僅僅是一個提交時候的ContentType問題,下面的例子演示從文件文件中讀取XML信息并提交給服務器的過程,該過程可以用來測試Web服務。

    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;

     

    /**

     * 用來演示提交XML格式數據的例子

     */

    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”);

            // 設置請求的內容直接從文件中讀取

            post.setRequestBody(new FileInputStream(input));

           

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

                post.setRequestContentLength(input.length());

            else            post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);

           

            // 指定請求內容的類型

            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. 通過HTTP上傳文件

    httpclient使用了單獨的一個HttpMethod子類來處理文件的上傳,這個類就是MultipartPostMethod,該類已經封裝了文件上傳的細節,我們要做的僅僅是告訴它我們要上傳文件的全路徑即可,下面的代碼片段演示如何使用這個類。

    MultipartPostMethod filePost = new MultipartPostMethod(targetURL);

    filePost.addParameter("fileName", targetFilePath);

    HttpClient client = new HttpClient();

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

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

    int status = client.executeMethod(filePost);


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

    7. 訪問啟用認證的頁面

    我們經常會碰到這樣的頁面,當訪問它的時候會彈出一個瀏覽器的對話框要求輸入用戶名和密碼后方可,這種用戶認證的方式不同于我們在前面介紹的基于表單的用戶身份驗證。這是HTTP的認證策略,httpclient支持三種認證方式包括:基本、摘要以及NTLM認證。其中基本認證最簡單、通用但也最不安全;摘要認證是在HTTP 1.1中加入的認證方式,而NTLM則是微軟公司定義的而不是通用的規范,最新版本的NTLM是比摘要認證還要安全的一種方式。

    下面例子是從httpclient的CVS服務器中下載的,它簡單演示如何訪問一個認證保護的頁面:


    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. 多線程模式下使用httpclient

    多線程同時訪問httpclient,例如同時從一個站點上下載多個文件。對于同一個HttpConnection同一個時間只能有一個線程訪問,為了保證多線程工作環境下不產生沖突,httpclient使用了一個多線程連接管理器的類:MultiThreadedHttpConnectionManager,要使用這個類很簡單,只需要在構造HttpClient實例的時候傳入即可,代碼如下:

    MultiThreadedHttpConnectionManager connectionManager =

       new MultiThreadedHttpConnectionManager();

    HttpClient client = new HttpClient(connectionManager);

    以后盡管訪問client實例即可。

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


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


    public class UTF8PostMethod extends PostMethod
    {
       
        public static final String ENCODE_UTF8 = "UTF-8";
       
        /**
         * 默認構造函數
         * @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";

     /**
      * 默認構造函數
      *
      * @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;
     }
    }




    測試使用!

    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 飛飛 閱讀(1061) | 評論 (0)編輯 收藏

    2011年4月21日 #

     

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

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

        或許是用膩了Struts1那死板的WEB框架,才對Spring MVC愛不釋手,尤其是2.5版本以后,支持全注解配置方式,已經使很久沒有再寫過xml文件了。

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

    先回憶下2.5注解方式的@MVC,來一個示例:

    @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沒有實現任何接口,是一個最普通不過的pojo,如果瀏覽器來了articleView.do?id=xxx這個請求,Spring會找到getArticle()這個方法,該方法第一個參數綁定到了URL上的請求參數,第二個是J2EE標準的request對象(可見Spring MVC是非侵入式的,不像變態的Struts2),事實上還可以給定HttpServletResponse,ModelMap,甚至自己的類型,Spring都會為你將值傳入進來。通過一個邏輯層service組件根據id參數值去底層查找Article對象,并放入request作用域中,最后返回的是面頁視圖名,這個例子中是返回到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";
       }

    }

        對于articleView_aaa.do,articleView_bbbb.do,articleView_c5h8j2.do,articleView_xxx.do,這樣的請求都會由getArticle()這個方法來應付,是不是很有意思?

        Spring 3.0增加了一個@ PathVariable注解來支持可變的請求路徑,將上面的代碼在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";
       }

    }

    再變得復雜些:

    @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";
       }

    }

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

        根據內容協商制的視圖解析機制:

        2.5版是由@MVC控制器來決定視圖解析器,3.0版將變得更加靈活,似乎可以通過擴展名來轉到不同的解析器中,例如請求一個.pdf文件將是如何效果呢?3.0版都會帶來不可思議的模式。

        HTTP方法的轉換:

        先看前臺頁面一段Html代碼

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

        HTTP規范中form表單只有兩種方法——POST和GET,而3.0做了一個過濾器,可以轉換這些方法至四種——GET, PUT, POST, 和 DELETE。控制器接受請求:

    @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等等其它子集所有的變革,絕對可以稱得上Srping創始人所述的里程碑版本。3.0版使用的注解列表如下:

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

        筆者早先常用Struts1.x框架,它搭配了一套自己的ActionForm,使得編程工作量增加,雖然可以變通使用自己的Pojo,但對于沒有掌握J2EE底層工具類(BeanUtil)的開發人員來說,其類型匹配是非常復雜的事。事實上Spring MVC早在1.x版本就完全使用自己的pojo來對應表單的填充,配上屬性編輯器,可以解決類型轉換問題,完全實現領域模型驅動的設計模式。由于MVC層的控制器也是Spring容器的Bean而已,因此對整個項目的控制、擴展變得非常容易。同時上文也順便點評了Struts2,可見Spring MVC在各類MVC框架的優勢所在。本身羅德.約翰遜先生是設計模式高手,一個優秀的框架給我們帶來的遠遠不只是開發效率,還有更先進的開發模式和理念...

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

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

    從4個層面分析這部分實現: 
    1. iBatis的基本實現
    2. 基于事務的iBatis的基本實現
    3. 基于事務的Spring+iBatis實現
    4. 基于回調方式的Spring+iBatis實現

    1.iBatis的基本實現

    iBatis通過SqlMapClient提供了一組方法用于批處理實現:
    1. startBatch() 開始批處理
    2. executeBatch() 執行批處理

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

    這是基于iBatis的最基本實現,如果你一步一步debug,你會發現:其實,數據庫已經執行了插入操作!
    因此,除了這兩個核心方法外,你還需要開啟事務支持。否則,上述代碼只不過是個空架子!

    2.基于事務的iBatis的基本實現
    事務處理:
    1. startTransaction() 開始事務
    2. commitTransaction() 提交事務
    3. endTransaction() 結束事務


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

    replyList是一個List,要把這個List插入到數據庫,就需要經過這三個步驟:
    1. 開始批處理 startBatch()
    2. 插入      insert()
    3. 執行批處理 executeBatch()

    如果要在Spring+iBatis中進行批處理實現,需要注意使用同一個sqlMapClient!同時,將提交事務的工作交給Spring統一處理!

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

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

    想想,還有什么問題?其實問題很明顯,雖然解決了批處理實現的問題,卻造成了事務代碼入侵的新問題。 這么做,有點惡心!
    除此之外,異常的處理也很惡心,不能夠簡單的包裝為 DataAccessException 就無法被Spring當作統一的數據庫操作異常做處理。


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

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

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

    2011年4月18日 #

    Log4J的配置文件(Configuration File)就是用來設置記錄器的級別、存放器和布局的,它可接key=value格式的設置或xml格式的設置信息。通過配置,可以創建出Log4J的運行環境。

    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] 是日志輸出級別,共有5級:


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


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

    打印參數: Log4J采用類似C語言中的printf函數的打印格式格式化日志信息,如下:


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

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

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

    [配置文件]


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

    ### 輸出到控制臺 ###
    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級別以上的日志
    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

    ### 保存異常信息到單獨文件 ###
    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級別以上的日志!!!
    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 " );
        }
    }

    運行一下,看看異常信息是不是保存在了一個單獨的文件error.log中

    log4j.properties 使用
    一.參數意義說明
    輸出級別的種類
    ERROR、WARN、INFO、DEBUG
    ERROR 為嚴重錯誤 主要是程序的錯誤
    WARN 為一般警告,比如session丟失
    INFO 為一般要顯示的信息,比如登錄登出
    DEBUG 為程序的調試信息
    配置日志信息輸出目的地
    log4j.appender.appenderName = fully.qualified.name.of.appender.class
    1.org.apache.log4j.ConsoleAppender(控制臺)
    2.org.apache.log4j.FileAppender(文件)
    3.org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件)
    4.org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件)
    5.org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)
    配置日志信息的格式
    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(包含日志信息的級別和信息字符串),
    4.org.apache.log4j.TTCCLayout(包含日志產生的時間、線程、類別等等信息)
    控制臺選項
    Threshold=DEBUG:指定日志消息的輸出最低層次。
    ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出。
    Target=System.err:默認情況下是:System.out,指定輸出控制臺
    FileAppender 選項
    Threshold=DEBUF:指定日志消息的輸出最低層次。
    ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出。
    File=mylog.txt:指定消息輸出到mylog.txt文件。
    Append=false:默認值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內容。
    RollingFileAppender 選項
    Threshold=DEBUG:指定日志消息的輸出最低層次。
    ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出。
    File=mylog.txt:指定消息輸出到mylog.txt文件。
    Append=false:默認值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內容。
    MaxFileSize=100KB: 后綴可以是KB, MB 或者是 GB. 在日志文件到達該大小時,將會自動滾動,即將原來的內容移到mylog.log.1文件。
    MaxBackupIndex=2:指定可以產生的滾動文件的最大數。
    log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
    日志信息格式中幾個符號所代表的含義:
     -X號: X信息輸出時左對齊;
     %p: 輸出日志信息優先級,即DEBUG,INFO,WARN,ERROR,FATAL,
     %d: 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
     %r: 輸出自應用啟動到輸出該log信息耗費的毫秒數
     %c: 輸出日志信息所屬的類目,通常就是所在類的全名
     %t: 輸出產生該日志事件的線程名
     %l: 輸出日志事件的發生位置,相當于%C.%M(%F:%L)的組合,包括類目名、發生的線程,以及在代碼中的行數。舉例:Testlog4.main (TestLog4.java:10)
     %x: 輸出和當前線程相關聯的NDC(嵌套診斷環境),尤其用到像java servlets這樣的多客戶多線程的應用中。
     %%: 輸出一個"%"字符
     %F: 輸出日志消息產生時所在的文件名稱
     %L: 輸出代碼中的行號
     %m: 輸出代碼中指定的消息,產生的日志具體信息
     %n: 輸出一個回車換行符,Windows平臺為"\r\n",Unix平臺為"\n"輸出日志信息換行
     可以在%與模式字符之間加上修飾符來控制其最小寬度、最大寬度、和文本的對齊方式。如:
     1)%20c:指定輸出category的名稱,最小的寬度是20,如果category的名稱小于20的話,默認的情況下右對齊。
     2)%-20c:指定輸出category的名稱,最小的寬度是20,如果category的名稱小于20的話,"-"號指定左對齊。
     3)%.30c:指定輸出category的名稱,最大的寬度是30,如果category的名稱大于30的話,就會將左邊多出的字符截掉,但小于30的話也不會有空格。
     4)%20.30c:如果category的名稱小于20就補空格,并且右對齊,如果其名稱長于30字符,就從左邊較遠輸出的字符截掉。
    二.文件配置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 輸出 一天一個文件,輸出路徑可以定制,一般在根路徑下
    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配置文件實現了輸出到控制臺,文件,回滾文件,發送日志郵件,輸出到數據庫日志表,自定義標簽等全套功能。
    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
    三.高級使用
    實驗目的:
     1.把FATAL級錯誤寫入2000NT日志
     2. WARN,ERROR,FATAL級錯誤發送email通知管理員
     3.其他級別的錯誤直接在后臺輸出
    實驗步驟:
     輸出到2000NT日志
     1.把Log4j壓縮包里的NTEventLogAppender.dll拷到WINNT\SYSTEM32目錄下
     2.寫配置文件log4j.properties
    # 在2000系統日志輸出
     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.調用代碼:
     Logger logger2 = Logger.getLogger("NTlog"); //要和配置文件中設置的名字相同
     logger2.debug("debug!!!");
     logger2.info("info!!!");
     logger2.warn("warn!!!");
     logger2.error("error!!!");
     //只有這個錯誤才會寫入2000日志
     logger2.fatal("fatal!!!");
    發送email通知管理員:
     1. 首先下載JavaMail和JAF,
      http://java.sun.com/j2ee/ja/javamail/index.html
      http://java.sun.com/beans/glasgow/jaf.html
     在項目中引用mail.jar和activation.jar。
     2. 寫配置文件
     # 將日志發送到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.調用代碼:
     //把日志發送到mail
     Logger logger3 = Logger.getLogger("MailLog");
     logger3.warn("warn!!!");
     logger3.error("error!!!");
     logger3.fatal("fatal!!!");
    在后臺輸出所有類別的錯誤:
     1. 寫配置文件
     # 在后臺輸出
     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.調用代碼
     Logger logger1 = Logger.getLogger("console");
     logger1.debug("debug!!!");
     logger1.info("info!!!");
     logger1.warn("warn!!!");
     logger1.error("error!!!");
     logger1.fatal("fatal!!!");
    --------------------------------------------------------------------
     全部配置文件:log4j.properties
     # 在后臺輸出
     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系統日志輸出
     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
    # 將日志發送到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
     
    /*
      * 創建日期 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");
       //在后臺輸出
       Logger logger1 = Logger.getLogger("console");
       logger1.debug("debug!!!");
       logger1.info("info!!!");
       logger1.warn("warn!!!");
       logger1.error("error!!!");
       logger1.fatal("fatal!!!");
    //在NT系統日志輸出
       Logger logger2 = Logger.getLogger("NTlog");
       //NTEventLogAppender nla = new NTEventLogAppender();
       logger2.debug("debug!!!");
       logger2.info("info!!!");
       logger2.warn("warn!!!");
       logger2.error("error!!!");
       //只有這個錯誤才會寫入2000日志
       logger2.fatal("fatal!!!");
    //把日志發送到mail
       Logger logger3 = Logger.getLogger("MailLog");
       //SMTPAppender sa = new SMTPAppender();
       logger3.warn("warn!!!");
       logger3.error("error!!!");
       logger3.fatal("fatal!!!");
      }
     }

     

    本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/azheng270/archive/2008/03/12/2173430.aspx

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

    2011年4月15日 #

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

    主站蜘蛛池模板: 国产精品亚洲а∨无码播放不卡| 亚洲网站视频在线观看| 在线涩涩免费观看国产精品| 亚洲成AV人片久久| 四虎永久免费网站免费观看| 日本免费中文视频| 亚洲爆乳无码专区www| 亚洲色欲久久久综合网东京热| 国产精品免费αv视频| 亚洲乱码一二三四区国产| 四虎最新永久免费视频| 亚洲AV无码一区二区三区性色| 国产成人免费片在线视频观看 | 婷婷亚洲综合五月天小说在线| 真实乱视频国产免费观看| 三级网站免费观看| 亚洲一区二区三区高清在线观看| 青苹果乐园免费高清在线| 亚洲欧洲av综合色无码| 四虎影院永久免费观看| 成年网在线观看免费观看网址 | 91香蕉国产线在线观看免费| 粉色视频免费入口| 亚洲中文字幕在线无码一区二区| 成年人网站在线免费观看| 免费的全黄一级录像带| 色视频在线观看免费| 亚洲人成人无码网www电影首页 | 久爱免费观看在线网站| 黄色a三级免费看| 中文字幕在线观看亚洲日韩| 亚洲精品免费视频| 亚洲国产综合无码一区| 免费人成无码大片在线观看| 四虎国产精品免费久久| 最好看的中文字幕2019免费| 亚洲 日韩经典 中文字幕| 777亚洲精品乱码久久久久久| 免费看美女被靠到爽的视频| a一级爱做片免费| 亚洲第一se情网站|