Сходства и различия сервлетов и портлетов

Из-за того, что Portlet API – это расширение Servlet API, у них есть некоторые сходства и различия.

Сходства между сервлетами и портлетами:

· относятся к J2EE Web-компонентам;

· управляются контейнерами;

· генерируют динамическое Web-содержимое при помощи запросов и ответов.

Различия между сервлетами и портлетами:

· портлеты генерируют часть документа, в то время как сервлеты генерируют его полностью;

· за счёт того, что операции кодирования URL выполняются на стороне сервера, пользователь не может обратиться к нему напрямую, зная имя портлета: портлет ведь часть страницы, поэтому знания одного URL
мало;

· портлеты имеют несколько иную схему управления запросами, которые делятся на запросы выполнения действий и запросы генерирования содержимого;

· портлеты придерживаются стандартного набора состояний, которые определяют их контекст работы и правила генерации содержимого.

Портлеты превосходят сервлеты по следующим направлениям:

· имеют расширенный механизм для управления и сохранения своей конфигурационной информации;

· есть доступ к информации о пользовательском профиле, не таком тривиальном, как предоставляют сервлеты.

Приложения с использованием портлетов – это расширенные Web-приложения. Таким образом, оба типа приложений развертываются из WAR-файла и содержат дескриптор Web-приложения (файл web.xml). Портлет-приложения также содержат и дескриптор портлета (файл portlet.xml).

Жизненный цикл

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

Метод init() в качестве параметра принимает объект, который реализует интерфейс PortletConfig, и этот объект предоставляет необходимые для инициализации параметры. Он может быть использован для получения ссылки на объект, реализующий интерфейс PortletContext.

Разработчики портлетов, как правило, не тратят много времени на беспокойство о сложности обработки исключений инициализации портал-контейнера из-за того, что при происхождении оного разработчик реагирует на это должным образом (выясняя обстоятельство, при котором оно произошло). Как правило, нет ничего хуже, чем UnavailableException, которое обозначает, что портлет временно или постоянно недоступен. При создании портлета доступа к окружающему коду, например к контейнеру, нет и не может быть, поэтому код внутри портлета не может оценить, насколько портлет доступен извне.

Метод destroy() предоставляет возможность для произведения очистки ресурсов, которые были востребованы и инициализированы методом init(). Этот метод аналогичен методу destroy() в сервлетах и вызывается один раз: когда контейнер выгружает портлет.

Состояния

Состояния портлетов – это часть портальной модели отображения. Состояния позволяют портлету отображать различные «виды» в зависимости от ситуации.

Есть четыре состояния:

· View – основное состояние портлета;

· Help – если портлет обеспечивает состояние помощи;

· Edit – редактирование параметров портлета с сохранением результатов для этого конкретного пользователя;

· Configure – конфигурирование портлета с охранением результатов для всех пользователей, права к состояниям никак не относятся.

Портлет может быть минимизирован или максимизирован.

Портлет-контейнер

Портлет-контейнер – среда времени выполнения портлета. Она управляет жизненным циклом портлета и запросами от портала путем вызова портлетов внутри контейнера.

Компиляция и запуск

5. Установить переменную окружения JAVA_HOME=C:\jdk1.5.0

6. Добавить в переменную окружения PATH значение %JAVA_HOME%\bin

7. Загрузить и установить Apache Ant с http://ant.apache.org/

8. Распаковать скачанный архив, например, в папку C:\ant

9. Установить переменную окружения ANT_HOME=C:\ant

10. Добавить в переменную окружения PATH значение %ANT_HOME%\bin

11. Загрузить и установить Jetspeed2 c сервера http://portals.apache.org/jetspeed-2/

12. Распаковать загруженный архив, например, в папку C:\jetspeed2

13. Прописать в файле build.properties примеров

jetspeed.deploy.dir=C:/jetspeed2/jakarta-tomcat-

5.5.9 /webapps/jetspeed/WEB-INF/deploy

14. Перезагрузить Windows

15. Выполнить

C:/jetspeed2/jetspeed-database/start-database.bat

16. Выполнить

C:/jetspeed2/jakarta-tomcat-5.5.9/bin /startup.bat

17. Зайти в корневой каталог приложения и выполнить команду “ant deploy”

18. Ввести в браузер http://localhost:8080/jetspeed

19. Ввести пароль администратора (по умолчанию логин установлен
в “admin”, как и пароль)

20. Настроить отображаемые портлеты.

Простейший портлет

Для демонстрации возможностей Portlet API ниже рассмотрен пример, отображающий данные, введенные пользователем. На этой основе можно разрабатывать собственные portlet-приложения. Все необходимые для написания примеров классы находятся в пакете javax.portlet.

Вначале создается класс SamplePorltet. Этот класс, собственно, и является основным классом портлета. Все, что здесь происходит – это инициализация портлета в методе init(PortletConfig config), за каждое из представлений портлета отвечают методы doEdit(), doView(), doHelp(). В методе processAction() производится обработка событий портлета (в данном случае этот метод будет вызван при подтверждении пользователем желания отредактировать настройки портлета).

/*пример # 1: простой портлет : SamplePorltet.java*/

package com.learning.portlet;

import java.io.IOException;

import javax.portlet.ActionRequest;

import javax.portlet.ActionResponse;

import javax.portlet.GenericPortlet;

import javax.portlet.PortletConfig;

import javax.portlet.PortletContext;

import javax.portlet.PortletException;

import javax.portlet.PortletMode;

import javax.portlet.PortletPreferences;

import javax.portlet.PortletRequest;

import javax.portlet.PortletRequestDispatcher;

import javax.portlet.RenderRequest;

import javax.portlet.RenderResponse;

 

public class SamplePortlet extends GenericPortlet {

private static final String EDIT_PAGE_PARAM

= "Edit-Page";

private static final String HELP_PAGE_PARAM

= "Help-Page";

private static final String VIEW_PAGE_PARAM

= "View-Page";

 

public void init(PortletConfig config)

throws PortletException {

super.init(config); // инициализация

}

// метод, отвечающий за представление страницы редактирования

public void doEdit(RenderRequest request,

RenderResponse response)

throws PortletException,IOException {

PortletContext context = getPortletContext();

// получение контекста портлета

setRequestAttributes(request); // установка атрибутов

// получение диспатчера для включения ресурсов в responce

PortletRequestDispatcher rd = context.

getRequestDispatcher(getInitParameter(EDIT_PAGE_PARAM));

rd.include(request, response); /* включение

содержимого ресурса*/

}

// метод, отвечающий за представление страницы помощи

public void doHelp(RenderRequest request,

RenderResponse response)

throws PortletException, IOException {

PortletContext context = getPortletContext();

// получение контекста портлета

setRequestAttributes(request); // установка атрибута

// получение диспатчера для включения ресурсов в responce

PortletRequestDispatcher rd = context.

getRequestDispatcher(getInitParameter(HELP_PAGE_PARAM));

rd.include(request, response); // включение содержимого ресурса

}

// метод, отвечающий за представление страницы просмотра

public void doView(RenderRequest request,

RenderResponse response)

throws PortletException, IOException {

PortletContext context = getPortletContext();

// получение контекста портлета

setRequestAttributes(request); // устанавливаем атрибуты

// получение диспатчера для включения ресурсов в response

PortletRequestDispatcher rd = context.

getRequestDispatcher(getInitParameter(VIEW_PAGE_PARAM));

rd.include(request, response); // включение содержимого ресурса

}

// вызывается контейнером для обработки событий

public void processAction(ActionRequest request,

ActionResponse response)

throws PortletException, IOException {

PortletMode mode = request.getPortletMode(); /* получение

состояния*/

PortletPreferences preferences =

request.getPreferences(); // настройки

if (mode.equals(PortletMode.VIEW)) {

// сохранение настроек

preferences.setValue("firstName",

request.getParameter("firstName"));

 

preferences.setValue("lastName",

request.getParameter("lastName"));

 

preferences.setValue("address",

request.getParameter("address"));

 

preferences.setValue("telephone",

request.getParameter("telephone"));

preferences.store();

}

}

// для установки атрибутов

private void setRequestAttributes(PortletRequest

request) {

PortletPreferences preferences =

request.getPreferences();

request.setAttribute("firstName",

preferences.getValue("firstName", "undefined"));

 

request.setAttribute("lastName",

preferences.getValue("lastName", "undefined"));

 

request.setAttribute("address",

preferences.getValue("address", "undefined"));

 

request.setAttribute("telephone",

preferences.getValue("telephone", "undefined"));

 

request.setAttribute("portletName",

getPortletName());

}

}

