Как настроить смартфоны и ПК. Информационный портал
  • Главная
  • Windows Phone
  • Jsp описание для чего используется. Как можно предотвратить прямой доступ к JSP странице из браузера? Комментарии и символы цитирования

Jsp описание для чего используется. Как можно предотвратить прямой доступ к JSP странице из браузера? Комментарии и символы цитирования

Технология Java Server Pages (tm) (JSP) позволяет разработчикам и дизайнерам web-приложений быстро разрабатывать и легко сопровождать web-страницы с динамическим наполнением информацией. Но описание практически каждой технологии подобного назначения (ASP, PHP, Net.Data) сопровождают подобные слова -- быстро и легко...

При внешней схожести JSP отличают некоторые моменты, делающие данную технологию чем-то большим, чем ещё одно средство для создания динмически генерируемого содержания web-страниц.

Сначала простое перечисление:

  • действительно высокая межплатформенная переносимость; использование универсального языка высокого уровня Java в качестве скриптового;
  • JSP -- это не какое-то отдельно стоящее средство для решения достаточно узкого круга задач, пусть и достаточно мощное, а ещё одно в ряде целой плеяды технологий, объединяемых Java;
  • реальная возможность разделить задачи написания бизнес-логики web-приложения и пользовательского интерфейса, что позволяет разрабатывать и сопровождать различные части проекта независимо;
Технология JSP является прямым расширением ещё одной Java-технологии -- Servlets (tm) а также тесно связана с технологией Java Beans (tm) и использует XML-подобные теги (tags) и скриптлеты (scriptlets), написанные на языке программирования Java для введения логики создания динамического наполнения web-страницы, при этом HTML или XML-теги передаются клиентской стороне напрямую.

Количество тегов достаточно невелико, что упрощает начальное освоение данной технологии; впрочем, для простых вещей та же Net.Data или PHP тоже весьма просты. Как водится, рассмотрим примитивный случай класса Hello World!
<%@ page contentType="text/html; charset=ibm866" %> <%@ page import ="java.net.*" %> <%@ page import ="java.util.Date" %> Who Am I? <% InetAddress localHost = InetAddress.getLocalHost(); Date localTime = new Date(); %>

Who Am I?

I am called <%= localHost.getHostName() %> (<%= localHost.getHostAddress() %>).
This page last executed at <%= localTime.toString() %>.

Даже у человека, не знающего Java, понимание вышеприведенного кода, скорее всего, не вызовет проблем. Остановимся на некоторых моментах: код, находящийся внутри тегов <% %> , собственно и есть код скриптлета; всё находящееся между <%-- --%> -- комментарий; тег <%= позволяет вывести значение переменной в нужном месте страницы; <%@ page %> позволяет импортировать классы и также настраивать некоторые особенности в поведении страницы.

Если мощь таких конкурирующих (наверное, это всё-таки так;-) инструментов, как PHP и Net.Data, обусловлены в первую очередь огромным набором предопределённых функций, то за JSP стоит весь конгломерат классов и технологий Java.

Но на таком простом примере вовсе не очевидно, почему нужно выбрать JSP и всё с ними связанное, в первую очередь servlets и beans. Тем не менее попытаемся рассмотреть некоторые приятные стороны JSP.

Session Management

Значения, которые сохраняются и извлекаются из объекта сессии, не могут быть примитивными типами данных (int, double) и должны быть представлены в виде своих классов-аналогов (Integer, Double).
HttpSession session=request.getSession();//get session object or create one session.getId() //get the session ID number Integer item = (Integer) session.getValue("item") // retrieve Integer object session.putValue("ItemValue", itemName);//ItemValue must not be primitive

Application Management

Иногда необходимо обеспечить сервером некоторых значений переменных на уровне сайта, каждый клиент использует и манипулирует копиями этих данных. JSP использует объект ServletContext, который обеспечивает механизм, схожий с сессией (i.e. no primitive types).
getServletContext().setAttribute("Item", ItemValue);//to set an application variable Integer i=(Integer)getServletContext().getAttribute("ItemName");//get item color=blue>

JSP-Specific Language

Директивы JSP "говорят" серверу делать что-либо, когда они преобразуются из JSP в сервлет; директивы предваряются символом @. Некоторые важные директивы JSP перечислены ниже, для более полного знакомства естественно придется почитать что-то ещё.
include - включение статического или динамического файла (Server Side Include) <%@ include file="hello.jsp" %> import - итоговый сервлет будт импортировать данный пакет <%@ import = "java.util.*" %> extends - сервлет будет расширять (наследовать) указанный класс (это superclass) <%@ extends = "java.util.Dictionary" %> implements - сервлет будет имплементировать интерфейс <%@ implements = "java.util.Enumeration" %> content_type - устанавливает тип ответа, генерируемого сервлетом <%@ content_type = "text/plain" %> или <%@ content_type = "text/html" %>

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

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

Есть два варианта include:

  • Статическое включение , при этом обрабатываются JSP-элементы во включаемом файле, если они есть и попадают в результирующий сгенерированый Java-код, фактически серлет:
    <%@ include file="includeheader.jsp"%>
    или так
    <%@ include file="includeheader.html"%>
    то есть включаемый файл вовсе не обязан быть JSP страницей.
  • Динамическое включение , при этом контент включаемого файла обрабатывается независимо, фактически ему передается управление на момент выполнения:
Что интересно, динамически включенный контент может кэшироваться независимо, что в некоторых случаях даёт существенный выигрыш на сложных многокомпонентных страницах. Но возможность include тем не менее, наверное, самое примитивное из многогранных возможностей JSP.

Практически каждый, начав делать web-приложение, сталкивается с необходимостью предоставить пользователю удобное средство для ввода информации, и тут, как правило, возникают бо льшие проблемы, чем просто с предоставлением информации в виде сгенерёных HTML-страниц. Необходимо обеспечить достаточную интеллектуальность ввода, кроме того, при ошибках ввода не терять ранее введённое и передавать требуемую общую информацию от страницы к странице. В Net.Data, например, я не нашёл способа делать это иначе, чем использовать hidden-поля в формах ввода, хранение же информации с временем жизни "session" вырастает в сложную задачу; как можно выкрутиться с решением этой задачи в PHP, я не в курсе. Что же касается JSP/servlets -- есть стандартное средство JavaBeans (в данном контексте не будем останавливаться на таком более мощном развитии данной концепции, как EJB) -- это полноценные классы Java с некоторыми дополнительными правилами программирования.

Это очень мощное средство, но оно требует некоторой ломки стереотипов. JavaBeans -- это компоненты Java, которые могут выполнять хорошо определённые задачи и включать в себя объекты данных. JavaBeans следуют структурной объектной модели: Bean имеет public constructor, который не имеет аргументов, и его свойства устанавливаются с помощью управляющего сервлета с использованием интроспекции (introspection/reflection).

Включение некоторого бина в "страницу" JSP делается например так:

... Дополнение <%=formHandler.getErrorMsg("description")%> Владелец <%= formHandler.getOwnerName()%> | <%= formHandler.getOwnerName()%> <%=formHandler.getErrorMsg("owner")%> ===> или вот ещё один
I like <%= Cindy.getFlavor() %> coffee. //The Coffee Bean: Public class Coffee { private String m_flavor; public Coffee() { m_flavor = "Regular"; } public void setFlavor(String flavor) { m_flavor = flavor; } public String getFlavor() { return m_flavor; } }

Некоторые пояснения к этой выжимке: scope="request" означает, что время жизни бина -- request, property="*" означает, что данный бин принимает с помощью своих методов все параметры, переданные в запросе на данную страницу. Эти методаы имеют простое правило именования: если параметр формы -- lastName, то метод, принимающий данные, будет иметь имя setLastName, а отдающий данные -- getLastName.

К сожалению, достаточно трудно продемонстрировать всю мощь использования бинов в простом приложении. Впрочем, данная статья и не ставит своей целью дать всю глубину, задача заинтересовать.

Генеральная линия, которая прослеживается во множестве публикаций последнего времени -- разделение работы дизайнера и работы программиста, обеспечивающего написание собственно работы с базой данных и бизнес-логику web-приложения. Большая часть этого может быть вынесена именно на уровень бинов. К сожалению, трудоемкость написания, по крайней мере на начальном этапе, у связки JSP-servlets-beans выглядит большей, чем у Net.Data и PHP (впрочем, с последним я знаком на уровне чуть большем "Hello World!"). Но даже использование бинов не освобождает совсем от минимального использования Java на странице. Чтобы дойти до логического конца и оставить дизайнеру только правильную расстановку тегов на странице, в JSP ввели возможность написания библиотек тегов (custom JSP tag libraries).

Использование библиотек тегов позволяет, во первых, ещё повысить повторное использование кода, во вторых, снизить сложность написания прриложения, и, в третьих, ещё больше помочь в разделении труда. К сожалению, последнее в нашей действительности ещё не приобрело должного веса при выборе средства разработки. В заключение приведу небольшой пример использования пользовательских тегов, например, запрос к базе с выводом результата в виде таблицы может выглядеть вот так:
<%@ taglib uri="xsql.tld" prefix="xsql" %> ...

что-тонечтоописание
"$1$""$2$""$3$"
но это вовсе не значит, что он должен так выглядеть;-)

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

JSP (Java server pages) — это технология, которая позволяет внедрять Java-код, а также EL (expression language) в статичное содержимое страницы) и позволяющая веб-разработчикам динамически генерировать HTML, XML и другие веб-страницы. JSP является составной частью единой технологии создания бизнес-приложений J2EE.

JSP — может выполняться практически на любом веб сервере, так как эта технология основана на языке программирования Java, который не зависит от платформы. Java server pages поддерживает теги HTML, Javascript, а также собственный набор тегов.

JSP — позволяет отделить динамическую часть страницы от статической. Эта технология предусматривает вставку Java кода в страницу. Мы не будем рассматривать такой вариант использования JSP поскольку эта технология считается устаревшей и несовершенной. Причина проста: разработчики дизайнеры, которые разрабатывают внешний вид страницы не всегда могут быть знакомы с Java и это может вызвать дополнительные трудности при редактировании или поддержке веб приложений.

Вместо вставки Java кода сейчас используется библиотека тегов jstl или Javascript для совсем продвинутых. Мы рассмотрим пример именно с jstl тегами. Это очень удобная библиотека, которая имеет почти весь функционал, который необходим при создании динамических страниц. Если нужно что-то специфическое, то всегда можно написать собственный тег и вставить его содержимое на страницу.

Мы уже частично знакомы с JSP по первым . Основная часть JSP страницы это HTML, в которую вставляются теги с динамическим содержимым.

Пример JSP страницы

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

Директива JSP — это сообщение, которое страница может послать соответствующему контейнеру с указанием действий. Синтаксис директивы:<% @ атрибут = «значение» %>

Есть три основных типа директив:

  1. page (может использоваться для импорта классов);
  2. include (дает вам возможность вставить файл в класс сервлета при трансляции JSP файла в сервлет);
  3. taglib (дает возможность подключить библиотеку тегов).

Так, как код в страницу мы вставлять не будем, рассмотрим последние две директивы.

Например у нас есть страницы, которые будут иметь одинаковую верхнюю и нижнюю часть. Очень распространенный шаблон, в котором футер и хедер одинаковы для всех страниц. Для того, чтобы не писать Код этих страниц в каждом JSP файле можно вынести их код в отдельный файлы и потом подключить в нужном нам месте с помощью директивы include.

Расположение файлов в проекте:

В коде выше можно проследить использование директивы taglib. С ее помощью мы подключили библиотеку тегов jstl. С помощью этой директивы можно подключить библиотеку собственных тегов: <%@ taglib uri=»/WEB-INF/mylib.tld» prefix=»test» %>.

Заметьте, что важным атрибутом taglib является prefix. Это обязательный к использованию атрибут. С помощью prefix можно вызывать библиотеку в коде. Имя prefix можно выбирать любое. К стати, вот и использование jstl тегов на деле:

    < c: forEach items= "${accounts} " var = "account" >

    < tr align= "center" >

    < td> ${ account. number}

    < td> ${ account. balance}

    < td>< c: if test= "${!account.isBlocked}" > ${ statusActive }

    < c: if test= "${account.isBlocked}" > ${ statusBlocked }

    < td>< c: if test= "${!account.isBlocked}" >

    < a href= "?command=blockaccount&accountId=${account.accountId}" > ${ block }

    < td>< a href= "?command=showinfo&accountId=${account.accountId}" > ${ showInfo }

Код выше демонстрирует вывод всех элементов списка. О том, как мы его передали на страницу будет в следующих статьях. Его синтаксис:

${item}

Это код сайдбара, который подключался выше. Как видим, здесь используется разветвления, чтобы вывести только ту информацию, которая доступна определенном типу пользователя.

Синтаксис:
a equals b

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

К стати, код проекта, с которого был взят этот код, находится тут: https://github.com/caligula95/payment-systemapp

Я выложил проект на heroku: https://payment-systemapp.herokuapp.com/ — тут используется бесплатный аккаунт, так что для первого запроса нужно подождать пару минут, чтобы проект запустился.

Cервлеты позволяют получать запросы от клиента, совершать некоторую работу и выводить результаты на экран. Сервлет прекрасно работает до того момента, пока речь идет об обработке информации, т.е. до вывода информации на экран. В сервлет можно вставить достаточно сложную логику, сделать вызовы к базе данных и многое-многое другое, что необходимо для приложения. Но вот осуществлять вывод на экран внутри самого сервлета - очень неудобно. А как быть при разработке сложных дизайнерских идей и последующее внесение изменений в пользовательский интерфейс? Технология проектирования Java Server Pages (JSP) - это одна из технологий J2EE, которая представляет собой расширение технологии сервлетов для упрощения работы с Web-содержимым. Страницы JSP позволяет легко разделить Web-содержимое на статическую и динамическую часть, допускающую многократное использование ранее определенных компонентов. Разработчики Java Server Pages могут использовать компоненты JavaBeans и создавать собственные библиотеки нестандартных тегов, которые инкапсулируют сложные динамические функциональные средства. Спецификация Java Server Pages (http://java.sun.com/products/jsp) наследует и расширяет спецификацию сервлетов (http://java.sun.com/products/servlets). Как и сервлеты, компоненты JSP относятся к компонентам Web и располагаются в Web-контейнере. Страницы JSP не зависят от конкретной реализации Web-контейнера, что обеспечивает возможность их повторного использования. В дополнение к классам и интерфейсам для программирования сервлетов (пакеты javax.servlet и javax.servlet/http ), в пакетах javax.servlet.jsp и javax.servlet.jsp.target содержатся классы и интерфейсы, относящиеся к программированию Java Server Pages. Полное описание технологии Java Server Pages можно найти в спецификации по адресу (java.sun.com/products/jsp/download.htm)

Обзор технологии Java Server Pages

Технология Java Server Pages содержит четыре ключевых компонента:
  1. Директивы (directive) представляют собой сообщения для контейнера JSP, дающим возможность определить параметры страницы, подключения других ресурсов, использовать собственные нестандартные библиотеки тегов.
  2. Действия (actions) инкапсулируют функциональные возможности в предопределенных тегах, которые можно встраивать в JSP-страницу. Действия часто выполняются на основе информации, посылаемой на сервер в составе запроса от определенного клиента. Действия также могут создавать объекты Java для использования их в скриптлетах JSP.
  3. Скриптлеты (scriptlets) позволяют вставлять код Java в страницы JSP, который взаимодействует с объектами страницы при обработке запроса.
  4. Библиотеки тегов (tag library) являются составной частью механизма расширения тегов, допускающего разработку и использование собственных тегов.
Наличие данных с неизменяемой структурой определяют выбор программиста в принятии решения, какую технологию следует использовать: сервлеты или страницы JSP. Программисты предпочитают использовать страницы JSP, если основная часть посылаемого клиенту содержимого представляет собой данные с неизменяемой структурой, и лишь небольшая часть содержимого генерируется динамически с помощью кода Java. Сервлеты предпочтительнее использовать, если только небольшая часть содержимого, посылаемого клиенту, представляет собой данные с неизменяемой структурой. На самом деле отдельные сервлеты могут вообще не генерировать содержимого для клиента, выполняя определенную задачу в интересах клиента, а затем вызывают другие сервлеты или JSP-страницы, чтобы отправить ответ. Необходимо заметить, что во многих случаях сервлеты и JSP-страницы являются взаимозамеяемыми. Подобно сервлетам, JSP-страницы обычно выполняются на стороне Web-сервера, который называют контейнером JSP. Когда Web-сервер, поддерживающий технологию JSP, принимает первый запрос на JSP-страницу, контейнер JSP транслирует эту JSP-страницу в сервлет Java, который обслуживает текущий запрос и все последующие запросы к этой странице. Если при компиляции нового сервлета возникают ошибки, эти ошибки приводят к ошибкам на этапе компиляции. Контейнер JSP на этапе трансляции помещает операторы Java, которые реализует ответ JSP-страницы, в метод _jspService. Если сервлет компилируется без ошибок, контейнер JSP вызывает метод _jspService для обработки запроса. JSP-страница может обработать запрос непосредственно, либо вызвать другие компоненты Web-приложения, чтобы содействовать обработке запроса. Любые ошибки, которые возникают в процессе обработки, вызывают исключительную ситуацию в Web-сервере на этапе запроса . Весь статический текст HTML, называемый в документации JSP шаблоном HTML (template HTML), сразу направляется в выходной поток. Выходной поток страницы буферизуется. Буферизацию обеспечивает класс JspWriter , расширяющий класс Writer . Размер буфера по умолчанию ограничен до 8 Кбайт, но его можно изменить атрибутом buffer тега <%@ page> . Наличие буфера позволяет заносить заголовки ответа в выходной поток совместно с выводимым текстом. В буфере заголовки будут размещены перед текстом. Таким образом, достаточно написать страницу JSP, сохранить ее в файле с расширением jsp и установить файл в контейнер, так же, как и страницу HTML, не заботясь о компиляции. При установке можно задать начальные параметры страницы JSP так же, как и начальные параметры сервлета.
1) NetBeans 7.3;
2) Maven;
3) Hibernate;
4) Spring MVC;
5) JSP+JSTL;
6) Знание про Сервлеты, Сессии, JavaBean, XML и т.д.;
7) HTML+CSS (немного красоты по Вашему вкусу, но лучше заплатить левым людям, - у Вас с серверной стороной итак хлопот хватит);
8) Java SE (знание коллекций, умение обрабатывать исключения… В общем, стандартный набор);
9) Знание паттернов проектирования (DAO, Factory);
10) JPA;
11) SVN;
12) SQL (для написания скриптов, заполняющих наши БД).

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

SVN

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

После всего этого у Вас будет ссылка на Ваше пространство. Чтобы понять, что это такое - нужно взять один из ваших проектов (или создайте какой нибудь пустой проект в NetBeans). Нажимаете на нем правой кнопочкой и у Вас в меню будет доступно «Управление версиями» -> «импортировать в репозиторий Subversion». После этого будет диалоговое окно, в котом будет путь к репозиторию - это ссылка которую Вы получили на сайте во вкладке «Исходный код».

Далее, полностью удалите проект, который вы закоммитили. Дальше зайдите в папку, где у вас проекты хранятся, и проверьте что реально все удалено. Потом возвращаетесь в NetBeans и ищете в панели меню вкладку Группа(на панели где Файл, Вид, Правка, Переход, Источник...) в нем есть наш Subversion. И в подменю на нем есть «Получить». Дальше в диалоговых окнах надо будет указать ссылку на репозиторий (это ссылка которую вы получили на сайте во вкладке «Исходный код».) И когда он предложит выкачивать папки, то по дереву репозитория нужно будет найти ваш проект и выбрать его, и по окончанию вы выкачаете свой проект. Вот так происходит обмен кодом.
Ваш проект будет постоянно синхронизироваться с репозиторием и помечать файлы, которые были изменены, или новые(то что отличается от версии на репозитории). Чтобы обновить, нужно вызвать контекстное меню, и в закладке «Управление Версиями» будет большой список того, что можно делать с проектом. «Обновлять» - это обновить свои файлы; «Фиксировать» - ложить код который Вы написали или изменили в репозиторий; «Сбрасывать» - возвращаться к версии на репозитории, и «Сравнивать» - отображение изменений строк которые отличаются от удаленных. Это способ командного обмена кодом, который используется всегда и нужно к нему привыкать.

Вы уже скачали NetBeans, поигрались с SVN - теперь перейдем к делу. Создаете проект. Нажимаете «Создать проект», там выбираете Maven-> Веб-приложение. Называете как хотите, это все Ваша фантазия. Итак, у нас есть веб-приложение, сборка нашего проекта идет мавеном, у нас есть цель и теперь наступило время подумать над тем, как ее осуществить. То есть Вы, как разработчик, должны подумать над тем, как будет выглядеть Ваше приложение, какую иметь архитектуру, дерево пакетов и так далее. Общее количество строк кода здесь около 4000 и лучше позаботиться о красивой архитектуре заранее, иначе потом Вы просто не будете понимать что где и как у Вас работает, каким чудом Вы, к примеру, выводите последнюю купленную вещь, как считаете общую сумму покупок. И если Вас потом попросят что-то доделать или добавить - Вы осознаете что проще написать все с нуля.

Ну и конечно нам нужно прикинуть наш план действий.

Итак: План действий
1) описываем entity(entities) - сущности. Это POJO - класс, связанный с БД с помощью аннотации (@Entity) или через XML. Использовать будем JPA, поэтому импортировать надо javax.persistence.* Почему не Hibernate Persistence API, т.к если использовать его и потом мы захотим сменить ORM библиотеку, то придется переписывать и наши классы, а JPA - это стандарт от Sun. По поводу того, что такое JPA - ну для Вас могу своими словами сказать так: это библиотека предоставляющая API для работы с *долго живущими* объектами, то есть позволяет нам удобно сохранять наши объекты в БД. Могу дать совет: создайте для этого отдельный пакет назовите его entity или domain - как хотите, главное чтобы Вам было понятно. В конечном итоге это может выглядеть так: edu.shop.model.domain.Customer.java edu.shop.model.domain.Notebook.java.
Подробнее буду описывать непосредственно при рассмотрении данного пункта. Сейчас задача стоит прикинуть план действий.

