Развитие Web-технологий в Java
Платформа Enterprise Java всегда включала в себя Web-технологии. Они начинались и развивались с сервлетов.
Сервлеты первоначально использовались для формирования ответов на HTTP-запросы. Написание сервлета было в общем довольно противным занятием. Взгляните на пример в листинге 1.
Листинг 1. Сервлет, генерирующий HTML
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0
Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
out.println("<head>");
out.println("<meta http-equiv=\"Content-Type\" content=\"text/html;
charset=ISO-8859-1\" />");
out.println("<title>All Users</title>");
out.println("</head>");
out.println("<body>");
out.println(" <table>");
out.println(" <tr>");
out.println(" <td>UserID</td>");
out.println(" <td>UserName</td>");
out.println(" <td>Name</td>");
out.println(" </tr>");
UserDao dao = new UserDao();
List users = dao.getAllUsers();
for (int i=0;i<users.size();i++){
User user = (User) users.get(i);
out.println(" <tr>");
out.println(" <td>"+user.getId()+"</td>");
out.println(" <td>"+user.getUserName()+"</td>");
out.println(" <td>"+user.getFirstName()+'
'+user.getLastName()+"</td>");
out.println(" </tr>");
}
out.println(" </table>");
out.println("</body>");
out.println("</html>");
}
|
Сервлеты содержали много HTML-кода (как в примере), внедренного непосредственно в Java-код. Это делало поддержку сервлетов еще более сложной, чем разработку. Представьте, что вы хотите изменить таблицу, добавив к ней границу, в коде в листинге 1. Чтобы сделать это, придется изменять Java-код и перекомпилировать сервлет. К счастью, сервлеты были вскоре дополнены технологией JavaServer Pages (JSP).
Технология JSP улучшила сервлеты Java. JSP-компоненты предоставили множество усовершенствований по сравнению с сервлетами, включая возможность смешивания языка разметки с Java-кодом. В листинге 2 показан тот же самый сервлет, что и в листинге 1, но с использованием JSP.
Листинг 2. JSP, версия 1.0
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ page import="org.developerworks.*" %>
<%@ page import="java.util.List" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
<table>
<tr>
<td>UserID</td>
<td>UserName</td>
<td>Name</td>
</tr>
<%
UserDao dao = new UserDao();
List users = dao.getAllUsers();
for (int i=0;i<users.size();i++){
User user = (User) users.get(i);
%>
<tr>
<td><%= user.getId() %></td>
<td><%= user.getUserName() %></td>
<td><%= user.getFirstName() %> <%= user.getLastName()
%></td>
</tr>
<%
}
%>
</c:forEach>
</table>
</body>
</html>
|
Очевидно, то, что вы видите в листинге 2, является большим шагом по сравнению с исходным сервлетом. Компоненты JSP все еще компилируются в сервлеты, но это делается контейнером сервлетов (либо это может выполняться в процессе компиляции приложения). Таким образом, JSP-компонент позволял обеспечить такую же производительность, что и сервлеты. Синтаксис JSP похож на Active Server Page (ASP) и PHP, однако компиляция в сервлеты давала JSP-страницам значительное преимущество в производительности в сравнении с другими технологиями
В коде JSP, показанном в листинге 2, все еще есть несколько значительных проблем. В нем используются скриплеты - маленькие кусочки Java-кода. Применение скриплетов представляет проблему с точки зрения как дизайна, так и практического использования. В JSP-страницах бизнес-логика (формирование списка пользователей) свободно смешивалась с отображением. Архитектура JSP Model 2 была создана для решения этой проблемы. Появилась возможность использовать сервлет совместно с JSP-страницей. Взгляните на листинг 3.
Листинг 3. Сервлет в стиле Model 2
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
UserDao dao = new UserDao();
List users = dao.getAllUsers();
request.setAttribute("users", users);
request.getRequestDispatcher("/user.jsp").forward(request, response);
}
|
Сервлет может, например, производить первоначальную обработку запроса и выполнять бизнес-логику. Далее
он может сохранять свои результаты в объекте HttpServletRequest
и переадресовать его на страницу JSP. Это позволяет упростить JSP, как видно из листинга 4.
Листинг 4. JSP-страница в стиле Model 2
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ page import="org.developerworks.*" %>
<%@ page import="java.util.List" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
<table>
<tr>
<td>UserID</td>
<td>UserName</td>
<td>Name</td>
</tr>
<%
List users = (List) request.getAttribute("users");
for (int i=0;i<users.size();i++){
User user = (User) users.get(i);
%>
<tr>
<td><%= user.getId() %></td>
<td><%= user.getUserName() %></td>
<td><%= user.getFirstName() %> <%= user.getLastName()
%></td>
</tr>
<%
}
%>
</c:forEach>
</table>
</body>
</html>
|
Это решает часть архитектурных проблем. Однако остается еще одна проблема практического характера. Смешивание Java-кода и HTML делает JSP-страницу сложной в разработке как для Java разработчиков, которые не знают HTML, так и для Web-дизайнеров, не знающих языка Java.
JavaServer Pages Standard Tag Library (JSTL)
Одной из целей технологии JSP стало очищение JSP от всякого Java-кода. Конечным результатом этого процесса стала спецификация JSTL. JSTL представляла собой набор тегов в HTML-стиле, вызывающих объекты Java и выполняющих многие из конструкций языка Java, в том числе перебор коллекций, условную логику и форматирование текста. JSTL позволяет JSP-компоненту развиваться, как показано в листинге 5.
Листинг 5. JSP с использованием JSTL
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
<table>
<tr>
<td>UserID</td>
<td>UserName</td>
<td>Name</td>
</tr>
<c:forEach items="${users}" var="user">
<tr>
<td><c:out value="${user.id}"/></td>
<td><c:out value="${user.userName}"/></td>
<td><c:out value="${user.firstName}"/> <c:out
value="${user.lastName}"/></td>
</tr>
</c:forEach>
</table>
</body>
</html>
|
Тег <c:forEach> позволяет обходить
список пользователей. Тег <c:out>
позволяет обратиться к объекту Java и вывести его данные.
Выражения, использованные в тегах, такие как ${users} и
${user.id}, интерпретируются с помощью языка выражений (JSTL Expression
Language - EL). Например, EL интерпретирует строку
${users} и ищет атрибут users в различных
доступных объектах, например pageContext, request,
session и контекстах сервлета и приложения.
). Дальнейшим развитием JSP-страниц стала возможность использовать EL не только из
тегов JSTL. Это привело к виду JSP-страницы, показанному в листинге 6.
Листинг 6. JSP с использованием JSTL и EL
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
<table>
<tr>
<td>UserID</td>
<td>UserName</td>
<td>Name</td>
</tr>
<c:forEach items="${users}" var="user">
<tr>
<td>${user.id}</td>
<td>${user.userName}</td>
<td>${user.firstName} ${user.lastName}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
|
Эта современная форма JSTL и EL впервые появилась в спецификации JSP 2.0. Соединенная с архитектурой Model 2 (часто реализуемой в различных средах построения пользовательского интерфейса, например Apache Struts и других), эта комбинация JSTL и EL дает возможность создавать JSP-страницы, максимально свободные от Java-кода. Это позволяет непрограммистам работать с JSP-страницами и предоставляет Java-разработчикам возможность сконцентрироваться на реализации бизнес-логики.
Технология JavaServer Faces (JSF)
Однако технология JSP - не единственная Web-технология в составе архитектуры Enterprise Java. Вскоре после выхода спецификации JSP 2.0 была представлена технология JSF. JSF изначально была создана как компонентная архитектура. Объекты на Web-странице отображаются как компоненты с жизненным циклом, с которыми связанны объекты Java. Соответственно в рассматриваемом в данной статье примере JSP-страницы вы можете связать видимые компоненты с Java-объектами, используя JSF. Результирующая JSP-страница показана в листинге 7.
Листинг 7. JSP с использованием JSF
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http:.//java.sun.com/jsf/core" prefix="f" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
<f:view>
<h:dataTable id="users" value="#{UserBean.users}" var="user">
<h:column>
<f:facet name="header">UserID</f:facet>
<h:outputText value="#{user.id}"/>
</h:column>
<h:column>
<f:facet name="header">UserName</f:facet>
<h:outputText value="#{user.userName}"/>
</h:column>
<h:column>
<f:facet name="header">Name</f:facet>
<h:outputText value="#{user.firstName}"/> <h:outputText
value="#{user.lastName}"/>
</h:column>
</h:dataTable>
</f:view>
</body>
</html>
|
Заметьте, как производится связывание таблицы dataTable с объектом Java.
Теперь вы просто определяете столбцы таблицы, а итерирование по строкам компонент делает самостоятельно.
Это обеспечивается с помощью управляющего компонента
(UserBean), созданного с использованием ваших данных. Компонент
dataTable самостоятельно выводит HTML-код, так что вам не придется
писать никакого HTML-кода для таблицы. Это одно из преимуществ
JSF.
JSF изначально использовала технологию JSP. Однако на момент ее создания наиболее широко
используемой была версия JSP 1.2. Поэтому JSF базировалась на JSP версии 1.2 и,
соответственно, не поддерживала ни JSTL, ни EL. Вы могли бы заметить использование атрибутов-значений
в тегах <h:dataTable> и
<h:outputText>. Они выглядят похоже на EL,
используемый в JSTL. Но в JSF версии 1.0 это именно внешнее сходство.
JSF поддерживает собственный EL, который работает очень похоже на EL из
JSTL, позже сделанный частью технологии JSP. Однако JSF EL был несовместим
со стандартным JSTL EL—до нынешнего момента.
Унифицированный язык выражений
Одним из ключевых пунктов в спецификации Java EE 5 является унифицированный язык выражений. Таким образом, EL, используемые в JSTL и JSF были объединены. Теперь можно смешивать технологии JSTL и JSF в одном файле, как показано в листинге 8.
Листинг 8. Совместное использование JSF и JSTL
<f:view>
<c:forEach items="${UserBean.groups}" var="group">
${group.groupName}
<h:dataTable id="#{group.groupId}" value="#{group.users}"
var="user">
<h:column>
<f:facet name="header">UserID</f:facet>
${user.id}
</h:column>
<h:column>
<f:facet name="header">UserName</f:facet>
${user.userName}
</h:column>
<h:column>
<f:facet name="header">Name</f:facet>
${user.firstName} ${user.lastName}"
</h:column>
</h:dataTable>
</c:forEach>
</f:view>
|
Пример в листинге 8 показывает обход списка групп с использованием JSTL.
Теперь для каждой группы создается таблица, отображающая пользователей группы.
Обратите внимание, как различные диалекты EL используются для обработки данных как
в тегах JSTL (<c:forEach>), так и в выражениях EL
на странице JSP, и в JSF-компонентах (<h:dataTable>).
Благодаря возможности использовать смесь диалектов EL для JSTL и JSF вы получаете лучшее из обоих миров.
EL как часть платформы Java EE 5
В Java EE 5 есть еще одно значительное изменение, касающееся EL. Реализация JSTL не была обязательной частью спецификации J2EE 1.4. Разработчики Web-приложений могли выбирать, какую именно реализацию JSTL они будут использовать в своем приложении. Конечно, они могли выбрать и использование только реализации JSF для своих приложений.
Спецификация Java EE 5 требует реализации JSTL. Разработчики Web-приложений больше не обязаны беспокоиться о включении различных реализаций в свои приложения. Вместо этого они могут использовать JSTL без малейших колебаний. Кроме того, они на полную мощь могут применять JSF. Унифицированный язык выражений (EL), включенный в JSF, является частью спецификации Java EE 5.
Geronimo и реализация JSTL в GlassFish
В предыдущей части статьи говорилось, что до последнего времени разработчики Web-приложений могли выбирать, будет ли использоваться технология JSTL. Если они решались на это, то должны были выбрать, какую реализацию JSTL добавлять в приложение. Были доступны различные реализации JSTL.
Теперь, в Java EE 5, реализация JSTL устанавливается в составе сервера приложений. Таким образом, любая реализация спецификации Java EE 5 должна включать и реализацию JSTL. И когда разработчики Apache Geronimo начали работу над собственной реализацией Java EE 5 в —Geronimo 2.0—, они обязаны были добавить и реализацию JSTL.
Однако они не могли просто взять и использовать любую из существующих реализаций. Унифицированный язык выражений был одним из основных требований к реализации JSTL. Многие из JSTL-реализаций не были предназначены для работы с технологией JSF. К счастью, команде Geronimo не пришлось создавать собственный вариант JSTL и унифицированного языка выражений самостоятельно. Они могли использовать GlassFish от Sun.
Если вы не знакомы с GlassFish - это эталонная реализация спецификации Java EE 5, созданная Sun. Данное приложение построено на открытых исходных кодах и лицензировано как под Sun's Common Development and Distribution License (CDDL), так и под GNU General Public License (GPL). Sun всегда поддерживала эталонную реализацию технологии JSF, поэтому она быстро создала эталонную реализацию JSTL, включающую унифицированный язык выражений. Открытость кодов GlassFish позволила команде Geronimo использовать это достижение и включить реализацию JSTL из GlassFish в состав Geronimo 2.0. Она была добавлена в первой контрольной сборке Geronimo: Geronimo 2.0-M1.
Поскольку GlassFish лицензирован и под CDDL, и под GPL, он может быть добавлен в Geronimo. Однако эта лицензия не является лицензией в стиле Apache, как у остальных составляющих Geronimo, и это накладывало некоторые ограничения на команду Geronimo.
По существу, Geronimo включает реализацию JSTL из GlassFish, однако не содержит ее исходные кодов. Далее, команда Geronimo не может менять исходных кодов, хотя она очевидно могла бы внести свой вклад в развитие JSTL в GlassFish и далее включить новый пакет в составе Geronimo.
Одна из важных особенностей Geronimo - то, что вы можете менять его код и распространять Вашу собственную, измененную версию Geronimo. Однако реализация JSTL является исключением. Ее исходный код не включен в состав Geronimo, а лицензии накладывают ограничение на распространение и изменение. Например, если вы изменили исходный код GlassFish, Ваши изменения должны быть доступны под той же самой лицензией, что и GlassFish.
Развитие Web-технологий в Java в прошедшие годы принесло огромную выгоду разработчикам. Последний шаг в развитии - унифицированный язык выражений - обещает им дальнейшие улучшения, позволяя использовать совместно как JSTL-, так и JSF-технологии. Унифицированный язык выражений теперь стал одной из важных составных частей спецификации Java EE 5, и это делает его существенной составляющей Geronimo 2.0. Geronimo еще раз поддержал разработчиков, не только реализовав эту спецификацию, но и использовав ее эталонную реализацию. C JSTL из GlassFish и Geronimo 2.0 разработчики получают больше выбора, чем когда-либо ранее, для создания Web-приложений на Java.
Научиться
- Оригинал статьи
The Geronimo renegade: Using integrated packages: GlassFish JSTL 1.2 and Apache Geronimo 2.0 (EN)
- Получите детальное представление о JSP в
учебном пособии
"Введение в JavaServer Pages"
(developerWorks, февраль 2005) (EN).
- Почитайте продуктивную дискуссию об архитектуре Model 2
в статье JavaWorld
"Понимание архитектуры JavaServer Pages Model 2 (EN)."
- Узнайте больше об использовании JSTL из статьи
"Лучшие практики JSP: обновите Ваши JSP-страницы с
JSTL"
(developerWorks, май 2003) (EN).
- Изучите все возможное о языке выражений в
"Примеры JSTL, Часть 1: Язык выражений"
(developerWorks, февраль 2003) (EN).
- Получите представление о технологии JSF
"JSF для неверующих: Избавление от страхов, неуверенности и сомнений относительно JSF"
(developerWorks, февраль 2005) (EN).
- Посмотрите, как EL и JSF сочетаются в Java EE
"Учебное пособие по Java EE 5 (EN)
."
- Почитайте документацию и новости о Geronimo на wiki-странице Geronimo (EN).
- Присоединяйтесь к
проекту Geronimo. (EN)
- Присоединяйтесь к
списку рассылки Apache Geronimo. (EN)
- Изучите, что вам необходимо сделать, чтобы использовать
лицензию Apache Версии 2.0. (EN)
- Прочтите статью
"Содружество GlassFish разрабатывает сервер приложений Java EE,"
рассказывающую об этой инициативе разработки ПО с открытым кодом. (EN)
- Wikipedia содержит хороший
обзор проекта GlassFish (EN).
- В разделе проекта Apache Geronimo на developerWorks вы
найдете статьи, учебники и другие ресурсы, которые помогут вам начать разработку с использованием Geronimo уже сегодня.(EN)
- Найдите полезные для начинающих и опытных пользователей ресурсы
в разделе Начинаем работать с Apache Geronimo на developerWorks.(EN)
- Изучите предложение о поддержке IBM® для Apache Geronimo, которое позволит Вам разрабатывать приложения с Geronimo, пользуясь поддержкой мирового уровня от IBM.(EN)
- В разделе Open source сайта developerWorks можно найти дополнительную информацию, инструменты и новости проектов, которые помогут вам вести разработки при помощи ресурсов с открытым кодом и интегрировать их с ПО от IBM.
- Оставайтесь в курсе событий и Web-трансляций на сайте developerWorks.(EN)
- Изучите другие статьи об Apache и бесплатные учебные пособия по Apache, доступные в разделе открытого кода на developerWorks.
- Найдите книги по этой и другим темам в онлайн-магазине Safari.(EN)
- Подпишитесь на RSS-канал для данной серии. (Узнайте больше о RSS.)(EN)
Получить продукты и технологии
- Загрузите последнюю версию Apache Geronimo.(EN)
- Загрузите бесплатную копию сервера приложений
IBM WebSphere® Application Server Community Edition - простого сервера приложений J2EE, построенного на открытых кодах Apache Geronimo и созданного, чтобы помочь вам ускорить разработку и развертывание приложений.(EN)
- Придайте новый импульс вашему следующему проекту с открытым кодом,
воспользовавшись ознакомительным ПО от IBM, которое можно загрузить через Интернет или заказать на DVD.(EN)
Обсудить
- Примите участие в обсуждении материала на форуме.
- Станьте членом содружества developerWorks,
принимая участие в блогах developerWorks.(EN)