Пользователь
0,0
рейтинг
5 января 2011 в 11:05

Разработка → Учимся готовить: Spring 3 MVC + Spring Security + Hibernate

JAVA*
Добрый день! Меня зовут Антон Щастный.

Это моя очередная статья, посвящённая разработке веб приложений на Java. Хочу предложить вам сделать небольшую систему учёта клиентов, написанную с использованием фреймворка Spring и библиотеки Hibernate.

Что будет в приложении:


Будет простой менеджер контактов, позволяющий добавлять в базу новые записи, просматривать имеющиеся, удалять ненужные. Сведения будут храниться в базе данных. Доступ к приложению – через веб, с аутентификацией и авторизацией пользователей.

Что будем использовать:


  • веб фреймворк Spring MVC,
  • фреймворк Spring Security,
  • ORM библиотеку Hibernate,
  • MySQL в качестве СУБД.

Инфраструктура:
  • редактор SpringSource Tool Suite,
  • сборщик проектов Maven,
  • система логгирования Log4j,
  • постоянное подключение к интернету.


В моей предыдущей статье о Spring MVC был упущен ряд моментов по использованию аннотаций в Java-коде и применению Maven для сборки проекта. В данной статье я попытался исправить упущение.

Цель статьи – показать начинающим веб разработчикам совместное использование различных технологий платформы Java.


Содержание


  1. Создание нового проекта в IDE.
  2. Создание структуры пакетов.
  3. Добавление класса сущности в модель домена.
  4. Слой доступа к данным.
  5. Сервис-слой.
  6. Добавление веб.
  7. Контроллер.
  8. Вид.
  9. Запуск приложения.
  10. Безопасность.
  11. Заключение.


Архитектура разрабатываемого приложения.
Архитектура разрабатываемого приложения.

1. Создание нового проекта в IDE



Проект будем разрабатывать в SpringSource Tool Suite (STS) – удобном редакторе, основанном на Eclipse IDE.

После установки STS создадим шаблонный проект:
File > New > Spring Template Project > Spring MVC Project.

Project name: ContactManager
Top level package: net.schastny.contactmanager

STS

Редактор создаст шаблонный веб проект с базовыми настройками, имеющий следующую структуру:
src/main/java Java-классы приложения.
src/main/resources Все остальные файлы (ресурсы), необходимые для работы: например файл настроек логгера log4j.xml, папка META-INF.
src/test/java Папка для тестов JUnit.
src/test/resources Папка ресурсов юнит-тестов.
src/main/webapp Папка, в которой размещаются файлы веб составляющей менеджера контактов: дескриптор развёртывания приложения web.xml, xml-файлы с настройками фреймворка Spring, jsp-страницы.
Внимание, статические ресурсы приложения: картинки, css, js-скрипты лежат в папке resources.
pom.xml Файл настроек проекта для Maven’а, содержит наименование проекта и перечень зависимостей проекта от сторонних библиотек.


Поменяем в настройках проекта (pom.xml) версию Spring с 3.0.4.RELEASE на 3.0.5.RELEASE.

Примечание: как создавать Maven-проекты вне IDE читайте здесь.

2. Создание структуры пакетов


net.schastny.contactmanager.dao Слой доступа к данным.
В нём будем размещать Data Access Objects – объекты доступа к данным.
net.schastny.contactmanager.domain Доменный слой.
Именно здесь лежат POJO-классы, описывающие объекты-сущности системы. В нашем случае это класс Contact.
net.schastny.contactmanager.service Сервис-слой приложения.
Содержит интерфейсы, в которых описан функционал приложения. Также содержит одну или несколько практических реализаций этих интерфейсов.
net.schastny.contactmanager.web Веб-слой приложения.
Здесь лежат классы-контроллеры, описывающие порядок взаимодействия пользователя с системой через веб.

Примечание: класс-контроллер, созданный редактором, можно удалить.

3. Добавление класса сущности в модель домена


package net.schastny.contactmanager.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "CONTACTS")
public class Contact {

	@Id
	@Column(name = "ID")
	@GeneratedValue
	private Integer id;

	@Column(name = "FIRSTNAME")
	private String firstname;

	@Column(name = "LASTNAME")
	private String lastname;

	@Column(name = "EMAIL")
	private String email;

	@Column(name = "TELEPHONE")
	private String telephone;

	// Getters and setters
}

Не забудьте добавить методы геттеры и сеттеры для свойств бина.

Добавим зависимости проекта в файл pom.xml. Обратите внимание, что класс из модели домена не будет зависить ни от Спринга, ни от Хибернейта.
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0</version>
		</dependency>

Пояснение к использованным аннотациям.
@Entity Класс представляет объект, который нужно долговременно хранить.
@Table(name = "CONTACTS") Свойства класса будем хранить в таблице CONTACTS.
@Column(name = "FIRSTNAME") Это свойство будет храниться в столбце firstname.
@Id Это поле уникальное для объектов, то есть по нему будем искать объекты.
@GeneratedValue Значение этого поля будет назначаться не нами, а генерироваться автоматически.


4. Слой доступа к данным


Интерфейс и практическая реализация объекта доступа к данным.
package net.schastny.contactmanager.dao;

import java.util.List;
import net.schastny.contactmanager.domain.Contact;

public interface ContactDAO {

	public void addContact(Contact contact);

	public List<Contact> listContact();

	public void removeContact(Integer id);
}

package net.schastny.contactmanager.dao;

import java.util.List;

import net.schastny.contactmanager.domain.Contact;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class ContactDAOImpl implements ContactDAO {

	@Autowired
	private SessionFactory sessionFactory;

	public void addContact(Contact contact) {
		sessionFactory.getCurrentSession().save(contact);
	}

	@SuppressWarnings("unchecked")
	public List<Contact> listContact() {

		return sessionFactory.getCurrentSession().createQuery("from Contact")
			.list();
	}

	public void removeContact(Integer id) {
		Contact contact = (Contact) sessionFactory.getCurrentSession().load(
				Contact.class, id);
		if (null != contact) {
			sessionFactory.getCurrentSession().delete(contact);
		}

	}
}

Обновим зависимости проекта в файле pom.xml. Добавим Хибернейт.
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>3.3.2.GA</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-annotations</artifactId>
			<version>3.3.1.GA</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-commons-annotations</artifactId>
			<version>3.3.0.ga</version>
		</dependency>

Пояснение к использованным аннотациям.
@Repository Аннотация показывает, что класс функционирует как репозиторий и требует наличия прозрачной трансляции исключений. Преимуществом трансляции исключений является то, что слой сервиса будет иметь дело с общей иерархией исключений от Спринга (DataAccessException) вне зависимости от используемых технологий доступа к данным в DAO слое.
@Autowired Аннотация позволяет автоматически установить значение поля SessionFactory.


5. Сервис-слой


Опишем интерфейс взаимодействия пользователя с системой.
package net.schastny.contactmanager.service;

import java.util.List;
import net.schastny.contactmanager.domain.Contact;

public interface ContactService {

	public void addContact(Contact contact);

	public List<Contact> listContact();

	public void removeContact(Integer id);
}

Практическая реализация интерфейса сервиса – класс ContactServiceImpl.java.
package net.schastny.contactmanager.service;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import net.schastny.contactmanager.dao.ContactDAO;
import net.schastny.contactmanager.domain.Contact;
 
@Service
public class ContactServiceImpl implements ContactService {
 
    @Autowired
    private ContactDAO contactDAO;
 
    @Transactional
    public void addContact(Contact contact) {
        contactDAO.addContact(contact);
    }
 
    @Transactional
    public List<Contact> listContact() {
 
        return contactDAO.listContact();
    }
 
    @Transactional
    public void removeContact(Integer id) {
        contactDAO.removeContact(id);
    }
}

Обновим зависимости проекта в файле pom.xml. Добавим поддержку транзакций.
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

Пояснение к использованным аннотациям.
@Service Мы используем данную аннотацию, чтобы объявить, что этот класс представляет сервис – компонент сервис-слоя. Сервис является подтипом класса @Component. Использование данной аннотации позволит искать бины-сервисы автоматически (смотрите далее в root-context.xml).
@Transactional Перед исполнением метода помеченного данной аннотацией начинается транзакция, после выполнения метода транзакция коммитится, при выбрасывании RuntimeException откатывается.


