Как периодически добавлять новые поисковые хиты на текущую веб-страницу - PullRequest
1 голос
/ 15 ноября 2011

У меня есть самодельный фреймворк / API, и он выполняет поиск в базе данных, который может занять много времени. Долгое время означает от нескольких секунд до минут в зависимости от ввода. Поиск помещает найденные результаты в java.util.concurrent.BlockingQueue. Следовательно, первый результат поиска доступен сразу.

Теперь я хотел бы создать страницу поиска и после отправки результатов поиска страница результатов мгновенно загружается с этими первыми попаданиями, а затем периодически добавляет последующие обращения до завершения поиска. Как я мог это сделать?

1 Ответ

0 голосов
/ 25 ноября 2011

OK. Я придумал решение.

БОЛЬШОЕ ПРЕДУПРЕЖДЕНИЕ: непроверенный для производственного использования!

Используемые зависимости javascript: плагин JQuery, jquery datatables (http://datatables.net) и плагин fnStandingRedraw для datatables.

Зависимости Java: поиск в библиотеке Gson

У меня есть страница поиска, которая отправляется сервлету.

Сервлет начинает поиск и помещает поток поиска и BlockingQueue в сессию, а затем перенаправляет на страницу результатов:

final LinkedBlockingQueue<Integer> hits =
    new LinkedBlockingQueue<Integer>();
Thread searcher = new Thread() {

@Override
public void run() {

    query.search(hits);
}
};
searcher.start();
session.setAttribute("searchQueue", hits);            
session.setAttribute("searchThread", searcher);
response.sendRedirect("SearchResult.jsp");

Обратите внимание, что очередь заполнена первичным ключом из базы данных, следовательно, целым числом.

Страница результатов нуждается в следующих ссылках:

<link href="css/datatables/demo_table.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="js/jquery-1.6.2.js"></script>
<script type="text/javascript" src="js/jquery.dataTables.min.js"></script>               
<script type="text/javascript" src="js/datatables.fnStandingRedraw.js"></script>  

и следующий код JavaScript для инициализации таблицы и добавления строк:

<script type="text/javascript">    
    var resultsTable;
    var myTimer;

    $(document).ready(function() {
        resultsTable = $('#result').dataTable( {
            "bDeferRender": true,
            "bProcessing": true,
            "sPaginationType": "full_numbers",
            "iDisplayLength": 4,            
            "aLengthMenu": [[4, -1], [4, "All"]],
            "sScrollY": "580", 
            "aaSorting": [],
            "aoColumns": [
            /* column1 */   {"bSearchable": true, 
                    "bSortable": true,
                    "sWidth": "50px"},
                /* column2*/{"bSearchable": false, 
                    "bSortable": false,
                    "sWidth": "510px"}
            ]
        } );            
        getAndAddRows();
        startTimer();
    } ); 

    function startTimer() {
        myTimer = window.setInterval( function() {
            getAndAddRows();
        }, 500);
    };

    function stopTimer(){
        window.clearInterval(myTimer);
    }


    function getAndAddRows(){
    $.get(
        'getSearchHits',
        function(data){
            if(data[0] == 'searchCompleted'){
                    stopTimer();
                    $('#hitsFound').text('Hits Found: ' 
                        + resultsTable.fnSettings().fnRecordsTotal()
                        + ' Search Completed');  
                    return;
            }
            $('#result').dataTable().fnAddData(data, false);            
            resultsTable.fnStandingRedraw();
            $('#hitsFound').text('Hits Found: ' 
                + resultsTable.fnSettings().fnRecordsTotal()
                + ' Searching...');  
        }, 
        "json"
        );    
    } 
</script>

<h1 id="hitsFound">Hits Found:</h1>

<table id="result">
    <thead>
        <tr>
            <th>column1</th>
            <th>column2</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table>

Пожалуйста, также обратитесь к домашней странице datatables, чтобы узнать, как настроить такую ​​таблицу. Функция get JQuery периодически вызывается на основе таймера. Он вызывает другой сервлет, который читает из очереди и возвращает новые обращения, отформатированные как JSON:

int limit = 50; //amount of records ro return
int counter = 0;
BlockingQueue<Integer> hits = (BlockingQueue<Integer>) session.getAttribute("searchQueue");
Thread searcher = (Thread) session.getAttribute("searchThread");
Gson gson = new Gson();
ArrayList<ArrayList> rows = new ArrayList<ArrayList>();

while (hits.size() > 0 && limit > counter) {
    ArrayList row = new ArrayList();
    Integer key = hits.take();
    // get desired data and add it to current row example:
    String myData = dataccessObject.getMyData(key); 

    row.add(key);
    row.add(myData);

    rows.add(row);      
    counter++;
}

if (rows.size() < 1 && !searcher.isAlive()) {
    out.print("[\"searchCompleted\"]");
} else {
    String json = gson.toJson(rows); //==> json is [[1,"myData1"],[2,"myData2"]]        
    out.print(json);
}

Лимит и таймеры могут потребоваться отрегулировать в зависимости от вашей цели. Ограничение существует, поэтому новые результаты периодически добавляются. (Если получение данных происходит медленнее, чем скорость, с которой обнаруживаются новые попадания, то ничего не будет возвращено и отображено до завершения поиска).

Обратите внимание, что строка myData может быть HTML, и она отображается как HTML. В моем случае я возвращаю теги изображений. И эти теги изображений имеют другой сервлет в качестве источника, который создает изображения динамически. Обратите внимание, что опция datatables "bDeferRender": true отображает соответствующие строки (и в моем случае изображения), как только они становятся видимыми в первый раз. Например. если пользователь просматривает только первые 3 страницы, страницы 4-100 фактически не отображаются. И если пользователь нажимает на последнюю страницу, то отображается только последняя, ​​а не все между ними.

Пожалуйста, прокомментируйте в случае вопросов или улучшений / возможных ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...