«1. Обзор
В этой статье мы рассмотрим VRaptor, простую и понятную веб-инфраструктуру Java MVC, которая использует контексты Java и технологию внедрения зависимостей и проста для понимания.
Так же, как и Spring — он сильно зависит от аннотаций и отлично работает с Hibernate.
Он также поставляется с некоторыми полезными плагинами, например, для интернализации и модульного тестирования.
Итак, давайте изучим различные компоненты VRaptor и создадим пример проекта.
2. Зависимости и установка Maven
Один из быстрых способов приступить к работе — загрузить дистрибутив vraptor-blank-project-distribution из официального репозитория.
Пустой проект — это всего лишь скелет, который можно превратить в полноценное веб-приложение.
Скачав и разархивировав проект, давайте переименуем директорию в vraptor (или любое другое имя).
Каталог должен содержать:
-
src/pom.xml и README.md
Проект основан на Maven и поставляется с плагином tomcat7 Maven, который предоставляет контейнер сервлетов для запуска приложения.
Он также поставляется с IndexController по умолчанию, который имеет только один метод – index().
По умолчанию представление, отображаемое этим методом, находится в файле webapp/WEB-INF/jsp/index/index.jsp — это соответствует соглашению WEB-INF/jsp/имя_контроллера/имя_метода.
Чтобы запустить сервер, мы выполним команду mvn tomcat7:run из корня проекта.
В случае успеха, если мы посетим http://localhost:8080, браузер отобразит «Это работает!! VRaptor!».
Если мы столкнулись с «java.lang.LinkageError: нарушение ограничения загрузчика», то мы должны изменить следующие зависимости в pom.xml:
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-core</artifactId>
<version>2.1.2.Final</version>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.el</groupId>
<artifactId>jboss-el-api_3.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core-impl</artifactId>
<version>2.1.2.Final</version>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.el</groupId>
<artifactId>jboss-el-api_3.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
Виновником является включенный el-api в Weld-Servlet-Core и Weld-Core-Impl с областью компиляции; это приводит к конфликту зависимостей.
Следующие зависимости потребуются вдоль линии, поэтому давайте включим их в pom.xml:
<dependency>
<groupId>br.com.caelum.vraptor</groupId>
<artifactId>vraptor-freemarker</artifactId>
<version>4.1.0-RC3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.8-dmr</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.27-incubating</version>
</dependency>
Последняя версия артефактов vraptor-freemarker, mysql-connector-java и freemarker может быть можно найти в Maven Central.
Теперь, когда все готово, давайте создадим простой блог-сайт.
3. Поддержка Hibernate
VRaptor предоставляет различные плагины для взаимодействия с базами данных, один из них vraptor-hibernate, который работает с Hibernate 4.
Плагин делает компонент Hibernate SessionFactory доступным во время выполнения через CDI.
После установки плагина нам понадобится стандартный файл конфигурации Hibernate — пример можно найти в репозитории.
VRaptor использует технику под названием Producers, чтобы сделать объекты доступными для управления DI. Подробнее об этом здесь.
4. Определение веб-маршрутов в VRaptor
В VRaptor определения маршрутов находятся в контроллерах, которые представляют собой просто аннотированные @Controller Java-объекты — точно так же, как в Spring.
Аннотации @Path используются для сопоставления пути запроса с конкретным контроллером, а аннотации @Get, @Post, @Put, @Delete и @Patch используются для указания типов HTTP-запросов.
Конфигурация сопоставления маршрутов похожа на JAX-RS, но официально не реализует стандарт.
@Get("/posts/{id}")
Кроме того, при определении пути можно указать переменную пути в фигурных скобках:
@Get("/posts/{id}")
public void view(int id) {
// ...
}
Доступ к значению id можно получить внутри метода контроллера:
Когда форма отправленные на определенный маршрут, VRaptor может автоматически заполнить объект отправленными данными формы.
Давайте посмотрим на это в действии в следующем разделе статьи.
5. Представления и механизм шаблонов
По умолчанию представления могут быть реализованы с использованием JSP. Однако можно использовать и другие шаблонизаторы — в этой статье мы будем работать с Freemarker.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>VRaptor Blank Project</title>
</head>
<body>
It works!! ${variable}
</body>
</html>
Давайте начнем с создания index.ftl и сохранения его в каталоге представления по умолчанию (src/main/resources/templates):
@Path("/")
public void index() {
result.include("variable", "VRaptor!");
result.use(FreemarkerView.class).withTemplate("index");
}
Теперь мы можем использовать определенное представление с классом FreemarkerView для рендеринга представления:
Объект Result содержит состояние модели – у него есть методы для перенаправления на другую страницу, URL или метод контроллера; его можно ввести в контроллер с помощью CDI.
«В нашем примере переменная разрешается Freemarker. Таким образом, заполнитель ${variable} в index.ftl заменяется на «VRaptor!».
Здесь задокументировано более продвинутое использование.
6. Пример обработки отправки формы
@Post("/post/add")
public void add(Post post) {
post.setAuthor(userInfo.getUser());
validator.validate(post);
if(validator.hasErrors()) {
result.include("errors", validator.getErrors());
}
validator.onErrorRedirectTo(this).addForm();
Object id = postDao.add(post);
if(Objects.nonNull(id)) {
result.include("status", "Post Added Successfully");
result.redirectTo(IndexController.class).index();
} else {
result.include(
"error", "There was an error creating the post. Try Again");
result.redirectTo(this).addForm();
}
}
Давайте посмотрим, как мы можем обрабатывать отправку формы с проверкой:
Объект Post сначала проверяется с помощью проверки Java-бина, а затем сохраняется в базе данных с помощью postDao.add( ).
Поля объекта Post заполняются автоматически из значений отправленных данных формы, которые соответствуют полям ввода формы в файле представления.
Обратите внимание, что имя поля ввода должно начинаться с имени объекта в нижнем регистре.
<input type="text" class="form-control" placeholder="Title"
id="title" name="post.title" required />
<textarea rows="10" class="form-control" placeholder="Post"
id="post" name="post.post" required></textarea>
Например, представление, отвечающее за добавление новой записи, имеет поля ввода: post.title и post.post, которые соответствуют полям title и post в Post.java соответственно:
Полный add.ftl файл можно найти в исходном коде.
if(validator.hasErrors()) {
result.include("errors", validator.getErrors());
}
validator.onErrorRedirectTo(this).addForm();
Если есть ошибка при отправке формы, сообщение об ошибке включается и пользователь перенаправляется к тому же методу add():
7. Заключение
В заключение мы рассмотрели VRaptor. с первого взгляда и увидел, как можно реализовать базовую функциональность MVC.
Документация содержит более подробную информацию о фреймворке, а также о доступных плагинах.