KriegeR
@KriegeR
Software Engineer

Нужен совет по J2EE?

Добрый день, Хабрасообщество!



Очень неудобно просить, но все же… Изучаю я серверную Java не очень много. Так как наставника, который бил бы по рукам, кричал и ругал за быдлокодинг, у меня нет, то прошу посмотреть опытным глазом на мою поделку.



Собственно, Вы ее найдете тут.

Хотелось бы услышать все моменты, где я делаю не так и не то. Побольше конструктивной критики и ссылок на то, как делать правильно. Интересует все — от правильности пространства имен, до моментов, где система не оптимизирована. А еще Ваши советы/пожелания/замечания.



Заранее очень благодарен!
  • Вопрос задан
  • 3902 просмотра
Пригласить эксперта
Ответы на вопрос 5
YasonBy
@YasonBy
(Я посмотрел только MakeTransactionServlet и UMakeTransactions.jsp, для других файлов должно быть похоже).

У Вас недостаточно чётко разделены модель (БД), вид (JSP) и контроллер (сервлет).
Сейчас происходит так:
  1. сервлет получает запрос,
  2. проверяет права доступа,
  3. если всё ок — выполняет транзакцию согласно параметрам запроса,
  4. делает sendRedirect на JSP
  5. браузер вместо HTML с результатами получает ответ от сервлета: «HTTP 302, иди смотри JSP»
  6. браузер спрашивает у сервера JSP
  7. JSP получает запрос
  8. проверяет права доступа (это обязанность сервлета!)
  9. осуществляет запрос к БД (кажется, здесь, я c Hibernate знаком поверхностно) — это тоже обязанность сервлета,
  10. генерит HTML с результатом для браузера.

Прежде всего, пункты 4-6 лишние: сервлет должен передать запрос напрямую в JSP, а не прося браузер сделать второй запрос к JSP (подробнее об этом ниже).

Во-вторых, если у Вас есть сервлет, то работать с БД должен только он; прямого доступа к БД из JSP быть не должно (так как это противоречит концепции MVC). Доступ к JSP должен быть только у сервлета, нужно запретить к ней прямой доступ извне (это можно сделать, переместив JSP куда-нибудь под WEB-INF). Тогда и проверки прав доступа будет достаточно одной — в сервлете; и не будет нужен второй запрос от браузера. Передачу данных из сервлета в JSP можно делать через request.setAttribute().

Теоретические основы описаны здесь в разделе «Integrating Servlets and JSP Pages», вот краткая суть:
The servlet acts as a controller responsible for processing requests and creating any beans needed by the JSP page. The controller is also responsible for deciding to which JSP page to forward the request. The JSP page retrieves objects created by the servlet and extracts dynamic content for insertion within a template.
Вообще, конечно, хорошо бы изучить статью целиком.

В результате процесс будет выглядеть так:
  1. сервлет получает запрос,
  2. проверяет права,
  3. если права ОК — выполняет транзакцию,
  4. получает обновлённые данные из БД,
  5. складывает эти данные в отдельный объект (или несколько объектов, см. «beans» в цитате выше),
  6. присоединяет этот объект к запросу:
    request.setAttribute("resultsForJsp", bean)
  7. и передаёт запрос в JSP:
    getServletContext().getRequestDispatcher("/WEB-INF/jsp/myView.jsp").forward(request, response)

    В отличие от sendRedirect, forward просто передаёт запрос на обработку другому сервлету/JSP (сохраняя установленные ранее атрибуты запроса); sendRedirect же возвращает указание браузеру запросить другой адрес (атрибуты запроса теряются, выживает только сессия).
    Путь /WEB-INF/... доступен только «для своих» изнутри сервлет-контейнера, браузер туда никак не попадёт — поэтому проверка поступающих данных (в том числе прав доступа) не нужна: её уже сделал сервлет.
  8. JSP получает запрос с уже готовыми к показу данными,
  9. генерит HTML для браузера.

А ещё, старайтесь не использовать в JSP скриптлеты (<% java-код %>) — это считается моветоном, поскольку:
1) засоряет HTML Java-кодом, и
2) часто указывает на перенос части функций контроллера (сервлета) в вид (JSP).
Вместо скриптлетов лучше использовать JSTL.
Например, строки 45-52 из UMakeTransactions.jsp могли бы выглядеть так:
<c:forEach var='item' items='${resultsForJsp.items}'>
	<option value="<c:out value='${item.item_id}'/>"><c:out value='${item.item_name}'/>
</c:forEach>
Ответ написан
Комментировать
Fafnir
@Fafnir
Используйте maven (родительский pom и дочерние для под-проектов). Используйте Spring. Если хотите что-то поделать для веба, советую Play! c ним будем проще начать. Ну и удачи!
Ответ написан
Комментировать
@antalus
1. Как уже советовали — освойте maven2: разбивайте проект на модули с разной ответственностью; перенесите ресурсы в ресурсные папки, используйте jetty maven plugin для отладки всего веб-приложения и т.д. и т.п. Множество возможностей и дополнительных плагинов буквально на все случаи жизни.
2. Не надо хранить в SVN то что можно сгенерить из исхоодников — к примеру, эклипсовские папки. Проектные файлы для любых популярных IDE можно сгенерировать из pom-ов maven2. Аналогично с зависимостями. maven2 скачает за вас jar-ники которые вам нужны, положит в папку WEB-INF/lib и соберет war. За информацией — maven.apache.org/guides/getting-started/index.html
3. Именование пакетов. Стандартная практика — создавать пакеты в стиле com.mycompany.myproject.orm, com.mycompany.myproject.util и т.д., не бойтесь создавать вложенность.
4. Именование полей класса, user_id — плохая идея, используйте везде camel case. В целом, изучите и придерживайтесь Java Code Conventions java.sun.com/docs/codeconv/CodeConventions.pdf
5. Для небольшого тестового проекта рекомендую использовать вместо Оракла встраиваемую базу, например HSQLDB
Ответ написан
@Zamorozka
На вкладке Downloads только JPG со схемой БД и архив со скриптом sql.
J2EE я там не увидел.
Ответ написан
KriegeR
@KriegeR Автор вопроса
Software Engineer
Ну и, на всякий случай, добавил WAR с исходниками.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы