RequestOutput.Generate(resp, req);

}

}

В методе performTask() происходит обращение к другому классу-обработчику запроса пользователя с передачей ему объектов HttpServletRequest req иHttpServletResponse resp.

/* пример # 5 : извлечение информации из запроса клиента : RequestOutput.java */

package chapt18;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class RequestOutput {

public static void generate(HttpServletResponse resp,

HttpServletRequest req) {

try {

String name, value;

resp.setContentType("text/html; charset=utf-8");

PrintWriter out = resp.getWriter();

out.print("<HTML><HEAD>");

out.print("<TITLE>Результат</TITLE>");

out.print("</HEAD><BODY>");

out.print("<TABLE BORDER=3>");

Enumeration names = req.getParameterNames();

while (names.hasMoreElements()) {

name = (String) names.nextElement();

value = req.getParameterValues(name)[0]; /*

name = new String(name.getBytes("ISO-8859-1"), "utf-8");

value = new String(value.getBytes("ISO-8859-1"), "utf-8");

*/

out.print("<TR>");

out.print("<TD>" + name + "</TD>");

out.print("<TD>" + value + "</TD>");

out.print("</TR>");

}

out.print("</TABLE></BODY></HTML>");

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

В классе в объекте resp задается тип содержимого text/html и кодировка UTF-8, если нужно отобразить кириллицу. После этого объект out устанавливается в выходной поток resp.getWriter(), в который будут помещаться данные. Из запроса HttpServletRequest req извлекается объект типа Enumeration с текстовыми значениями имен переменных формы. Далее, итерируя по элементам этого объекта, последовательно извлекаются все параметры. Для каждого имени переменной можно при необходимости (если не указана кодовая страница) произвести перекодировку: вначале извлекается объект итерации
в кодировке, в которой он передается, а именно ISO-8859-1, после создается новая строка с необходимой кодировкой, в данном случае UTF-8. Для каждой из переменных извлекаются из запроса соответствующие им значения при помощи метода getParameterValues(name). Тем же способом их кодировка может быть изменена и добавлена в выходной поток.

Класс сервлета относится к пакету chapt18, поэтому файл
FormRequest.class должен быть размещен в папке

/webapps/FirstProject3/WEB-INF/classes/chapt18

и обращение к этому классу, например из документа HTML, должно производиться как chapt18.FormRequest. В файле web.xml должны находиться строки:

<servlet>

<servlet-name>MyForm</servlet-name>

<servlet-class>chapt18.FormRequest</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>MyForm</servlet-name>

<url-pattern>/testform</url-pattern>

</servlet-mapping>

Обращение к сервлету производится по его URL-имени testform. Результат выполнения:

RequestOutput.Generate(resp, req); - student2.ru

Рис. 18.2. Результат выполнения запроса

Метод getParameterValues() возвращает значения любой переменной формы по имени этой переменной. Массив возвращается потому, что некоторые переменные формы могут иметь несколько значений, например группа флажков или радиокнопок. Другой метод доступа не предполагает предварительного знания их имен. Метод getParameterNames() возвращает объект Enumeration, в котором содержатся все имена переменных, извлеченных из формы.

Многопоточность

Контейнер сервлетов будет иметь несколько потоков выполнения, распределяемых согласно запросам клиентов. Вероятна ситуация, когда два клиента одновременно вызовут методы doGet() или doPost(). Метод service() должен быть написан с учетом вопросов многопоточности. Любой доступ к разделяемым ресурсам, которыми могут быть файлы, объекты, необходимо защитить ключевым словом synchronized. Ниже приведен пример посимвольного вывода строки сервлетом с паузой между выводом символов в 500 миллисекунд, что позволяет другим клиентам, вызвавшим сервлет, успеть вклиниться в процесс вывода при отсутствии синхронизации.

/* пример # 6 : доступ к синхронизированным ресурсам :

ServletSynchronization.java */

package chapt18;

import java.io.*;

import javax.servlet.ServletException;

import javax.servlet.http.*;

public class ServletSynchronization extends HttpServlet {

// синхронизируемый объект

private StringBuffer locked = new StringBuffer();

protected void doGet(HttpServletRequest req,

HttpServletResponse res)

throws ServletException, IOException {

performTask(req, res);

}

private void performTask(HttpServletRequest req,

HttpServletResponse res)

throws ServletException, IOException {

try {

Writer out = res.getWriter();

out.write(

"<HTML><HEAD>"

+ "<TITLE>SynchronizationDemo</TITLE>"

+ "</HEAD><BODY>");

out.write(createString());

out.write("</BODY></HTML>");

out.flush();

out.close();

} catch (IOException e) {

throw new RuntimeException(

"Failed to handle request: " + e);

}

}

protected String createString() {

// оригинал строки

final String SYNCHRO = "SYNCHRONIZATION";

synchronized (locked) {

try {

for (int i = 0; i < SYNCHRO.length(); i++) {

locked.append(SYNCHRO.charAt(i));

Thread.sleep(500);

}

} catch (InterruptedException e) {

e.printStackTrace();

}

String result = locked.toString();

locked.delete(0, SYNCHRO.length() - 1);

return result;

}

}

}

Результаты работы сервлета при наличии и отсутствии синхронизации представлены на рисунках.

RequestOutput.Generate(resp, req); - student2.ru

Рис. 18.3. Результат работы сервлета Synchronization
с блоком синхронизации

RequestOutput.Generate(resp, req); - student2.ru

RequestOutput.Generate(resp, req); - student2.ru

Рис. 18.4. Результат работы сервлета Synchronization
без синхронизации

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

Электронная почта

Рассылка электронной почты, в том числе и автоматическая, является стандартным родом деятельности при использовании Web-приложений. Собственный почтовый сервер создать достаточно легко, только необходимо указать адрес почтового севера, который будет использован в качестве транспорта.

Следующий пример использует интерфейсы API JavaMail для работы с электронной почтой в сервлетах и JSP. API JavaMail содержит классы, с помощью которых моделируется система электронной почты. Класс javax.mail.Session представляет сеанс почтовой связи, класс javax.mail.Message – почтовое сообщение, класс javax.mail.internet.InternetAddress – адреса электронной почты.

RequestOutput.Generate(resp, req); - student2.ru

Рис. 18.5. Формирование запроса на отправку письма

Для работы с данной частью платформы J2EE необходимо скачать zip-файлы, расположенные по адресу http://java.sun.com/products/javamail/, содержащие архивы mail.jar и activation.jar. И добавить эти файлы в каталог jar-файлов серверам приложений (common/lib для Tomcat). Также необходимо запустить почтовую программу James, являющуюся также одним из проектов apache.org.

Ниже приведена страница JSP, содержащая форму для заполнения основных полей: «Кому» – «to», «От кого» – «from», «Тема сообщения» – «subj»

<!-- пример # 7 : страница создания электронного письма : index.jsp-->

<%@ page language="java" contentType=

"text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html><head><title>SendMail Application</title></head>

<b>Мой почтовый сервер</b>

<form method="post" action="sendmail">

<table>

<tr><td><b>To(email):</b></td><td>

<input name="to" type="text" size=40></td></tr>

<tr><td><b>From(email):</b></td><td>

<input name="from" type="text" size=40></td></tr>

<tr><td><b>Subject:</b></td><td>

<input name="subj" type="text" size=40></td></tr>

</table>

<hr>

<textarea name="body" type="text" rows=5 cols=45>

Добрый день!</textarea>

<br>

<input type="submit" value="Отправить!">

</form>

</body></html>

Параллельные процессы по отправке письма и предложению пользователю в это же самое время создать новое письмо организуются с применением потока
в следующем сервлете.

/* пример # 8 : доступ к синхронизированным ресурсам :

SendMailServlet.java */

packagechapt18;

import javax.mail.Message;

import javax.mail.MessagingException;

import javax.mail.Session;

import javax.mail.Transport;

import javax.mail.internet.AddressException;

import javax.mail.internet.InternetAddress;

import javax.mail.internet.MimeMessage;

import javax.activation.*;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.PrintWriter;

public class SendMailServlet

extendsjavax.servlet.http.HttpServlet

implements javax.servlet.Servlet {

//объект почтовой сессии

private Session mailSession = null;

public void init(ServletConfig config)

throws ServletException {

//mailSession = Session.getDefaultInstance(System.getProperties());

final String host = "mail.smtphost";

final String port = "mail.smtpport";

//запрос параметров почтового сервера из web.xml

String hostvalue = config.getInitParameter(host);

String portvalue = config.getInitParameter(port);

java.util.Properties props = new java.util.Properties();

//загрузка параметров почтового сервера в объект свойств

props.put(host, hostvalue);

props.put(port, portvalue);

//загрузка параметров почтового сервера в объект почтовой сессии

mailSession = Session.getDefaultInstance(props, null);

}

protected void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

//извлечение параметров письма из запроса

String from = request.getParameter("from");

String to = request.getParameter("to");

String subject = request.getParameter("subj");

String content = request.getParameter("body");

if((from == null) || (to == null)

|| (subject == null) || (content == null)) {

/*при отсутствии одного из параметров предлагается повторить

ввод*/

response.sendRedirect("index.jsp");

return;

}

//запуск процесса отправки почты в отдельном потоке

(new MailSender(to, from, subject, content)).start();

//формирование страницы с предложение о создании нового письма

response.setContentType("text/html; charset=CP1251");

PrintWriter out = response.getWriter();

out.println("<html><head><title>");

out.println("SendMail Application</title></head>");

out.println("Message to <b>" + to

+ "</b> sending in progress");

out.println("<a href = \"index.jsp\">New message</a>");

out.println("</body></html>");

}

private class MailSender extends Thread {

private String mailTo;

private String mailFrom;

private String mailSubject;

private String mailContent;

MailSender(String mailTo, String mailFrom,

String mailSubject, String mailContent) {

setDaemon(true);

this.mailTo = mailTo;

this.mailFrom = mailFrom;

this.mailSubject = mailSubject;

this.mailContent = mailContent;

}

public void run() {

try {

//создание объекта почтового сообщения

Message message = new MimeMessage(mailSession);

//загрузка параметров в объект почтового сообщения

message.setFrom(new InternetAddress(mailFrom));

message.setRecipient(Message.RecipientType.TO,

new InternetAddress(mailTo));

message.setSubject(mailSubject);

message.setContent(mailContent, "text/plain");

//отправка почтового сообщения

Transport.send(message);

} catch(AddressException e) {

e.printStackTrace();

System.err.print("Ошибка адреса");

} catch(MessagingException e) {

e.printStackTrace();

System.out.print("Ошибка сообщения");

}

}

}

}

В результате в браузер будет выведено:

Message to [email protected] sending in progress New message

где New message представляет собой активную ссылку, перенаправляющую при запуске на index.jsp для создания еще одного письма. Процесс же отправки письма будет функционировать независимо от дальнейшей работы приложения.

Файл web.xml для данного приложения имеет вид:

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>FirstMail</display-name>

<servlet>

<display-name>

SendMailServlet</display-name>

<servlet-name>SendMailServlet</servlet-name>

<servlet-class>

SendMailServlet</servlet-class>

<init-param>

<param-name>mail.smtphost</param-name>

<param-value>mail.bsu.bsu</param-value>

</init-param>

<init-param>

<param-name>mail.smtpport</param-name>

<param-value>25</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>chapt18.SendMailServlet</servlet-name>

<url-pattern>/sendmail</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

В качестве значения параметра mail.smtphost можно попробовать использовать адрес почтового сервера mail.attbi.com.

Задания к главе 18

Вариант А

Создать сервлет и взаимодействующие с ним пакеты Java-классов и JSP-страницы, выполняющие следующие действия:

1. Генерация таблиц по переданным параметрам: заголовок, количество строк и столбцов, цвет фона.

2. Вычисление тригонометрических функций в градусах и радианах с указанной точностью. Выбор функций должен осуществляться через выпадающий список.

3. Поиск слова, введенного пользователем. Поиск и определение частоты встречаемости осуществляется в текстовом файле, расположенном на сервере.

4. Вычисление объемов тел (параллелепипед, куб, сфера, тетраэдр, тор, шар, эллипсоид и т.д.) с точностью и параметрами, указываемыми пользователем.

5. Поиск и (или) замена информации в коллекции по ключу (значению).

6. Выбор текстового файла из архива файлов по разделам (поэзия, проза, фантастика и т.д.) и его отображение.

7. Выбор изображения по тематике (природа, автомобили, дети и т.д.)
и его отображение.

8. Информация о среднесуточной температуре воздуха за месяц задана
в виде списка, хранящегося в файле. Определить:

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

9. Игра с сервером в “21”.

10. Реализация адаптивного теста из цепочки в 3–4 вопроса.

11. Определение значения полинома в заданной точке. Степень полинома
и его коэффициенты вводятся пользователем.

12. Вывод фрагментов текстов шрифтами различного размера. Размер шрифта и количество строк задаются на стороне клиента.

13. Информация о точках на плоскости хранится в файле. Выбрать все точки, наиболее приближенные к заданной прямой. Параметры прямой
и максимальное расстояние от точки до прямой вводятся на стороне клиента.

14. Осуществить сортировку введенного пользователем массива целых чисел. Числа вводятся через запятую.

15. Реализовать игру с сервером в крестики-нолики.

16. Осуществить форматирование выбранного пользователем текстового файла, так чтобы все абзацы имели отступ ровно 3 пробела, а длина каждой строки была ровно 80 символов и не имела начальными и конечными символами пробел.

Вариант B

Для заданий варианта В главы 4 на основе сервлетов разработать механизм аутентификации и авторизации пользователя. Сервлет должен сгенерировать приветствие с указанием имени, роли пользователя, а также указать текущую дату и IP-адрес компьютера пользователя.

Тестовые задания к главе 18

Вопрос 18.1.

Каким образом в методе init() сервлета получить параметр инициализации сервлета с именем “URL”? (выберите два)

1) ServletConfig.getInitParameter("URL");

2) getServletConfig().getInitParameter("URL");

3) this.getInitParameter("URL");

4) HttpSerlet.getInitParameter("URL");

5) ServletContext.getInitParameter("URL").

Вопрос 18.2.

Какой метод сервлета FirstServlet будет вызван при активизации ссылки следующего HTML-документа?

<html><body>

<a href="/FirstProject/FirstServlettest">OK!</a>

</body><html>

Соответствующий сервлету тег <url-pattern> в файле web.xml имеет вид:

<url-pattern>/FirstServlettest</url-pattern>

1) doGet();

2) doGET();

3) performTask();

4) doPost();

5) doPOST().

Вопрос 18.3.

Контейнер вызывает метод init() экземпляра сервлета…

1) при каждом запросе к сервлету;

2) при каждом запросе к сервлету, при котором создается новая сессия;

3) при каждом запросе к сервлету, при котором создается новый поток;

4) только один раз за жизненный цикл экземпляра;

5) когда сервлет создается впервые;

6) если время жизни сессии пользователя, от которого пришел запрос, истекло.

Вопрос 18.4.

Каковы типы возвращаемых значений методов getResource()
и getResourceAsStream()интерфейса ServletContext?

1) ServletContext не имеет таких методов;

2) String и InputStream;

3) URL и InputStream;

4) URL и StreamReader.

Вопрос 18.5.

Какие интерфейсы находятся в пакете javax.servlet?

1) ServletRequest;

2) ServletOutputStream;

3) PageContext;

4) Servlet;

5) ServletContextEvent;

6) ни один из перечисленных.

Вопрос 18.6.

Как можно получить всю информацию из запроса, посланного следующей формой? (выберите два варианта ответа)

<HTML><BODY>

<FORM action="/com/MyServlet">

<INPUT type="file" name="filename">

<INPUT type="submit" value="Submit">

</FORM></BODY></HTML>

1) request.getParameterValues("filename");

2) request.getAttribute("filename");

3) request.getInputStream();

4) request.getReader();

5) request.getFileInputStream().

 
Глава 19

Java Server Pages

Технология Java Server Pages (JSP) была разработана компанией Sun Microsystems, чтобы облегчить создание страниц с динамическим содержанием.

В то время как сервлеты наилучшим образом подходят для выполнения контролирующей функции приложения в виде обработки запросов и определения вида ответа, страницы JSP выполняют функцию формирования текстовых документов типа HTML, XML, WML и некоторых других.

под терминами “динамическое/статическое содержание” обычно понимаются не части JSP, а содержание Web-приложения:

1) динамические ресурсы, изменяемые в процессе работы: сервлеты, JSP, а также java-код;

