Журнал LinuxFormat - перейти на главную

LXF98:Java EE

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(http://hedewayn.strefa.pl/sitemap.htm)
(Отмена правки № 5894 участника OlosiTdelc (обсуждение))
Строка 1: Строка 1:
[http://hedewayn.strefa.pl/sitemap.htm url] [http://lakinkea.strefa.pl/comment-1042.htm panasonic canada] [http://brqashenv.ifrance.com/news-sun-facts-2008-12-05.html sun facts] [http://wejolly.strefa.pl/oklahoma-shareholder-20081127.html oklahoma shareholder] [http://virosaur.strefa.pl/topic461.htm slayer music]
+
{{Цикл/Java EE}}
{{Цикл/Java EE}}
+
==<font color=darkred>Struts</font>, великий и ужасный==
==<font color=darkred>Struts</font>, великий и ужасный==
+
  
''<font color=darkred>'''ЧАСТЬ 10'''</font> Компьютеры были придуманы, чтобы избавить человечество от рутины – так зачем делать вручную то, что можно сгенерировать автоматически? '''Александр Бабаев''' покажет, как Struts позволяет избежать монотонного кодирования приложений J2EE.''
+
''<font color=darkred>'''ЧАСТЬ 10'''</font> Компьютеры были придуманы, чтобы избавить человечество от рутины – так зачем делать вручную то, что можно сгенерировать автоматически? '''Александр Бабаев''' покажет, как Struts позволяет избежать монотонного кодирования приложений J2EE.''
  
Вручную делать простые вещи хорошо: быстро, просто, понятно. Но что делать, если нужно так же быстро и просто создать нечто большое? Сайт-портал, например? Не тот портал, который Яндекс, а корпоративный – где интегрирована система хранения документов, информационная система, наша адресная книга?
+
Вручную делать простые вещи хорошо: быстро, просто, понятно. Но что делать, если нужно так же быстро и просто создать нечто большое? Сайт-портал, например? Не тот портал, который Яндекс, а корпоративный – где интегрирована система хранения документов, информационная система, наша адресная книга?
  
В PHP в этом случае приходит на помощь ''CMS''. Сладкие слова, которые обещают «в два клика» сделать вам все что угодно. Маркетинг, конечно, страшная сила, но почему так много ''CMS'' на PHP, и нет на ''Java''?
+
В PHP в этом случае приходит на помощь ''CMS''. Сладкие слова, которые обещают «в два клика» сделать вам все что угодно. Маркетинг, конечно, страшная сила, но почему так много ''CMS'' на PHP, и нет на ''Java''?
  
Возможно, просто потому что не нужно. Место ''CMS'' в ''Java'' занимают разнообразные инструментарии разработчика, которые помогают обходить сложные и рутинные работы. В результате можно небольшими силами сделать систему, по сложности намного превосходящую то, что можно сделать «вручную».
+
Возможно, просто потому что не нужно. Место ''CMS'' в ''Java'' занимают разнообразные инструментарии разработчика, которые помогают обходить сложные и рутинные работы. В результате можно небольшими силами сделать систему, по сложности намного превосходящую то, что можно сделать «вручную».
  
===Что включается в Struts?===
+
===Что включается в Struts?===
  
''Struts'' не изобретает велосипедов. В его основе лежит шаблон «MODEl-View-Controller», который мы рассматривали в [[LXF92:Java EE|LXF92]], но с его помощью проще создать грамотное приложение, так как четко определены задачи по его созданию; проще разобраться, что необходимо написать для получения результата.
+
''Struts'' не изобретает велосипедов. В его основе лежит шаблон «MODEl-View-Controller», который мы рассматривали в [[LXF92:Java EE|LXF92]], но с его помощью проще создать грамотное приложение, так как четко определены задачи по его созданию; проще разобраться, что необходимо написать для получения результата.
  
Итак, ''Struts'' (будем рассматривать более простую, первую версию) содержит:
+
Итак, ''Struts'' (будем рассматривать более простую, первую версию) содержит:
  
*''API'' для создания обработчика запросов (менеджер, распределяющий запросы по действиям) и для создания самих действий (<font color=darkred>Actions</font>).
+
*''API'' для создания обработчика запросов (менеджер, распределяющий запросы по действиям) и для создания самих действий (<font color=darkred>Actions</font>).
*''API'' для создания обработчиков форм.
+
*''API'' для создания обработчиков форм.
*''API'' для работы с проверкой корректности заполнения (валидации) форм.
+
*''API'' для работы с проверкой корректности заполнения (валидации) форм.
*''Tiles''. Расширение для создания модульных страниц (что-то «вроде SSI»).
+
*''Tiles''. Расширение для создания модульных страниц (что-то «вроде SSI»).
*''JSP-taglib'', библиотека ''JPS''-тэгов для упрощения написания JSP-страниц.
+
*''JSP-taglib'', библиотека ''JPS''-тэгов для упрощения написания JSP-страниц.
*''XML''-конфигурационные файлы, для простой и быстрой настройки всего вышеперечисленного и связи его друг с другом.
+
*''XML''-конфигурационные файлы, для простой и быстрой настройки всего вышеперечисленного и связи его друг с другом.
  
Все это в предыдущих статьях мы делали вручную. Теперь настало время проделать то же самое более «технологично».
+
Все это в предыдущих статьях мы делали вручную. Теперь настало время проделать то же самое более «технологично».
  
===Как этим пользоваться?===
+
===Как этим пользоваться?===
  
Во-первых, библиотеку нужно скачать. Это можно сделать со странички http://struts.apache.org/download.cgi#struts138. После чего следует распаковать полученный файл и вытащить оттуда все JAR-архивы.
+
Во-первых, библиотеку нужно скачать. Это можно сделать со странички http://struts.apache.org/download.cgi#struts138. После чего следует распаковать полученный файл и вытащить оттуда все JAR-архивы.
  
В качестве примера, создадим уже знакомую телефонную книгу. Сперва каталог; в нем, как всегда, организуем подкаталоги для исходных текстов, скомпилированного кода, библиотек и JSP-файлов. Получится что-то такое:
+
В качестве примера, создадим уже знакомую телефонную книгу. Сперва каталог; в нем, как всегда, организуем подкаталоги для исходных текстов, скомпилированного кода, библиотек и JSP-файлов. Получится что-то такое:
  
 
*'''libs'''
 
*'''libs'''
Строка 63: Строка 62:
 
**'''WEB-INF'''
 
**'''WEB-INF'''
  
Затем в каталог библиотек нужно положить JAR-файлы ''Struts''. Готово? Тогда можно приступать к кодированию.
+
Затем в каталог библиотек нужно положить JAR-файлы ''Struts''. Готово? Тогда можно приступать к кодированию.
  
Когда запрос приходит в сервлет, он первым делом попадает в ''Struts'', который перенаправляет его в менеджер запросов (<font color=darkred>ActionServet</font>) и далее в нужное действие (<font color=darkred>Action</font>). Это происходит примерно так:
+
Когда запрос приходит в сервлет, он первым делом попадает в ''Struts'', который перенаправляет его в менеджер запросов (<font color=darkred>ActionServet</font>) и далее в нужное действие (<font color=darkred>Action</font>). Это происходит примерно так:
  
Как видно, схема здорово напоминает примененную нами при создании адресной книги. Зачем тогда ''Struts''? А затем, чтобы не писать много-много однотипного кода, который повторяется из проекта в проект.
+
Как видно, схема здорово напоминает примененную нами при создании адресной книги. Зачем тогда ''Struts''? А затем, чтобы не писать много-много однотипного кода, который повторяется из проекта в проект.
  
===Конфигурационные файлы===
+
===Конфигурационные файлы===
  
Вначале научимся запускать ''Struts''. Для этого нужно перенаправить все запросы сервлету-обработчику и написать файл конфигурации. Вот
+
Вначале научимся запускать ''Struts''. Для этого нужно перенаправить все запросы сервлету-обработчику и написать файл конфигурации. Вот
простой дескриптор для простого ''Struts''-приложения:
+
простой дескриптор для простого ''Struts''-приложения:
 
<source lang="xml">
 
<source lang="xml">
 
   <?xml version="1.0" encoding="UTF-8"?>
 
   <?xml version="1.0" encoding="UTF-8"?>
Строка 90: Строка 89:
 
   </web-app>
 
   </web-app>
 
</source>
 
</source>
Видно, что все запросы <font color=darkred>*.do</font> передаются сервлету <font color=darkred>action</font>, обрабатываемому классом <font color=darkred>ActionServlet</font>. Это стандартный класс Struts, который перенаправляет запросы в действия. Ему передается конфигурационный файл '''struts-config.xml'''. Вот он:
+
Видно, что все запросы <font color=darkred>*.do</font> передаются сервлету <font color=darkred>action</font>, обрабатываемому классом <font color=darkred>ActionServlet</font>. Это стандартный класс Struts, который перенаправляет запросы в действия. Ему передается конфигурационный файл '''struts-config.xml'''. Вот он:
 
<source lang="xml">
 
<source lang="xml">
 
   <?xml version="1.0" encoding="UTF-8" ?>
 
   <?xml version="1.0" encoding="UTF-8" ?>
Строка 116: Строка 115:
 
  </struts-config>
 
  </struts-config>
 
</source>
 
</source>
В данном файле описана форма добавления контакта (<font color=darkred>form-bean</font>), с использованием стандартного класса формы с поддержкой автоматической проверки полей (<font color=darkred>DynaValidatorForm</font>).
+
В данном файле описана форма добавления контакта (<font color=darkred>form-bean</font>), с использованием стандартного класса формы с поддержкой автоматической проверки полей (<font color=darkred>DynaValidatorForm</font>).
  
После этого описано, какие запросы в какие классы перенаправляются.
+
После этого описано, какие запросы в какие классы перенаправляются.
 
<source lang="xml">
 
<source lang="xml">
 
  <action path="/list" type="ru.linuxformat.actions.ShowAll">
 
  <action path="/list" type="ru.linuxformat.actions.ShowAll">
Строка 124: Строка 123:
 
  </action>
 
  </action>
 
</source>
 
</source>
В этом примере запрос <font color=darkred>/list.do</font> пойдет в класс <font color=darkred>ShowAll.Forward</font> используется внутри действия, чтобы упростить перенаправление вывода. Дальше будет понятно, как.
+
В этом примере запрос <font color=darkred>/list.do</font> пойдет в класс <font color=darkred>ShowAll.Forward</font> используется внутри действия, чтобы упростить перенаправление вывода. Дальше будет понятно, как.
  
После описания действий все становится совсем просто.Описывается файл, откуда будут браться локализованные строки, и
+
После описания действий все становится совсем просто.Описывается файл, откуда будут браться локализованные строки, и
подключается модуль, который обеспечивает простую и мощную валидацию (проверку) форм.
+
подключается модуль, который обеспечивает простую и мощную валидацию (проверку) форм.
  
===Действия===
+
===Действия===
  
Перейдем к классам. Все они должны быть унаследованы от класса <font color=darkred>org.apache.struts.action.Action</font>. При этом в простейшем случае нужно переопределить только один метод, <font color=darkred>execute(…)</font>. Например, вот действие, которое показывает список контактов:
+
Перейдем к классам. Все они должны быть унаследованы от класса <font color=darkred>org.apache.struts.action.Action</font>. При этом в простейшем случае нужно переопределить только один метод, <font color=darkred>execute()</font>. Например, вот действие, которое показывает список контактов:
 
<source lang="java">
 
<source lang="java">
 
  public class ShowAll extends Action {
 
  public class ShowAll extends Action {
Строка 145: Строка 144:
 
  }
 
  }
 
</source>
 
</source>
В этом действии в атрибут запроса кладется список всех контактов, после чего вызывается форвард <font color=darkred>"ok"</font> – именно он был описан чуть выше.
+
В этом действии в атрибут запроса кладется список всех контактов, после чего вызывается форвард <font color=darkred>"ok"</font> – именно он был описан чуть выше.
 
<source lang="xml">
 
<source lang="xml">
 
  <action path="/list" type="ru.linuxformat.actions.ShowAll">
 
  <action path="/list" type="ru.linuxformat.actions.ShowAll">
Строка 151: Строка 150:
 
  </action>
 
  </action>
 
</source>
 
</source>
Из описания видно, что форвард перенаправляет обработку запроса в '''List.jsp''. Посмотрим, что в нем написано:
+
Из описания видно, что форвард перенаправляет обработку запроса в '''List.jsp''. Посмотрим, что в нем написано:
 
<source lang="xml">
 
<source lang="xml">
 
  <%@ page pageEncoding="UTF-8" language="java" contentType="text/
 
  <%@ page pageEncoding="UTF-8" language="java" contentType="text/
Строка 160: Строка 159:
 
  <html:html>
 
  <html:html>
 
   <head>
 
   <head>
       …
+
      
 
   </head>
 
   </head>
 
   <body>
 
   <body>
       …
+
      
 
   <table border="1">
 
   <table border="1">
 
       <tr>
 
       <tr>
Строка 184: Строка 183:
 
  </html:html>
 
  </html:html>
 
</source>
 
</source>
На многоточия заменены неинтересные куски кода, а интересное – в самом начале листинга (<font color=darkred>taglib</font>). Это так называемые библиотеки тэгов. Примеры можно видеть здесь же. Скажем, <font color=darkred><bean:messagekey="AddressBook.list.name"/></font> вставляет локализованную строку, соответствующую данному ключу. А <font color=darkred><logic:iterate></font> умеет итерировать по коллекциям (списки, ассоциативные массивы и так далее). В данном случае мы итерируем по атрибуту запроса <font color=darkred>contacts</font>, который мы положили туда в действии.
+
На многоточия заменены неинтересные куски кода, а интересное – в самом начале листинга (<font color=darkred>taglib</font>). Это так называемые библиотеки тэгов. Примеры можно видеть здесь же. Скажем, <font color=darkred><bean:messagekey="AddressBook.list.name"/></font> вставляет локализованную строку, соответствующую данному ключу. А <font color=darkred><logic:iterate></font> умеет итерировать по коллекциям (списки, ассоциативные массивы и так далее). В данном случае мы итерируем по атрибуту запроса <font color=darkred>contacts</font>, который мы положили туда в действии.
  
===Формы, проверка корректности форм===
+
===Формы, проверка корректности форм===
  
Другая интересная часть – формы. Второе действие, добавление контакта, выглядит следующим образом (приведен только код метода <font color=darkred>execute</font>):
+
Другая интересная часть – формы. Второе действие, добавление контакта, выглядит следующим образом (приведен только код метода <font color=darkred>execute</font>):
 
<source lang="java">
 
<source lang="java">
 
       if (aHttpServletRequest.getParameter("name") == null) {
 
       if (aHttpServletRequest.getParameter("name") == null) {
Строка 200: Строка 199:
 
       }
 
       }
 
</source>
 
</source>
Логика очень похожа на ту, что была в предыдущих статьях. Если форма не заполнена, переходим по форварду <font color=darkred>form</font>, который показывает форму для ввода. Если она заполнена (и валидирована), то контакт добавляется в список, и мы переходим на форвард <font color=darkred>done</font>. Вот и сама форма (точнее, ее основная часть):
+
Логика очень похожа на ту, что была в предыдущих статьях. Если форма не заполнена, переходим по форварду <font color=darkred>form</font>, который показывает форму для ввода. Если она заполнена (и валидирована), то контакт добавляется в список, и мы переходим на форвард <font color=darkred>done</font>. Вот и сама форма (точнее, ее основная часть):
 
<source lang="xml">
 
<source lang="xml">
 
     <html:form action="/add" method="post" onsubmit="return
 
     <html:form action="/add" method="post" onsubmit="return
Строка 209: Строка 208:
 
               <td><html:text property="name"/></td>
 
               <td><html:text property="name"/></td>
 
           </tr>
 
           </tr>
           …
+
          
 
           <tr>
 
           <tr>
 
               <td colspan="2"><html:submit titleKey="AddressBook.add.
 
               <td colspan="2"><html:submit titleKey="AddressBook.add.
Строка 218: Строка 217:
 
     <html:javascript formName="addForm"/>
 
     <html:javascript formName="addForm"/>
 
</source>
 
</source>
Тут интересны два момента. Во-первых, используются тэги ''Struts'' (<font color=darkred>html:…</font>), упрощающие создание компонентов формы. Во-вторых, используется скрипт валидации (<font color=darkred>onsubmit="…"</font> и <font color=darkred><html:Javascript …></font>). Он обеспечивает валидацию прямо в браузере, не отсылая запрос на сервер.
+
Тут интересны два момента. Во-первых, используются тэги ''Struts'' (<font color=darkred>html:</font>), упрощающие создание компонентов формы. Во-вторых, используется скрипт валидации (<font color=darkred>onsubmit=""</font> и <font color=darkred><html:Javascript ></font>). Он обеспечивает валидацию прямо в браузере, не отсылая запрос на сервер.
  
Сами правила валидации задаются в файле '''validation.xml'''. Вот как это выглядит:
+
Сами правила валидации задаются в файле '''validation.xml'''. Вот как это выглядит:
 
<source lang="xml">
 
<source lang="xml">
 
   <form-validation>
 
   <form-validation>
Строка 240: Строка 239:
 
   </form-validation>
 
   </form-validation>
 
</source>
 
</source>
Форму я создал в '''struts-config'''. Называться она должна так же. Для поля <font color=darkred>age</font> задается три правила валидации: <font color=darkred>required</font>, <font color=darkred>integer</font>, <font color=darkred>intRange</font>. Первое говорит, что поле обязательно, второе – что значение должно быть целочисленным, третье правило сообщает, что значение должно лежать в пределах от 10 до 20. В качестве параметров задаются аргументы сообщений, которые будут выводиться при ошибочном заполнении формы (<font color=darkred>arg</font>), и параметры для правил валидации (<font color=darkred>var</font>).
+
Форму я создал в '''struts-config'''. Называться она должна так же. Для поля <font color=darkred>age</font> задается три правила валидации: <font color=darkred>required</font>, <font color=darkred>integer</font>, <font color=darkred>intRange</font>. Первое говорит, что поле обязательно, второе – что значение должно быть целочисленным, третье правило сообщает, что значение должно лежать в пределах от 10 до 20. В качестве параметров задаются аргументы сообщений, которые будут выводиться при ошибочном заполнении формы (<font color=darkred>arg</font>), и параметры для правил валидации (<font color=darkred>var</font>).
  
===Локализация===
+
===Локализация===
  
Последняя часть, пока не описанная – локализация. Сообщения хранятся в так называемых properties-файлах, причем если property-файл называется '''MessageResources''', то, например, файл русской локализации должен называться '''MessageResources_ru.properties''', а английской – '''MessageResources_en.properties'''. Если нужно уточнить – например, английский язык, Америка – то получается так: '''MessageResources_en_US.properties'''.
+
Последняя часть, пока не описанная – локализация. Сообщения хранятся в так называемых properties-файлах, причем если property-файл называется '''MessageResources''', то, например, файл русской локализации должен называться '''MessageResources_ru.properties''', а английской – '''MessageResources_en.properties'''. Если нужно уточнить – например, английский язык, Америка – то получается так: '''MessageResources_en_US.properties'''.
  
Структура файлов '''properties''' очень проста. Каждая строка (не пустая и не комментарий) состоит из двух частей, разделенных знаком равенства (<font color=darkred>=</font>). Слева – ключ, справа – значение этого ключа.
+
Структура файлов '''properties''' очень проста. Каждая строка (не пустая и не комментарий) состоит из двух частей, разделенных знаком равенства (<font color=darkred>=</font>). Слева – ключ, справа – значение этого ключа.
  
Эти файлы нужно положить в каталог '''src''', и проконтролировать, чтобы они переписались туда же, куда попадают class-файлы. Плюс, для неанглийских
+
Эти файлы нужно положить в каталог '''src''', и проконтролировать, чтобы они переписались туда же, куда попадают class-файлы. Плюс, для неанглийских
файлов, их нужно преобразовать в ASCII-формат. Это делается утилитой ''native2ascii'' из поставки JDK. Инструкции по пользованию утилитой можно найти здесь: http://Java.sun.com/Javase/6/docs/technotes/tools/windows/native2ascii.html.
+
файлов, их нужно преобразовать в ASCII-формат. Это делается утилитой ''native2ascii'' из поставки JDK. Инструкции по пользованию утилитой можно найти здесь: http://Java.sun.com/Javase/6/docs/technotes/tools/windows/native2ascii.html.
  
После этого можно использовать в JSP вставки вида <font color=darkred><bean:message key="AddressBook.add.name"/></font>, вместо которых будет вставлена локализованная строка, соответствующая данному ключу (в примере – <font color=darkred>AddressBook.add.name</font>).
+
После этого можно использовать в JSP вставки вида <font color=darkred><bean:message key="AddressBook.add.name"/></font>, вместо которых будет вставлена локализованная строка, соответствующая данному ключу (в примере – <font color=darkred>AddressBook.add.name</font>).
  
===Что дальше?===
+
===Что дальше?===
  
''Struts'' – великолепная библиотека, позволяющая упростить разработку сложных приложений. Особенно хорошо такого рода библиотеки подходят для задач, в которых много монотонной работы: больших форм, большого количества простых действий, необходимость проверки данных, вводимых в форму, локализация.
+
''Struts'' – великолепная библиотека, позволяющая упростить разработку сложных приложений. Особенно хорошо такого рода библиотеки подходят для задач, в которых много монотонной работы: больших форм, большого количества простых действий, необходимость проверки данных, вводимых в форму, локализация.
  
Также полезно, что используются стандартные средства: ''JSP'', ''Servlets'', да и сам ''Struts'' – самая распространенная библиотека для такого рода работ. В результате при приеме на работу, например, знание именно ''Struts'' позволяет набрать несколько дополнительных баллов.
+
Также полезно, что используются стандартные средства: ''JSP'', ''Servlets'', да и сам ''Struts'' – самая распространенная библиотека для такого рода работ. В результате при приеме на работу, например, знание именно ''Struts'' позволяет набрать несколько дополнительных баллов.
  
Правда, еще больше баллов дает знание ''EJB3''. Но об этом мы поговорим в следующей, заключительной статье.
+
Правда, еще больше баллов дает знание ''EJB3''. Но об этом мы поговорим в следующей, заключительной статье.

Версия 12:26, 11 декабря 2008

Содержание

Struts, великий и ужасный

ЧАСТЬ 10 Компьютеры были придуманы, чтобы избавить человечество от рутины – так зачем делать вручную то, что можно сгенерировать автоматически? Александр Бабаев покажет, как Struts позволяет избежать монотонного кодирования приложений J2EE.

Вручную делать простые вещи хорошо: быстро, просто, понятно. Но что делать, если нужно так же быстро и просто создать нечто большое? Сайт-портал, например? Не тот портал, который Яндекс, а корпоративный – где интегрирована система хранения документов, информационная система, наша адресная книга?

В PHP в этом случае приходит на помощь CMS. Сладкие слова, которые обещают «в два клика» сделать вам все что угодно. Маркетинг, конечно, страшная сила, но почему так много CMS на PHP, и нет на Java?

Возможно, просто потому что не нужно. Место CMS в Java занимают разнообразные инструментарии разработчика, которые помогают обходить сложные и рутинные работы. В результате можно небольшими силами сделать систему, по сложности намного превосходящую то, что можно сделать «вручную».

Что включается в Struts?

Struts не изобретает велосипедов. В его основе лежит шаблон «MODEl-View-Controller», который мы рассматривали в LXF92, но с его помощью проще создать грамотное приложение, так как четко определены задачи по его созданию; проще разобраться, что необходимо написать для получения результата.

Итак, Struts (будем рассматривать более простую, первую версию) содержит:

  • API для создания обработчика запросов (менеджер, распределяющий запросы по действиям) и для создания самих действий (Actions).
  • API для создания обработчиков форм.
  • API для работы с проверкой корректности заполнения (валидации) форм.
  • Tiles. Расширение для создания модульных страниц (что-то «вроде SSI»).
  • JSP-taglib, библиотека JPS-тэгов для упрощения написания JSP-страниц.
  • XML-конфигурационные файлы, для простой и быстрой настройки всего вышеперечисленного и связи его друг с другом.

Все это в предыдущих статьях мы делали вручную. Теперь настало время проделать то же самое более «технологично».

Как этим пользоваться?

Во-первых, библиотеку нужно скачать. Это можно сделать со странички http://struts.apache.org/download.cgi#struts138. После чего следует распаковать полученный файл и вытащить оттуда все JAR-архивы.

В качестве примера, создадим уже знакомую телефонную книгу. Сперва каталог; в нем, как всегда, организуем подкаталоги для исходных текстов, скомпилированного кода, библиотек и JSP-файлов. Получится что-то такое:

  • libs
    • antlr-2.7.2.jar
    • bsf-2.3.0.jar
    • commons-beanutils-1.7.0.jar
    • commonschain-1.1.jar
    • commons-digester-1.8.jar
    • commons-fileipload-1.1.1.jar
    • commons-io-1.1.jar
    • commons-logging-1.0.4.jar
    • commons-validator-1.3.1.jar
    • jstl-1.0.2.jar
    • oro-2.0.8.jar
    • standart-1.0.2.jar
    • struts-core-1.3.8.jar
    • struts-el-1.3.8.jar
    • struts-extras-1.3.8.jar
    • struts-faces-1.3.8.jar
    • struts-mailreader-dao-1.3.8.jar
    • struts-scripting-1.3.8.jar
    • struts-taglib-1.3.8.jar
    • struts-tiles-1.3.8.jar
  • out
  • src
    • MessageResources_en.properties
    • MessageResources_ru.properties
    • ru
  • web
    • index.jsp
    • pages
    • WEB-INF

Затем в каталог библиотек нужно положить JAR-файлы Struts. Готово? Тогда можно приступать к кодированию.

Когда запрос приходит в сервлет, он первым делом попадает в Struts, который перенаправляет его в менеджер запросов (ActionServet) и далее в нужное действие (Action). Это происходит примерно так:

Как видно, схема здорово напоминает примененную нами при создании адресной книги. Зачем тогда Struts? А затем, чтобы не писать много-много однотипного кода, который повторяется из проекта в проект.

Конфигурационные файлы

Вначале научимся запускать Struts. Для этого нужно перенаправить все запросы сервлету-обработчику и написать файл конфигурации. Вот простой дескриптор для простого Struts-приложения:

  <?xml version="1.0" encoding="UTF-8"?>
  <web-app>
    <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
        <init-param>
           <param-name>config</param-name>
           <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
  </web-app>

Видно, что все запросы *.do передаются сервлету action, обрабатываемому классом ActionServlet. Это стандартный класс Struts, который перенаправляет запросы в действия. Ему передается конфигурационный файл struts-config.xml. Вот он:

   <?xml version="1.0" encoding="UTF-8" ?>
  <struts-config>
    <form-beans>
        <form-bean name="addForm" type="org.apache.struts.validator.DynaValidatorForm">
           <form-property name="name" type="java.lang.String" initial="Name"/>
           <form-property name="phone" type="java.lang.String" initial="1234567"/>
          <form-property name="age" type="java.lang.Integer" initial="20"/>
          <form-property name="comment" type="java.lang.String" initial="NoComment"/>
       </form-bean>
      <action-mappings>
       <action path="/add" name="addForm" validate="true" type="ru.linuxformat.actions.Add">
          <forward name="form" path="/pages/Add.jsp"/>
          <forward name="done" path="/list.do"/>
       </action>
       <action path="/list" type="ru.linuxformat.actions.ShowAll">
          <forward name="ok" path="/pages/List.jsp"/>
       </action>
   </action-mappings>
   <message-resources parameter="MessageResources"/>
   <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
       <set-property property="pathnames" value="/org/apache/struts/validator/validator-rules.xml,/WEB-INF/validation.xml"/>
   </plug-in>
 </struts-config>

В данном файле описана форма добавления контакта (form-bean), с использованием стандартного класса формы с поддержкой автоматической проверки полей (DynaValidatorForm).

После этого описано, какие запросы в какие классы перенаправляются.

 <action path="/list" type="ru.linuxformat.actions.ShowAll">
   <forward name="ok" path="/pages/List.jsp"/>
 </action>

В этом примере запрос /list.do пойдет в класс ShowAll.Forward используется внутри действия, чтобы упростить перенаправление вывода. Дальше будет понятно, как.

После описания действий все становится совсем просто.Описывается файл, откуда будут браться локализованные строки, и подключается модуль, который обеспечивает простую и мощную валидацию (проверку) форм.

Действия

Перейдем к классам. Все они должны быть унаследованы от класса org.apache.struts.action.Action. При этом в простейшем случае нужно переопределить только один метод, execute(…). Например, вот действие, которое показывает список контактов:

 public class ShowAll extends Action {
   public ActionForward execute(ActionMapping aActionMapping,
                        ActionForm aActionForm,
                        HttpServletRequest aHttpServletRequest,
                        HttpServletResponse aHttpServletResponse)
                                            throws Exception {
      aHttpServletRequest.setAttribute("contacts",
             Contacter.getInstance().getContactsSortedByName());
      return aActionMapping.findForward("ok");
   }
 }

В этом действии в атрибут запроса кладется список всех контактов, после чего вызывается форвард "ok" – именно он был описан чуть выше.

 <action path="/list" type="ru.linuxformat.actions.ShowAll">
   <forward name="ok" path="/pages/List.jsp"/>
 </action>

Из описания видно, что форвард перенаправляет обработку запроса в 'List.jsp. Посмотрим, что в нем написано:

 <%@ page pageEncoding="UTF-8" language="java" contentType="text/
 html; utf-8" %>
 <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
 <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
 <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
 <html:html>
   <head></head>
   <body><table border="1">
      <tr>
          <td><bean:message key="AddressBook.list.name"/></td>
          <td><bean:message key="AddressBook.list.phone"/></td>
          <td><bean:message key="AddressBook.list.comment"/></td>
          <td><bean:message key="AddressBook.list.age"/></td>
      </tr>
   <logic:iterate id="contact" type="ru.linuxformat.Contact"
 name="contacts" scope="request">
      <tr>
          <td><%=contact.getName()%></td>
          <td><%=contact.getPhone()%></td>
          <td><%=contact.getComment()%></td>
          <td><%=contact.getAge()%></td>
      </tr>
   </logic:iterate>
   </table>
   </body>
 </html:html>

На многоточия заменены неинтересные куски кода, а интересное – в самом начале листинга (taglib). Это так называемые библиотеки тэгов. Примеры можно видеть здесь же. Скажем, <bean:messagekey="AddressBook.list.name"/> вставляет локализованную строку, соответствующую данному ключу. А <logic:iterate> умеет итерировать по коллекциям (списки, ассоциативные массивы и так далее). В данном случае мы итерируем по атрибуту запроса contacts, который мы положили туда в действии.

Формы, проверка корректности форм

Другая интересная часть – формы. Второе действие, добавление контакта, выглядит следующим образом (приведен только код метода execute):

       if (aHttpServletRequest.getParameter("name") == null) {
           return aActionMapping.findForward("form");
       } else {
           DynaActionForm form = (DynaActionForm) aActionForm;
           Contacter.getInstance().addContact(form.getString("name"), form.
 getString("phone"), form.getString("comment"), (Integer) form.
 get("age"));
           return aActionMapping.findForward("done");
       }

Логика очень похожа на ту, что была в предыдущих статьях. Если форма не заполнена, переходим по форварду form, который показывает форму для ввода. Если она заполнена (и валидирована), то контакт добавляется в список, и мы переходим на форвард done. Вот и сама форма (точнее, ее основная часть):

    <html:form action="/add" method="post" onsubmit="return
 validateAddForm(this);">
       <table>
           <tr>
              <td><bean:message key="AddressBook.add.name"/>:</td>
              <td><html:text property="name"/></td>
           </tr><tr>
              <td colspan="2"><html:submit titleKey="AddressBook.add.
 submit"/></td>
           </tr>
       </table>
    </html:form>
    <html:javascript formName="addForm"/>

Тут интересны два момента. Во-первых, используются тэги Struts (html:…), упрощающие создание компонентов формы. Во-вторых, используется скрипт валидации (onsubmit="…" и <html:Javascript …>). Он обеспечивает валидацию прямо в браузере, не отсылая запрос на сервер.

Сами правила валидации задаются в файле validation.xml. Вот как это выглядит:

  <form-validation>
    <formset>
       <form name="addForm">
           <field property="age" depends="required,integer,intRange">
              <arg key="AddressBook.add.age"/>
              <arg position="1" name="intRange" key="10"
 resource="false"/>
              <arg position="2" name="intRange" key="20"
 resource="false"/>
              <var><var-name>min</var-name><var-value>10</var-value></
 var>
              <var><var-name>max</var-name><var-value>20</var-value></
 var>
           </field>
       </form>
    </formset>
  </form-validation>

Форму я создал в struts-config. Называться она должна так же. Для поля age задается три правила валидации: required, integer, intRange. Первое говорит, что поле обязательно, второе – что значение должно быть целочисленным, третье правило сообщает, что значение должно лежать в пределах от 10 до 20. В качестве параметров задаются аргументы сообщений, которые будут выводиться при ошибочном заполнении формы (arg), и параметры для правил валидации (var).

Локализация

Последняя часть, пока не описанная – локализация. Сообщения хранятся в так называемых properties-файлах, причем если property-файл называется MessageResources, то, например, файл русской локализации должен называться MessageResources_ru.properties, а английской – MessageResources_en.properties. Если нужно уточнить – например, английский язык, Америка – то получается так: MessageResources_en_US.properties.

Структура файлов properties очень проста. Каждая строка (не пустая и не комментарий) состоит из двух частей, разделенных знаком равенства (=). Слева – ключ, справа – значение этого ключа.

Эти файлы нужно положить в каталог src, и проконтролировать, чтобы они переписались туда же, куда попадают class-файлы. Плюс, для неанглийских файлов, их нужно преобразовать в ASCII-формат. Это делается утилитой native2ascii из поставки JDK. Инструкции по пользованию утилитой можно найти здесь: http://Java.sun.com/Javase/6/docs/technotes/tools/windows/native2ascii.html.

После этого можно использовать в JSP вставки вида <bean:message key="AddressBook.add.name"/>, вместо которых будет вставлена локализованная строка, соответствующая данному ключу (в примере – AddressBook.add.name).

Что дальше?

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

Также полезно, что используются стандартные средства: JSP, Servlets, да и сам Struts – самая распространенная библиотека для такого рода работ. В результате при приеме на работу, например, знание именно Struts позволяет набрать несколько дополнительных баллов.

Правда, еще больше баллов дает знание EJB3. Но об этом мы поговорим в следующей, заключительной статье.

Персональные инструменты
купить
подписаться
Яндекс.Метрика