2) Создаем HibernateUtil (вообще суффикс или приставка Util подразумевает, что код в этом классе есть универсальный и используется множеством классов).
Итак, в HibernateUtil мы размещаем SessionFactory. Он тяжеловесный. Этот код, по идее, должен быть независим от всего приложения, так как он устанавливает соединение с базой данных при старте и должен нам давать только Сессии с базой данных. Еще мы в этом классе регистрируем наши классы-сущности. Подробнее про этот класс расскажу позже. Засунем его тоже в отдельный пакет, к примеру, edu.shop.model.hbutil.HibernateUtil.java

3) Пишем DAO.
Что в нем писать? Пишем то, что мы хотим получить от базы данных, но нам не нужно думать как получились эти данные, важен результат. К примеру, мы определяем интерфейс ProductDAO и пишем в нем методы
List> getAllProducts(); потом пишем его реализацию ProductDAOImpl.

В чем идея? Если бы это приложение писал я и Вы, Вы бы сказали: «Миха, мне нужны от БД следующие данные: все товары что у меня есть в БД». Я отвечаю: «не вопрос». И далее следующее развитие событий: вы в своем коде, везде где нужно делать запросы к базе пишете следующее%

*здесь обращение к методу*.getAllProducts(); - и видите, что компилятор не ругается, а реализацию этого интерфейса я мог еще не успеть написать. И какой итог? У Вас все скомпилилось, а рабочего кода даже нет. Здесь мы применим Enums и паттерн Factory, и еще кое-что, но всему свое время. Именно в DAO нужно уделить особое внимание обработке исключений, хотя бы генерировать страницы с ошибками. Чтобы Вы быстро находили кусок неработающего кода. Иначе, Вы просто замучаетесь с отладкой.

3)Здесь начнется наша работа с Spring MVC. Это долгая история и этому будет посвящена отдельная статья. Сразу скажу - это самое сложное в этом приложении. Но я Вам покажу и более простой вариант, как выводить все, не особо заботясь про паттерн MVC.
Затронем использование скриплетов.

4) Здесь у нас будут вспомогательные классы, добавляющие всякие вкусности в наш проект: подсчет общей суммы покупок; последняя купленная вещь; вспомогательные переменные, которые пригодятся нам для работы метода, который, к примеру, будет выводить нам с БД вещи не дороже 5000 грн, или не дешевле 500; вывод всех ноутбуков марки Асус. Этот пункт тесно взаимосвязан с предыдущим.

Пока остановимся на этом. С остальным разберемся чуть позже. Итак, у нас есть намеченный план, приступим к его реализации.

Entity

Мы создали наш проект и создали наш пакет с сущностями. Пусть это будет edu.shop.entity. Там мы создаем такие классы:

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

1) Product
2) Notebook
3) Camera
4) Book
5) Cable
6) Customer
7) Cart

Поговорим немного о том, что такое класс-сущность.
Entity (Сущность) - POJO-класс, связанный с БД с помощью аннотации (@Entity) или через XML. К такому классу предъявляются следующие требования:

Должен иметь пустой конструктор (public или protected);
- Не может быть вложенным, интерфейсом или enum;
- Не может быть final и не может содержать final-полей/свойств;
- Должен содержать хотя бы одно @Id-поле.

При этом entity может:

Entities могут быть связаны друг с другом: один-к-одному, один-ко-многим, многие-к-одному и многие-ко-многим.

Использовать мы будем аннотации. И тут сразу у нас появляется возможность описать двумя способами. Либо мы будем писать аннотации непосредственно над полями, либо над геттерами. Скажу одно: правильно писать над геттерами, а причину Вы спросите в гугле. Не могу я все темы абсолютно здесь описать.

Есть еще одно что хочу сказать. Для этого придется показать 2 примера описания класса сущности. Итак, первый пример:
Коментарии к нему я написал в самом коде:

Import java.io.Serializable; import javax.persistence.*; import javax.validation.constraints.Size; /** * * @author Mikhail Shumenko */ @Entity //Этой аннотацией мы указываем, что данный класс является сущностью. @Table(name = "CART")// Этой аннотацией мы указываем, что за эту сущность в БД отвечает таблица с именем CART //Хочу отметить, что регистр не важен, эту анотацию можно не указывать, тогда хибернейт создаст нам БД с //именем как у класса public class CartEntity implements Serializable { //Здесь мы пишем аннотации над полями. Правильно писать над геттерами //Описываем Id таблицы @Id //Указываем, что это поле класса отвечает за столбец в таблице с именем Id //Если мы его указывать не будем, хибернейт создаст столбец с именем как у поля. @Column(name = "ID") //Здесь написать можно много)) Почему я написал здесь так? В общем можно в //@GeneratedValue(strategy=GenerationType.вместо TABLE написать AUTO) тогда //при первой загрузке таблицы, Id сгенерируются автоматически от 1 до своего максимального значения. //Если у вас 20 вещей в таблице, то сгенерируется от 1 до 20. //Но при последующих добавлениях, id у добавленной вещи будет примерно таким - 345768. //Я написал все так, чтобы последний мой id хранился в таблице и генерировался потом адекватно при последующих добавлениях. //Также есть SEQUENCE, но он не поддерживается в Derby, а работать мы будем именно с ней. //В общем, это нюансы. Можете узнать про них самостоятельно @TableGenerator(name = "cartid", table = "cartpktb", pkColumnName = "idCart", pkColumnValue = "idCartValue",allocationSize = 1) @GeneratedValue (strategy = GenerationType.TABLE, generator = "cartid") private Integer id; //Указываем максимальный размер. Это строка из 25 символов. @Size(max = 25) @Column(name = "NAMEITEM") //Если тип нашего поля String, то и создаваться будет столбец с типом VARCHAR(в Derby) //Если Integer, то будет столбец, в который поместить можно только Integer //boolean в Derby - это столбец с типом SMALLINT private String nameItem; @Column(name = "PRICE") private Integer price; public CartEntity() { } public CartEntity(String nameItem, int price) { this.nameItem = nameItem; this.price = price; } public CartEntity(Integer id,String nameItem, int price) { this.id=id; this.nameItem = nameItem; this.price = price; } public CartEntity(Integer id) { this.id = id; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNameItem() { return nameItem; } public void setNameItem(String nameItem) { this.nameItem = nameItem; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } }

Второй способ: пишем над геттерами. Пояснения смотрим в коде.

import java.io.Serializable; import javax.persistence.*; /** * * @author miha */ @Entity //Видите, я не указывал аннотацию @Table //Hibernate все поймет за меня. public class Product implements Serializable { private Integer id; private String nameProduct; private Integer availableProduct; @Id @GeneratedValue(strategy = GenerationType.AUTO) //Я описал Id над геттером, значит, и с остальными полями работа будет идти через геттеры. public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNameProduct() { return nameProduct; } public void setNameProduct(String nameProduct) { this.nameProduct = nameProduct; } public Integer getAvailableProduct() { return availableProduct; } public void setAvailableProduct(Integer availableProduct) { this.availableProduct = availableProduct; } }

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

Теперь приведем пример нашего HibernateUtil