2) статические ресурсы, не изменяемые в процессе работы – HTML, JavaScript, изображения и т.д.

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

Рекомендуется разделить и разрабатывать параллельно две части приложения: Web-приложение, состоящее только из динамических ресурсов, и Web-приложение, состоящее только из статических ресурсов.

Некоторые преимущества использования JSP-технологии над другими методами создания динамического содержания страниц:

d) Разделение динамического и статического содержания.

Возможность разделить логику приложения и дизайн Web-страницы снижает сложность разработки Web-приложений и упрощает их поддержку.

d) Независимость от платформы.

Так как JSP-технология, основанная на языке программирования Java, не зависит от платформы, то JSP могут выполняться практически на любом Web-сервере. Разрабатывать JSP можно на любой платформе.

e) Многократное использование компонентов.

Использование JavaBeans и Enterprise JavaBeans (EJB) позволяет мно­гократно использовать компоненты, что ускоряет создание Web-сайтов.

f) Скрипты и теги.

Спецификация JSP объявляет собственные теги, кроме того, JSP поддерживают как JavaScript, так и HTML-теги. JavaScript обычно используется, чтобы добавить функциональные возможности на уровне HTML-страницы. Теги обеспечивают возможность использования JavaBean и выполнение обычных функций.

Чтобы облегчить внедрение динамической структуры, JSP использует ряд тегов, которые дают возможность проектировщику страницы вставить значение полей объекта JavaBean в файл JSP.

Содержимое Java Server Pages (теги HTML, теги JSP и скрипты) переводится в сервлет код-сервером. Этот процесс ответствен за трансляцию как динами­ческих, так и статических элементов, объявленных внутри файла JSP. Об архитектуре сайтов, использующих JSP/Servlet-технологии, часто говорят как о thin-client (использование ресурсов клиента незначительно), потому что большая часть логики выполняется на сервере.

JSP составляется из стандартных HTML-тегов, JSP-тегов, action-тегов, JSTL и пользовательских тегов. В спецификации JSP 2.0 существует пять основных тегов:

<%@директива%>–используются для установки параметров серверной страницы JSP.

<%!объявление%>–содержит переменные Java и методы, которые вызываются в expression-блоке и являются полями генерируемого сервлета. Объявление не должно производить запись в выходной поток out страницы, но может быть использовано в скриптлетах и выражениях.

<%скриптлет%>–вживление Java-кода в JSP-страницу. Скриптлеты обыч­но используют маленькие блоки кода и выполняются во время обработки запроса клиента. Когда все скриптлеты собираются воедино в том порядке, в котором они записаны на странице, они должны представлять собой правильный код языка программирования. Контейнер помещает код Java в метод _jspService() на этапе трансляции.

<%=вычисляемое выражение%>–операторы языка Java, которые вычисляются, после чего результат вычисления преобразуется в строку String и посылается в поток out.

<%-- JSP-комментарий --%>–комментарий, который не отображается в исходных кодах JSP-страницы после этапа выполнения.

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

Большинство тегов, объявленных выше, применяются не так уж часто. Наиболее используемыми являются стандартные действия версии JSP 2.0. Они позволяют создавать правильные JSP –документы с помощью следующих тегов:

1) jsp:declaration– объявление, аналогичен тегу <%! ... %>;

2) jsp:scriptlet – скриптлет, аналогичен тегу <% ... %>;

3) jsp:expression– скриптлет, аналогичен тегу<%= ... %>;

4) jsp:text– вывод текста;

2 jsp:useBean – позволяет использовать экземпляр компонента Java Bean. Если экземпляр с указанным идентификатором не существует, то он будет создан с областью видимости page (страница), request (запрос), session (сессия) или application(приложение). Объявляется, как правило, с атрибутами id(имя объекта), scope (область видимости), class(полное имя класса), type (по умолчанию class).

<jsp:useBean id=”ob”

scope=”session”

class=”test.MyBean” />

Создан объект ob класса MyBean, и в дальнейшем через этот объект можно вызывать доступные методы класса. Специфика компонентов JavaBean в том, что если компонент имеет поле field, экземпляр компонента имеет параметр field, а метод, устанавливающий значение, должен называться setField(type value), возвращающий значение – getField().

package test;

public class MyBean {

private String field = "нет информации";

public String getField() {

return info;

}

public void setField(String f) {

field = f;

}

}

5) jsp:setProperty– позволяет устанавливать значения полей указанного в атрибуте name объекта. Если установить значение property в «*», то значения свойств компонента JavaBean будут установлены таким образом, что будет определено соответствие между именами параметров и именами методов-установщиков (setter-ов) компонента:

<jsp:setProperty name=”ob”

property=”field”

value=”привет” />

e) jsp:getProperty– получает значения поля указанного объекта, преобразует его в строку и отправляет в неявный объект out:

<jsp:getProperty name=”ob” property=”field” />

f) jsp:include– позволяет включать файлы в генерируемую страницу при запросе страницы:

<jsp:include page=”относительный URL”

flush=”true”/>

g) jsp:forward– позволяет передать запрос другой странице:

<jsp:forward page=”относительный URL”/>

h) jsp:plugin– замещается тегом <OBJECT>или <EMBED>, в зависимости от типа браузера, в котором будет выполняться подключаемый апплет или Java Bean.

i) jsp:params– группирует параметры внутри тега jsp:plugin.

6) jsp:param– добавляет параметры в объект запроса, например в элементах forward, include, plugin.

7) jsp:fallback– указывает содержимое, которое будет использоваться браузером клиента, если подключаемый модуль не сможет запуститься. Используется внутри элемента plugin.

В качестве примера можно привести следующий фрагмент:

<jsp:plugin type=”bean | applet”

code=”test.com.ReadParam”

width=”250”

height=”250”>

<jsp:params>

<jsp:param name=”bNumber” value=”7” />

<jsp:param name=”state” value=”true” />

</jsp:params>

<jsp:fallback>

<p> unable to start plugin </p>

</jsp:fallback>

</jsp:plugin>

Код апплета находится в примере 5 главы 11, и пакет, в котором он объявлен, должен быть расположен в корне папки /WEB-INF, а не в папке /classes.