6. Добавление веб


Настройку веб приложения начнём с самого главного – с тьмы xml-файлов. В большом приложении очень удобно хранить различные настройки в разных файлах.

После xml-портянок напишем простенький контроллер.

Файлы настроек вы можете найти по ссылкам ниже.
web.xml Это дескриптор развертывания. Файл, который описывает настройки развертывания приложения на сервере.
spring/root-context.xml Root Context. Контекст всего приложения. Бины, описанные здесь, будут доступны всем сервлетам и фильтрам. Также здесь следует описывать бины безопасности и доступа к данным (в нашей конфигурации они вынесены в отдельные файлы).
spring/data.xml Файл с настройками ресурсов для работы с данными.
spring/security.xml Файл с настройками безопасности.
spring/appServlet/servlet-context.xml DispatcherServlet Context. Определяет настройки одного сервлета и бины, которые доступны только этому сервлету.
spring/appServlet/controllers.xml Файл с настройками контроллеров для данного сервлета.


spring/security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">

</beans:beans>


Пояснение к используемым бинам.
messageSource Бин для обеспечения интернациолизации приложения. Ниже мы создадим файлы messages_en.properties и messages_ru.properties с локализованными сообщениями на русском и английском.
propertyConfigurer Для загрузки файла с настройками БД jdbc.properties.
dataSource Датасорс, используется для подключения к БД. Мы предоставляем класс jdbc-драйвера, имя пользователя, пароль, другие настройки.
sessionFactory Это бин конфигурации Хибернейта. В файле hibernate.cfg.xml будут содержаться маппинги на классы сущностей.
transactionManager Бин настройки менеджера транзакций. Мы используем менеджер транзакций для управления транзакциями приложения.

Файлы:
/src/main/resources/messages_en.properties
/src/main/resources/messages_ru.properties
/src/main/resources/hibernate.cfg.xml
WEB-INF/jdbc.properties

7. Контроллер


package net.schastny.contactmanager.web;

import java.util.Map;

