JSP – расширяем возможности представления

Как мы уже видели в предыдущей статье, сервлеты позволяют нам получать запросы от клиента, совершать некоторую работу и выводить ее результаты на экран. До того момента, как надо осуществлять вывод на экран сервлет прекрасно работает. В него можно вставить достаточно сложную логику, сделать вызовы к базе данных и многое-многое другое, что необходимо для приложения. Но вот осуществлять вывод на экран внутри самого сервлета — очень неудобно. В нашем примере мы ограничились крайне простым решением. А что придется делать в случае вывода сложных дизайнерских идей ? Вряд ли Web-дизайнер сможет понять, как надо осуществлять вывод внутри нашего сервлета. И когда он захочет осуществить свои дизайнерские идеи, то ему придется приходить к программисту и просить поменять код сервлета для того, чтобы изменить дизайн. Это надо будет перекомпилировать, надо будет придумывать умные алгоритмы для вывода не только картинок, но и того же JavaScript. Просто кошмар.
Каждому здравомыслящему разработчику ясно, что надо использовать иное решение. Самое очевидное – придумать механизм, который разделил бы задачу на две составляющие: одна часть обрабатывает запрос, меняет данные, собирает данные, укладывает это в некий пакет и передает второй части, которая делает только одно – показывает эти данные.
Так мы подошли к уже известному нам петтерну – Model-View-Controller (MVC). Для случая Web-приложений контроллером у нас становится сервлет, пакет данных, который мы сформировали – моделью. А вот на роль представления (View) прекрасно подходит JSP – Java Server Pages.
В этой статье мы сделаем общий обзор этой технологии. А «Отдел кадров» продолжим в следующей статье, где сможем сразу использовать знакомые технологии – сервлеты и JSP.
Основная идея JSP очень проста – сама страница пердставляет из себя шаблон с уже заготовленными HTML-тэгами, между которыми надо вставить нужные данные. Что-то вроде такого (это только схема)

Чтобы вам не было скучно и для наглядности давайте изменим наш самый первый сервлет HelloWorldServlet из предыдущей статьи. Мы добавим ему возможность работать с параметром, который передадим с помощью URL. Его мы увидим чуть позже. А пока давайте посмотрим на несколько измененный сервлет HelloWorldServlet. Его задача сейчас очень проста – вывести приветствие «Hello, world !» в случае если не будет передано параметра name. Если же он передан, то приветствие несколько изменится. Например, при передаче параметра name=Antonсервлет должен вывести надпись «Hello, world. I’m Anton».
Ничего сложного в задаче нет и ее можно решить без JSP, но для демонстрации нам подойдет.

Самая интересная строка (она же пока и единственная) позволяет нам получить ресурс (в нашем случае это hello.jsp) и передать этому ресурсу наши данные. В данном случае мы ничего не меняли и не добавляли. Теперь давайте посмотрим на файл hello.jsp, который должен представить пользователю некую страницу. В данном случае она не очень сложная, но все-таки мы остановимся на ней подробнее.

Как видите наш HTML-файл представляет из себя смесь тэгов для HTML и кода на Java. По сути JSP при первом обращении преобразуется в сервлет и работает уже как сервлет. Это очень важно понять. JSP НЕ ЯВЛЯЕТСЯ страницей наподобие HTML-страницы — начинающему програмисту важно четко осознавать, что это еще один сервлет — просто его вывод не надо программировать. Его можно просто нарисовать. И в нужные места подставить данные. Но т.к. JSP-страница хоть как-то напоминает HTML, то дизайнеру явно будет проще. И я еще раз НАСТОЙЧИВО говорю начинающим — JSP является СЕРВЛЕТОМ. Ее подготовка со всеми данными происходит на сервере. Именно там подставляются все данные. А пользователю в броузер приходит уже готовая HTML-страница, на которой никаких признаков JAVA нет. Разве что апплет какой-нибудь — но это уже совсем другая технология. Просто JSP удобно использовать — вы делаете логику получения данных в одном сервлете (который не выглядит как JSP) и потом передаете данные другому сервлету (на этот раз в виде JSP), задача которого с помощью этих данных нарисовать HTML-страничку. Только рисовать надо не так много. К тому же вам не надо перекомпилировать классы JSP. Можно просто заменить JSP на более современную и она автоматичски будет скомпилирована заново. Что в общем-то достаточно удобно — просто скопировали нужную страничку на место старой. Как можно видеть код Java заключается в угловые скобки со знаком процента «<%» и здесь вам можно написать любой код, который будет нужен.
Как видите наш код проверяет наличие параметра name в запросе (request.getParameter(«name»)) и, если он существует, то выводится одна надпись. В противном случае мы увидим «укороченный» вариант надписи.
Еще немного информации — JSP имеет в своем составе несколько предопределенных объектов. Т.е. их надо воспринимать, как уже готовые объекты, которые могут быть использованы. Это request, response, out, session, application, config, pageContext и page. Я дам коротенькую справку на них, возможно, что это пока будет не очень интересно, да и не понятно. Но на всякий случай.

request
Это объект HttpServletRequest, связанный с запросом, который позволяет вам обращаться к параметрам запроса (через метод getParameter), типу запроса (GET, POST, HEAD, и т.д..), и входящим HTTP заголовкам (cookies, Referer, и т.д..). Если быть более точным, request является подклассом ServletRequest и может отличаться от HttpServletRequest если используется протокол отличный от HTTP, что на практике практически никогда не встречается. Поэтому про него можно думать, что это HttpServletRequest.

response
Это объект типа HttpServletResponse, связанный с ответом на запрос клиента. Обратите внимание что, поскольку поток вывода (см. out далее) буферизован, можно изменять коды состояния HTTP и заголовки ответов, даже если это недопустимо в обычном сервлете, но лишь в том случае если какие-то данные вывода уже были отправлены клиенту.

out
Это объект типа PrintWriter, используемый для отправки вывода клиенту. Однако, чтобы сделать объект response (см. предыдущий раздел) полезным, следует использовать буферизированный вариант PrintWriter — JspWriter. Помните что вы можете изменять размер буфера и даже отключить буферизацию, изменяя значение атрибута buffer директивы page. Также обратите внимание что out используется практически исключительно скриплетами, поскольку выражения JSP автоматически помещаются в поток вывода, что избавляет от необходимости явного обращения к out.

session
Это объект типа HttpSession, связанный с запросом. Сессии создаются автоматически, и эта переменная существует даже если нет ссылок на входящие сессии. Единственным исключением является ситуация, когда вы отключаете использование сессий используя атрибут session директивыpage. В этом случае ссылки на переменную session приводят к возникновению ошибок при трансляции JSP страницы в сервлет.

application
Это объект типа ServletContext полученный через использование метода getServletConfig().getContext().

config
Это объект типа ServletConfig для текущей страницы.

pageContext
В JSP представлен новый класс PageContext для изолированного использования специфических особенностей сервера, таких как более эффективные JspWriters. Идея заключается в том, что если вы обращаетесь к ним через этот класс, а не непосредственно, ваш код может исполняться на «обычных» движках сервлет/JSP.

page
По сути является синонимом для this, и не нужен при работе с Java. Эта переменная создавалась с расчетом на перспективу, когда возможно появятся другие языки программирования скриптов, отличные от Java.

Давайте все-таки посмотрим на наше творение в действии. Скомпилировать наш сервлет можно командой

javac –cp .;servlet-api.jar students\web\*.java

После этого поместим наш класс HelloWorldServlet в каталог <TOMCAT_HOME>\webapps\studentsApp\WEB-INF\students\web\. А файл hello.jsp в корневой каталог нашего приложения — <TOMCAT_HOME>\webapps\studentsApp.
Теперь наше дерево каталогов несколько проще (мы не используем некоторые классы)

Уже известный файл web.xml будет выглядеть точно так же, как и в предыдущей части

Запускаем Tomcat и потом попробуйте вызвать наше приложение по URL
http://localhost:8080/studentsApp/hello

Если же хотите увидеть мое имя используйте такой URL
http://localhost:8080/studentsApp/hello?name=Anton
Свое имя можно подставить потом 🙂

Custom Tag

Теперь мы можем окунуться немного глубже в JSP. Как вы уже наверняка заметили JSP представляет собой эдакую смесь Java-кода и тэгов HTML. При увеличении сложности логики представления (а JSP используется именно в качестве представления – но даже представление может иметь достаточно изощренную логику – цвета, шрифты и прочая) страница из более-менее понятного HTML превращается в «макароны по-флотски». И дизайнер уже не будет способен что-либо понять. Абсолютно избавиться от логики в JSP скорее всего не получится, но как-то «причесать» код и использовать более удобные средства – такое решение существует. И оно называется CustomTags. По сути это упрощение конструкций JSP, которого хотелось достичь.

Давайте рассмотрим несложный пример того, как можно написать и задействовать свой собственный тэг. Для этого нам потребуется три шага:

  1. Написать TLD-файл (Tag Library Definition) – файл описателя библиотеки тэгов.
  2. Написать класс для реализации самого тэга
  3. Исправить HTML-файл

Итак. Файл TLD имеет расширение .tld и обычно развертывается внутри каталога WEB-INF в каталоге вашего приложения. Хотя можно разместить и в другом. Если у вас много таких файлов, то для них можно предусмотреть отдельный каталог. Вот наш вариант hello.tld.

 

Как вы наверно заметили из описания тэг – это класс HelloTag. Именно он отвечает за отображение информации. Давайте напишем его.

Для сборки нашего сервлета и нового тэга нам потребуется более сложная строка

javac –cp .;servlet-api.jar;jsp-api.jar students\web\*.java students\web\tag\*.java

Новую библиотеку jsp-api.jar можно взять там же где и servlet_api.jar – в <TOMCAT_HOME>\common\lib. Теперь, чтобы подключить наш тэг к приложению, необходимо прописать нашу библиотеку в файле web.xml

Ну и наконец нам нужен пример HTML-файла для использования нашего нового тэга. Использование нашего тэга сделало код нашей странички гораздо симпатичнее.

Теперь нам осталось только разместить наши новый файлы в нужные каталоги и мы можем попробовать наши новые файлы. Итак, вот наша новая структура каталогов:

Мы с вами попробовали очень простой тэг (правда мы его сами написали – и за это нам честь и хвала). Но как вы сами прекрасно понимаете большинство задач требует очень похожих тэгов. Отсюда предсказуемо появилась JSTL – JSP Standard Tag Library – библиотека стандартных тэгов JSP, в которой достаточно большое количество очень удобных тэгов, позволяющих работать с данными — циклы, условия и прочая. Конечно, многие моменты мы не рассмотрели, но думаю, что будет лучше отложить это до следующей статье, которая будет посвящена уже непосредственно нашему проекту «Студенческий отдел кадров». Там мы разработаем общий алгоритм, напишем необходимые сервлеты и JSP, в которых на примере будут показаны те моменты, которые мы не рассматривали здесь.
Итак, мы переходим к заключительной части по сервлетам и JSP — Часть 9 — Простое WEB-приложение

13 comments to WEB: что такое JSP ?

  • Alexey  says:

    Некорректно вставилось. В общем используйте заголовок с DOCTYPE.

  • Aslan  says:

    Здравствуйте, очень полезная статья спасибо за нее, но хотелось бы уточнить, в чем могла быть ошибка, все делал по инструкции, а вылетело вот что:HTTP Status 404 — /tetsApp/hello никак не могу найти причину вроде бы все делал как надо подскажите пожалуйста, я буду очень признателен, заранее спасибо.

    • admin  says:

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

  • Aslan  says:

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

  • V*  says:

    В xml поменял заголовок на DOCTYPE и всё заработало.

  • some8uddy  says:

    Чудесный ресурс, один из немногих с работающими примерами.
    При добавлении секции в .xml файл Tomcat сервер перестает стартовать (ошибка FAIL — Application at context path /stud could not be started), и соответственно появляется ошибка 404.
    Если не добавлять, то Tomcat стартует и весь остальной код работает.
    Пробовал менять заголовок на DOCTYPE, не помогает.

    • some8uddy  says:

      Съело теги. Имелась в виду секция taglib /taglib и все ее содержимое.

      • admin  says:

        Я заменяю знаки «больше» и «меньше» на &lt; и &gt;

  • Dmitry  says:

    Аналогично, помогло.
    Примеры компилировал через IDEA.

    • Dmitry  says:

      Не в ту ветку попало, сорри.
      Я имел ввиду «В xml поменял заголовок на DOCTYPE и всё заработало.».

  • Александр  says:

    Все получилось!!! Большое спасибо за статью!

  • Павел  says:

    Всё заработало, когда УБРАЛ вот это:

    http://www.someurl.ru

    /WEB-INF/hello.tld

    Idea 2016, Tomcat 9, Java 8

  • Павел  says:

    чето не так вставилось. Короче, не вставлял открывающий и закрывающий теги taglib и все что между ними

Leave a reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.