Элементы <jsp:attribute>,<jsp:body>,<jsp:invoke>,<jsp:doBody>,<jsp:element>,<jsp:output>используются в основном при включении в страницу пользовательских тегов.

JSP-документ

Предпочтительно создавать JSP-страницу в виде JSP-документа – кор­рект­ного XML-документа, который ссылается на определенное пространство имен, содержит стандартные действия JSP, пользовательские теги и теги ядра JSTL, XML-эквиваленты директив JSP. В JSP-документе вышеперечисленные пять тегов неприменимы, поэтому их нужно заменять стандартными действиями и кор­ректными тегами. JSP-документы необходимо сохранять с расширением .jspx.

Директива taglib для обычной JSP:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c"%>

для JSP-документа:

<jsp:root xmlns:c="http://java.sun.com/jsp/jstl/core"/>

Директива page для обычной JSP:

<%@ page contentType="text/html"%>

для JSP-документа:

<jsp:directive.page contentType="text/html" />

Директива include для обычной JSP:

<%@ include file="file.jspf"%>

для JSP-документа:

<jsp:directive.include file="file.jspf" />

Ниже приведены два примера, демонстрирующие различие применения стандартных действий и тегов при создании JSP-страниц и JSP-документов.

<!--пример # 1 : обычная jsp-страница: page.jsp -->

<%@ page contentType="text/html; charset=Cp1251" %>

<html><head><title>JSP-страница</title></head>

<%! private int count = 0;

String version = new String("J2EE 1.5");

private String getName(){return "J2EE 1.6";} %>

<% out.println("Значение count: "); %>

<%= count++ %>

<br/>

<% out.println("Значение count после инкремента: " + count); %>

<br/>

<% out.println("Старое значение version: "); %>

<%= version %>

<br/>

<% version=getName();

out.println("Новое значение version: " + version); %>

</html>

Версия в виде JSP-документа несколько более громоздка, но читать и искать ошибки в таком документе проще, нежели в предыдущем.

<!--пример # 2 : правильный jsp-документ : page.jspx -->

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"

version="2.0">

<jsp:directive.page contentType=

"text/html; charset=UTF-8" />

<html><body>

<jsp:declaration>

private int count = 0;

String version = new String("J2EE 1.5");

private String getName(){return "J2EE 1.6";}

</jsp:declaration>

<jsp:scriptlet>

out.println("Значение count: ");

</jsp:scriptlet>

<jsp:expression>

count++

</jsp:expression>

<br />

<jsp:scriptlet>

out.println("Значение count после инкремента:"

+ count);

</jsp:scriptlet>

<br/>

<jsp:scriptlet>

out.println("Старое значение version: "); </jsp:scriptlet>

<jsp:expression> version </jsp:expression>

<br/>

<jsp:scriptlet> version=getName();

out.println("Новое значение version: " + version);

</jsp:scriptlet>

</body></html>

</jsp:root>

Далее в главе примеры будут приведены в виде JSP-документов.

JSTL

JSP-страницы, включающие скриптлеты, элементы action (стандартные действия) и пользовательские теги, не могут быть технологичными без использования JSTL (JSP Standard Tag Library). Создание страниц с применением JSTL позволяет упростить разработку и отказаться от вживления Java-кода в JSP. Как было показано ранее, страницы со скриптлетами трудно читаемы, что вызывает проблемы как у программиста, так и у веб-дизайнера, не обладающего глубокими познаниями в Java.

Библиотеку JSTL версии 1.1.2 (jstl-1.1.2.jarиstandard-1.1.2.jar) или более позднюю версию можно загрузить c сайта apache.org. Библиотеки следует разместить в каталоге /lib проекта. При указании значения параметра xmlns элемента root (для JSP-страницы значение параметра taglib uri="") необходимо быть внимательным, так как если адрес будет указан неправильно, JSP-страница не сможет иметь доступ к тегам JSTL. Проверить правильность значение параметра uri (оно же справедливо и для параметра xmlns) можно в файле подключаемой библиотеки (например c.tld). Простейшая JSP с применением тега JSTL, выводящим в браузер приветствие будет выглядеть следующим образом:

<!--пример # 3 : правильный jsp-документ: simple.jspx -->

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"

xmlns:c=http://java.sun.com/jsp/jstl/core

version="2.0">

<jsp:directive.page contentType=

"text/html; charset=Utf-8"/>

<html><body>

<c:out value="Welcome to JSTL"/>

</body></html>

</jsp:root>

Тег <c:out/> отправляет значение параметра value в поток JspWriter.

JSTL предоставляет следующие возможности:

- поддержку Expression Language, что позволяет разработчику писать простые выражения внутри атрибутов тега и предоставляет “прозрачный” доступ к переменным в различных областях видимости страницы;

- организацию условных переходов и циклов, основанную на тегах, а не на скриптовом языке;

- простое формирование доступа (URL) к различным ресурсам;

- простую интернационализацию JSP;

- взаимодействие с базами данных;

- обработку XML, а также форматирование и разбор строк.

Expression Language

В JSTL вводится понятие Expression Language (EL). EL используется для упрощения доступа к данным, хранящимся в различных областях видимости (page, request, application) и вычисления простых выражений.

EL вызывается при помощи конструкции “${имя}”.

Начиная с версии спецификации JSP 2.0 / JSTL 1.1, EL является частью JSP и поддерживается без всяких сторонних библиотек. С версии web-app 2.4 атрибут isELIgnored по умолчанию имеет значение true. В более ранних версиях необходимо указывать его в директиве page со значение true.

EL-идентификатор ссылается на переменную, возвращаемую вызовом PageContext.findAttribute(имя). В общем случае переменная может быть сохранена в любой области видимости: page(PageContext), request(HttpServletRequest), session (HttpSession), application (ServletContext). В случае если переменная не найдена, возвращается null. Также возможен доступ к параметрам запроса через предопределённый объект paramValues и к заголовкам запроса через requestHeaders.

Данные приложения, как правило, состоят из объектов, соответствующих спе­цификации JavaBeans, или представляют собой коллекции, такие как List, Map, Array и др. EL предоставляет доступ к этим объектам при помощи операторов “.” и “[]”. Применение этих операторов зависит от типа объекта. Например:

<c:out value=”${student.name}”/>

<!--пример # 4 : правильный jsp-документ : simple2.jspx -->

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"

xmlns:c="http://java.sun.com/jsp/jstl/core"

version="2.0">

<jsp:directive.page contentType=

"text/html; charset=Utf-8"/>

<html>

<head><title>Простое использование EL</title></head>

<body>

<c:set var="login" value="Бендер" scope="page"/>

<c:out value="${login} in Rio"/>

<br/>

<c:out value="Бендер в байтовом виде: ${login.bytes} "/>

</body></html>

</jsp:root>

С помощью оператора “.”можно вызывать некоторые методы класса, к которому принадлежит объект. Вызов login.bytesв переводе на обычную Java означает login.getBytes().

В результате запуска этого документа в браузер будет выведено:

Бендер in Rio
Бендер в байтовом виде: [B@edf730

Операторы в EL поддерживают наиболее часто используемые манипуляции данными.

Типы операторов:

Стандартные операторы отношения:

== (или eq), != (или neq), < (или lt), > (или gt), <= (или le), >= (или ge).

Арифметические операторы: +, -, *, / (или div), % (или mod).

Логические операторы: && (или and), || (или or), ! (или not).

Оператор empty – используется для проверки переменной на null, или “пустое значение”. Термин “пустое значение” зависит от типа проверяемого объекта. Например, нулевая длина для строки или нулевой размер для коллекции.

Например:

<c:if test=”${not emptyuser anduser.nameneq‘guest’}>

User is Customer.

</c:if>

Наши рекомендации