Ниже приведен файл portlet.xml, который является дескриптором портлета и необходим для его развертывания.

<!--пример # 2: дескриптор портлета : portlet.xml- ->

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

<portlet-app

xmlns=

"http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"

version="1.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/

portlet-app_1_0.xsd

http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">

 

<portlet id="sample-application">

<!-- описание -->

<description>Portlet Application</description>

<!-- название -->

<portlet-name>SamplePortlet</portlet-name>

<!-- отображаемое имя -->

<display-name>Sample Portlet</display-name>

<!-- класс портлета -->

<portlet-class> com.learning.portlet.SamplePortlet</portlet-class>

<!-- параметры инициализации -->

<init-param>

<name>ViewPage</name>

<value>/WEB-INF/jsp/sample-view.jsp</value>

</init-param>

<init-param>

<name>HelpPage</name>

<value>/WEB-INF/jsp/sample-help.jsp</value>

</init-param>

<init-param>

<name>EditPage</name>

<value>/WEB-INF/jsp/sample-edit.jsp</value>

</init-param>

<!-- количество секунд, на которое кешируется портлет. -1 значит cache
не истекает -->

<expiration-cache>-1</expiration-cache>

<!-- поддерживаемые режимы -->

<supports>

<mime-type>text/html</mime-type>

<portlet-mode>view</portlet-mode>

<portlet-mode>help</portlet-mode>

<portlet-mode>edit</portlet-mode>

</supports>

<!-- локализация -->

<supported-locale>en</supported-locale>

<!-- текстовые ресурсы -->

<resource-bundle> com.learning.portlet.SamplePortlet</resource-bundle>

<!-- информация -->

<portlet-info>

<!-- заголовок -->

<title>Portlet Application</title>

<short-title>Portlet</short-title>

<!-- ключевые слова -->

<keywords>portlet</keywords>

</portlet-info>

</portlet>

</portlet-app>

Файл web.xml является дескриптором web-приложения, поскольку портлет-приложение является и web-приложением, то понадобится и этот файл.

/* пример # 3: дескриптор приложения: web.xml*/

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

<web-app 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"

version="2.4">

<display-name>Sample</display-name>

</web-app>

Далее приведены JSP-страницы, отвечающие за представления портлета. Единственное, что следует отметить: библиотеку тегов для работы с портлетами, которая необходима для непосредственного доступа к специфическим классам портлетов (классам, используемым портлетом): RenderRequest, RenderResponse, PortletConfig. Также эта библиотека предлагает функциональность по созданию ссылок, пригодных для работы с портлетами.

<!-- пример # 4: представление портлета : sample-edit.jsp - ->

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

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

<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet"%>

<portlet:defineObjects/>

<portlet:actionURL var="editAction" portletMode="view"/>

<c:set var="inputTextStyle" value="border: none; width: 150px; color: #000000;"/>

<c:set var="inputSubmitStyle" value="border: none; width: 75px;"/>

<c:set var="labelStyle" value="text-align: right; color: #000000; white-space: nowrap;"/>

<fmt:setBundle basename="com.learning.portlet.SamplePortlet"/>

<form action="${editAction}" method="post">

