我试图从我的Java代码中捕获应用程序的浏览器DOM。 目标是在Web浏览器上呈现Web应用程序。用户将填充字段或执行任何操作以在应用程序中导航。 将有一个独立的Java代码,它将捕获Web应用程序将导航到的每个页面的浏览器DOM。 我使用HtmlUnit捕获DOM和Selenium WebDriver来呈现Web应用程序,因为HtmlUnit是无头的。
问题是我无法跟踪我是否在应用程序的新页面上。 声明HtmlPage page = webClient.getCurrentWindow()。getEnclosedPage()不起作用,因为HtmlPage对象不会改变。
我尝试过实现DomChangeListener,但似乎没有DomChangeEvent,如果数据填充是手动完成的,即在java代码之外。如果我填充内容并从代码中提交页面,那么DomChangeListener可以正常工作。但那不是我想要的。
任何建议,如何实现这一目标?还有其他api对此有用吗?
此致
答案 0 :(得分:1)
使用Selenium / Webdriver这不是一件容易的事。我做了一些非常相似的事情并让它发挥作用(我很快就会发布)。基础知识是JavaScript事件处理程序,并从Java轮询数据。
JavaScript:
var events = [];
var eventQueue = [];
var eventHistory = {};
var processing = false;
var nativeEvents = {
'submit': 'HTMLEvents',
'keypress': 'KeyEvents',
'click': 'MouseEvents',
'dblclick': 'MouseEvents',
'dragstart': 'MouseEvents',
'dragend': 'MouseEvents',
}
for(var eventName in nativeEvents) {
document.addEventListener(eventName, processEvent, true);
};
processEvent = function(event) {
if(event.triggeredManually) {
return true;
}
if(event.type in nativeEvents) {
storeEvent(event);
event.stopPropagation();
event.preventDefault();
return false;
}
}
storeEvent = function(event) {
ev = convertEvent(event);
if(processing) {
eventQueue.push(ev);
} else {
events.push(ev);
}
}
convertEvent = function(event) {
var ev = {};
var id = new Date().getTime() + ":" + Math.random();
ev['id'] = id;
ev['type'] = event.type;
ev['target'] = event.target;
ev['button'] = event.button;
ev['charCode'] = event.charCode;
ev['keyCode'] = event.keyCode;
ev['altKey'] = event.altKey;
ev['ctrlKey'] = event.ctrlKey;
ev['shiftKey'] = event.shiftKey;
ev['clientX'] = event.clientX;
ev['clientY'] = event.clientY;
ev['offsetX'] = event.offsetX;
ev['offsetY'] = event.offsetY;
eventHistory[id] = ev;
return ev;
}
这些功能用于检测和存储用户事件。需要以下内容来检索Java中的事件并在事后对事件进行三舍五入。这是页面卸载所必需的,因为unload
事件不能安全地在每个浏览器中运行。
getEvents = function() {
processing = true;
events = events.concat(eventQueue);
eventQueue = [];
setTimeout(resetEvents, 10);
return events;
};
resetEvents = function() {
events = [];
processing = false;
};
triggerEvents = function(idsAsJson) {
// trigger pending events
var ids = JSON.parse(idsAsJson);
for (var i = 0; i < ids.length; i++) {
var event = eventHistory[ids[i]];
if(event) {
var evObj = null;
var evObjType = null;
var bubbling = true;
var cancelable = false;
if(event['type'] in nativeEvents) {
evObjType = nativeEvents[event['type']];
evObj = document.createEvent(evObjType);
// more info: http://www.howtocreate.co.uk/tutorials/javascript/domevents
if(evObjType == 'KeyEvents') {
evObj.initKeyEvent(event['type'], bubbling, cancelable, window, event['ctrlKey'], event['altKey'], event['shiftKey'], false, event['keyCode'], event['charCode']);
} else if(evObjType == 'MouseEvents') {
evObj.initMouseEvent(event['type'], bubbling, cancelable, window, 1, event['offsetX'], event['offsetY'], event['clientX'], event['clientY'], event['ctrlKey'], event['altKey'], event['shiftKey'], false, event['button'], null);
} else {
evObj.initEvent(event['type'], bubbling, cancelable);
}
evObj.triggeredManually = true;
event['target'].dispatchEvent(evObj);
}
}
}
};
然后你需要循环遍历getEvents()
函数的Java代码,你可以存储你需要的任何东西。之后,您需要执行triggerEvents()
函数以处理用户交互。
答案 1 :(得分:0)
不幸的是,我不熟悉HtmlUnit或Selenium WebDriver,所以这个答案可能对你没用。但是,一般来说,这种事情相对容易实现。
在浏览器端,只要有需要捕获的用户输入,就可以实现事件处理程序。这些事件处理程序将使用您需要在服务器上捕获的任何数据对您的Web服务器进行Ajax调用。如果数据完全复杂,我建议您使用Json将数据作为对象传递。有一些标准的Javascript字符串(参见https://github.com/douglascrockford/JSON-js)在Java方面,有一些工具可以将json字符串转换为java对象(参见http://code.google.com/p/google-gson/)。你也可以到这里寻找更多选择:http://www.json.org/
在服务器端,您的java代码只是驻留在jsps或servlet中。它处理数据。如果数据是瞬态的,您可以使用会话(javax.servlet.http.HttpSession)将其保留在内存中。如果它是持久的,您可以将其写入数据库或数据文件。
一般来说,我经常发现自己实现这种方式很有用,而不是使用软件包。我的解决方案通常更小,更容易调试和维护。希望这会有所帮助。