Как захватить действие пользователя в браузере с помощью кода Java? - PullRequest
0 голосов
/ 21 марта 2012

Я пытаюсь захватить DOM браузера приложения из моего кода Java. Цель состоит в том, чтобы отобразить веб-приложение в веб-браузере. Пользователь будет заполнять поля или выполнять какие-либо действия для навигации по приложению. Будет отдельный код Java, который будет записывать DOM браузера для каждой страницы, на которую будет переходить веб-приложение. Я использую HtmlUnit для захвата DOM и Selenium WebDriver для рендеринга веб-приложения, поскольку HtmlUnit безголовый.

Проблема в том, что я не могу отследить, нахожусь ли я на новой странице приложения. Инструкция HtmlPage page = webClient.getCurrentWindow (). GetEnclosedPage () не работает, поскольку объект HtmlPage не изменяется.

Я пытался реализовать DomChangeListener, но кажется, что DomChangeEvent не существует, если заполнение данных выполняется вручную, то есть вне кода Java. Если я заполняю содержимое и отправляю страницу из кода, то DomChangeListener работает. Но это не то, что я хочу.

Есть предложения, как этого добиться? Есть ли другие полезные API для этого?

Привет

Ответы [ 2 ]

1 голос
/ 22 марта 2012

Это непростая задача с 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);
            }
        }
    }

};

Затем вам нужен код Java, который зацикливается на функции getEvents(), и вы можете хранить все, что вам нужно. После этого вам нужно выполнить функцию triggerEvents(), чтобы обработать взаимодействия с пользователем.

0 голосов
/ 21 марта 2012

К сожалению, я не знаком с HtmlUnit или Selenium WebDriver, поэтому этот ответ может оказаться бесполезным для вас. Однако, в общем, такого рода вещи относительно легко осуществить.

На стороне браузера реализуйте обработчики событий каждый раз, когда есть пользовательский ввод, который вам нужно захватить. Эти обработчики событий будут выполнять вызовы 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 или сервлетах. Обрабатывает данные. Если данные временные, вы можете оставить их в памяти во время сеанса (javax.servlet.http.HttpSession). Если он постоянен, вы можете записать его в базу данных или файл данных.

В общем, я часто нахожу полезным самому реализовывать подобные вещи, а не использовать программный пакет. Мое решение обычно намного меньше и его легче отлаживать и поддерживать. Надеюсь, это поможет.

...