<table style="border: none;">

<tbody>

<tr><td style="${labelStyle}">

<fmt:message key="portlet.label.firstname"/>:

</td>

<td nowrap="nowrap">

<input type="text" name="firstName" value="${firstName}"

style="${inputTextStyle}"/>

</td>

</tr>

<tr><td style="${labelStyle}">

<fmt:message key="portlet.label.lastname"/>:

</td>

<td nowrap="nowrap">

<input type="text" name="lastName" value="${lastName}"

style="${inputTextStyle}"/>

</td>

</tr>

<tr><td style="${labelStyle}">

<fmt:message key="portlet.label.address"/>:

</td>

<td nowrap="nowrap">

<input type="text" name="address" value="${address}"

style="${inputTextStyle}"/>

</td>

</tr>

<tr><td style="${labelStyle}">

<fmt:message key="portlet.label.telephone"/>:

</td>

<td nowrap="nowrap">

<input type="text" name="telephone" value="${telephone}"

style="${inputTextStyle}"/>

</td>

</tr>

<tr><td colspan="2" align="right">

<button type="submit" style="${inputSubmitStyle}">

<fmt:message key="portlet.button.submit"/>

</button>

</td>

</tr>

</tbody>

</table>

</form>

<!-- пример # 5:: sample-help.jsp- ->

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

<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet"%>

<portlet:defineObjects/>

<fmt:setBundle basename="com.learning.portlet.SamplePortlet"/>

<table><tbody>

<tr>

<td colspan="2">

&nbsp;&nbsp;

<fmt:message key="portlet.name.message">

<fmt:param>${portletName}</fmt:param>

</fmt:message><br>

&nbsp;&nbsp;

<fmt:message key="portlet.storeduser.message">

<fmt:param>${firstName}</fmt:param>

<fmt:param>${lastName}</fmt:param>

</fmt:message>

</td></tr>

<tr>

<td align="center">

<portlet:renderURL var="viewUrl" portletMode="view"/>

<a href="${viewUrl}" style="text-decoration: none;">

<fmt:message key="portlet.viewpage.link"/>.

</a>

</td>

<td align="center">

<portlet:renderURL var="editUrl" portletMode="edit"/>

<a href="${editUrl}" style="text-decoration: none;">

<fmt:message key="portlet.editpage.link"/>.

</a>

</td></tr>

</tbody>

</table>

<!-- пример # 6:: sample-view.jsp- ->

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

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

<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet"%>

<portlet:defineObjects/>

<c:set var="labelStyle" value="text-align: right; color: #000000; white-space: nowrap;"/>

<c:set var="textStyle" value="text-align: left; color: #000000; white-space: nowrap;"/>

<fmt:setBundle basename="com.learning.portlet.SamplePortlet"/>

<table>

<tbody style="background-color: ">

<tr>

<td style="${labelStyle}">

<fmt:message key="portlet.label.firstname"/>:

</td>

<td style="${textStyle}">

${firstName}

</td>

</tr>

<tr>

<td style="${labelStyle}">

<fmt:message key="portlet.label.lastname"/>:

</td>

<td style="${textStyle}">

${lastName}

</td>

</tr>

<tr>

<td style="${labelStyle}">

<fmt:message key="portlet.label.address"/>:

</td>

<td style="${textStyle}">

${address}

</td>

</tr>

<tr>

<td style="${labelStyle}">

<fmt:message key="portlet.label.telephone"/>:

</td>

<td style="${textStyle}">

${telephone}

</td>

</tr>

</tbody>

</table>

# пример # 7: файл свойств для русского языка :SamplePortlet_en.txt

portlet.label.firstname = First name

portlet.label.lastname = Last name

portlet.label.address = Address

portlet.label.telephone = Telephone number

portlet.button.submit = Store

portlet.name.message = This is the simple help page of the portlet <span style="font-weight: bolder">{0}</span>.

portlet.storeduser.message = Stored user is <span style="font-weight: bolder"> {0} {1}</span>.

