国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
用DWR2.0做的一個(gè)Server日志查看器

[DWR(Ajax)]用DWR2.0做的一個(gè)Server日志查看器
軟件技術(shù)

lhwork 發(fā)表于 2007-1-4 22:43:17

有時(shí)候我需要查看已經(jīng)部署到服務(wù)器上的應(yīng)用程序的日志,每次都要遠(yuǎn)程登錄服務(wù)器感覺很麻煩,所以一般我會(huì)把log文件的目錄用apache做個(gè)網(wǎng)站,這樣通過IE就可以訪問到了。但是有時(shí)要看即時(shí)輸出情況,就要不斷的F5,很麻煩。所以就有個(gè)想法,不如用DWR2.0的反轉(zhuǎn)Ajax來(lái)做個(gè)程序,讓日志有變化時(shí)自動(dòng)的發(fā)送到客戶端,這樣就我一個(gè)勁的按F5了。

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

首先是環(huán)境:
DWR 2.0.rc1
Sun JDK 1.5

先看張運(yùn)行起來(lái)的圖吧,大家一看就知道這是個(gè)什么東西了。


你可以制定要監(jiān)視的log文件,當(dāng)然有哪些文件文件可以被監(jiān)視,你必須在服務(wù)端的xml配置中文件設(shè)置,當(dāng)然你也可以監(jiān)視一個(gè)目錄里的log文件,這對(duì)于而 log文件是每天生成一個(gè)的情況很有用。你可以設(shè)定在瀏覽器上顯示的行數(shù),操作行數(shù),屏幕會(huì)自動(dòng)滾動(dòng)。你還可以添加一些過濾器,過濾掉不想看見的行,我目前只做了到了過濾掉一些信息,當(dāng)然如果你有興趣,你也再添加一些更復(fù)雜的過濾器。過濾器的模式是用正則表達(dá)式表示的。

下面是點(diǎn)擊“開始監(jiān)聽”,運(yùn)行后樣子

如果服務(wù)器上的catalina.2006-12-09.log文件發(fā)生變化,客戶端的瀏覽器上log顯示區(qū)也會(huì)自動(dòng)的向上滾動(dòng)。


下面我就大致的介紹一下如何用DWR2.0來(lái)實(shí)現(xiàn)這樣的功能。在這里介紹的可能不是很詳細(xì),不清楚的地方請(qǐng)看我提供的源碼。

先來(lái)介紹一下目錄結(jié)構(gòu)
├─lib  -- 編譯和測(cè)試用的第三方類庫(kù)
├─webapp -- 部署目錄
├─test -- 測(cè)試程序
├─java -- 主程序
└─build.xml -- ant構(gòu)建文件

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

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

└─script -- javascript文件


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

當(dāng)頁(yè)面加載時(shí)執(zhí)行startPoll()方法,復(fù)雜開始與服務(wù)器的通信,并且把log文件選擇框初始化,把已經(jīng)添加過濾器列表顯示出來(lái)。

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


當(dāng)點(diǎn)擊“開始監(jiān)聽”按鈕時(shí)調(diào)用服務(wù)端的LogManager的send方法,服務(wù)端開啟監(jiān)聽線程,開始監(jiān)聽做為參數(shù)傳遞的文件,如果文件有變動(dòng)就會(huì)把最近增加的行發(fā)送到瀏覽器上來(lái)。

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


當(dāng)點(diǎn)擊“結(jié)束監(jiān)聽”按鈕,調(diào)用LogManager的stop()方法,結(jié)束掉監(jiān)聽線程。

 

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

 


當(dāng)點(diǎn)擊“清空日志”按鈕,清除mainPanel中的所有子元素

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

當(dāng)點(diǎn)擊“添加過濾器”,填充輸入框,要求輸入做為過濾器的正則表達(dá)式,輸入完成后,要做兩件事:
1、LogManager.addFilter方法,把輸入的正則表達(dá)式傳送給服務(wù)端。
2、把這個(gè)正則表達(dá)式添加到頁(yè)面上。

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

如果你足夠細(xì)心的話,應(yīng)該會(huì)發(fā)現(xiàn)在這個(gè)js文件中有一個(gè)叫做addNewLine的方法在index.html中是沒有被調(diào)用的。這個(gè)方法其實(shí)是給服務(wù)端的LogManager.send函數(shù)調(diào)用的。

上面這些內(nèi)容就是服務(wù)端腳本的主要內(nèi)容了,其實(shí)很簡(jiǎn)單。主要負(fù)責(zé)通過DWR與服務(wù)端通信和處理頁(yè)面顯示。

下面介紹服務(wù)端的核心類:LogManager

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

    
/**
     * 發(fā)送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;
    }

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

    }

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

    
/**
     * 取得現(xiàn)在所有的過濾器列表
     
*/
    
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;
    }

對(duì)于大家都做過Java的朋友來(lái)說(shuō),這些代碼應(yīng)該很容易就能看懂,我就不多說(shuō)了。大家主要注意一下ScriptSession類,這個(gè)類就是起到主要功能的類了。

其中的LogFileWatcher是一個(gè)Thread類,它是用來(lái)監(jiān)視log文件的。

SequenceGenerator.java是用來(lái)生成過濾器的id的。

LogUpdateListener.java是一個(gè)接口,用于實(shí)現(xiàn)事件回調(diào)的。

然后看一個(gè)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我這里設(shè)置成了session范圍的。這樣就可以多個(gè)人同時(shí)監(jiān)視不同的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的包名發(fā)生了變化,并且要開啟反轉(zhuǎn)ajax,就要把pollAndCometEnabled參數(shù)設(shè)置為true。

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

源碼下載:
http://www.blogjava.net/Files/mstar/LogViewer.part1.rar
http://www.blogjava.net/Files/mstar/LogViewer.part2.rar
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
struts2的ajax支持,ajax校驗(yàn)
Struts 2與AJAX(第三部分)
瀏覽器從服務(wù)器下載文件的Servlet實(shí)例
DWR學(xué)習(xí)筆記(四)
DWR3實(shí)現(xiàn)服務(wù)器端向客戶端精確推送消息
Spring+DWR 全注解版
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服