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

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

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

    細心!用心!耐心!

    吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學業,五六點粗墨,七八筆買賣,九十道人情。

    BlogJava 聯系 聚合 管理
      1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks

    有時候我需要查看已經部署到服務器上的應用程序的日志,每次都要遠程登錄服務器感覺很麻煩,所以一般我會把log文件的目錄用apache做個網站,這樣通過IE就可以訪問到了。但是有時要看即時輸出情況,就要不斷的F5,很麻煩。所以就有個想法,不如用DWR2.0的反轉Ajax來做個程序,讓日志有變化時自動的發送到客戶端,這樣就我一個勁的按F5了。

    我下面就把這個程序分享給大家,希望大家提提意見。

    首先是環境:
    DWR 2.0.rc1
    Sun JDK 1.5

    先看張運行起來的圖吧,大家一看就知道這是個什么東西了。
    logviewer.png
    你可以制定要監視的log文件,當然有哪些文件文件可以被監視,你必須在服務端的xml配置中文件設置,當然你也可以監視一個目錄里的log文件,這對于而log文件是每天生成一個的情況很有用。你可以設定在瀏覽器上顯示的行數,操作行數,屏幕會自動滾動。你還可以添加一些過濾器,過濾掉不想看見的行,我目前只做了到了過濾掉一些信息,當然如果你有興趣,你也再添加一些更復雜的過濾器。過濾器的模式是用正則表達式表示的。

    下面是點擊“開始監聽”,運行后樣子
    logviewer2.png
    如果服務器上的catalina.2006-12-09.log文件發生變化,客戶端的瀏覽器上log顯示區也會自動的向上滾動。


    下面我就大致的介紹一下如何用DWR2.0來實現這樣的功能。在這里介紹的可能不是很詳細,不清楚的地方請看我提供的源碼。

    先來介紹一下目錄結構
    ├─lib  -- 編譯和測試用的第三方類庫
    ├─webapp -- 部署目錄
    ├─test -- 測試程序
    ├─java -- 主程序
    └─build.xml -- ant構建文件

    webapp下的文件和目錄
    │  style.css  -- 樣式表文件
    │  index.html -- 主畫面文件

    ├─WEB-INF
    │  │  web.xml -- 部署配置文件
    │  │  dwr.xml -- dwr的配置文件
    │  │  conf.xml -- 我們這個應用程序配置文件,主要是配置log文件
    │  │
    │  ├─classes
    │  │
    │  └─lib

    └─script -- javascript文件


    index.html中就是我們上面的圖片上能看到的頁面元素。其中的控件的事件處理都寫在\script\logviewer.js文件中。

    當頁面加載時執行startPoll()方法,復雜開始與服務器的通信,并且把log文件選擇框初始化,把已經添加過濾器列表顯示出來。

    function  startPoll() {
        DWREngine.setActiveReverseAjax(
    true );

        LogManager.getLogFileNames(
    function  (data) {
            DWRUtil.removeAllOptions(
    " log_file " );
            DWRUtil.addOptions(
    " log_file " , data);
        });

        LogManager.getFilters(
    function (data) {
            
    for  ( var  i  =   0 ; i  <  data.length; i ++ ) {
                addFilterDiv(data[i].pattern, data[i].id);
            }
        });
    }


    當點擊“開始監聽”按鈕時調用服務端的LogManager的send方法,服務端開啟監聽線程,開始監聽做為參數傳遞的文件,如果文件有變動就會把最近增加的行發送到瀏覽器上來。

    var  startWatch  =   function () {
        clearLog();
        LogManager.send(DWRUtil.getValue(
    " log_file " ));
    }


    當點擊“結束監聽”按鈕,調用LogManager的stop()方法,結束掉監聽線程。

     

    function  stopWatch() {
        LogManager.stop();
    }

     


    當點擊“清空日志”按鈕,清除mainPanel中的所有子元素

    function  clearLog() {
        
    var  mainPanel  =  $( " main_panel " );
        
    while  (mainPanel.hasChildNodes()) {
            mainPanel.removeChild(mainPanel.firstChild);
        }
    }

    當點擊“添加過濾器”,填充輸入框,要求輸入做為過濾器的正則表達式,輸入完成后,要做兩件事:
    1、LogManager.addFilter方法,把輸入的正則表達式傳送給服務端。
    2、把這個正則表達式添加到頁面上。

    function  addFilter() {
        
    var  regex  =  prompt( " 輸入正則表達式 " "" );
        
    if  (regex  !=   null   &&  regex  !=   "" ) {
            LogManager.addFilter(regex, 
    function  (filterId) {
                addFilterDiv(regex, filterId);
            });
        }
    }
    注意這里,我們用到了DWR的回調模式,在調用服務端方法LogManager.addFilter成功后我們才調用客戶端的addFilterDiv方法把這個輸入的正則表達式顯示到頁面上。

    如果你足夠細心的話,應該會發現在這個js文件中有一個叫做addNewLine的方法在index.html中是沒有被調用的。這個方法其實是給服務端的LogManager.send函數調用的。

    上面這些內容就是服務端腳本的主要內容了,其實很簡單。主要負責通過DWR與服務端通信和處理頁面顯示。

    下面介紹服務端的核心類:LogManager

    這個類主要就這樣幾個方法:
       /**
         * 停止監控
         
    */
        
    public void stop() {
            
    if (watcher != null) {
                watcher.halt();
            }
        }

        
    /**
         * 發送log信息
         
    */
        
    public void send(String filename) {
            WebContext wctx 
    = WebContextFactory.get();
            
    final ScriptSession scriptSession = wctx.getScriptSession();
            
    if (watcher != null) {
                watcher.halt();
            }

            
    try {
                watcher 
    = new LogFileWatcher(filename);
                watcher.addListener(
    new LogUpdateListener() {
                    
    public void onLogUpdate(List<String> lines) {
                        
    for (String line : lines) {
                            
    if (checkFilters(line)) {
                                ScriptBuffer scriptBuffer 
    = new ScriptBuffer();
                                scriptBuffer.appendScript(
    "addNewLine(")
                                        .appendData(line)
                                        .appendScript(
    ");");
                                scriptSession.addScript(scriptBuffer);
                            }
                        }
                    }
                });
                watcher.start();
            } 
    catch (IOException e) {
                ScriptBuffer scriptBuffer 
    = new ScriptBuffer();
                scriptBuffer.appendScript(
    "addNewLine(")
                        .appendData(e.getMessage())
                        .appendScript(
    ");");
                scriptSession.addScript(scriptBuffer);
                log.warn(e);
            }
        }

        
    /**
         * 取得指定的日志文件路徑
         *
         * 
    @return 指定的日志文件路徑
         
    */
        
    public List<String> getLogFileNames() {
            List
    <String> filenames = new ArrayList<String>();
            
    try {
                XMLConfiguration config 
    = getConfiguration();
                List logfiles 
    = config.getList("log-files.file");
                
    for (Object o : logfiles) {
                    filenames.add((String) o);
                }
            } 
    catch (ConfigurationException e) {
                log.warn(e);
            }

            
    return filenames;
        }

        
    /**
         * 取得指定的日志目錄下的文件
         *
         * 
    @return 指定的日志目錄下的文件
         
    */
        
    public List<String> getLogFileNamesFromDir() {
            List
    <String> filenames = new ArrayList<String>();
            
    try {
                XMLConfiguration config 
    = getConfiguration();
                String dir 
    = config.getString("log-dir.dir");
                
    if (dir != null) {
                    File rootDir 
    = new File(dir);
                    
    if (rootDir.exists()) {
                        
    if (rootDir.isFile()) {
                            filenames.add(rootDir.getPath().replace(
    '\\''/'));
                        } 
    else if (rootDir.isDirectory()) {
                            String patternString 
    = config.getString("log-dir.filter");
                            File[] files;
                            
    if (patternString != null && !patternString.equals("")) {
                                files 
    = rootDir.listFiles(new LogFileFilter(patternString));
                            } 
    else {
                                files 
    = rootDir.listFiles();
                            }

                            
    for (File file : files) {
                                filenames.add(file.getPath().replace(
    '\\''/'));
                            }
                        }
                    }
                }
            } 
    catch (ConfigurationException e) {
                log.warn(e);
            }

            
    return filenames;
        }

        
    /**
         * 添加一個過濾器,返回過濾器的id
         
    */
        
    public int addFilter(String regex) {
            
    synchronized (filters) {
                Filter filter 
    = new Filter(regex, SequenceGenerator.getInstance().next(), FilterType.INCLUDE);
                filters.add(filter);
                
    return filter.getId();
            }

        }

        
    /**
         * 根據id刪除一個過濾器
         
    */
        
    public void removeFilter(int id) {
            
    synchronized (filters) {
                filters.remove(
    new Filter(id));
            }
        }

        
    /**
         * 取得現在所有的過濾器列表
         
    */
        
    public List<Map<String, Object>> getFilters() {
            List
    <Map<String, Object>> result = new ArrayList<Map<String, Object>>();
            
    synchronized (filters) {
                
    for (Filter filter : filters) {
                    Map
    <String, Object> filterItem = new HashMap<String, Object>();
                    filterItem.put(
    "id", filter.getId());
                    filterItem.put(
    "pattern", filter.getPattern().pattern());
                    result.add(filterItem);
                }
            }
            
    return result;
        }

    對于大家都做過Java的朋友來說,這些代碼應該很容易就能看懂,我就不多說了。大家主要注意一下ScriptSession類,這個類就是起到主要功能的類了。

    其中的LogFileWatcher是一個Thread類,它是用來監視log文件的。

    SequenceGenerator.java是用來生成過濾器的id的。

    LogUpdateListener.java是一個接口,用于實現事件回調的。

    然后看一個dwr的配置文件
    <dwr>
        
    <allow>
            
    <create creator="new" javascript="LogManager" scope="session">
                
    <param name="class" value="org.devside.logviewer.LogManager"/>
                
    <include method="send"/>
                
    <include method="stop"/>
                
    <include method="getLogFileNames"/>
                
    <include method="getLogFileNamesFromDir"/>
                
    <include method="addFilter"/>
                
    <include method="removeFilter"/>
                
    <include method="getFilters"/>
            
    </create>
        
    </allow>
    </dwr>

    這里的配置文件和1.x幾乎沒什么兩樣,就是scope我這里設置成了session范圍的。這樣就可以多個人同時監視不同的log文件了。

    web.xml文件也基本上是老樣子
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="LogViewer" version="2.4"
             xmlns
    ="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi
    ="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation
    ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        
    <display-name>Web Log Viewer</display-name>

        
    <servlet>
            
    <description>Direct Web Remoter Servlet</description>
            
    <display-name>DWR Servlet</display-name>
            
    <servlet-name>dwr-invoker</servlet-name>
            
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
            
    <init-param>
                
    <param-name>debug</param-name>
                
    <param-value>true</param-value>
            
    </init-param>
            
    <init-param>
                
    <param-name>pollAndCometEnabled</param-name>
                
    <param-value>true</param-value>
            
    </init-param>
            
    <load-on-startup>1</load-on-startup>
        
    </servlet>

        
    <servlet-mapping>
            
    <servlet-name>dwr-invoker</servlet-name>
            
    <url-pattern>/dwr/*</url-pattern>
        
    </servlet-mapping>

        
    <welcome-file-list>
            
    <welcome-file>index.html</welcome-file>
        
    </welcome-file-list>
    </web-app>
    dwr的包名發生了變化,并且要開啟反轉ajax,就要把pollAndCometEnabled參數設置為true。

    總結,總體來說DWR2.0中的反轉ajax還是很容易使用的,這也是dwr的一貫風格,不用知道過多的細節就能容易的實現ajax。dwr絕對是Java開發者的首選ajax框架。
    另外我這個程序其實還是為了演示用的,如果想要用戶實際開發可能還需要修改,比如安全性上面,性能上面。而性能上面的主要問題是客戶端瀏覽器,如果服務端的log文件過大,而瀏覽器有不能即時的回收內存,就會造成客戶端瀏覽器內存占用過大而死掉的問題。而服務端由于java的內容回收機制已經比較成熟應該不會有什么問題。我在ie6和firefox2都試過了,firefox效果能好一些。

    源碼下載:
    http://www.tkk7.com/Files/mstar/LogViewer.part1.rar
    http://www.tkk7.com/Files/mstar/LogViewer.part2.rar
    posted on 2007-04-16 15:02 張金鵬 閱讀(275) 評論(0)  編輯  收藏 所屬分類: AJAX技術
    主站蜘蛛池模板: 日韩中文字幕免费| 妞干网在线免费视频| 亚洲色偷偷狠狠综合网| 亚洲人成人网毛片在线播放| 91福利免费视频| 亚洲第一中文字幕| 中文字幕无码免费久久| 亚洲国产成人高清在线观看 | 亚洲国产精品xo在线观看| 99热精品在线免费观看| 亚洲∧v久久久无码精品| 国产猛男猛女超爽免费视频| 亚洲免费人成在线视频观看| 中文在线日本免费永久18近| 亚洲一区二区三区香蕉| 国内精品久久久久影院免费 | 成人免费看黄20分钟| 亚洲AV噜噜一区二区三区| 日本媚薬痉挛在线观看免费| 色屁屁www影院免费观看视频| 亚洲国产精品丝袜在线观看| 亚洲一区二区三区免费| 亚洲日韩乱码中文无码蜜桃臀网站| 最新久久免费视频| 亚洲美女视频一区| 思思99re66在线精品免费观看| 精品亚洲福利一区二区| 亚洲色欲久久久久综合网| 国产免费爽爽视频在线观看| 亚洲国产成人精品无码区在线秒播| 中字幕视频在线永久在线观看免费 | 香蕉视频在线观看亚洲| 免费v片在线观看视频网站| 亚洲国产精品无码久久久秋霞1| 亚洲国产成人久久综合区| 久久精品免费一区二区三区| 亚洲人成影院77777| 免费亚洲视频在线观看| 成在人线av无码免费高潮喷水 | 四虎亚洲国产成人久久精品| 在线观看特色大片免费网站|