portlet.viewpage.link = View page

portlet.editpage.link = Edit page

# пример # 8:: файл свойств для английского языка:SamplePortlet_ru.txt

portlet.label.firstname = Имя

portlet.label.lastname = Фамилия

portlet.label.address = Адрес

portlet.label.telephone = Номер телефона

portlet.button.submit = Сохранить

portlet.name.message = Страница помощи портлета <span style="font-weight: bolder">{0}</span>.

portlet.storeduser.message = Сохраненный пользователь <span style="font-weight: bolder"> {0} {1}</span>.

portlet.viewpage.link = Смотреть

portlet.editpage.link = Редактировать

/* пример # 9: файл развертывания : build.xml*/

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

<project name="SamplePortlet" default="war" basedir=".">

<property file="build.properties"/>

<property name="src.dir" value="src"/>

<property name="jsp.dir" value="jsp"/>

<property name="java.dir" value="java"/>

<property name="message.dir" value="message"/>

<property name="config.dir" value="config"/>

<property name="lib.dir" value="lib"/>

<property name="src.lib.dir" value="${src.dir}/${lib.dir}"/>

<property name="src.java.dir" value="${src.dir}/${java.dir}"/>

<property name="src.jsp.dir" value="${src.dir}/${jsp.dir}"/>

<property name="src.message.dir" value="${src.dir}/${message.dir}"/>

<property name="src.config.dir" value="${src.dir}/${config.dir}"/>

<property name="webapp.dir" value="WEB-INF"/>

<property name="result.dir" value="result"/>

<property name="classes.dir" value="classes"/>

<property name="project.name" value="SamplePortlet"/>

<property name="localization.encoding" value="Cp1251"/>

<property name="localization.src.dir" value="${src.message.dir}/com/learning/portlet"/>

<property name="localization.result.dir" value="${result.dir}/${classes.dir}/com/learning/portlet"/>

<property name="localization.ext" value=".properties"/>

<target name="compile" description="Compiles all source files of the portlet.">

<mkdir dir="${result.dir}/${classes.dir}"/>

<javac srcdir="${src.java.dir}" destdir= "${result.dir} /${classes.dir}" optimize="yes" debug="no">

<classpath>

<fileset dir="${src.lib.dir}">

<include name="**/*.jar"/>

</fileset>

</classpath>

</javac>

<copy todir="${result.dir}/${classes.dir}">

<fileset dir="${src.message.dir}" excludes="**/*.txt"/>

</copy>

<native2ascii src="${localization.src.dir}" dest=

"${localization.result.dir}" includes="**/*.txt"

encoding="${localization.encoding}" ext="${localization.ext}"/>

</target>

<target name="war" depends="compile" description= "Creates .war file of the portlet.">

<war destfile="${result.dir}/${project.name}.war"

webxml="${src.config.dir}/web.xml" compress="on">

<lib dir="${src.lib.dir}">

<exclude name="**/portlet-api-1.0.jar"/>

</lib>

<classes dir="${result.dir}/${classes.dir}"/>

<zipfileset dir="${src.config.dir}" prefix="${webapp.dir}">

<include name="**/*.*"/>

<exclude name="**/web.xml"/>

</zipfileset>

<zipfileset dir="${src.jsp.dir}" prefix=

"${webapp.dir}/${jsp.dir}"/>

</war>

</target>

<target name="deploy" depends="war" description ="Deploys .war file of the portlet.">

<copy todir="${jetspeed.deploy.dir}">

<fileset file="${result.dir}/${project.name}.war"/>

</copy>

</target>

<target name="clean" description=

"Deletes all result files of the portlet.">

<delete dir="${result.dir}"/>

</target>

</project>

# пример # 10: файл свойств для ant : build.properties

jetspeed.deploy.dir = E:/web/jetspeed-2.0-M3-Tomcat-5.5.9 /jakarta-tomcat-5.5.9/webapps/jetspeed/WEB-INF/deploy