import net.schastny.contactmanager.domain.Contact;
import net.schastny.contactmanager.service.ContactService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class ContactController {

	@Autowired
	private ContactService contactService;

	@RequestMapping("/index")
	public String listContacts(Map<String, Object> map) {

		map.put("contact", new Contact());
		map.put("contactList", contactService.listContact());

		return "contact";
	}
	
	@RequestMapping("/")
	public String home() {
		return "redirect:/index";
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public String addContact(@ModelAttribute("contact") Contact contact,
			BindingResult result) {

		contactService.addContact(contact);

		return "redirect:/index";
	}

	@RequestMapping("/delete/{contactId}")
	public String deleteContact(@PathVariable("contactId") Integer contactId) {

		contactService.removeContact(contactId);

		return "redirect:/index";
	}
}

Пояснение к использованным аннотациям.
@Controller Аннотация используется для магического превращения любого java класса в класс контроллера.
Данный класс представляет собой компонент, похожий на обычный сервлет (HttpServlet) (работающий с объектами HttpServletRequest и HttpServletResponse), но с расширенными возможностями по применению в MVC-приложениях.
@RequestMapping Аннотация используется для маппинга урл-адреса запроса на указанный метод или класс. Запрос можно маппить как на метод класса, так и на целый класс. Допускается указывать конкретный HTTP-метод, который будет обрабатываться (GET/POST), передавать параметры запроса.
@ModelAttribute Аннотация, связывающая параметр метода или возвращаемое значение метода с атрибутом модели, которая будет использоваться при выводе jsp-страницы.
@PathVariable Аннотация, которая показывает, что параметр метода должен быть связан с переменной из урл-адреса.


8. Вид


/src/main/webapp/WEB-INF/views/contact.jsp

9. Запуск приложения


До запуска системы нам необходимо сделать ещё две вещи:

Во-первых, создать базу данных для приложения и пользователя под неё в соответствии с настройками файла jdbc.properties:
CREATE USER contactmanager@localhost identified BY '1234';
GRANT usage ON *.* TO contactmanager@localhost identified BY '1234';
CREATE DATABASE IF NOT EXISTS contactmanager;
GRANT ALL privileges ON contactmanager.* TO contactmanager@localhost;
USE contactmanager;
CREATE TABLE CONTACTS
  (
     id        INT PRIMARY KEY AUTO_INCREMENT,
     firstname VARCHAR(30),
     lastname  VARCHAR(30),
     telephone VARCHAR(15),
     email     VARCHAR(30),
     created   TIMESTAMP DEFAULT NOW()
  ); 

Во-вторых, обновить зависимости в pom.xml.
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
		</dependency>


Теперь запустим приложение на сервере: ContactManager > Run As > Run on Server > SpringSource tc Server Developer Edition v2.0.



Откройте адрес http://localhost:8080/ContactManager в браузере.



Примечание: Проверьте кодировку базы данных, таблиц в БД, соединения с БД, кодировку проекта в редакторе, так как вместо родных кириллических букв в браузере могут появиться кракозябры.

Для отладки работы Хибернейта можете в файл src/main/resources/log4j.xml добавить следующую строку:
	<!--org.hibernate.SQL logger-->
	<logger name="org.hibernate">
		<level value="info"/>
	</logger>

10. Безопасность


Обновим зависимости проекта в файле pom.xml. Добавим модули Spring Security.
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>


Добавим в web.xml фильтр безопасности, действующий на всё приложение.
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


В целях безопасности страницу логина не следует помещать внутри папки WEB-INF, так что разместим её в корне веб приложения – в папке webapp.
webapp/login.jsp

Там же разместим страницу ошибки 403: webapp/error403.jsp

Подредактируем файл security.xml.
security.xml

Пояснение к сделанным настройкам в файле security.xml


Выделим в приложении три группы пользователей (роли пользователей):
  • анонимный пользователь (ROLE_ANONYMOUS),
  • просто пользователь (ROLE_USER),
  • администратор (ROLE_ADMIN).

Разграничим доступ к приложению:
  • Сделаем возможность просматривать контакты доступной всем категориям пользователей.
  • Добавлять новые контакты смогут только зарегистрированные пользователи.
  • Удалять записи сможет только админ.


Где хранить данные о пользователях


Можно прямо в конфигурационном файле, если их немного. Можно в базе данных, можно в LDAP-хранилище.

Пример записи (security.xml) при использовании БД для хранения паролей.
	<authentication-manager>
		<authentication-provider>
			<jdbc-user-service data-source-ref="dataSource" />
		</authentication-provider>
	</authentication-manager>


Пояснения к некоторым элементам.
<remember-me />
Поддержка мультисессии. После повторного запуска браузера не нужно заново логиниться.
<anonymous username="guest" granted-authority="ROLE_ANONYMOUS" />
Определение анонимного пользователя и наделение его ролями, так чтобы с ним можно было работать, как с обыкновенным пользователем приложения.
<password-encoder hash="md5" />
Хранение паролей в зашифрованном виде.
В нашем приложении не используется.


11. Заключение


Вот и всё! Осталось прикрутить дизайн, рюшечки на jQuery (статья для начинающих) и продавать поделку за деньги. Но это, дорогие мои читатели, уже совсем другая история.

После выполнения всех манипуляций у вас должна получиться следующая структура проекта:
image

Буду признателен за указанные ошибки и неточности в статье.

Использованные ресурсы:


1. Spring Recipes: A Problem-Solution Approach, Second Edition, Gary Mak, Ken Sipe, Josh Long, Daniel Rubio.
2. Create Spring 3 MVC Hibernate 3 Example using Maven in Eclipse,
3. The Spring Framework Reference Documentation,
4. Mastering Spring MVC 3 by Keith Donald.

Скачать готовый проект можно здесь, а базу данных для проекта — здесь.
Антон Щастный @schaan
карма
68,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (51)

  • +1
    Спасибо за статью, узнал несколько новых интересных штук…
    • 0
      Пожалуйста )
      Я рад, если статья была полезной.
  • 0
    А где собственно валидация ModelAttribute и редактирование данных? Без них подобных примеров в интернете тоннами.
    • +1
      В статье я делаю упор на совместный запуск кучи кода. Я нашёл лишь пару вменяемых туториалов на английском, которые в одном посте учили, как подружить MVC, Security и Hibernate.

      Согласитесь, что валидацию можно прикрутить позднее, с редактированием данных тоже повозиться после начального запуска системы.

      Можете пример считать ступенькой к изучению официальных мануалов по технологиям, в которых всё описано уже детально.
      • 0
        Про это написано как минимум в трех книгах которые я читал к примеру в
        Spring in Action
        Spring Enterprise Recipes
        Pro Spring 2.5

        Плюс есть такая штука как Pet Clinic и собственно Reference. Так что увы ничего нового или оригинального чего нет в интернете я тут не вижу. А вот отсутствие валидации и обновления и редактирования данных увы вижу.
        • 0
          Ок, я готов услышать ваши пожелания по тематике второй части данной статьи.
          Валидация, редактирование данных.

          Напишу пост, будем обсуждать.

          Ну и чуть-чуть не в тему.
          На хабре очень удобно писать статьи (мне нравится редактор и подход к публикации постов, аудитория), но имхо конструктивных комментариев по сабжу больше можно услышать всё-таки в тематических комьюнити.
          • 0
            Как я уже писал это: валидация данных, редактирование данных, редактирование малого объема данных (это где в форме отображаются два поля из десяти), использование REST, реализация своего UserDetailsService далеко не всегда подходит стандартный источник данных, использование GenericDAO, что такое Transaction propagation и зачем оно нужно. Достаточно? :]

            PS Если что я в свое время писал как сделать свое представление в Spring и использование ModelAttribute при редактировании.
  • +3
    А почему бы нам не использовать Spring Roo, который избавит нас от нудного написание DAO, Контроллеров, сущностей?
    • 0
      Где-то в ru_java я прочитал рекомендуемый к использованию в веб стек технологий:
      Core Java (I/O, Collections, Threads),
      Spring 3 (MVC, Security),
      JPA на базе Hibernate,
      Freemarker/JSP.

      С ним согласен, от него и пляшу. Если вы расскажете преимущества использования Roo, я охотно поменяю свою позицию.
      • +1
        Ну, вероятно тогда roo просто не существовал ))
        По крайней мере, вероятно вам стоит о нем почитать.
        Там, конечно, к core java прибавляется aspectJ, но ИМХО это не криминал.
      • +2
        Прежде чем так писать неплохобы почитать что такое Roo.
        Собственно Roo никак не относится к тому стеку что вы описали. Да и вообще это не технология.
        Это удобное скриптовое описание проекта.
        Одной строчкой описываете вашу ентити, затем по строчке на каждое поле.
        В результате генерится проект с объектами, что убирает нудное начальное описание всего.
        Также генерится по желанию конфиг хибера для доступа к БД.
        Ну и скаффолдинг никто не отменял. Все очень удобно.
        А потом получившуюся болванку можно уже руками дописывать до нужного стостояния.
        И что самое интересное — все что вы допишете руками подхватится Roo…
        Т.е. если через какое-то время вам понадобится еще одна ентити например, то вы просто в консоли Roo наберете команду создать ентити и все…
        В общем это скриптовый инструмент управления проектом… причем очень толковый и удобный.
        Который не заменяет что-то, а дополняет существующие инструменты.

        Единственно что расстраивает, это то, что он еще версии 1. Т.е. он очень активно развивается и меняется. А это непозволяет пока его юзать в продакшене.
        • 0
          В таком случае Roo — это инструмент, к которому следует присмотреться.

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

          Спасибо вам за обстоятельный комментарий.
          • 0
            «офтопик»
            Начинающим конечно надо все руками делать… но есть один ньюанс.
            Сейчас, для бизнеса, все большую роль играет так назваемый «тайм ту продакт».
            Т.е. не так важно качество как время его запуска в производство.
            Отсюда столько генераторов всего что только можно…
            и в этих условиях многие начинающие разработчики просто непонимают что делают.
            Они научились запускать генераторы и гуевые дизайнеры… и для получения результата им больше ничего ненадо… а бизнес поддерживает это монетой…
            А потом мы удивляемся, что 4-х процессорный сервак с 16 гигами памяти ложится от 100 пользователей…
            В общем грустно это… думаю время настоящих джедаев потихоньку проходит…
            • 0
              А как же всякие ERP, биллинг-системы? Джедаи пока-что нужны. Ну а про копроэкономику и её последствия в сети уже написали целые трактаты.
          • 0
            Думаю надо добавить, что кроме автоматизации написания скучных сущностей и контроллеров, Roo еще умеет генерировать файндеры — методы, которые позволяют искать что-то по параметрам. И уж эти файндерыгенерируются просто отлично, причем очень гибко.
            И еще Roo позволяет не думать о том, как работает база данных — все сущности нашей программы автоматически генерируются в нашей базе, что тоже весьма удобно (ИМХО, конечно)
        • 0
          Ну, уже 1.1 ))
          В нем добавили еще такой крутой штук, как реверс инжиниринг базы данных.
          А значит можно разрабатывать с уже готовой базой )
        • 0
          Соглашусь, сейчас в большинстве случаев очень критична гибкость на старте проекта, когда сам не понимаешь, что должно получиться в итоге (прототипирование). А вот уже когда удачная концепция нащупана (обычно это сопровождается ростом нагрузки), пора приниматься за оптимизацию. На этом этапе гибкости требуется меньше, архитектура становится более монолитная (заточенная под конкретные задачи). Думаю, это типичный цикл для приложений.
    • 0
      К примеру потому что Roo очень активно использует аспекты как результат то что он генерит это кхм сильное.
      • 0
        А мне удобно с ним работать и аспекты его не так уж и плохи, а уж генерация файндеров — это вообще что-то потрясающее.
        • 0
          Ну вкус и цвет фломастеры разные ;) Шибко много их там с моей точки зрения просто.
          • 0
            Ну так никто не мешает сделать push-in рефакторинг, ни одного аспекта не останется
            правда и ру работать перестанет.
            но можно сбэкапиться на всякий
  • +1
    Спасибо! И поддержу изпользования Roo. По сути будет тоже самое как у Вас, но многое он Вам сгенерит сам.
    Это не еще одна технология, а метод генерации классов и связи между ними
  • 0
    Нужно где-то прописывать сервисы и дао, чтобы спринг их нашел? Или он автоматом знает, что в пакете services или dao нужно искать классы для включения их в IoC движок?
    • 0
      в файле root-context.xml
      <context:component-scan base-package="net.schastny.contactmanager.dao"/>
      <context:component-scan base-package="net.schastny.contactmanager.service"/>
      


      Ну а в классах:
      @Component
      

      или

      @Service
      

  • +7
    Тонны xml конфигов, помы, мавены, хуявены, аннотации, мапингы, какие-то слои, DAO, сервисы, 3 фреймворка, отдельная система логирования, которую опять настраивать. Плюс сборка проекта мавеном и многочисленные компиляции. Это ад и чистилище для нормального веб-разработчика.
    А ну и мануальчик на несколько листов А4 со скриншотиками и 11 пунктами для тупейшего веб-приложения, которое пишется, используя правильные для веб-разработки инструменты, за 10 минут.

    Зачем писать веб-приложения на Java?

    <_valexey_> пока скачаешь одну библиотеку, пока другую, пока их xml конфигом на полметра склеишь, пока маппинг для hibernate настроишь, пока базу нарисуешь, пока веб-сервисы поднимешь
    <_valexey_> вроде и hello world пишешь, а уже две недели прошло и всем кажется, что это учетная система для малого бизнеса

    © ibash.org.ru/quote.php?id=13399

    А ну и ещё кто-то умный сказал предназначение Java:
    Java is a DSL for converting large XML files into Stack Traces.


    • +1
      Всё так и есть, как вы сказали.
    • +1
      Велкам ту зе ентерпрайз-ворлд. Ты прям как в первый раз это увидел :)
      • 0
        Мне так никто и не рассказал сакрального смысла понятия«ынтерпрайз» :(
        Быть может, «ынтерпрайз» — это когда делаешь простейшее приложение несколько месяцев и потом берешь за это приложение кучу денег?
        • +1
          В первую очередь это действительно долгая жизнь приложения, большое количество кода и большое количество программистов. К примеру Spring за счет слабой связности позволяет без каких либо серьезных последствий добавлять функционал и осуществлять рефакторинг приложения.
    • 0
      Поэтому сайтеги никто на javaEE практически не делает
    • +1
      А чем вас не устаривает Maven? Что вы предлагаете в альтернативу? Как по мне Maven это хорошее решение, когда проект вырастает из хомпаги… Или когда работаете в команде. Все пытаюстся его повторить — для питона, пхп, руби, но я еще не видел удачных решений.

      Чем вам не нравятся аннотации? Опять же в джаного они тоже появился, потому что это удобно. Очень удобная штука как замена XML конфигов. Так что тут вы тоже не правы.

      Всё остальное это EE, но это не означает, что на Java нельзя сделать хорошую платформу для удобной и простой разработки. Например, я сейчас этим занимаюсь на базе Tapestry 5 (отличный веб-фреймворк, но нужно кое-что допилить) делаю простую и удобную платформу, где нет кучи XML конфигов и прочего J2EE оверхеда.
    • +1
      вот поэтому я и люблю SpringRoo
      Все то же самое делается в двадцать строк ))
      А отальное генерится автоматически )
      • 0
        В идеале веб разработчику нужно иметь инструмент, где для создания сайта пишем всего одну строку: «Сайт!».
        Остальное генерится автоматически.

        Хотим магазин с интеграцией в фейсбуке, пишем: «Сайт! Интеграция: фейсбук.»

        Такое время придёт, и Spring Roo, в котором для создания приложения нужно аж двадцать строк, объявят вне игры.

        • 0
          Еще одна причина, почему многие остаются на PHP. Тут у нас поле не паханое, есть куда направить творческие и интелектуальные ресурсы…
          • 0
            Совсем не понятно, что вы хотели сказать )
    • +2
      На Java не надо писать веб-сайты. На нем надо писать сложные веб-приложения, тогда и будет стрелять. Иначе же использование java выливается в попытку БЕЛАЗом перевозить тачку песка.
      • 0
        Чего такого сложного должно быть в веб-приложении, чтобы выбрать Java?
        • +2
          Сложная и длинная бизнес-логика. К примеру внутренняя система автоматизации предприятия типа SAP. Java заточена именно под такие большие программные комплексы.
  • 0
    Я бы в пример ещё валидацию через JSR 303 прикрутил для полноты картины.
    • 0
      Хорошо. В следующем посте рассмотрю валидацию и редактирование данных, может быть использование Roo. Хотя это наверно должно быть два разных топика.

      Чего на ваш взгляд ещё не хватает, что можно было бы дописать во второй части?
  • 0
    Спасибо за статью, только файлы не все открываются.
    • 0
      моя ошибка, все открывается. Автору спасибо!
  • 0
    великолепно! большое дело сделали, спасибо!
  • 0
    А почему javax.persistence- аннотации использованы? Это альтернатива ...hbm.xml-файлам?
    • 0
      Хибернейт выступает в качестве JPA провайдера. Не понравится хибер, можно заменить на другую библиотеку, реализующую Java Persistence API.
  • +1
    развитие проекта (если можно так сказать)
    habrahabr.ru/post/145158/
    habrahabr.ru/post/171911
  • 0
    Часть 4, добавляем REST-сервис habrahabr.ru/post/173593
  • 0
    В концах jsp страниц какие-то странные фрагменты, похоже на запакованный javascript. Малварь?
    • 0
      Спасибо, убрал.
  • 0
    И спустя годы ваш пост помогает в освоении этой связки :)
  • 0
    У меня тут есть 2 места где посвечивает красным и никак не могу решить проблему:
    1) файл «contact.jsp» строка "/logout" />">" где подсвечивает красным "/logout"
    2) файл «login.jsp» строка "/index" />">">" где подсвечивает красным "/index"
    Кто знает как решить проблему?

    И еще: папка «resources» должна быть в папке «WEB-INF» или в папке «main»?

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