Лекция 18
JSP Технология Java Server Pages (JSP) была разработана компанией Sun Microsystems, для создания страниц с динамическим содержанием. Страница JSP обеспечивает разделение динамической и статической частей страницы, результатом чего является возможность изменения дизайна страницы, не затрагивая динамическое содержание.
Содержимое Java Server Pages (теги HTML, теги JSP и скрипты) переводится в сервлет код-сервером. Этот процесс ответствен за трансляцию как динамических, так и статических элементов, объявленных внутри файла JSP. Процессы, выполняемые с файлом JSP при первом вызове или при его изменении: 1. Браузер делает запрос к странице JSP. 2. JSP-engine анализирует содержание файла JSP. 3. JSP-engine создает временный сервлет с кодом, основанным на исходном тексте файла JSP, при этом контейнер транслирует операторы Java в метод _jspService(). Если нет ошибок компиляции, то этот метод вызывается для непосредственной обработки запроса. Полученный сервлет ответствен за исполнение статических элементов JSP, определенных во время разработки в дополнение к созданию динамических элементов.
4. Полученный текст компилируется в файл *.class. 5. Вызываются методы init() и service() (doGet() или doPost()), и сервлет логически исполняется. 6. Сервлет установлен. Комбинация статического HTML и графики вместе с динамическими элементами, определенными в оригинале JSP, пересылаются браузеру через выходной поток объекта ответа ServletResponse. Последующие вызовы файла JSP просто вызовут сервисный метод сервлета. Сервлет используется до тех пор, пока сервер не будет остановлен и сервлет не будет выгружен вручную либо пока не будет изменен файл JSP.
Рабочий цикл JSP имеет вид:
JSP-код Java заключается в специальные теги, которые указывают контейнеру, чтобы он использовал этот код для генерации сервлета или его части. Таким образом поддерживается документ, который одновременно содержит и страницу, и код Java, который управляет этой страницей. Статические части HTML-страниц посылаются в виде строк в метод write(). Динамические части включаются прямо в код сервлета. JSP составляется из стандартных HTML-тегов, JSP-тегов и пользовательских JSP-тегов. В спецификации JSP 1.1 существует шесть основных тегов:
Директивы Директивы используются для установки параметров серверной страницы JSP и имеют общий вид:
Рассмотрим пример: Параметр language директивы page определяет используемый язык, пока он только один. В параметр info можно помещать информацию о данной странице, которую можно получить, используя метод getServletInfo(). Параметр import описывает пакеты и типы, доступные среде выполнения сценариев. Параметр contentType специфицирует декодирование символов и MIME-тип JSP-ответа. Директива taglib подключает библиотеки пользовательских тегов.
Директива include Директива include позволяет включать в код данной страницы JSP другие документы допустимых типов. При этом включение осуществляется на этапе трансляции. Если включаемый ресурс изменился, то эти изменения не будут отражены на jsp странице Пример: jsp01.jsp First JSP
jsp02.jsp was included in jsp01.jsp Запуск JSP: Параметр errorPage указывает на страницу, переход к которой будет осуществлен в случае возникновения ошибки в текущей странице.
Страница, вызываемая при ошибках, может иметь статический вид errorjsp.jsp Exception Generated! Роль простейшей JSP может сыграть обычная HTML-страница, переименованная с расширением.jsp.
Директива page Директива page задает глобальные настройки для JSP-страницы в контейнере JSP. Может использоваться несколько директив page при условии, что при этом имеется только одно вхождение каждого из атрибутов. Атрибуты директивы page. 1. language Язык сценария, используемый JSP-страницей. На данный момент единственным допустимым значением для этого атрибута является java.
2. extends Задает класс, которому будет наследовать транслированная JSP- страница. В качестве значения этого атрибута должно задаваться полное имя пакета или класса. 3. import Задает список отделяемых запятыми имен классов и/или пакетов, которые будут использоваться в текущей JSP-странице. Если языком сценария является java, список для импортирования по умолчанию имеет вид: java.lang.*, javax.servlet.*, javax.servlet.jsp.*, Javax.servlet.http.* Если задано несколько свойств import, контейнер помещает имена пакетов в список.
4. session Задает, участвует ли страница в сеансе. Значением этого атрибута может быть true (участвует в сеансе - по умолчанию) или false (не участвует в сеансе). Если страница участвует в сеансе, неявный объект JSP session доступен для использования на странице. В противном случае объект session недоступен, и использование его в коде сценария приводит к ошибке на этапе трансляции.
5. buffer Задает размер буфера вывода, используемого неявным объектом out. Этот атрибут может иметь значение none при отсутствии буферизации, либо конкретное значение, например, 8 kb (размер буфера по умолчанию). Спецификация JSP указывает, что размер используемого буфера должен быть не меньше заданного размера.
6. autoFlush При установке значения true (значение по умолчанию) этот атрибут указывает, что буфер вывода, используемый с неявным объектом out должен автоматически очищаться при заполнении буфера. При установке значения false в случае переполнения буфера возбуждается исключение. Для этого атрибута следует установить значение true, если для атрибута buffer задано значение none.
7. isThreadSafe Определяет, обеспечивает ли страница безопасное выполнение потоков (thread safe). При задании значения true (по умолчанию) считается, что страница обеспечивает безопасность программных потоков и может обрабатывать несколько запросов одновременно. При задании значения false сервлет, который представляет страницу, реализует интерфейс java.lang.SingleThreadModel, и этой JSP-страницей может одновременно обрабатываться только один запрос. Стандарт JSP допускает существование нескольких экземпляров JSP для JSP-страниц, которые не являются безопасными для выполнения потоков. Это позволяет контейнеру более эффективно обрабатывать запросы. Однако при этом не гарантируемся, что доступ к ресурсам, совместно используемым экземплярами JSP, будет осуществляться посредством безопасных программных потоков.
8. info Задает строку информации, описывающей страницу. Эта строка возвращается методом getServletlnfo сервлета. Этот метод может быть вызван посредством неявного объекта JSP page. 9. errorPage Любые, не перехваченные на текущей странице исключения, отправляются для обработки странице ошибок.
10.isErrorPage Определяет, является ли текущая страница, страницей обработки ошибок, которая будет вызываться в ответ на ошибку, имевшую место в другой странице. Если атрибут имеет значение true, создается неявный объект exception, который ссылается на изначально возникшее исключение. Если атрибут имеет значение false (по умолчанию), любое использование объекта exception на странице приводит к ошибке на этапе трансляции.
11. conatantType Задает MIME-тип данных в ответе клиенту. По умолчанию используется тип text/html.
Объявления Блок объявлений содержит переменные Java и методы, которые вызываются в expression- блоке. Объявление не должно производить запись в выходной поток out страницы, но может быть использовано в скриптлетах и выражениях. Например:
Скриптлеты JSP поддерживает вживление Java-кода в скриптлет-блок. Скриптлеты обычно используют маленькие блоки кода и выполняются во время обработки запроса клиента. Когда все скриптлеты собираются воедино в том порядке, в котором они записаны на странице, они должны представлять собой правильный код языка программирования. Контейнер помещает код Java в метод _jspServlet() на этапе трансляции. Рассмотрим пример:
11 * = Верно! ОШИБКА!
Выражения В качестве выражений используются операторы языка Java, которые вычисляются, после чего результат вычисления преобразуется в строку String и посылается в поток out, как в случае Первое выражение к строке text присоединяет вновь созданную строку и отправляет результат в поток out. Второе выражение определяет количество свободной памяти. Рассмотрим пример:
Страницу посетили раз, начиная с
Неявные объекты JSP-страница всегда имеет доступ ко многим функциональным возможностям сервлета, создаваемым Web-контейнером по умолчанию. Неявный объект: request – представляет запрос клиента. Обычно объект является экземпляром класса, реализующего интерфейс javax.servlet.http.HttpServletRequest. Для протокола, отличного от HTTP, это будет объект реализации интерфейса javax.servlet.ServletRequest. Область видимости в пределах страницы. response – представляет ответ клиенту. Обычно объект является экземпляром класса, реализующего интерфейс javax.servlet.http.HttpServletResponse. Для протокола, отличного от HTTP, это будет объект реализации интерфейса javax.servlet.ServletResponse. Область видимости в пределах страницы.
pageContext – определяет контекст JSP-страницы и предоставляет доступ к неявным объектам. Объект класса javax.servlet.jsp.PageContext. Область видимости в пределах страницы. session – создается контейнером для протокола HTTP и является экземпляром класса javax.servlet.http.HttpSession, предоставляет информацию о сессии клиента, если такая была создана. Область видимости в пределах сессии. application – контейнер, в котором исполняется JSP-страница, является экземпляром класса javax.servlet.ServletContext. Область видимости в пределах приложения
out – содержит выходной поток сервлета. Информация, посылаемая в этот поток, передается клиенту. Объект является экземпляром класса javax.servlet.jsp.JspWriter. Область видимости в пределах страницы. config – содержит параметры конфигурации сервлета и является экземпляром класса javax.servlet.ServletConfig. Область видимости в пределах страницы. page – ссылка this для текущего экземпляра данной страницы является объектом java.lang.Object. Область видимости в пределах страницы. exception – представляет собой исключение одного из подклассов класса java.lang.Throwable, которое передается странице сообщения об ошибках и доступно только на ней.
Стандартные элементы action Действие Данное действие позволяет использовать экземпляр компонента JavaBean. Если экземпляр с указанным идентификатором не существует, то он будет создан с областью видимости page (страница), request (запрос), session (сессия) или application (приложение). Объявляется, как правило, с атрибутами id (имя объекта), scope (область видимости), class (полное имя класса), type (по умолчанию class, может быть суперклассом или интерфейсом, реализуемым этим классом). Создан объект ob класса MyBean, и в дальнейшем через это имя можно вызывать доступные методы класса.
Действие Данное действие позволяет устанавливать значения полей указанного в атрибуте name объекта(имеется ввиду действие ). Рассмотрим пример. Пусть класс реализующий бин public class MyBean { private String info = "нет информации"; public String getInfo() { return info;} public void setInfo(String s) {info = s;} } Тогда действие будет иметь вид: (В классе MyBean должен быть поле info)
Действие Данное свойство получает значения полей указанного объекта, преобразует его в строку и отправляет в неявный объект out Рассмотрим пример. Класс реализующий бин имеет вид: package aaa; public class MyBean { private String info = " "; public String getInfo() { return info;} public void setInfo(String s) {info = s;} }
Jsp страница имеет вид( my.jsp):
Для развертывания данного приложения необходимо: 1.Создать папку myjsp в c:\tomcat\webapps\myjsp\ 2.Создать в myjsp директорию jsp и положить туда файл my.jsp 3. В каталоге myjsp создать папку WEB- INF/classes/aaa и поместить туда файл MyBean.class Запуск сервлета имеет вид:
Действие Данное действие позволяет включать файлы в генерируемую страницу при запросе страницы: (Необязательный атрибут flush управляет переполнением. Если этот атрибут имеет значение true и выходной поток страницы JSP буферизуется, то буфер освобождается при переполнении, в противном случае - не освобождается. По умолчанию значение атрибута flush равно false ) Отличие от директивы include заключается в том, что если подключаемый ресурс изменился в промежутке между запросами, то следующий запрос к JSP – странице, содержащий действие, будет осуществлять включение нового содержимого.
Действие Данное действие позволяет передать запрос другой странице: Рассмотрим пример. Файл (my.jsp) Hello.jsp
Файл index.jsp Hello1.jsp
Действие Данное действие – замещается тэгом или, в зависимости от типа браузера, в котором будет выполняться подключаемый апплет или Java Bean. Вмести с данным действием может использоваться jsp:params – группирует параметры внутри тега. jsp:param – добавляет параметры в объект запроса (может также использоваться с действиями forward, include). jsp:fallback – указывает содержимое, которое будет использоваться браузером клиента, если подключаемый модуль не сможет запуститься.
Атрибуты тега 1.type – Тип компонента: компонент JavaBeans или applet 2.code – Класс, который представляет компонент. 3.codebase – местоположение класса, задаваемого атрибутом code, и архивов, задаваемых атрибутом archive 4.align – способ выравнивания компонента 5.archive- список архивных файлов, разделенных пробелами, которые содержат ресурсы, используемые компонентом, такой архив может включать класс задаваемый атрибутом code. 6.height - Высота компонента на странице, заданная в пикселях
7. hspace – пространство слева и справа от компонента, выраженное в пикселях 8. vspace – пространство над и под компонентом выраженное в пикселях 9. width – ширина компонента выраженная в пикселях или процентах.
Рассмотрим пример: Using jsp:plugin to load an applet
Файл аплета ShapesApplet.java имеет вид: import java.applet.* ; import java.awt.event.*; import java.awt.* ; import java.awt.geom.* ; import javax.swing.* ; public class ShapesApplet extends JApplet { public void init() { try { int red = Integer.parseInt( getParameter("red")); int green = Integer.parseInt(getParameter ("green")); int blue = Integer.parseInt(getParameter("blue")); Color backgroundColor = new Color(red,green,blue); setBackground(backgroundColor ) ; } catch ( Exception exception ) {}; }
public void paint( Graphics g ) { int xPoints[] ={55, 67, 109, 73, 83, 55, 27, 37, 1, 43 } ; int yPoints[] ={0, 36, 36, 54, 96, 72, 96, 54, 36, 36 }; Graphics2D g2d = ( Graphics2D ) g; // создание звезды из набора точек GeneralPath star = new GeneralPath(); star.moveTo( xPoints[ 0 ], yPoints[ 0 ] ); for(int k = 1; k < xPoints.length; k++) star.lineTo( xPoints[k], yPoints[k]); star.closePath(); g2d.translate(200,200); for ( int j = 1; j
Библиотека нестандартных тегов Пользовательские теги организуют в виде целой библиотеки, даже если в нее входит только один тег Описание каждой библиотеки хранится в отдельном XML-файле c расширением tld
Описатель TLD библиотеки тегов. Шапка
Описатель TLD библиотеки тегов 1.0 /sdo head sdotags.HeadTag JSP size false true
На странице JSP перед применением пользовательских тегов следует сослаться на библиотеку тегом например в этом случае на странице можно использовать теги вида
к каждой странице JSP всегда подключается библиотека с префиксом тегов jsp стандартные теги JSP входят в эту библиотеку каждый тег создаваемой библиотеки реализуется классом Java, называемым обработчиком тега обработчик тега должен реализовать интерфейс Tag
если у тега есть тело, которое надо выполнить несколько раз, то надо реализовывать его расширение -интерфейс IterationTag если тело пользовательского тега требует предварительной обработки, то следует использовать расширение интерфейса IterationTag - интерфейс BodyTag эти интерфейсы собраны в пакет javax.servlet.jsp.tagtext
есть готовые реализации указанных интерфейсов -класс TagSupport, реализующий интерфейс IterationTag есть BodyTagSupport -расширение TagSupport реализующий BodyTag для создания пользовательского тега без тела или с телом, но не требующим предварительной обработки, нужно реализовывать Tag или расширить класс TagSupport
для создания тега с телом, которое надо предварительно преобразовывать, нужно реализовать интерфейс BodyTag или расширить класс BodyTagSupport в случае простых преобразований можно реализовать интерфейс SimpleTag или расширить класс SimpleTagSupport
public int doStartTag() основной метод интерфейса Tag выполняет действия, предписанные открывающим тегом К нему сервлет обращается автоматически, начиная обработку элемента. Метод должен вернуть одну из двух констант EVAL_ BODY_ INCLUDE – обрабатывать тело элемента SKIP_ PAGE –не обрабатывать тело элемента
public int doAfterTag() дополнительный метод интерфейса IterationTag позволяет повторно обрабатывать тело пользовательского тега будет выполнен перед методом doEndTag() метод должен вернуть одну из двух констант EVAL_BODY_AGAIN- тело элемента будет обработано еще раз SKIP_BODY –обработка тела не станет повторяться
public int doEndTag() После обращения к методу doStartTag сервлет обращается к методу doEndTag Здесь выполняются действия завершающие обработку тега Метод должен вернуть одну из двух констант EVАL_PAGE продолжить обработку страницы jsp SKIP_PAGE –завершить обработку страницы jsp
Интерфейс BodyTag позволяет буферизовать выполнение тела элемента буферизация производится, если метод doStartTag() возвращает константу EVAL_ BODY_BUFFERED интерфейса BodyTag в таком случае перед обработкой тела тега контейнер обращается к методу public void doInitBody() у этих методов нет аргументов
информацию они получают из объекта класса PageContext, который всегда создается контейнером для выполнения любой страницы JSP при реализации интерфейса Tag или BodyTag данный объект можно получить методом getPageContext() класса JspFactory, предварительно получив объект класса JspFactory его статическим методом getDefaultFactory() лучше расширить класс TagSupport или BodyTagSupport
Для создания пользовательского тега без тела или с телом, не требующим обработки - расширить класс TagSupport Для создания пользовательского тега c обработкой тела -расширить класс BodyTagSupport в этом случае объект класса PageContext содержится в защищенном поле с именем pageContext
TagSupport public int doStartTag() throws JspException{ return SKIP_BODY; } public int doEndTag() throws JspException{ return EVAL_PAGE; } public int doAfterBody() throws JspException{ return SKIP_BODY; }
Рассмотрим пример. Пользовательский тег без тела и без атрибутов. Файл my.jsp Simple Custom Tag Example
The following text demonstrates a tag: Директива taglib дает возможность JSP- странице использовать теги из пользовательской библиотеки тегов. Рассмотрим обработчик тегов. Каждый обработчик должен реализовывать интерфейс Tag.
package aaa; import java.io.*; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class WelcomeTagHandler extends TagSupport { // Метод, вызываемый, чтобы начать обработку тега public int doStartTag() throws JspException { try{ // получение объекта JspWriter для вывода содержимого JspWriter out = pageContext.getOut(); out.print( Heloooo" ); } catch( IOException ioException ) { throw new JspException( ioException.getMessage() ); } return SKIP_BODY; // игнорировать тело тега }
Теперь рассмотрим дескриптор библиотеки тегов. Файл myjsp-taglib.tld
empty Файлы myjsp-taglib.tld и my.jsp необходимо поместить в папку c:\tomcat\webapps\myjsp\jsp\ Файл WelcomeTagHandler.class в папку c:\tomcat\webapps\myjsp\WEB-INF\classes\aaa\
Пример. Пользовательский тег с атрибутами JSP страница использующая тег с атрибутами. Файл my.jsp
The following text demonstrates a tag: 2. Рассмотрим обработчик тегов. public class WelcomeTagHandler extends TagSupport { private String firstName=; // Метод, вызываемый, чтобы начать обработку тега public int doStartTag() throws JspException { try{ // получение объекта JspWriter для вывода содержимого JspWriter out = pageContext.getOut(); out.print( Heloooo+firstName); } catch( IOException ioException ) { throw new JspException( ioException.getMessage() ); } return SKIP_BODY; // игнорировать тело тега }
public void setFirstName( String username ){ firstName = username; } } 3. Рассмотрим дескриптор библиотеки тегов. Файл myjsp-taglib.tld
welcome aaa.WelcomeTagHandler empty firstName true
- определяет, может ли значение атрибута быть результатом вычисления выражения JSP в процессе выполнения (true) или оно должно представляеть собой строковый литерал.
Пример. Пользовательский тег с телом если у пользовательского тега есть тело, то при описании тега в TLD-файле в элементе вместо слова EMPTY следует написать слово JSP(по умолчанию) у тела элемента могут быть еще два значения: tagdependent -если содержимое тела тега написано не на JSP scriptless -показывает, что в теге нет скриптлетов
Если содержимое тега не нужно обрабатывать, а надо только отправить клиенту, то при создании его обработчика достаточно реализовать интерфейс Tag или расширить TagSupport Если метод doStartTag() обработчика вернет значение EVAL_BODY_INCLUDE, то все тело тега будет автоматически отправлено в выходной поток
head myjsp.HeadTag JSP size false true
public class HeadTag extends TagSupport{ private String size="4"; public String getSize(){ return size; } public void setSize(String size){ this.size = size;} public int doStartTag(){ try{ JspWriter out = pageContext.getOut(); out.print(" "); } catch (Exception e){ System.err.println(e);} return EVAL_BODY_INCLUDE; }
public int doEndTag(){ try{ JspWriter out = pageContext.getOut(); out.print(" "); } catch (Exception e){ System.err.println(e);} return EVAL_PAGE; }
после этого на странице JSP можно использовать пользовательский тег Сегодня new java.util.Date() текст, написанный в теле, будет выведен у клиента шрифтом указанного размера
тело тега требует обработки, то его класс обработчик должен реализовывать интерфейс BodyTag или расширить класс BodyTagSupport метод doStartTag() должен вернуть EVAL_ BODY_BUFFERED после завершения метода doStartTag(), если тело тега не пусто, контейнер вызовет метод doInitBody() doInitBody -действия, которые необходимо выполнить до обработки тела
Далее контейнер обратится к doAfterBody() в котором надо проделать обработку тела тега к моменту вызова doAfterBody() тело тега будет прочитано и занесено в объект BodyContent
Класс BodyContent расширяет JspWriter можно рассматривать, как хранилище информации, полученной из тела тега объект класса BodyContent создается после каждой итерации метода doAfterBody() и все эти объекты хранятся в стеке.
ссылку на объект класса BodyContent можно получить двумя способами: public BodyContent getBodyContent() BodyContent nc = pageContext.pushBody() содержимое тела тега можно прочитать из объекта класса BodyContent тоже двумя способами: public Reader getReader() public String getString()
после обработки прочитанного содержимого его надо отправить в выходной поток out методом public void writeOut(Writer out) выходной поток out выводит информацию в стек объектов класса BodyContent, его можно получить двумя способами: public JspWriter getPreviosOut() класса BodyTagSupport public JspWriter getEnclosingWriter() класса BodyContent
Рассмотрим пример: в теле тега будет sql-запрос SELECT * FROM students
query sdotags.QueryTag tagdependent size false true
public class QueryTag extends BodyTagSupport{ private Connection con; private ResultSet rs; public int doStartTag(){... return EVAL_BODY_BUFFERED; } public int doInitBody(){ conn = DriverManager.getConnection(... ); }
public int doAfterBody(){ BodyContent bc = getBodyContent(); if(bc==null){ return SKIP_BODY; } String query = bc.getString(); try{ Statement st = conn.createStatement(); ResultSet rs= st.executeQuery(query); JspWriter out = pageContext.getOut(); out.print(Results");} catch (Exception e){ System.err.println(e);} return SKIP_BODY; }
public int doEndTag(){ conn = null; return EVAL_PAGE; }