Интеграция JSP и jQuery

Несмотря на то, что на сайте рассматриваются различные технологии, библиотеки и фреймворки, связанные с Java SE/EE, в отдельных случаях нельзя обойтись без JavaScript. Особенно когда возникают вопросы, связанные с частичной перезагрузкой определенной информации на странице или размещением на странице интерактивной диаграммы с анимационными эффектами Chart.js. К примеру, если необходимо обновить на странице параметры учетной записи пользователя или процент выполненной сервером задачи, то не следует перезагружать всю страницу целиком, когда можно обновить только одно или несколько полей. Для этой цели можно использовать библиотеку jQuery с ее асинхронными ajax-запросами (Asynchronous Javascript and XML - асинхронный JavaScript и XML запрос). В данной статье будут представлены примеры интеграции JSP, сервлета и jQuery.

Рассмотрим два примера применения jQuery. В первом примере со страницы JSP отправим серверу асинхронный запрос и отобразим ответ - стандартный пример «Hello World!», когда пользователь вводит свое имя, а сервер его обрабатывает и возвращает ответ. Во втором примере с определенной частотой будем отправлять на сервер асинхронные запросы и на стороне клиента (в браузере) обрабатывать ответы, связанные с анализом процента выполнения задачи. Отправку ajax-запросов на сервер прекратим, как только задача будет выполнена на 100%.

Описание примеров

На следующем скриншоте представлена структура проекта в среде Eclipse, включающего :

  • сервлеты ProgressServlet, UserServlet, вызываемые из браузера при выполнении асинхронных ajax-запросов;
  • скриптовые функции (JavaScript) в файлах app-ajax.js, progress.js, выполняющие ajax-запросы;
  • JSP-страницы index.jsp, progress.jsp

JSP страница timer.jsp и скриптовая функция в файле timer.js приведены только для демонстрации использования JavaScript на JSP-странице.

Дескриптор приложения web.xml

В дескрипторе приложения в тегах <servlet> регистрируем сервлеты (UserServlet, ProgressServlet) и определяем обращения к ним в тегах <servlet-mapping>.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
              http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee">
   <display-name>Web Application</display-name>
   <servlet>
        <servlet-name>jQueryServlet</servlet-name>
        <servlet-class>com.servlets.UserServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>jQueryServlet</servlet-name>
        <url-pattern>/userServlet</url-pattern>
    </servlet-mapping>
   <servlet>
        <servlet-name>ProgressServlet</servlet-name>
        <servlet-class>com.servlets.ProgressServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ProgressServlet</servlet-name>
        <url-pattern>/server</url-pattern>
    </servlet-mapping>
</web-app>

Выполнение запроса без перезагрузки страницы

Пример выполнения запроса к серверу без перезагрузки страницы включает сервлет, выполняющий обработку запроса на стороне сервера, JavaScript функцию, выполняющую обработку ajax-запроса на стороне клиента, и страницу JSP. На следующем скриншоте представлен интерфейс страницы после выполненного ajax-запроса.

Листинг сервлета UserServlet.java

При поступлении запроса в сервлет извлекается имя пользователя, формируется строка ответа, которая записывается в выходной поток в кодировке UTF-8.

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class UserServlet extends HttpServlet
{
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response) 
                                 throws ServletException, IOException
    {
        String userName = request.getParameter("userName").trim();
        if(userName == null || "".equals(userName))
        userName = "Guest";

        String content = "Привет, " + userName;
        response.setContentType("text/plain");

        OutputStream outStream = response.getOutputStream();
        outStream.write(content.getBytes("UTF-8"));
        outStream.flush();
        outStream.close();
    }
}

Листинг скрипта app-ajax.js

Чтобы не загромождать код JSP-страницы не свойственной ее технологии информацией скрипты обработки (JavaScript) вынесены в отдельный файл. Комментарии отражают всю последовательность обработки запроса : сразу же после загрузки страницы выполняется функция и ждет события "потери компонентов фокуса". Как только курсор покидает компонент 'userName' выполняется ajax-запрос. В качестве параметров запроса указывается URL (сервлет, прописанный в web.xml), и data - данные в формате JavaScript. Результат обработки сервером запроса вернется в функцию 'success', которая разместит полученное значение в поле 'ajaxUserServletResponse'.

// вызов функции по завершению загрузки страницы
$(document).ready(function() {
    // вызов функции после потери полем 'userName' фокуса
    $('#userName').blur(function() {
        $.ajax({
            url : 'userServlet',     // URL - сервлет
            data : {                 // передаваемые сервлету данные
                userName : $('#userName').val()
            },
            success : function(response) {
                                     // обработка ответа от сервера
                $('#ajaxUserServletResponse').text(response);
            }
        });
    });
});

Листинг страницы index.jsp

Страница JSP содержит поле ввода 'userName' и поле ответа сервера 'ajaxUserServletResponse'. После ввода имени необходимо покинуть поле 'userName', чтобы ajax-запрос вызвал сервлет. Для этого можно щелкнуть мышью на пустом месте страницы, что приведет к выполнению ajax-запроса сервером и отображению результата запроса на странице. Для правильного отображения символов кириллицы используется кодировка UTF-8, согласованная с кодировкой в сервлете.

