- •Обозначения и сокращения
- •введение
- •1. Установка и настройка инструментальных средств
- •1.1. Установка и подготовка к работе операционной системы
- •1.2. Установка программного обеспечения
- •1.3. Создание таблиц в базе данных
- •2. Основы Java EE 6
- •2.1. Распределенные многоуровневые приложения
- •2.2. Контейнеры Java EE
- •2.3. Сервер GlassFish v3
- •2.4. Структура приложения
- •2.5. Конфигурирование приложений
- •2.6. Задание ссылок на ресурсы
- •4. Введение в компоненты Facelets
- •4.1. Веб-страницы
- •4.2. Разработка простого приложения Facelets
- •4.3. Использование шаблонов
- •5. Унифицированный язык записи выражений
- •6.1. Добавление компонент библиотеки HTML на страницу
- •6.2. Использование компонент для таблиц баз данных
- •6.3. Использование тегов библиотеки Core
- •7. Использование конвертеров, слушателей и проверок
- •7.1. Использование стандартных преобразователей
- •7.2. Регистрация слушателей для компонентов
- •8. Внешние объекты (JavaBeans)
- •8.1. Создание класса внешних объектов
- •8.2. Описание свойств бинов
- •8.3. Написание методов внешних бинов
- •8.4. Проверка бинами
- •9.1. Файл конфигурации ресурсов приложения
- •9.2. Упорядочение ресурсов конфигурации приложения
- •9.3. Конфигурирование состояния проекта
- •9.4. Выбор конфигурации бина
- •9.5. Регистрация сообщений об ошибках как пакет ресурса
- •9.7. Конфигурирование правил навигации (Navigation Rules)
- •9.8. Основные требования приложения JavaServer Faces
- •10. Технология Java Servlet
- •11. Введение в Java Persistence API
- •11.1. Требования к классам сущностей
- •11.3. Внедряемые классы в сущностях
- •11.4. Наследование сущностей
- •11.5. Стратегии наследования сущностей с отображением
- •11.6. Управление сущностями
- •11.7. Запросы сущностей
- •12. Примеры хранимых сущностей
- •12.1. Приложение order
- •12.2. Пример получения схемы отношений на основе таблиц БД
- •13.1. Терминология языка запросов
- •13.3. Упрощенный синтаксис языка запросов
- •13.4. Примеры запросов
- •13.5. Запросы с навигацией связанных сущностей
- •13.6. Запросы с другими условными выражениями
- •13.7. Изменение и удаление группы сущностей
- •13.8. Полный синтаксис языка запросов
- •14. Язык запросов Criteria API
- •14.3. Корни запроса
- •14.4. Использование объединения в запросе
- •14.5. Навигация путей в запросах
- •14.6. Ограничения на результаты запроса
- •14.7. Управление результатами запросов
- •14.8. Исполнение запросов
- •15. Связывание ресурсов
- •15.1. Ресурсы и служба имен JNDI
- •15.2. Объекты DataSource и пулы соединений (Connection Pools)
- •15.3. Внедрение ресурсов
- •15.4. Адаптеры ресурсов
- •15.5. Аннотации метаданных
- •16. Безопасность веб-приложений
- •16.1. Краткий обзор
- •16.2. Механизмы обеспечения безопасности
- •16.3. Безопасность сервера предприятия
- •16.4. Использование защищенного соединения SSL
- •18. Пример приложения
- •18.1. Создание проекта веб-приложения
- •18.3.Структура приложения JavaEE 6
- •18.4. Программирование вида для объектов
- •18.5. Дизайн главной страницы
- •18.6. Страница просмотра записей таблицы городов
- •18.7. Страница добавления записей о городах
- •18.8. Страница редактирования записей о городах
- •18.9. Страница удаления записей о городах
- •19. Обработка связей внешних ключей
- •19.1. Разработка класса для вида сущности
- •19.2. Доработка вида для городов
- •19.3. Разработка обзорной страницы
- •19.5. Страница для редактирования записей с внешними ключами
- •20. Дополнительные функции
- •20.1. Сортировка записей таблицы
- •20.2. Контроль за удалением связанных записей
- •20.3. Контроль ввода наименований
- •20.4. Запросы к БД на языке Java Persistence Query Language
- •20.5. Управление страницами при просмотре таблицы
- •20.6. Создание и просмотр отчетов
- •20.7. Использование шаблонов и стилей
- •20.8. Защита приложения паролем
- •Заключение
- •Библиографический список
18. Пример приложения
Для иллюстрации возможностей технологии JavaEE 6 приведем пример закон-
ченного приложения для ведения таблиц данных, включающего просмотр, добавление, модификацию и удаление записей в базе данных в СУБД Postgresql. Структура таблиц
приводится в упражнении 1 первой главы учебного пособия (п. 1.3.1).
Диаграмма связей классов, экземпляров, свойств и методов приведена на
рис. 1.10.
18.1. Создание проекта веб-приложения
1.Выбрать File > New Project (Ctrl-Shift-N) из главного меню. В разделе
Categories выбрать Java Web. В Projects выбрать Web Application, затем на-
жать «Далее/Next».
2.Ввести имя проекта (например, HelloWeb) в поле Project Name.
3.Задать в поле Project Location любую папку компьютера. Для нужд этого
обучающего курса эта папка будет именоваться $PROJECTHOME.
4.(По выбору.) Установить флаг Use Dedicated Folder for Storing Libraries и за-
дать папку общих библиотек для нескольких проектов.
5.Нажать кнопку «Далее». Откроется панель Server and Settings. Выбрать вер-
сию Java EE, которую вы желаете использовать для приложения (версия 6).
6.Выбрать сервер для развертывания приложения (GlassFish v3).
7.Нажать «Далее». В панели Frameworks выбрать JavaServer Faces, нажать «Завершить/Finish» для создания проекта.
18.2.Создание и редактирование файлов веб-приложения
Создайте три пустых пакета в Source Packages:
•Entities — для хранения файлов классов сущностей;
•Facades — для хранения файлов классов фасадов сущностей;
•Views — для хранения файлов классов видов сущностей.
18.2.1. Создание блока хранилища
Правойкнопкоймышищелкнутьпоименипроекта,выбрать«Создать–Единица
сохраняемости (Persistence)». В окне помощника в поле Data source выбрать ранее
зарегистрированный ресурс jdbc/testDB для доступа к базе данных test (см. п. 1.4). В поле Table Generation Strategy установить переключатель на «Нет», поскольку та-
блицы уже созданы ранее. Завершить операцию.
18.2.2.Создание классов для сущностей
1.Раскройте папку Entities.
2.Нажмите правую кнопку мыши на папке Entities и выберите «Новый – Класс сущностей из базы данных».
3.Задайте в поле Data Source имя зарегистрированного выше на сервере ре-
сурса. Если его нет в списке, то перезапустите NetBeans.
212
4.В окне выбора таблиц переместите нужные для веб-приложения таблицы в
правое окно.
5.В следующем окне проверить правильность выбора таблиц и завершить
операцию. Можно заменить тип коллекций для возвращаемых наборов
объектов-записей на java.util.List.
Генератор кода для приложений поддерживает несколько стратегий работы
с ключевыми полями таблиц БД. Для ключевых полей типа serial необходимо у всех
сущностей добавить аннотацию @GeneratedValue между аннотациями @Id и @Basic,
как показано ниже (выделена жирным).
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Basic(optional = false)
Для устойчивой работы подсистемы хранения целесообразно изменить тип
ключевого поля Integer на Long во всех упоминаниях ключевого поля, включая методы get/set, их параметры и возвращаемые результаты. Для сущности Cities это касается
следующих фрагментов текста класса: private Long idCity;
public Cities(Long idCity) { this.idCity = idCity;
}
public Cities(Long idCity, String name, int population) { this.idCity = idCity;
this.name = name; this.population = population;
}
public Long getIdCity() { return idCity;
}
public void setIdCity(Long idCity) { this.idCity = idCity;
}
Кроме того, придётся исправить имя свойства bDay сущности Persons на bday,
поскольку прописная буква D не опознается в имени свойства. private Date bDay;
public Date getBday() { return bDay;
}
public void setBday(Date bDay) { this.bDay = bDay;
}
213
18.2.3.Создание классов для фасадов сущностей
1.Раскройте папку Facades.
2.Нажмите правую кнопку мыши на узле Facades и выберите «Новый > Session
Beans for Entity Classes».
3.В окне выбора таблиц переместите нужные для веб-приложения таблицы в
правое окно.
4.В следующем окне проверьте правильность выбора таблиц и завершите операцию.
18.2.4.Создание классов для видов сущностей
1.Раскройте папку Views.
2.Нажмите правую кнопку мыши на узле Views и выберите «Новый > JSF
Managed Bean».
3.В окне параметров введите имя класса (обычно <Имя сущности>View) и область видимости Scope (session). Проверьте правильность выбора и за-
вершите операцию. Обратите внимание на область видимости session. По
умолчанию устанавливается request, что приведёт к неправильной работе
приложения, и попытка исправить область в сгенерированном тексте класса не будет иметь успеха.
Среда создаст класс бина имяView.java и откроет его в редакторе. В редакторе видны аннотации @ManagedBean с именем бина имяView и @SessionScoped.
@ManagedBean(name="имяView") @RequestScoped
public class ИмяView {
/** конструктор без параметров ИмяView */ public ИмяView() {
}
}
Обратите внимание на следующий факт: автоматически созданное имя бина начинается с заглавной буквы, что противоречит соглашениям Java: имена экземпля-
ров следует начинать со строчной буквы. Поэтому рекомендуется вручную исправить
прописную букву на малую. Например: @ManagedBean(name="citiesView").
Далее нужно добавить аннотацию @EJB для использования инъекции и получения ссылки на бин ИмяFacade.
1.Установить курсор после заголовка класса.
2.Щелчок правой клавишей мыши в окне редактора, выбрать Insert Code.
3.Выбрать Call Enterprise Bean и имя фасада из списка, нажать Ok.
Сгенерируется фрагмент кода внутри описания вида сущности, например:
@EJB
private CitiesFacade citiesFacade;
Остальная часть класса для вида сущности зависит от назначения приложения и дорабатывается вручную по потребности программиста.
214
Упражнения
1.Создайте новое веб-приложение, папки для хранения файлов, классы сущностей,фасадовивидовдляработысранеесозданнымитаблицами cities, persons
и staffs.
2.Отредактируйте описание классов сущностей, фасадов и видов, заменив в классе сущности тип Integer для ключей на Long и начальные символы имен экземпляров.
18.3.Структура приложения JavaEE 6
Приложение в технологии JavaEE 6 содержит страницы для отправки клиен-
ту и ряд бинов для взаимодействия с базами данных. Общая схема взаимодействия
частей приложения приведена на рис. 1.10. Жирные стрелки показывают связи по информации, тонкие — связи по управлению функциями системы.
Обычный сеанс взаимодействия пользователя с веб-приложением включает
следующие шаги.
1.Клиент направляет запрос на сервер, который формирует начальную стра-
ницу (обычно index.xhtml), отправляемую в браузер клиента. Начальная страница может содержать ссылки и формы для продолжения диалога с приложением на сервере.
2.Клиент своими манипуляциями задаёт команду (ссылка или кнопка), отправ-
ляемую на сервер.
3.Сервер извлекает ссылку на нужную страницу из поступившей команды или вызывает метод-обработчик, который вычисляет имя следующей страницы, формируемой на сервере для передачи клиенту (эта процедура называется навигацией). Формируемая страница-ответ в свою очередь может содержать
форму с полями для ввода данных и кнопки. Поле ввода ссылается на свой-
ство вида (класс ИмяView) для связи с объектом сущности. При посылке страницы клиенту в поле ввода будет установлено начальное значение соответствующего свойства экземпляра сущности (копия записи базы данных). Это называется немедленным вычислением выражения-свойства.
4.После ввода данных в поле формы и нажатия кнопки передачи данных в то
же самое свойство будет записано принятое от клиента значение из поля ввода («откуда взяли, туда и положили»). Это называется отложенным вычислением выражения. Далее вызывается метод-обработчик для командной
кнопки.
5.Обработчик обращается к методам фасада для сохранения принятых от
пользователя данных в таблице базы данных и вычисляет имя следующей
страницы.
6.Метод фасада использует подсистему хранения для выполнения операций с
записями таблицы базы данных.
Классы сущности, фасада и вида представляют собой обычные классы — бины,
подчиняющиеся правилам их создания и использования. Эти правила включают следующие требования:
•класс должен иметь среди прочих конструктор без параметров;
•экземпляры классов должны иметь приватные поля для хранения значений свойств;
215
•для доступа к свойствам экземпляры класса должны иметь методы чтения
(get) и методы записи (set) свойств с соблюдением соглашений об именах.
Имя свойства в описании метода должно начинаться с прописной буквы,
а при обращении к свойству в выражениях — со строчной.
Идеология JavaEE 6 ориентирована на работу с классами для представления объектов различной природы, включая записи баз данных. Экземпляры класса сущно-
сти служат для отображения в их свойствах содержимого записей, соответствующих
классу таблиц БД (mapping). Обратите внимание на работу с внешними ключами. В
поле, соответствующем ключу внешней таблицы, хранится ссылка (не ключ!) на про-
читанный и размещенный в памяти экземпляр соответствующей сущности, что значительно упрощает навигацию по связанным таблицам. Этот «сервис» предоставляет
подсистема хранения Java EE 6.
Экземпляр фасада является посредником между экземплярами сущностей в
памяти сервера и хранилищем таблиц БД. Он выполняет работу по поиску записей в
таблицах и размещению их в памяти, по добавлению, модификации и удалению записей, передавая запросы подсистеме хранения. Проанализируйте состав методов фа-
сада. Среди них есть create для добавления новой записи на основе свойств объекта
в памяти, edit для модификации записи, ключ и поля которой содержатся в указывае-
мом объекте, remove для удаления указанной записи, группа методов find для поиска записей. Автоматически генерируемые методы работы с записями таблиц используют средства языка Criteria API для доступа к БД. Автор приложения может самостоятельно переписать тела этих методов с использованием Java Persistence API. Заготовки
именованных запросов на языке Java Persistence API можно найти в описании классов
сущности с аннотацией @NamedQuery, например:
@NamedQueries({
@NamedQuery(name = "Staffs.findAll", query = "SELECT s FROM Staffs s"),
... })
Экземпляр вида сущности является посредником между формируемой дизайнером страницей документа и источниками данных и методами обработки событий на форме клиента и в ссылках. Дизайнер не должен знать детали внутреннего устройства источников данных и программирования обработчиков событий. Это зона ответствен-
ности программиста. Программист разрабатывает перечисленные классы и сообщает
дизайнеру спецификацию на правила доступа нужных ему данных и методов: названия свойств и методов, их типы, необходимые параметры, регламенты их использования. Дизайнер создает макет страницы, используя согласованные с программистом
спецификации. Таким образом технология Java EE 6 реализует концепцию создания
информационных систем под названием MVC: Model – View – Controller, где модель —
это база данных, вид — страница документа, контроллер — программы на языке Java.
Концепция MVC отражает стремление менеджеров проектов разделить функции по разработке и сопровождению информационных систем между специалистами разного
профиля, согласовав между ними вопросы информационного взаимодействия.
Пример согласованных интерфейсов разрабатываемого приложения приведён
в табл. 18.1.
На рис. 18.1 приведена детальная диаграмма взаимодействия компонент при-
ложения Java EE 6. Для каждой таблицы создаётся класс сущностей, в примере это
Cities. Поля записи отображаются в свойства экземпляров сущностей. Экземпляры сущностей порождаются динамически на сервере по потребности: при чтении из БД, при получении данных с формы ввода или редактирования, в конструкторе вида и т. д.
216
Экземпляры сущностей доступны дизайнеру в выражениях как свойства вида, например: «#{citiesView.city}», и могут передаваться как параметры вызова методов.
|
|
|
Таблица 18.1 |
Интерфейсные свойства и методы основных классов |
|||
|
|
|
|
Метод |
|
|
Назначение |
|
public class Cities |
|
|
Long getIdCity() |
|
|
Свойство idCity |
String getName() |
|
|
Свойство name |
int getPopulation() |
|
|
Свойство population |
List<Persons> getPersonsList() |
|
Свойство personsList |
|
|
public class CitiesView |
||
Cities getCity() |
|
|
Свойство city |
int getNumberOfCities() |
|
|
Свойство numberOfCities |
List<Cities> getAllOfCities() |
|
|
Свойство allOfCities |
String saveCity() |
-> "citiesPage" |
|
Метод «Сохранить город» |
String modCity(Cities city) |
-> "city_mod" |
|
Метод «Редактировать город |
String mod_yes_City() |
|
|
Метод «Сохранить изменения» |
-> "citiesPage" |
|
|
|
String delCity(Cities city) |
-> "city_del" |
|
Метод «Удаления города» |
String del_yes_City() |
-> "citiesPage" |
|
Метод «Разрешить удаление» |
ArrayList getCitiesSelector() |
|
|
Свойство citiesSelector |
|
public class Persons |
|
|
Long getIdPerson() |
|
|
Свойство idPerson |
String getName() |
|
|
Свойство name |
String getFamily() |
|
|
Свойство family |
String getFather() |
|
|
Свойство father |
Date getBday() |
|
|
Свойство bday |
Cities getCityId() |
|
|
Свойство cityId |
|
public class PersonsView |
||
Persons getPerson() |
|
|
Свойство person |
int getNumberOfPersons() |
|
|
Свойство numberOfPersons |
List<Persons> getAllOfPersons() |
|
Свойство allOfPersons |
|
String savePerson ()-> "personsPage" |
|
Метод «Сохранить персону» |
|
String modPerson(Persons person) -> "person_mod" |
|
Метод «Редактировать |
|
|
|
|
персону» |
String mod_yes_Person() -> "personsPage" |
|
Метод «Записать изменения» |
|
String delPerson(Persons person) -> "person_del" |
|
Метод «Удалить персону» |
|
String del_yes_Person() -> "personsPage" |
|
Метод «Разрешить удаление» |
|
Long getId_City() |
|
|
Свойство id_City |
217
Рис. 18.1. Диаграмма связей объектов и методов приложения
Упражнения
1.Поясните, что такое mapping записей и объектов в технологии Java EE 6?
2.Проанализируйте информационные связи подсистемы работы с таблицей городов, приведённой в упражнении 1 к главе 1.
218
