Программирование

индекс
177,57

Познаём Java. Четвёртая чашка: сервлеты и мидлеты

Надеюсь, глянув на J2SE вы поняли как всё серьёзно, и как просто захватить весь компьютерный мир, изучив лишь один язык. Давайте теперь рассмотрим особенности двух других реализаций этого языка: J2EE и J2ME.

Преамбула, которую лучше можно не читать


Сейчас я рассмотрю особенности разработки для серверов и для мобильных телефонов. Здесь не будет примеров — их вы вполне сможете добыть в указанных местах. К сожалению, данный пост сильно запоздал после предыдущих. Это объясняется пересдачей экзамена по матану, днём рожденья и небольшим авральчиком на работе, связанным с правкой багов в новом сервисе для wap.megafonpro.ru. В итоге всё закончилось хорошо и у меня появилось свободное время. Этот пост будет, вероятно, последним, в котором рассматриваются теоретические особенности разработки. Дальше будет 2-3 поста практики: коллекции, потоки, enum'ы, аннотации и прочие радости, а потом уж посмотрим :)
P.S. Если встретили незнакомое название — гуглите по нему или смотрите в забугорной википедии. Полные описания найти не проблема.

Что общего у серверов и мобилок?


Приложения для J2EE и J2ME имеют нечто схожее (хотя это скорее наблюдение, чем свод требований):
— часто сильно зависят от сторонних библиотек;
— обычно распространяются в архивах (war, jar);
— в их структуре выделяют конфигурационную часть и, собственно, java-классы.

J2EE


Java Enterprise — звучит сильно, а? Но мы не можем сказать, что J2EE это очень мощный инструмент и всё такое прочее. Почему? Потому, что J2EE — это целая туча инструментов, спецификаций, API, и прочих радостей современной жизни.
Давайте посмотрим на основные разделы J2EE и программные продукты, которые их реализуют (внимания, слова Java и API в названиях опущены):
  • Servlet — самый простой EE API. Реализует элементарную логику веб-приложения. Его основа — два понятия: Filter и Servlet;
  • JSP — Java Server Pages. Это спецификация, описывающая язык страниц. В приложении они могут играть роль View, обычные сервлет-контейнеры умеют обрабатывать jsp-хи. Для них обычно запущен отдельный сервлет, передающий в страницу request и response — см. ниже.
  • Persistence — API, обеспечивающий хранение данных. Сейчас самая популярная реализация — Hibernate, частично использующая свой собственный API.
  • API для обмена сообщениями: JMS (некий почтоподобный протокол), RMI (набор классов для передачи данных/команд по сети) и другие
  • Enterprise Java Beans — о, вы о скорее всего слышали. По сути это спецификация о том, как надо строить классы чтобы их было просто обслуживать автоматизированным инструментам — пересыльщикам сообщения, службам хранения, классам, контроллирующим многопоточность etc.
  • Transaction — API, отвечающий за организацию транзакций. Признаюсь, не использовал;
  • Portlet — API, упомянутое на хабре в отдельной статье. Основывается на разделении веб-страницы на участки и представления каждого в виде отдельного сервиса;

Итак, думаю вы получили представление о наборе стандартных средств. Кроме них, стоит упоминуть добрую сотню веб-морд (JSF, Tapestry5, Struts и прочее), которые с разными извращениями предлагают вам реализовать веб-интерфейс, предлагая всяческие вкусности и автоматизацию в обмен на вашу душу требования притирки к архитектуре.

Структура простого J2EE-приложения выглядит так:
Контейнер сервлетов - Фильтр - Фильтр - ... - Фильтр - Сервлет
Контейнер — некое приложение, например Apache Tomcat или Jetty. Оно служит для реализации веб-доступа к вашему приложению и отвечает за приём и распределение согласно конфигурации запросов, хранение сессий и за доступ к статичному контенту. Фильтры и сервлеты описываете вы, реализуя в них нужную вам логику. Помните, они должны уметь себя проинициализировать и похоронить. Кроме того, каждый фильтр при получении запроса должен либо пустить его дальше по цепочке фильтров (таким образом запрос «падает» до сервлета), обработать его самостоятельно или же отправить на другой сервлет, по другому адресу, для обработки. Сам же сервлет так же может перенаправить запрос, или же ответить на него.
Основные понятия в работе с сервлетами — запрос и ответ, request и response. По факту, они попадают к вам извне, ваша цель — написать тело ответа.
Теоретически, этого достаточно. В клинических случаях некоторые могут обойтись одними JSP и не использовать Сервлеты/Фильтры — подключаться к БД, доставать инфу и обрабатывать ошибки прямо в JSP. Но это — не правильно.

