Статьи

Серия Wicket Tutorial: Настройка проекта

Каждый день на этой неделе будет выходить новая статья, в которой подробно рассматривается процесс создания Java-проекта и реализации веб-интерфейса с помощью Apache Wicket .

Wicket — это инфраструктура веб-приложений Java, которая позволяет «дизайнерам» (людям, которые хорошо разбираются в Dreamweaver) и «разработчикам» (людям, которые разбираются в Java и базах данных) сотрудничать в проекте с минимальными шансами наступить друг другу на ноги или надеть шляпы друг друга.

Прелесть Wicket в том, что он использует простые страницы HTML в качестве шаблонной разметки. Это означает, что HTML-страницы могут быть загружены в Dreamweaver (или любой другой инструмент, который удобен для дизайнера), и они будут очень похожи на те, которые отображаются на веб-сервере развертывания.

Workflow

Основной рабочий процесс, связанный с созданием и поддержкой html-кода, представленного Wicket, выглядит следующим образом:

  1. Дизайнер создает html для веб-сайта и добавляет его в разделы «макет». Например , в приложении мы намерены создать в течение наших пяти дней калитки будет Pastebin приложения под названием «Mystic Paste». В нашем приложении будет страница «Добавить код в Mystic Paste», фиктивные данные могут включать в себя некоторое пользовательское содержимое в текстовой области страницы. Все css / images и т. Д. Настроены так, что если бы они были помещены на веб-сервер, все работало бы.
  2. Разработчик должен конкретизировать динамические области веб-страницы, то есть он должен указать Wicket, где ему нужно будет показывать информацию с сервера. Разработчик делает это путем украшения html-страницы дизайнера специальными тегами и атрибутами Wicket. Поскольку эти теги и атрибуты просто считаются частью другого пространства имен, отдельного от xhtml, редакторы, такие как Dreamweaver и браузеры, будут просто игнорировать их.
    Важно отметить: разработчик все равно будет сохранять «поддельные» разделы страницы нетронутыми, это так страница отображается и выглядит отдельно. Пересмотренные разделы будут заменены реальными данными при визуализации с помощью Wicket.
  3. Разработчик передает файл обратно дизайнеру. Дизайнер может вносить дополнительные изменения, если он / она не удаляет и не манипулирует тегами и атрибутами Wicket, присутствующими в файле. Если Дизайнеру действительно необходимо удалить какие-либо теги или атрибуты Wicket, они должны проконсультироваться с Разработчиком, так как такое действие «сломает» веб-страницу, когда Wicket ее отобразит.

Пример страницы калитки

Вот пример страницы калитки. Этот пример был взят из книги Manning Publishing «Калитка в действии»:

<html>
<head>
<title>Cheesr - Making cheese taste beta</title>
<link href="style.css" rel="stylesheet" />
</head>
<body>
<div id="container">
<div id="header">...</div>
<div id="contents">
<div id="main">
<div wicket:id="cheeses" class="cheese">
<h3 wicket:id="name">Gouda</h3>
<p wicket:id="description">Gouda is a Dutch...</p>
<p>
<span wicket:id="price">$1.99</span>
<a wicket:id="add" href="#">add to cart</a>
</p>
</div>
<wicket:remove>
<!-- this section will be removed by wicket, it's only purpose is to flesh out the page -->
<div class="cheese">
<h3>Emmental</h3>
<p>Emmental is a Swiss che...</p>
<p>
<span>$2.99</span>
<a href="#">add to cart</a>
</p>
</div>
</wicket:remove>
</div>
<div id="cart">...</div>
</div>
</div>
</body>
</html>

Это выглядит почти на 100% как обычная веб-страница, единственное отличие состоит в добавлении атрибутов «wicket: XXX» и тегов, разбросанных по документу. Части документа, использующие специальные модификаторы пространства имен Wicket, будут заменены / удалены в окончательной разметке, когда Wicket отобразит страницу в браузере пользователя. Обратите внимание на элемент <wicket: remove>? Именно здесь ваш дизайнер может поместить «поддельную» версию того, как должна выглядеть эта область страницы. Вы, как разработчик, можете взять этот смоделированный html и разделить его на шаблон, динамически управляемый из серверной части.

Вот как выглядит последняя страница, если вы просто загрузите ее в веб-браузер (или Dreamweaver) с жесткого диска:

Подготовка к настройке

Немного отклоняясь от Стандартной Конвенции о калитках

Первое, на что обращает внимание разработчик, начиная с Wicket, — это соглашение, согласно которому Wicket нравится, когда его файлы HTML-шаблонов находятся на том же уровне и в тех же пакетах, что и исходные файлы Java. Конечно, вы можете перепрыгивать через обручи, чтобы заставить Wicket загружать файлы шаблонов html из других мест, но хорошим компромиссом является простое хранение файлов шаблонов html в той же структуре каталогов пакета, но в исходной папке отдельно от классов Java. Зачем? Что ж, довольно просто, чтобы ваши дизайнеры (пользователи Dreamweaver!) Не брали исходные файлы Java вместе с html-файлами, над которыми они работают. Это просто смущает их и загромождает их каталоги.

Вы можете, конечно, придерживаться типичного соглашения «Исходные файлы Java вдоль стороннего HTML», если хотите, но я считаю, что гораздо удобнее разделять их во время разработки, и Maven объединяет их только во время сборки в целевую войну (которая с удовольствием буду делать автоматически).

Структура папок проекта

.
|-- pom.xml
|-- src
| `-- main
| |-- filters
| |-- java
| | `-- com
| | `-- mysticcoders
| | `-- mysticpaste
| | |-- model
| | |-- persistence
| | | |-- exception
| | | |-- hibernate
| | |-- services
| | `-- web
| | |-- ajax
| | |-- pages
| | |-- panels
| | `-- servlet
| |-- resources
| | |-- com
| | | `-- mysticcoders
| | | `-- mysticpaste
| | | |-- spring
| | | `-- web
| | | |-- ajax
| | | |-- pages
| | | `-- panels
| | `-- log4j.properties
| |-- sql
| `-- webapp
| |-- WEB-INF
| |-- images
| |-- js
| `-- css
  • src / main : maven создает исходный код и ресурсы из этого каталога для основной развертываемой цели (т.е. нашего файла войны)

    • фильтры : мы храним набор файлов «фильтров», которые maven может использовать для интерполяции переменных во время сборки. Что это значит? Это означает, что внутри ваших файлов конфигурации, файлов, которые вы используете для настройки соединений с базой данных или путей к файлам, вы можете вставить переменные заполнители, такие как $ {db.host}. Когда maven выполняет сборку, он ищет нужный файл фильтра и ищет часть ключ = значение, соответствующую «db.host», и вставляет ее в файл конфигурации для вас. Это гарантирует, что вы сможете сконфигурировать ваше приложение для каждой среды, в которой вы развертываете (например, DEV, QA, PROD и т. Д.), Имея разные файлы фильтров с одинаковыми ключами, но разными значениями. Для получения дополнительной информации см . Документацию Maven по фильтрованию ресурсов .
    • java / * : эта папка будет содержать весь исходный код приложения. Все, от кода доступа к базе данных, кода калитки и сервисного кода для приложения mysticpaste (см. Ниже).

      • модель : все «доменные» классы, то есть классы, которые представляют объекты в приложении. Для мистической пасты вы увидите такие классы, как «PasteItem», который представляет элемент, вставленный в мистическую пасту.
      • постоянство : на этом уровне пакета постоянства будет храниться список интерфейсов. Интерфейсы содержат базовый уровень доступа, который сервисный уровень будет использовать для сохранения, извлечения и обновления элементов в / из бункера вставки.

        • исключение : постоянный уровень должен сообщать сервисному уровню, когда что-то пошло не так. Это делается с помощью сброса и выдачи исключений.
        • hibernate : таков наш случай, наши персистентные интерфейсы будут реализованы через ORM, известный как Hibernate. Этот пакет будет хранить все пользовательские реализации Hibernate и специальные классы Hibernate.
      • services : Здесь будет храниться уровень сервисов. Как универсальные интерфейсы, так и их классы реализации. Постоянный слой будет впрыскиваться через пружину.
      • web : в этой папке будут находиться наши классы Wicket, и она разделена на несколько категорийных пакетов:

        • ajax : mysticpaste использует Ajax для визуализации частей своего пользовательского интерфейса. Классы калитки, которые отображают xml / html для динамического добавления на страницу, хранятся здесь.
        • страницы : здесь хранятся стандартные классы страниц калитки, которые используются в приложении.
        • панели : классы многоразовых панелей хранятся здесь. Панели могут быть включены в страницы Wicket ради шаблонов
        • servlet : любой прогон нужного нам кода сервлета mill хранится здесь. Хорошим примером может быть ImageUploadServlet
    • resources / * : папка resources будет содержать наши файлы, не основанные на java. Примечательно HTML-файлы и файлы весенней конфигурации

      • spring : содержит любые файлы конфигурации spring, необходимые для подключения сервисов и уровня персистентности.
      • web : эта папка и все подпапки отражают пакеты в каталоге src / main / java /… / web и содержат файлы .html, которые классы страницы / панели Wicket используют в качестве своих шаблонов. Как описано выше, «стандартное» приложение для калитки просто хранит файлы .html вместе со своими классами Wicket в src / main / java /… / web, однако мы хотим, чтобы эти файлы были отделены от исходного кода Java, чтобы сохранить каталог наши дизайнеры извлекают из системы контроля версий только те файлы, с которыми им нужно работать.
    • sql : любые сценарии sql, которые нам нужны для создания базы данных mysticpaste.
    • webapp : в этой папке будут храниться файлы, которые находятся в базовом каталоге нашего файла war

      • WEB-INF : где вы храните файл web.xml
      • images : любой ресурс изображений, файлы .gif / .png / .jpg, на которые ссылается ваше веб-приложение.
      • js : файлы javascript, на которые будет ссылаться ваше веб-приложение
      • CSS : таблицы стилей вашего веб-приложения
  • src / test / * : все файлы, которые находятся в этой папке, являются тестовыми классами и ресурсами, необходимыми для поддержки тестов. Maven соберет все в src / main / java и добавит его в путь классов создаваемых вами классов JUnit или TestNG.

    • java : тестовые классы JUnit или TestNG, которые будут запускаться во время сборки
    • resources : файлы ресурсов, необходимые для поддержки тестов

Начиная

Поскольку мы используем Maven в качестве нашего инструмента для сборки, мы можем воспользоваться тем, что опытные люди в проекте Wicket создали специальный « архетип », который создает каркасное веб-приложение со структурой папок, которая примерно соответствует тому, что мы описали выше. и Maven pom.xml файл, используемый для построения войны. Участники Wicket пошли еще дальше и создали небольшую веб-страницу, которая на основе нескольких выпадающих опций сгенерирует команду maven, которую вам нужно выполнить для создания проекта Wicket. Вы можете найти эту веб-страницу на сайте Apache Wicket по ссылке « Быстрый старт ».

Копирование вышеупомянутой команды Maven создает Скелетный проект калитки

Чтобы быть точным, команда, которую я использовал, была:

mvn archetype:create
-DarchetypeGroupId=org.apache.wicket
-DarchetypeArtifactId=wicket-archetype-quickstart
-DarchetypeVersion=1.3.5
-DgroupId=com.mysticcoders
-DartifactId=mysticpaste

И я получил следующую структуру папок:

.
`-- mysticpaste
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mysticcoders
| | |-- HomePage.html
| | |-- HomePage.java
| | `-- WicketApplication.java
| |-- resources
| | `-- log4j.properties
| `-- webapp
| `-- WEB-INF
| `-- web.xml
`-- test
`-- java
`-- com
`-- mysticcoders
|-- Start.java
`-- TestHomePage.java

Теперь, очевидно, нам придется изменить некоторые вещи, например, я хочу, чтобы мой базовый пакет был com.mysticcoders.mysticpaste, но это достаточно просто сделать, как только мы окажемся в IDE. А пока давайте протестируем этот пример веб-приложения и посмотрим, работает ли он. Для этого перейдите в каталог mysticpaste (каталог, в котором есть pom.xml) и введите следующее:

mvn jetty:run

Это запустит контейнер веб-приложения Jetty, работающий на порту 8080 (если у вас уже что-то работает, используйте опцию -Djetty.port = <portNum>). Запустите браузер и перейдите по адресу http: // localhost: 8080 / mysticpaste /. Вы должны увидеть:

Ты едешь

Рано или поздно вы захотите взломать IDE и начать взламывать. Maven делает это чрезвычайно просто, позволяя вам создавать специфичные для IDE файлы проекта на основе файла Maven pom.xml.

Затмение
мвн затмение: затмение

Для eclipse вам также нужно установить переменную classpath M2_REPO для рабочей области, в которой находится ваш проект. Сделайте это, введя следующую команду:

mvn -Declipse.workspace=<your_workspace_location> eclipse:add-maven-repo

IntelliJ IDEA
mvn idea: идея -ИЛИ- в IDEA 7+ просто откройте файл pom.xml

Netbeans
Netbeans поддерживает maven из коробки, просто «Откройте проект» и выберите каталог mysticpaste, содержащий файл pom.xml

