有时候我需要查看已经部署到服务器上的应用程序的日志,每次都要远程登录服务器感觉很麻烦,所以一般我会把log文件的目录用apache做个网站,这样通过IE就可以访问到了。但是有时要看即时输出情况,就要不断的F5,很麻烦。所以就有个想法,不如用DWR2.0的反转Ajax来做个程序,让日志有变化时自动的发送到客户端,这样就我一个劲的按F5了。
我下面就把这个程序分享给大家,希望大家提提意见。
首先是环境:
DWR 2.0.rc1
Sun JDK 1.5
先看张运行起来的图吧,大家一看就知道这是个什么东西了。
你可以制定要监视的log文件,当然有哪些文件文件可以被监视,你必须在服务端的xml配置中文件设置,当然你也可以监视一个目录里的log文件,这对于而 log文件是每天生成一个的情况很有用。你可以设定在浏览器上显示的行数,操作行数,屏幕会自动滚动。你还可以添加一些过滤器,过滤掉不想看见的行,我目前只做了到了过滤掉一些信息,当然如果你有兴趣,你也再添加一些更复杂的过滤器。过滤器的模式是用正则表达式表示的。
下面是点击“开始监听”,运行后样子
如果服务器上的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.blogjava.net/Files/mstar/LogViewer.part1.rar
http://www.blogjava.net/Files/mstar/LogViewer.part2.rar
分享到:
相关推荐
这个"用DWR2.0做的一个Server日志查看器"是利用DWR 2.0版本的功能,构建的一个实用工具,用于实时查看服务器的日志信息,对开发者调试和监控应用运行状态具有很大帮助。 首先,DWR的核心概念是Remoting,即远程方法...
在本场景中,我们利用DWR的功能来模拟一个控制台,实时将后台的日志输出到JSP(JavaServer Pages)页面上,从而提供一种直观的方式来监控应用程序的运行状态。 首先,理解DWR的工作原理至关重要。DWR的核心是异步...
标题 "DWR同一个页面中多次引用engine.js出现:Incomplete reply from server" 描述了一个常见的问题,涉及Direct Web Remoting (DWR)框架在Web应用程序中的使用。DWR是一种JavaScript库,它允许在浏览器和服务器...
DWR (Direct Web Remoting) 是一个开源的Java库,它允许JavaScript在浏览器端与服务器端的Java对象进行交互,实现动态的Web应用。DWR简化了AJAX(Asynchronous JavaScript and XML)的开发,使得开发者可以像调用...
在"用dwr做的上传下载"这个主题中,我们将深入探讨如何利用DWR实现文件的上传和下载功能。 首先,让我们理解DWR的基本工作原理。DWR通过创建JavaScript对象映射到服务器端的Java方法,使得在前端JavaScript可以直接...
在这个"Dwr做的一个聊天室例子"中,我们可以深入探讨DWR如何被用来创建一个简单的在线聊天系统。 1. **DWR基础** DWR的核心功能是提供了一个安全且高效的机制,使得JavaScript可以调用服务器端的Java方法,就像...
总的来说,"学习dwr的一个例子"这个压缩包提供了一个实战平台,帮助初学者理解DWR的使用方法和它在实际项目中的应用,通过学习和研究这个例子,你将能够熟练地将DWR集成到你的Web应用中,提升Web应用的交互性和性能...
Direct Web Remoting (DWR) 是一个开源的Java库,它允许在JavaScript和服务器端Java之间进行实时的、安全的通信。DWR使得Web应用程序能够像桌面应用一样更新页面,无需刷新整个页面或使用复杂的Ajax技术。在这个描述...
dwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwr
在标题中提到的"DWRtree DWR实现AJAX的一个树形",指的是使用DWR来创建一个基于AJAX的动态树形结构。这种树形结构通常用于网站导航、文件目录展示或者层级数据的交互操作。通过AJAX,用户可以在不刷新整个页面的情况...
可以使用DWR提供的内置控制台进行调试,查看调用日志和返回结果。 通过这个"TestDWR"例子,你可以亲身体验DWR如何与SSH框架协同工作,实现动态、实时的Web应用。在实际项目中,这种技术可以用于各种场景,如表格...
这个“DWR做的简单登录实例”是基于DWR技术实现的一个基本用户登录系统,它展示了如何利用DWR进行异步数据交换,以及在jsp页面上进行前端交互。 在DWR的环境中,我们通常有三个主要组件:`DWR Engine`、`Servlet`和...
这是我用dwr做的一个例子,非常好懂,就是一个文本框,旁边一个按钮,连接了mysql数据库,在文本框里输入注册名,如果数据库里面已有,就会在旁边提示出来,用的是DWR技术,DER是ajax技术里的一个框架,简单易学,只要看了我这...
总结来说,"server-side clock"例子是DWR技术的一个直观展示,演示了如何使用DWR的JavaScript API与服务器端进行通信,实现实时更新页面内容。通过对这个示例的学习,开发者能够更好地理解和运用DWR进行富互联网应用...
Direct Web Remoting (DWR) 是一个开源的Java库,它允许JavaScript在浏览器端与服务器端的Java对象进行交互,实现Ajax功能。DWR 1.0 版本是早期的一个版本,尽管现在可能已经被更新的版本替代,但它仍为理解Web应用...
DWR作为Java世界中的一个强大工具,极大地简化了AJAX开发,使得JavaScript能够轻松地与服务器进行通信。通过理解其核心功能、配置步骤以及使用流程,开发者可以快速地在项目中引入DWR,构建高效、动态的Web应用。
Direct Web Remoting (DWR) 是一个开源Java库,它允许Web应用程序在浏览器和服务器之间进行安全、简单、异步的通信。DWR的核心功能是将JavaScript与Java方法直接绑定,使得前端开发者能够调用服务器端的方法,就像...
Direct Web Remoting (DWR) 是一个开源Java库,它允许JavaScript在Web浏览器中与Java服务器端进行交互,实现AJAX功能。这个压缩包包含了DWR的三个主要版本:DWR1.0、DWR2.0和DWR3.0的jar包,这些jar包是运行DWR应用...
- DWR提供了一个内置的调试工具,可以在浏览器中查看Ajax请求和响应,方便调试。 - 开发者可以通过启用调试模式,获取更详细的错误信息。 7. **DWRDemo项目**: - "DWRDemo"项目是一个实例,展示了如何在...
对于初学者来说,这是一个很好的起点,它涵盖了DWR基本的使用方式和配置,同时也提供了一个可运行的示例,帮助理解Ajax通信的工作原理。通过深入学习和实践,你可以利用DWR构建更复杂的交互式Web应用。