Да и просто реализовать Сервлет — не самая лучшая идея. Вам придётся самостоятельно доставать GET/POST-параметры из тела запроса и правильно сформировать заголовки ответа. Чтобы не заниматься вознёй есть специальный HttpServlet. Он сделает всё это за вас — вам остаётся только добавить заголовков и сформировать тело ответа и переопределить методы doGet/doPost, которые по умолчанию отдают сообщение об ошибке. Собственно, на формировании тела запроса вы и должны сконцентрироваться.

Таким образом, ваши задачи:
  • привязывание сервлетов и фильтров к URL'ам (см. ссылку ниже);
  • обработка запросов в сервлетах;
  • реализация рутины (типа подсчёта кликов) в фильтрах;
  • контроль зависимостей: при работе с веб-приложениями создаётся далеко не один class-loader, не забывайте таскать библиотеки;
  • самостоятельная реализация хранения данных или делегация его какому-то готовому back-end'у типа того же Hibernate.

Что ж, надеюсь в этом месте вы уже поняли основной принцип работы J2EE-приложений. Однако, набор сервлетов и фильтров нужно ещё и как-то подставить сервлет-контейнеру.

Конфигурируем


Для распространения веб-приложений также служат зип-архивы, но на этот раз с расширением .war (web archive).
Структура у них такая:
/
  WEB-INF/
    web.xml - файл настройки приложения (<a href="http://www.javaworld.com/jw-10-1999/servletapi/web.xml">пример</a>)
    classes/ - сюда кладём скомпилированные классы
    lib/ - jar'ы c нужными библиотеками
  http-контент (т.е. все html, css, js, jsp...)

Готовый war вы подкидываете в магическую папку (обычно webapps) вашего контейнера и перезапускаете его. Контейнер его распаковывает и вешает его содержимое на IP.в.настройках.контейнера: порт/имя_war'а/.
Весь контент из корня архива станет виден по соответствующему адресу.

Если заинтересовало — качайте Tomcat/Jetty — в их поставке есть набор примеров, на которых вы сможете потренироваться.
И ещё есть хороший туториал с простыми примерами. Рекомендуется хотя бы «чисто поглядеть».

J2ME


Казалось бы, мир J2ME не должен быть так же велик, как J2EE, правда? Вроде бы это не целая гора спецификаций да и цели другие… Однако, это не так. Здесь всё то же самое, но повязано на другом принципе: вы не можете выбрать набор библиотек, он определён телефоном. Здесь всё несколько интереснее.
Кроме обрезанного ядра Java (кроме всего прочего нету Java Collections Framework и в некоторых реализациях нет нецелых чисел), вы получаете набор реализованных API, так называемых JSR. Каждый имеет свой номер. По сути это небольшая библиотека, которая даёт телефону некоторый функционал. Например 82 отвечает за доступ к блютус из Java, 205 — даёт вам MMS и так далее. На самом деле большинство из них не относится к J2ME, например мы можем найти там даже спецификацию сервлетов, однако именно с J2ME выяснение набора поддерживаемых JSR становится необходимым.
Про все JSR-ки можно почитать на жутко официальном сайте.

Каждая J2ME-платформа состоит из двух основных компонент: профиля и конфигурации.
Конфигурации описывают API, реализующий внутрепрограммные операции, а профили — взаимодействие.
Конфигурации на телефонах используются две: CDC, CLDC. Они реализуют работу с потоками ввода-вывода, математическими функциями, исключениями и т.д. CLDC — более ограничена, в первой версии отсутствуют числа с плавающей точкой, слабые ссылки. В версии 1.1 (самой распространённой) эти возможности есть, но отсутствует сериализация и часть механизма Reflection.
Из профилей, для разработки MIDlet'ов используются MIDP — Mobile Information Device Profile. В него изначально входят классы для отображения мидлетов, GUI, а также систему хранения пользовательской информации RMS. В новых версиях (сейчас распространена 2.0 и в разработке находится версия 3.0) включена поддержка специфических для игр возможностей, а также поддержка мультимедиа. Кроме того, на многих телефонах реализована работа с файлами в хранилище телефона, а также API для сетевых взаимодействий — SMS, MMS, Bluetooth.

Структура программы J2ME напоминает J2SE: вы наследуете Главный Класс от MIDlet и пользуетесь магией вида
Display.getDisplay(экземпляр_мидлета).setCurrent(...)
Таким образом вы подсовываете телефону некоторые экраны (Displayable, а обычно — GameScreen, у него удобнее всего ловить нажатия клавиш), за перерисовку которых отвечаете самоятоятельно. Вы можете рисовать картинки, текст, прямоугольники и ещё несколько геометрических фигур. Кстати, хорошая новость — J2ME абсолютно адекватно рисует полупрозрачные PNG.