При создании файлов проекта через Maven проект настраивается таким образом, чтобы записи пути к классам указывали на ваш локальный репозиторий Maven (т. Е. ~ / .M2 / repository или C: Documents and Settingsyourusername.M2repository в Windows). Он также устанавливает src / main / java, src / main / resources в качестве «исходных папок». При необходимости вы можете добавить другие папки в список исходных папок в соответствии с вашей IDE. Единственное, что вам нужно помнить, это то, что если вы когда-нибудь будете использовать mvn eclipse: clean, а затем mvn eclipse: eclipse, то эти другие исходные папки придется читать заново. через вашу IDE. Вместо этого вы должны добавить папки источника / ресурса непосредственно в ваш pom.xml, таким образом, они будут поддерживаться.

весна

Приложение Mystic Paste будет использовать Spring, и вы действительно должны это делать. Если вы не спрятались под скалой или не работаете в корпоративной среде, столь хромой в отношении того, какие технологии, более новые, чем 2002, запрещены, вы должны научиться принимать Spring в качестве стандарта де-факто. Инъекция зависимости на победу!

Мы добавляем следующее в наш pom.xml:

<!-- Note: versions have been left off intentionally to future proof this article -->
<dependency> <!-- 1 -->
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-spring-annot</artifactId>
</dependency>
<dependency> <!-- 2 -->
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</dependency>
<dependency> <!-- 3 -->
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency> <!-- 4 -->
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
  1. wicket-spring-annot : позволяет связать наше приложение Wicket с помощью удобных аннотаций внедрения зависимостей (например, @SpringBean, более подробно см. документацию Wicket )
  2. весна : это только основные библиотеки весны
  3. spring-test : набор классов интеграции Spring для модульного тестирования
  4. spring-tx : API -интерфейс Spring Transaction Management для декларативных транзакций

Дополнения web.xml для Spring

Чтобы Spring мог управлять нашим приложением Wicket, нам нужно настроить фильтр Wicket с фабрикой приложений, поддерживающей Spring. Это позволяет нам связать наш класс Wicket Application с нашим файлом applicationContext.xml, что очень удобно, если у вас есть сервисы и параметры конфигурации, которые вы хотите внедрить в объект Wicket Application, чтобы остальная часть вашего приложения могла получить к ним доступ. Для этого мы изменим оригинальный фильтр Wicket следующим образом:

    <filter>
<filter-name>wicket.mysticpaste</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<!--<param-name>applicationClassName</param-name>-->
<param-name>applicationFactoryClassName</param-name>
<param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
</init-param>
</filter>

Кроме того, мы хотим, чтобы наш контекст Spring был доступен для нашего веб-приложения, если когда-либо потребуется одна из наших страниц для прямого доступа к управляемым компонентам Spring:

    <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:com/mysticcoders/mysticpaste/spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

Hibernate

Hibernate — это наш ORM, который позволяет нам сохранять и извлекать объекты нашей модели из базовой базы данных и из нее, какой бы она ни была.

Мы добавляем следующее в наш pom.xml:

<!-- Note: versions have been left off intentionally to future proof this article -->
<dependency> <!-- 1 -->
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
</dependency>
<dependency> <!-- 2 -->
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
</dependency>
<dependency> <!-- 3 -->
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency> <!-- 4 -->
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.0.1B</version>
</dependency>
  1. hibernate-annotations : используется для того, чтобы мы могли аннотировать наши классы моделей информацией о отображении, вместо того чтобы создавать отдельный файл mysticpaste.hbm.xml.
  2. c3p0 : предоставляет библиотеку пулов соединений, которую может использовать Hibernate
  3. commons-dbcp : еще одна библиотека пула подключений, мы также добавим ее и решим, использовать ее позже или c3p0
  4. jta : это API транзакций Java, который необходим Hibernate (Hibernate предоставляет реализацию API)

Дополнения web.xml для Hibernate

Чтобы Hibernate Session был открыт и готов к нашему веб-приложению во время цикла запроса, нам нужно настроить фильтр Hibernate следующим образом (в противном случае, удачной работы с отложенной загрузкой!):

    <filter>
<filter-name>open.hibernate.session.in.view</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>

<!-- Important! This filter mapping must come before Wicket's! -->
<filter-mapping>
<filter-name>open.hibernate.session.in.view</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Как указано в комментарии выше, убедитесь, что это сопоставление фильтра существует * до * вашего фильтра wicket.mysticpaste, иначе оно просто не будет работать.

База данных

Для Mystic Paste мы решили использовать свободно доступный PostgreSQL . Добавить поддержку PostgreSQL очень просто, в отличие от некоторых коммерческих СУБД, где вам нужно загрузить и установить их драйвер JDBC в ваш репозиторий. Чтобы добавить поддержку Postgres, мы просто добавляем следующее в наш pom.xml:

<!-- Note: versions have been left off intentionally to future proof this article -->
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>

сервлеты

Независимо от того, какой фреймворк для веб-приложений вы выберете, бывают случаи, когда простой сервлет jane оказывается действительно полезным. Если вам нужны сервлеты и сервлет должен иметь доступ к сеансу Wicket, добавьте в файл web.xml следующее:

    <filter>
<filter-name>wicket.session</filter-name>
<filter-class>org.apache.wicket.protocol.http.servlet.WicketSessionFilter</filter-class>
<init-param>
<param-name>filterName</param-name>
<param-value>wicket.mysticpaste</param-value>
</init-param>
</filter>

И затем, после ваших других сопоставлений фильтров, добавьте следующее (при условии, что вы монтируете свои сопоставления сервлетов в / servlet /):

    <filter-mapping>
<filter-name>wicket.session</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>

Maven фильтры и профили

Чтобы создать проект Mystic Paste для различных сред (DEV / QA / PROD), нам необходимо реализовать как профили Maven, так и фильтры.

фильтры

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

Включить фильтры довольно просто, мы открываем файл pom.xml, находим раздел для <resources> и устанавливаем значение для элемента <filtering> в true следующим образом:

<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
.
.
.
</resources>

Но чтобы фильтрация работала, нам нужно указать файл фильтров. Недостаточно указать только один файл фильтра, потому что нам нужно указать разные фильтры для среды, и мы сделаем это с помощью профилей Maven.

профили

Чтобы настроить профиль, создайте новый набор элементов, следуя разделу <build> в файле pom.xml. Вот так:

<properties>
<!-- default env when no profile is specified -->
<env>DEV</env>
</properties>
<profiles>
<profile>
<id>DEV</id>
<properties>
<env>DEV</env>
</properties>
</profile>

<profile>
<id>QA</id>
<properties>
<env>QA</env>
</properties>
</profile>

<profile>
<id>PROD</id>
<properties>
<env>PROD</env>
</properties>
</profile>
</profiles>

and just above your <resources> tag underneith your <build> tag you would add the following elements:

<build>
<finalName>mysticpaste</finalName>
<filters>
<filter>src/main/filters/filters-${env}.properties</filter>
</filters>

<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>

src/main/filters will contain the following files.

|-- pom.xml
|-- src
| `-- main
| |-- filters
| | `-- filters-DEV.properties
| | `-- filters-QA.properties
| | `-- filters-PROD.properties

filters-DEV.properties

jdbc.url=jdbc:postgresql://localhost:5432/mysticpaste
jdbc.user=mysticpaste
jdbc.password=password
image.upload.path=/tmp/pasetbin/userimages
image.upload.size.limit=4096K

filters-PROD.properties

jdbc.url=jdbc:postgresql://192.168.2.10:5432/mysticpaste
jdbc.user=mysticpaste
jdbc.password=CrYp71c
image.upload.path=/mysticpaste/userimages
image.upload.size.limit=4096K

Now within any file under src/main/resources that has variables of the form ${variable.name} will have those variables replaced with the values specified in the proper filters file located under src/main/filters. For instance here is an example of a Spring applicationContext.xml file which will be interpolated with proper variables values at build time:

applicationContext.xml

    <bean id="photoServiceConfig" class="com.mysticcoders.mysticpaste.services.ImageServiceConfig">
<property name="absoluteFilePath" value="${image.upload.path}"/>
<property name="imageSizeLimit" value="${image.upload.size.limit}"/>
</bean>
<bean id="photoService" class="com.mysticcoders.mysticpaste.services.ImageManagementServiceImpl">
<constructor-arg ref="photoServiceConfig"/>
<property name="photoManagementDao" ref="photoDao"/>
</bean>

To determine which filters file will be used depends on the profile chosen when building. For example, to build to production using the filters-PROD.properties we would execute the following:

mvn clean deploy -P PROD

The profile you use with the -P switch must match one of the values of the <ID> element for a profile.

Conclusion

Although it’s quite easy to get started with the Maven QuickStart project it is sometimes a bit frustrating putting some of the additonal pieces together. Building to several environments, setting up depenencies not included in the QuickStart project and strucuturing your project in an effort to make life easy for yourself as a developer and for your designer.

I hope our Day 1 tutorial leaves you with a good sense of how a Wicket project is setup, now we can move onto coding the app!

In the next four days we will be covering:

  • Writing the Tests
  • Designing the backend
  • Designing the Wicket components
  • Putting it all together


For more about Mystic, check us out at http://www.mysticcoders.com