/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package edu.shumenko.hibernate; import edu.shumenko.entity.BookEntity; import edu.shumenko.entity.CableEntity; import edu.shumenko.entity.CameraEntity; import edu.shumenko.entity.CartEntity; import edu.shumenko.entity.CustomerEntity; import edu.shumenko.entity.NotebookEntity; import edu.shumenko.entity.ProductEntity; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.SessionFactory; /** * Hibernate Utility class with a convenient method to get Session Factory * object. * * @author Mikhail Shumenko */ public class HibernateUtil { //Создаем нашу SessionFactory. private static final SessionFactory sessionFactory; static { try { //Создаем новый екземпляр AnnotationConfiguration AnnotationConfiguration ac = new AnnotationConfiguration(); //Это нам нужно для того, чтобы мы добавили все наши классы сущности. //каждый ваш Entity здесь нужно прописать, не пропишете - не будет работать. ac.addAnnotatedClass(ProductEntity.class).addAnnotatedClass(BookEntity.class).addAnnotatedClass(CableEntity.class) .addAnnotatedClass(CameraEntity.class).addAnnotatedClass(NotebookEntity.class). addAnnotatedClass(CartEntity.class).addAnnotatedClass(CustomerEntity.class); //Вот мы собственно и создали нашу Фабрику сессий. //Она нужна т.к с БД мы работаем через сессии //Подробности будут чуть позже, пока знайте, как ее сделать и как с ней работать. sessionFactory = ac.configure().buildSessionFactory(); } catch (Throwable ex) { // Log the exception. System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }

DAO

Приступим к следующей части. Что такое DAO. Это шаблон проектирования.

Его смысл:
- Весь доступ к базе данных в системе производится через DAO для инкапсуляции.
- Каждый экземпляр DAO отвечает за один первичный доменный объект или сущность. Если доменный объект имеет независимый цикл жизни, он должен иметь свой собственный DAO.
- DAO отвечает за операции создания, чтения (по первичному ключу), обновления и удаления (то есть, CRUD (create, read, update, delete)) доменного объекта.
- DAO может разрешать запросы, основанные на критерии, отличном от первичного ключа. Я ссылаюсь на такие методы как finder или finders. Метод finder обычно возвращает коллекцию доменных объектов, за которые отвечает DAO.
- DAO не занимается обработкой транзакций, сессий или соединений. Это делается вне DAO для обеспечения гибкости.
Подробнее всегда расскажет гугл.

Мы пока напишем DAO для наших продуктов.
Итак, подумаем что нам вообще нужно. Таблица Product будет иметь 4 поля Id,nameProduct,available+amount+actionForServlet. Она нам будет нужна, чтобы создать на нашем сайте категории. Над последним полем пока не заморачиваемся. Единственное что нам нужно - это получение списка продуктов.

Пишем интерфейс
public interface ProductDAO { ProductDAO INSTANCE_PRODUCT= new ProductDAOImpl(); ListGetProducts(); //и метод с которым мы будем работать }

Реализация нашего интерфейса. Пояснения смотрим в коде
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package edu.shop.model.dao; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Session; /** * * @author Mikhail Shumenko */ public class ProductDAOImpl implements ProductDAO { @Override public ListGetProducts() { ListResult = null; //Создаем сессию, она нужна для использования транзакций //Грубо говоря, транзакция - это как точка восстановления, если не прошла до конца, то все изменения откатываются. Session session = HibernateUtil.getSessionFactory().openSession(); try { session.beginTransaction().begin(); //Criteria используется для запроса с целью получения данных из БД //Такой формулировки, думаю, Вам пока хватит //Параметром мы передаем тот класс-сущность, который используем. Если бы данные получали из таблицы Cart то передавать //надо было бы Cart.class Criteria criteria = session.createCriteria(Product.class); result = (List) criteria.list(); session.getTransaction().commit } catch (Exception e) { //Обработку исключений обязательно пишите. Но это я оставлю Вам на самостоятельную работу. e.printStackTrace(); }finally { if (session != null) session.close(); } return result; } }

Итак, теперь у нас есть возможность получать данные из БД. Вы можете, используя скриплеты, создать незамысловатый цикл for-each и вывести свою продукцию на вашу страницу index.jsp

Категории

//INSTANCE_PRODUCT что это такое? //В ProductDAO описана такая переменная, отвечает за создание ProductDAOImpl //Ну у нас все будет по-другому, можете особо не запоминать это. //ProductDAO INSTANCE_PRODUCT= new ProductDAOImpl(); <% for (Product product:ProductDAO.INSTANCE_PRODUCT.getProducts()) {%> <%}%> <% for (Product product: ProductDAO.INSTANCE_PRODUCT.getProducts()) {%> <%}%>
Категория"><%=product.getName()%>
Наличие<%=product.getAvailable()%>

Но это на первое время, а вообще так делать плохо. Это нарушает наш паттерн MVC. Как сделать правильно я объясню в следующем уроке, если мне дадут инвайт. Во втором уроке мы займемся Spring, в третьем коснемся паттерна Factory, и углубимся в хибернейт. Для особо нетерпеливых, покажу как нужно удалять из БД, сохранять в БД и удалять полностью все из БД. Ну, а как сделать, чтобы все это взаимодействовало в целом с нашим приложением и подробное рассмотрение оставим на потом.

Сохранить в БД

public void addItemToCart(CartEntity cart) { Session session = HibernateUtil.getSessionFactory().openSession(); try { session.beginTransaction().begin(); session.save(cart); session.getTransaction().commit(); } catch (Exception ex) { ex.printStackTrace(); } finally { if (session != null) { session.close(); } } }

Удалить из базы по id

public void deleteItemFromCart(Integer id) { Session session = HibernateUtil.getSessionFactory().openSession(); try { session.beginTransaction().begin(); CartEntity itemDelete = (CartEntity) session.get(CartEntity.class, id); session.delete(itemDelete); session.getTransaction().commit(); } catch (Exception ex) { ex.printStackTrace(); } finally { if (session != null) { session.close(); } } }

Удаление из базы группы id .

public void deleteAllItemToCart(List idAllItemsInCart) { Session session = HibernateUtil.getSessionFactory().openSession(); try { session.beginTransaction().begin(); for(Integer id:idAllItemsInCart){ CartEntity itemDelete = (CartEntity) session.get(CartEntity.class, id); session.delete(itemDelete); } session.getTransaction().commit(); } catch (Exception ex) { ex.printStackTrace(); } finally { if (session != null) { session.close(); } } }

Также Вам нужен будет файл настройки Hibernate. Создайте в Derby БД shop. Имя и пароль пользователя root и pass соответственно. Если не получится - не расстраивайтесь - я уделю еще этому время.

org.hibernate.dialect.DerbyDialect org.apache.derby.jdbc.ClientDriver jdbc:derby://localhost:1527/shop root pass UTF-8 update

О том, как заполнять наши БД поговорим позже. Можете заполнить их вручную. Либо дождаться следующего урока.

13.05.05 14.8K

Введение

Технология Java Server Pages (JSP) является составной частью единой технологии создания бизнес-приложений J2EE. JSP — это альтернативная методика разработки приложений, динамически генерирующих ответ на те или иные запросы клиента. Прежде чем JSP документ будет использован, специальная процедура преобразует его в соответствующий сервлет. В свою очередь, сервлет, как правило, пишется на языке Java и реализует определенный интерфейс. Далее, сервлет также не является самостоятельным приложением и функционирует, только будучи помещен в соответствующий web-контейнер. Web-контейнер обеспечивает обмен данными между сервлетом и клиентами, берет на себя выполнение таких функций, как создание программной среды для функционирующего сервлета, идентификацию и авторизацию клиентов, организацию сессии для каждого из них.

На настоящий момент реализована трансляция JSP страницы в сервлет, программный код которого пишется на языке Java. Однако авторы спецификации Java Server Pages оставляют возможность реализации JSP и на других языках программирования.

Соотношение между сервлетами бизнес-приложения и адресами URL на сервере задается в дескрипторе размещения. Технология реализации сервлетов обсуждается в отдельной статье. Сейчас же важно отметить тот факт, что программный код, используемый для написания сервлетов, не всегда удобен для динамической генерации текстовых документов в ответ на запрос клиента. Например, фрагмент сервлета, где осуществляется генерация динамической HTML страницы, может выглядеть следующим образом:

PrintWriter out = res.getWriter(); out.println(""); out.println(""); ... out.println(""); out.println(""); out.close();

Как видим, каждой строке HTML документа в сервлете соответствует определенный фрагмент программного кода, что не способствует простоте разработки и сопровождения бизнес-приложений.

Удобнее разделить динамическую и статическую части генерируемой web-страницы. Для создания динамической части по-прежнему будет использоваться Java или другой язык программирования. Статическую же часть имеет смысл оформить как текстовый документ — Java Server Page (JSP страницу), оформленную в соответствии с требованиями HTML, XML или другого стандарта разметки. Фактически, JSP страница можно рассматривать как шаблон или прообраз динамической страницы, которую остается дополнить динамическими элементами. Для описания динамической составляющей, в технологии JSP предусмотрено два основных механизма: компоненты JavaBean и библиотеки дополнительных тэгов. Как результат, технология JSP предполагает параллельную работу над приложением двух разных специалистов: программиста и ответственного за верстку документов (web мастера), которые отвечают, соответственно, за разработку динамической и статической частей документов, генерируемых в ответ на запросы клиентов.

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

Сервлет, полученный после преобразования JSP страницы, функционируют в рамках стандартного контейнера сервлетов и используют строго регламентированный интерфейс. Поэтому эта технология не зависит от каких-либо особенностей той или иной аппаратной платформы. С другой стороны, поскольку JSP технологии может строиться на базе интерпретируемого языка Java, то это дает гарантию портируемости приложений, построенных на технологии JSP, на любую платформу, где можно установить виртуальную Java машину.

JSP страница

Как правило, JSP страница хранится в отдельном файле с расширением.jsp. Большая часть содержимого JSP страницы преобразуется в сервлете в набор инструкций out.println(). Пример JSP страницы:

<%@ taglib uri="/exttags.tld" prefix="dscat" %> <%@ page import = "xbcat.util.*" %> All Customers <% Vector menu=pagescroll.getMenu(); if(pagescroll.page.size() > 0) { %>

<%= pagescroll.getTotalPages() %> <% if(!pagescroll.isSinglePage()) { for(int i=0; i "><%= name %> <% } else { %> <%= name %> <% } } } %>

Динамическая составляющая JSP страницы представлена тремя типами специальных элементов: директивами, action и скриптами. Подробнее каждый из них рассматривается в соответствующем разделе.

Директивы

Поскольку web контейнер, прежде чем использовать JSP страницу, предоставленную разработчиками бизнес-приложения, транслирует ее в соответствующий сервлет, имеет смысл предоставить возможность оставлять на JSP странице директивы, которые будут управлять процессом трансляции. Директивы имеют синтаксис

<%@ директива... %>

Рассмотрим некоторые из таких директив

Директива page. Декларирует ряд свойств JSP страницы. Синтаксис директивы:

<%@ page список_параметров %>

Опишем некоторые наиболее интересные параметры данной директивы:

  • import — Как уже говорилось, JSP страница перед использованием должна быть преобразована в программный код — класс, соответствующего сервлета. В свою очередь, класс сервлета может обращаться к другим классам из стандартных библиотек Java или классам из других пакетов. По умолчанию, класс сервлета, получаемый после трансляции JSP страницы, может иметь связь с пакетами java.lang, java.servlet, java.servlet.jsp и java.servlet.http. Если для класса сервлета требуется обеспечить связь с другими пакетами, например, с xbcat.util как в приведенном выше примере JSP страницы, последнюю следует дополнить директивой page, имеющей атрибут import с названием соответствующего пакета.
  • session — Если для связи с клиентом используется протокол HTTP, то для каждого сеанса по умолчанию создается объект session, позволяющий сохранять информацию об этом клиенте в интервале между его обращениями к серверу. С другой стороны, если атрибут session был указан со значением false, это позволяет отказаться от создания объекта сессии и использовать освободившиеся ресурсы сервера для решения других задач.
  • buffer — Содержимое страницы, созданной в ответ на запрос клиента, сервлет передает в поток вывода out, откуда оно затем передается web контейнером непосредственно клиенту. Чтобы получить более оптимальный режим передачи, в этом потоке предусмотрен режим буферизации. При этом объем буфера по умолчанию составляет 8 килобайт. Параметр buffer директивы page позволяет либо задать другой объем буфера, либо вообще отказаться от режима буферизации, передав атрибуту значение «none».
  • isThreadSafe — Согласно спецификации сервлетов, web контейнер по умолчанию позволяет одному и тому же экземпляру сервлета параллельно обрабатывать запросы сразу от нескольких клиентов. При этом каждому из запросов выделяется отдельный трэд. Между тем, в некоторых случаях бывает полезно запретить параллельную обработку запросов. (Соответствующий контроллер в web контейнере выстраивает приходящие запросы в очередь и передает их сервлету на обработку строго по одному.) Для этого достаточно использовать атрибут isThreadSafe, со значением false.
  • pageEncoding — Позволяет разработчику приложения декларировать кодировку, которая должна использоваться в документе, передаваемом клиенту. По умолчанию считается, что страница имеет кодировку ISO-8859-1.
  • contentType — В ответ на запрос клиента, JSP страница по умолчанию генерирует документ типа HTML. Вместе с тем, область применения технологии Java Server Pages гораздо шире, поскольку она позволяет генерировать любые другие типы текстовых документов: XML, WML, VRML и т.д. MIME-тип генерируемого документа декларируется атрибутом contentType. Как уже понятно, по умолчанию этот атрибут имеет значение «test/html». Вместе с типом документа, спецификация JSP позволяет в том же атрибуте указывать также кодировку генерируемого документа.

Директива taglib. Позволяет использовать на JSP страницах дополнительные тэги, созданные разработчиком приложения (custom тэги). Синтаксис директивы:

<%@ taglib uri="URI библиотеки тэгов" prefix="имя префикса" %>

где, uri — абсолютный или относительный адрес URI, уникальным образом идентифицирующий дескриптор библиотеки тэгов, связанных с указанным префиксом. Указанный префикс используется для идентификации соответствующих custom тэгов.

<%@ taglib uri="http://www.mycorp/supertags" prefix="super" %> ... ... ...

Процедуру создания custom тэгов мы рассмотрим позднее.

Директива include. Используется для помещения в JSP страницу текстов и программного кода из других источников. Подстановка выполняется в момент, трансляции JSP страницы в соответствующий сервлет. Пример использования директивы:

<%@ include file="menu.jsp" %>

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

Фрагмент программного кода на JSP странице (скрипт)

Скрипт, как и остальные элементы, привносит в конечный документ динамическую составляющую. Однако, в отличие от них, скрипт — программный код, помещенный непосредственно в текст JSP страницы. Скрипт может производить вычисления или манипулировать объектами, что позволяет наглядно связывать характеристики генерируемой страницы с параметрами запроса клиента и бизнес-правилами приложения. Элементы скриптов бывают трех типов: декларации, скриплеты и выражения.

Декларации

После преобразования JSP страницы в сервлет большая часть ее содержимого попадает в метод _jspService(), который вызывается всякий раз, когда появляется необходимость обработать заказ клиента. Декларация на JSP странице чаще всего используется для того, чтобы объявить дополнительные атрибуты и методы в классе сервлета, которые будут доступны при обработке любого запроса клиента. Декларации имеют синтаксис <%! … %> .

Примеры деклараций на JSP странице:

<%! int i; %> <%! int i = 0; %> <%! public String f(int i) { ... } %>

Скриплеты

Скриплет может содержать программный код и декларации локальных переменных, которые будут использованы для обработки запросов клиентов. Фактически, скриплет — это фрагмент программного кода из будущего сервлета, который в свое время будет помещен в метод _jspService(). Являясь частью сервлета, скриплет получает доступ к объекту response и, соответственно, может самостоятельно формировать определенную часть конечной динамической страницы. Однако чаще всего скриплеты используются не для этого, а для того, чтобы управлять объектами бизнес-логики и логикой приложения.

Скриплет имеет синтаксис <% … %> . Пример использования скриплетов в содержимом JSP страницы:

<% if (i == 0) { %> Good morning <% } else { %> Good afternoon <% } %>

Чтобы оценить наглядность и простоту этой конструкции, сравните ее с эквивалентным фрагментом программного кода в сервлете:

if (i == 0) { out.println("Good morning"); } else { out.println("Good afternoon"); }

Выражения

Часто страница, передаваемая клиенту, содержит результаты вычислений или обращений к тем или иным методам и атрибутам определенных классов. Любой из таких динамических элементов можно преобразовать в строку и представить на JSP странице с помощью вызова out.println в соответствующем скриплете:

<% UserProfile user = (UserProfile) session.getValue("Profile"); %> <% out.println(user.getFaxNumber()); %>

Вторую строку в приведенном примере удобнее и нагляднее представить в боле кратном виде, используя синтаксис выражения <%= … %> :

<%= user.getFaxNumber() %>

Другой пример использования выражения в теле JSP страницы:

<%! int i = 0; %> Hi, now the servlet processing <%= ++i %>th request.

JSP страницы и объекты

В ходе обработки запросов, JSP страница может получать доступ к объектам, расположенным на сервере, создавать их и модифицировать. Доступ к объектам осуществляется через элементы скриптов и action. Каждый создаваемый в приложении объект имеет определенное время существования, которое декларируется в соответствующем атрибуте. Спецификацией предусматривается четыре интервала:

  • page — Объект, чье время существования определяется как page, доступен в пределах только той JSP страницы, где он был создан. Все ссылки на этот объект должны быть освобождены сразу же после того, как запрос клиента был обработан.
  • request — Объект, чье время существования определяется как request, доступен для всех страниц, связанных с обработкой данного запроса. В частности, если имеет место переадресация обработки на новую JSP страницу, данный объект будет доступен и на прежней, и на новой странице. Как и в предыдущем случае, ссылки на объект после обработки запроса должны быть освобождены.
  • session — Объект с областью видимости session доступен для всех страниц, обрабатывающих запросы, связанные с определенной сессией (сеансом связи с конкретным клиентом). Ссылки на объекты, связанные с сессией, помещаются в объект session. По окончании сеанса связи ссылки должны быть освобождены.
  • application — Наиболее общая область видимости. Объекты, имеющие область существования application, не привязаны к какой-либо отдельной странице или сеансу связи и доступны со всех JSP страниц данного приложения.

JSP страница всегда имеет доступ к определенному набору объектов, создаваемых web контейнером по умолчанию:

  • request — Объект, содержащий запрос клиента. Относится к классу javax.servlet.ServletRequest или другому наследующему его классу. Например, для протокола HTTP это будет объект класса javax.servlet.http.HttpServletRequest. Область видимости объекта — request.
  • response — Объект, в который сервлет будет помещать ответ на запрос пользователя. Относится к классу javax.servlet.ServletResponse или другому наследующему его классу. Например, для протокола HTTP это будет объект класса javax.servlet.http.HttpServletResponse. Область видимости объекта — request.
  • pageContext — Объект, определяющий контекст JSP страницы. Область видимости объекта — page
  • session — Объект, создаваемый контейнером для идентификации клиента, а также хранения персональных объектов. Создается контейнером для протокола HTTP и является экземпляром класса javax.servlet.http.HttpSession.
  • application — Объект, связанный с конфигурацией сервлета, соответствующего данной JSP странице. Область видимости объекта — application.
  • out — Объект, содержащий выходной поток сервлета. Информация, посылаемая в этот поток, будет передана клиенту. Объект является экземпляром класса javax.servlet.jsp.JspWriter. Например, большая часть статического шаблона на JSP странице, в идеале, должна быть записана в виде соответствующего набора команд out.println(). Область видимости объекта — page.
  • config — Объект, связанный с конфигурацией сервлета. Является экземпляром класса javax.servlet.ServletConfig. Для JSP страницы область видимости объекта config — page.
  • page — Объект, связанный с обработкой данной страницы. Область видимости — page

Элементы action

Независимо от того, какой тип будет иметь документ, генерируемый в ответ на запрос пользователя, в общем случае, JSP страница содержит текст и тэги. Очевидно, что последние соответствуют типу генерируемого документа: HTML, XML и т.д. Кроме того, в теле JSP страницы могут содержаться фрагменты программного кода на языке Java, которые должны войти в состав сервлета, получаемого после трансляции: декларации, скриплеты и выражения. Идея заключается в том, чтобы дополнить набор тэгов стандартной разметки специальными тэгами — элементами action, за которыми разработчик бизнес-приложения может скрыть часть программного кода, относящегося к приложению, либо некоторые дополнительные инструкции.

Заметим, что с точки зрения специалиста по верстке документов, элементы action являются такими же тэгами, как и все остальные, а потому допустимо их совместное использование с другими элементами:

Рассмотрим некоторые из этих элементов.

Стандартные элементы action

Стандартные элементы action выглядят как обычные тэги, название которых начинается с сочетания символов jsp:, например . Согласно терминологии XML, это означает, что стандартные элементы action в технологии JSP принадлежат пространству имен jsp.

jsp:useBean

Элемент jsp:useBean позволяет использовать на JSP странице объекты, соответствующие компонентам JavaBean. Элемент содержит параметр, который связывает с компонентом некий уникальный идентификатор. Последний затем будет использоваться при обращениях к этому объекту:

В данном примере создается объект класса com.myco. В дальнейшем, чтобы обратиться к нему, достаточно воспользоваться идентификатором «customer». Например:

<%= customer.getName() %>

По умолчанию, объекты, связанные с элементом JavaBean, по умолчанию имеют область видимости page. Разработчик JSP страницы может указать более продолжительное время существования объекта JavaBean, воспользовавшись при написании элемента jsp:useBean элементом scope. Возможные значения этого атрибута — page, request, session и application — мы обсуждали несколько ранее во время разговора об области видимости объектов, связанных с JSP страницей.

Мы не будем рассматривать остальные атрибуты элемента jsp:useBean. Приведем лишь еще один пример его использования:

Внутреннее устройство элементов JavaBean будет рассмотрено нами в отдельной статье.

jsp:setProperty и jsp:getProperty

Любой класс должен давать доступ к некоторым из своих атрибутов и методов. Отличие элемента JavaBean заключается в том, что доступ к атрибутам у него унифицирован и реализуется на JSP странице с помощью элементов jsp:setProperty и jsp:getProperty.

Элемент jsp:getProperty берет экземпляр Bean, извлекает значение указанного атрибута, преобразует его в случае необходимости в строку и помещает в поток данных, передаваемых клиенту. Например, согласно следующей записи

в генерируемый документ помещается значение свойства name из экземпляра Bean, имеющего идентификатор user.

Элемент jsp:setProperty, в отличие от предыдущего, не извлекает, а задает новое значение атрибута. Например:

Помимо явного задания новых значений, элемент jsp:setProperty позволяет заносить в атрибут объекта значение, извлеченное из запроса клиента. Например:

Данная запись означает, что среди данных, полученных от клиента, находится параметр login и его значение передается для помещения в атрибут name объекта Bean, имеющего идентификатор «user».

Наконец, когда названия полей в запросе клиента совпадают с названиями атрибутов объекта Bean, предусмотрен еще один вариант, когда разом осуществляется перенос всех значений. Например:

jsp:include

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

Отличие директивы include от элемента jsp:include заключается в том, что для нее включаемый материал не может быть динамическим, а поиск и обработка возможных динамических фрагментов осуществляется не отдельно, а после включения, со всей страницей.

Пример использования элемента jsp:include:

jsp:forward

Данный элемент позволяет переадресовать дальнейшее формирование динамической страницы на другую JSP страницу, сервлет или использовать для завершения заранее приготовленный текст. Например:

В следующем, более сложном примере динамическая страница завершается содержимым текстового файла, название которого берется из переменной someValue:

В заключение следует заметить, что есть две основные схемы обработки запросов клиента:

В первом случае, обработка запроса клиента и формирование в ответ динамической страницы производятся в рамках одной JSP страницы или сервлета. Последняя, в случае необходимости, может обращаться к объектам JavaBean или импортировать материал из внешних источников с помощью директивы include или элемента jsp:include.

Во втором случае, обработка производится в два этапа. Сперва управление подается на сервлет или JPS страницу, осуществляющую собственно обработку запроса. Например, из запроса клиента извлекаются данные и помещаются в базу данных или атрибуты определенных объектов. Затем управление передается на отдельную JSP страницу или сервлет, ответственные за генерацию динамической страницы для последующей передачи ее клиенту. При этом между обработкой запроса и генерацией новой страницы необязательно должна существовать какая-либо взаимосвязь. Например, это может быть всего лишь возврат клиента на главную страницу по завершении какой-либо процедуры.

Дополнительные наборы тэгов

Введение

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

Построение custom тэгов связано с написанием определенного программного кода. Технология JSP предусматривает размещение этого кода в отдельном программном модуле — библиотеке custom тэгов. Разработка подобных библиотек может быть поручена сторонним компаниям. Подключение JSP страницы к той или иной библиотеке custom тэгов осуществляется с помощью ранее описанной директивы taglib. Указанная директива связывает дескриптор соответствующей библиотеки с определенным префиксом, который, в свою очередь, идентифицирует в теле JSP страницы все custom тэги из данной библиотеки. Так, директива

<%@ taglib uri="/exttags.tld" prefix="dscat" %>

объявляет, что в JSP странице используется библиотека дополнительных тэгов, название каждого из которых начинается с префикса dscat. Например:

All Customers

Программный код данной библиотеки описывается дескриптором exttags.tld. Мы не будем здесь останавливаться на правилах написания дескриптора библиотеки, а рассмотрим лишь один из возможных примеров его реализации:

1.0 1.2 dscat pageheader ru.view.tag.PageHeader

Создание библиотеки custom тэгов

Custom тэги без обработки содержимого

Программный код для поддержки custom тэга — это специальным образом написанный экземпляр Java класса, который вызывается web контейнером всякий раз, когда требуется обработать JSP страницу, содержащую соответствующий тэг.

В простейшем случае, для поддержки custom тэга можно взять какой-либо из классов бизнес-приложения и дополнить его методами, соответствующими интерфейсу Tag. Если же внешних объектов использовать не надо, то в качестве базового класса можно использовать TagSupport. Эти и другие стандартные классы и интерфейсы находятся в пакете javax.servlet.jsp.tagext.

Пример класса, осуществляющего поддержку custom тэга:

public CopyrightTag extends TagSupport { public int doStartTag() throws Exception { pageContext.getOut().print("© Copyright, 2001"); return SKIP_BODY; } public int doEndTag() { return EVAL_PAGE; } }

Методы класса, который осуществляет обработку custom тэга, вызываются в определенной последовательности. Когда в JSP странице обработка доходит до открывающего custom тэга, для его обработки вызывается метод doStartTag(). Когда обработка доходит до соответствующего закрывающего тэга, вызывается метод doEndTag(). Для обработки той части JSP страницы, которая заключена между этими двумя тэгами, используются методы doInitBody() и doAfterBody().

Помимо того, что метод doStartTag() может осуществлять какую-либо обработку запроса, большое значение имеет возвращаемое им значение. Если это SKIP_BODY, то информация, заключенная между соответствующими открывающим и закрывающим тэгами, будет игнорироваться, а обработка JSP страницы сразу перейдет на закрывающий тэг. Чтобы содержимое custom тэга все же обрабатывалось, медот должен возвратить EVAL_BODY_INCLUDE. Аналогично, если метод doEndTag() возвратит значение SKIP_PAGE, то оставшаяся часть JSP страницы после закрывающего тэга будет проигнорирована. Чтобы не допустить этого, метод должен возвратить значение EVAL_PAGE.

В некоторых случаях бывает необходимо показать содержимое custom тэга не один, а несколько раз. В этом случае, класс, осуществляющий обработку тэга, должен реализовывать интерфейс IterationTag, либо использовать в качестве родителя класс TagSupport. Чтобы повторить вывод содержимого custom тэга еще раз, необходимо, чтобы методы doStartTag и doAfterBody возвращали EVAL_BODY_AGAIN.

Custom тэги с обработкой содержимого

Если требуется доступ к содержимому custom тэга, то соответствующий Java класс должен реализовывать интерфейс BodyTag или же наследовать класс BodyTagSupport. И в том, и в другом случае класс может реализовать методы doInitBody и doAfterBody.

Метод doInitBody вызывается сразу после того, как выявлено содержимое тэга, но до того, как оно будет обработано. Обычно этот метод используется когда необходимо выполнить инициализацию класса в зависимости от содержимого custom тэга.

Метод doAfterBody вызывается после того, как содержимое custom тэга было обработано. Как и в предыдущем разделе, метод doAfterBody может указывать, следует ли повторить обработку содержимого тэга еще раз. Если это необходимо, метод должен возвратить значение EVAL_BODY_BUFFERED. В противном случае он должен возвратить SKIP_BODY.

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

Непосредственно для доступа к содержимому custom тэга технологией предусмотрено два метода: getString и getReader.

Атрибуты в custom тэгах

Помимо информации в промежутке между открывающим и закрывающим тэгами, custom тэг может иметь некоторые атрибуты, которые также могут оказывать влияние на порядок обработки запроса клиента. Для каждого из таких атрибутов в классе, реализующем custom тэг, должен быть указан соответствующий атрибут, а также два метода get и set. Например, если custom тэг имеет вид

то реализующий этот custom тэг класс должен содержать следующий код:

из

Хорошо Плохо

Лучшие статьи по теме