Отдельная песня — отлов нажатий на кнопки. Реализация примитивная — на вход вы получаете число, соответствующее коду некой кнопки. В принципе, опытным путём (или из документации) они подбираются достаточно быстро, но здесь бывает подлянка: на некоторых телефонах коды кнопок могут отличаться. Этим грешат моторолы и LG.

К сожалению, боюсь я не смогу раскрыть всех прелестей программирования для мобилок. На самом деле это совершенно отдельный жанр. Работая с телефоном вы всегда должны заботиться о том, чтобы вашей программе было негде повиснуть и чтобы она не жрала память, которой может быть всего мегабайт-два. Кроме того, вы должны адекватно обрабатывать случаи, когда телефон пользователя имеет специфическое разрешение или не поддерживает нужный вам JSR. Да, ещё: для старых телефонов размер jar'а с приложением не должен превышать 300кб.

Конфигурация


Конфигурировать своё приложение вы должны в файле MANIFEST.MF в папке META-INF jar'а. Кроме того, полезно указать те же сведения о приложении в .jad файле — на некоторых телефонах это немного ускоряет загрузку. Формат есть в википедии,

Отладка


Для отладки таких приложений используется Sun Wireless Toolkit. Если некий производитель телефонов хочет выпустить эмулятор своего нового телефона, он берёт WTK, вешает на него свой скин и реализованные JSR-ки. Эмулятор готов.

К счастью, подцепить IDE к отладчику проблем не составляет, однако отлаженное в «тепличных условиях» приложение не всегда будет работать идеально на всех телефонах, поэтому на реальных моделях тоже стоит потестировать.
Пример отладки (извиняюсь за хреновое качество), но это был первый найденный скриншот из тех, что я не удалил.
А примерно вот так выглядит отладка на телефонах. На столе их 5 штук, не считая собственного :)

Что вы должны уметь для работы с J2ME:
  • натренироваться рисовать интерфейс, постоянно рассчитывая всякие координатные смещения, выделенные объекты и прочее;
  • прикидывать, когда какие объекты/картинки нужно выгрузить из памяти, чтобы её не забить;
  • обходиться минимумом средств для реализации логики приложения;
  • доставать ресурсы, например так: Image.createImage("/test.jpg").


P.S. Если надумаете эксперементировать — гуглите по java tutorial j2me/j2ee — найдёте кучу примеров. В качестве IDE рекомендую триал IntelliJ IDEA, но подойдут и Eclipse/NetBeans.

Удачи вам, уважаемые читатели. Задавайте вопросы.
+21
7 февраля 2009, 00:21
53

комментарии (25)

0
Q2W #
> Да, ещё: для старых телефонов размер jar'а с приложением не должен превышать 300кб.
Для старых нокий S40 не больше 64Кб, для новых — не больше 128Кб.
0
Devgru #
У нас на Нокии-Навигаторе 300кб нормально кушались, вроде как.
0
Q2W #
Мы когда собрались продавать свою первую ява-игру, нам контент-провайдеры с агрегаторами задали самый первый вопрос: ваша игра сороковую серию поддерживает?
Мы удивились вопросу, мол, с чего бы не поддерживать?
Оказалось, что вот такое ограничение, и что с ним крайне сложно бороться.
И как на зло основные продажи ява-игр были как раз на 40-ю серию.

Это была, наверное, самая жёсткая проблема, с которой мы столкнулись в производстве ява-игр.

P.S.: актуально на 2005 год, сейчас, возможно, за таким убожеством не большинство.
0
proxor #
На моем старом 2626 было 256Кб. Вообще ограничения есть только на младших моделях. Допустим на 6500 ограничений нет вообще.
+1
boOn #
В конце первого абзаца, видимо, должно быть: J2EE и J2ME
0
Devgru #
Брр. Спасибо.
+1
darkstyler #
Во втором предложении четвертого абзаца:

"[...] это очень мощный мощный инструмент [...]"

хватает и одного слова «мощный» :)
+1
AnatolyB #
Есть замечание относительно мидлетов:

Статья написана таким образом, как будто Java ME существует только для создания мидлетов, а это не так.

По-моему, нужно или расписать, из чего состоит Java ME, или к какой ее части относятся мидлеты.

Пояснить, что такое:

1. Connected Limited Device Configuration
2. Mobile Information Device Profile
3. Information Module Profile
4. Connected Device Configuration
5. Foundation Profile
6. Personal Basis Profile
7. Personal Profile
0
Devgru #
Ок, чуть попозже допишу.
+1
iZENfire #
К теме J2ME
Первый экзерcис: Первый мидлет
Второй экзерcис: Мидлет с настройками
(руки не доходят реализовать в примере долговременное хранение настроек в RMS)
0
Devgru #
Хорошие примеры, добавлю в топик.
а десктоп у тебя зачётный
НЛО прилетело и опубликовало эту надпись здесь
0
iZENfire #
Так же, как в J2SE 1.4.
0
trix #
Vector
0
Devgru #
Если вам просто нужно использовать — используйте Vector.
А внутри него происходит вызов нативного метода unchecked_obj_arraycopy класса com.sun.cldchi.jvm.JVM.
+2
3biga #
Просмотрел по диагонали.
> Enterprise Java Beans — о, вы о скорее всего слышали. По сути это спецификация о том, как надо строить классы чтобы их было просто обслуживать автоматизированным инструментам — пересыльщикам сообщения, службам хранения, классам, контроллирующим многопоточность etc.