<%@ page language="java" contentType="text/html; 
                         charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                      "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" 
              content="text/html; charset=UTF-8">
        <title>Интеграция JSP и jQuery/Servlet</title>

        <script src="http://code.jquery.com/jquery-2.2.4.js" 
                type="text/javascript"></script>
        <script src="js/app-ajax.js" type="text/javascript"></script>
    </head>
    <body>
        <p />
	    Ваше имя : <input type="text" id="userName" /><br />
	    <span style="font-style:italic; font-size:75%">
                сервлет ответит после потери полем курсора</span>
	    <p />
        <strong>Ответ сервлета </strong>: 
                       <span id="ajaxUserServletResponse"></span>
    </body>
</html>

Контроль исполнения сервером задачи

Пример демонстрирует периодическое выполнение ajax-запроса к серверу. «Бедненький» интерфейс страницы, представленный на следующем скриншоте, включает только результат выполнения в виде процентного значения.

Листинг сервлета ProgressServlet.java

Сервлет моделирует процент выполнения задачи. Для этого при каждом запросе к текущему значению добавляется 10%. Полученное новое значение сохраняется в качестве атрибута в сессии и отправляется клиенту.

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ProgressServlet extends HttpServlet
{
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response) 
                                 throws ServletException, IOException
    {
        HttpSession session = request.getSession();
        Integer progress = 0;
        if ((session != null) && 
             session.getAttribute("Progress") != null)
            progress = (Integer) session.getAttribute("Progress");

        progress += 10;
        session.setAttribute("Progress", progress);

        response.setContentType("text/plain");
        response.getWriter().write(String.valueOf(progress));
    }
}

Листинг файла progress.js

Код скриптовой функции вынесен в файл progress.js, загружаемый браузером при открытии страницы. При выполнении ajax-запроса вызывается сервлет 'server', который возращает числовое значение. Если процесс выполнения не завершен, т.е. при значении меньше 100%, выполнение запроса повторится через 2 сек.

function startProgress()
{
    // ajax-запрос к серверу
    $.ajax({
        url : 'server',  // сервлет
        success : function(responseText) {
            // обработка ответа
            $('#progressId').text(responseText + "%");
            var progress = parseInt(responseText);
            // при значении меньше 100 повторить запрос через 2 сек
            if (progress < 100) {
                setTimeout(startProgress, 2000);
            }
        }
    });
}

Листинг страницы progress.jsp

Интерфейс страницы включает только поле 'progressId', в который скриптовая функция записывает процент выполнения задачи.

<%@ page language="java" contentType="text/html; charset=UTF-8"
                         pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                      "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; UTF-8">
      <script src="http://code.jquery.com/jquery-2.2.4.js" 
              type="text/javascript"></script>
      <script src="js/progress.js" type="text/javascript"></script>
      <title>Progress bar</title>
   </head>
   <body onload="startProgress()">
        <p />
        <span id="progressId" style="color: #46f; font-size: 150%;
	                                  font-weight: bold;">0%</span>
   </body>
</html>

Таймер на странице JSP

На статическую WEB-страницу можно загрузить JavaScript код, который без обращения к серверу будет выполнять определенные функции. Данный пример демонстрирует размещение на JSP-странице таймера, который ведет обратный отсчет времени. При старте страницы вызывается функция startTimer, код которой хранится в файле timer.js. Интерфейс страницы включает только поле таймера.

<%@ page language="java" contentType="text/html; charset=UTF-8"	
                         pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                      "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; UTF-8">
      <script src="js/timer.js" type="text/javascript"></script>
      <title>Таймер</title>
   </head>
   <body onload="startTimer()">
        <p><span id="timer" style="color: #4af; font-size: 150%; 
                        font-weight: bold;">01:20:30</span></p>
   </body>
</html>

Листинг функции таймера

Функция таймера читает текущее значение, раскладывает его на часы:минуты:секунды и вычитает секунду. После этого «собирает» новое текущее время и отображает его значение в интерфейсе страницы без перезагрузки. Как только время завершится, процесс обновления времени остановится.

function startTimer() {
    var timer = document.getElementById("timer");
    var time = timer.innerHTML;
    var arr = time.split(":");
    var hh = arr[0];
    var mm = arr[1];
    var ss = arr[2];
    if (ss == 0) {
      if (mm == 0) {
        if (hh == 0) {
          alert("Время вышло");
          window.location.reload();
          return;
        }
        hh--;
        mm = 60;
        if (hh < 10) 
        	hh = "0" + hh;
      }
      mm--;
      if (mm < 10) 
    	  mm = "0" + mm;
      ss = 59;
    } else ss--;
    if (ss < 10) 
        ss = "0" + ss;
    document.getElementById("timer").innerHTML = hh+":"+mm+":"+ss;
    setTimeout(startTimer, 1000);
}

Скачать пример

Рассмотренный пример в виде проекта Eclipse с использованием maven можно скачать здесь (2.3 Кб).

  Рейтинг@Mail.ru