Вы не знаете, что такое EJB.

> Контейнер — некое приложение, например Apache Tomcat или Jetty.
Контейнер — это не приложение, а Tomcat — не контейнер. Если говорить о томкате, то он использует контейнер Catalina.

Люди, читайте книги и не учитесь из сомнительных источников.
0
man4j #
Абсолютно непрофессиональное описание Java EE.
1. Не J2EE а Java EE
2. Спецификации приведены от балды, а JSF засунута в «сотню веб морд»
3. Причем тут Java EE и портлеты?
4. RMI — это часть Java SE
5. JSP — постепенно вымирает, основной упор в Java EE 6 сделан на JSF 2.0
6. «контроль зависимостей: при работе с веб-приложениями создаётся далеко не один class-loader, не забывайте таскать библиотеки» — куда таскать? mvn clean package.
7. Ничего не сказано про полноценные application серверы вроде glassfish, только про те что попадают под спецификацию сервлет-контейнеров.

А так статья неплохая )
+1
Devgru #
1. Думаю вы знаете, что изначально называлось именно J2EE, и оба названия до сих пор активно используются.
2. JSF — UI-фреймворк. Даже у Sun он описан в таком контексте.
3, 4. Не буду спорить, но, признаться, не понимаю, что отделяет их от понятия Java EE, кроме упоминаний в формальных списках. Странно, но спецификация Portlet'ов в забугорной wiki описана как часть Java EE.
5. Не спорю, но они остаются наиболее простым способом добиться чего-то от web-приложения.
6. Не все используют maven/ant. Статья не для тех, кто готов убить месяцы на обучение, а для тех, кто хочет просто прикаснуться к серьёзным вещам. Разумеется, матёрые разработчики позаботятся об автоматизации деплоймента.
7. Думаю, я уберу стоит упомянуть их, убрав подобие описание EJB.

Я думал Вы скажете «этому не место на главной».
+1
johndow #
>JSP — Java Server Pages. Это спецификация, описывающая язык страниц. В приложении они могут играть роль View, обычные сервлет-контейнеры умеют обрабатывать jsp-хи. Для них обычно запущен отдельный сервлет, передающий в страницу request и response — см. ниже.

Хоть бы почитали информацию о том о чём пишете.
Каждая JSP компилируется в сервлет.
java.sun.com/products/jsp/faq.html#2
How does the JavaServer Pages technology work?
...JSP pages are compiled into servlets…

Про EJB — поржал.
RMI — часть SE.
0
Devgru #
«Каждая JSP компилируется в сервлет. „
Да, но компиляцией/отдачей этого сервлета занимается другой сервлет. В Tomcat и Jetty использутся движок Jasper.
0
garbuz #
Devgru, отличная статья, хоть местами и с небольшими неточностями! Ждем продолжения :)
0
takeit #
День добрый!
Прочитал несколько раз Ваши посты в этот блог на тему Java. Отличный труд! Так же поискал в гугле и яндексе информацию, почитал.
Интересно было бы почитать про создание web-приложения на Java. Так сказать, пошаговый мануал.
Я могу написать простейший калькулятор на Java и запустить в командной строке, но очень интересует написание web-сайтов.
Буду благодарен за любую информацию!
0
Devgru #
foror.ru/ можете посмотреть, там есть tapestry5-пример, да и в интернете много мануалов по Spring, JSF и прочему.
0
takeit #
Я, наверное, один из тех неудачников, которым нужно показать на примере что и как делать.
В голове ужасная путаница. J2EE, JSP, JSF, jdk, jde etc.
0
Devgru #
JRE — набор библиотек, которые используются java-приложением;
JDK — то же самое, но с несколькими пряниками для разработчиком (исходники, документация, может быть ещё что-то;
J2EE — набор абстрактных спецификаций о том, как строить веб-приложения;
JSP — скрипты на стороне сервера, запускающиеся в JRE-окружении;
JSF — не знаю, никогда не использовал, но если верно понимаю — веб-фреймворк.

Советую посмотреть простенький пошаговый tutorial по JSP, например www.jsptut.com/ или погуглите, может русский какой найти удастся. Самое трудное там — установка Apache Tomcat и великий вопрос программиста — «куда писать код?». Надеюсь запуск простых примеров придаст вам уверенности :)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.