Онлайн проект Topjava
- Не стоит стремится прочитать все ссылки урока, их можно использовать как справочник. Гораздо важнее пройти весь материал урока и сделать Домашнее Задание
- Обязательно посмотрите правила работы с патчами на проекте
- Код проекта обновляется и не всегда совпадает с видео (можно увидеть как развивался проект). Изменения в проекте указывается после соответствующего патча.
Материалы занятия (скачать все патчи можно черезЕго прямая замена Download папки patch)
- Apply 1-1-HW0-stream.patch
Изменения в проекте: переименовал классы
UserMeal*в более красивыеMeal*
- Apply 1-2-HW0-cycle.patch
Изменения в проекте:
map.getOrDefaultземенил наmap.merge,forзаменены наforEach
что делает метод
Map.merge?
никогда не надо ленится зайти в код Map.merge и почитать там javadoc. Когда, если не сейчас?
что означает
Integer::sum?
это ссылка на метод, сокращенная форма лямбды. IDEA иногда предлагает замену, например
m->m.getCalories() заменяет на Meal::getCalories.
почему не использовать в
TimeUtilметодыisBefore/isAfter?
это строгие (excluded) сравнения, а нам также нужны краевые значения
В
MealsUtilу нас где-то есть ключевое словоfinal, где-то нет. В чем разница?
В проекте (Wrike.com) final был обязательным (в сеттингах IDEA галочка стояла). Но это скорее исключение, чем правило в проектах java (в Java 8 вообще ввели эффективный финал, те по факту). Во всех новомодных языках переменные final по умолчанию, а в java нужно помнить и везде добавлять, утомительно. Но если приучитесь- хуже не будет. Я обычно ставлю там, где важно по смыслу (если не забываю).
- Обзор популярности инструментов и технологий Java за 2014 г.
- Обзор популярности инструментов и технологий Java за 2016 г.
- Видео "Приложение Spring Pet Clinic"
- Приложение Spring Pet Clinic.
- Demo Spring Pet Clinic
4. Maven.
- Среда сборки проектов Maven.
- The Central Repository
- Настройка пропертей Maven: кодировка, java version, зависимости, maven-compiler-plugin
- The Reactor. Snapshots
- Недостатки Maven. Другие инструменты сборки.
- Справочник:
- Apply 1-3-switch-to-war.patch
Обновил сервлеты до версии 3.1 (Tomcat 8 использует это API, хотя для нас не принципиально, т.к. мы никакие фичи 3.x Servlet API не используем)
Сервлет добавляется в следующем патче, те в web.xml он будет подчеркиваться красным.
- Apply 1-4-add-servlet-api.patch
Если зависимость servlet-api не подтянулсаь, обновите maven проект.
- Apply 1-5-forward-to-redirect.patch
Проверка, кто занял порт в Windows (в случае проблем с запуском и дебагом на портах 8080, 8000)
- Tomcat Home Page
- Сервлеты.
- Настройка и деплой в Tomcat. Tomcat manager. Remote debug.
- Запуск Tomcat из IDEA. Динамическое обновление без передеплоя и Application context
- Redirect, Forward, Servlet context
- Томкат менеджер: http://localhost:8080/manager
- Наше приложение: http://localhost:8080/topjava
- Наш сервлет: http://localhost:8080/topjava/users
- Справочник:
- Отладчик IntelliJ IDEA
- Yakov Fain: Intro to Java EE. Glassfish. Servlets (по русски)
- Yakov Fain: HTTP Sessions, Cookies, WAR deployments, JSP (по русски)
- Golovach Courses: Junior.February2014.Servlets
- Remotely debug on tomcat from IDEA
- Java Server Page
- Java объекты, доступные в JSP
- Java Server Pages (JSP)
6. Логирование.
- Apply 1-6-logging.patch
установите переменную окружения на TOPJAVA_ROOT на корень проекта и перезапустите IDEA
изменения в проекте: убрал
LoggerWrapperи логирую напрямую в логгер SLF4J. При логгировании через вспомогательный класс, в логе теряется имя исходного класса.
удалил зависимость
jul-to-slf4j. Она нам не нужена и, согласно видео Владимира Красильщика про логирование, она замедляет работу
- Java Logging: история кошмара
- Ведение лога приложения
- Log4j, Logback
- Добавление зависимостей логирования в проект.
- Конфигурирование логирования. Настройка Live Template.
- Тестирование логирования в сервлете.
- Что нужно изменить в
pom.xml, чтобы перейти с logback на log4j ?
- Apply 1-7-remote-jmx.patch
Для подключения к Remote Process (
localhost:1099) положитьsetenv.batв$TOMCET_HOME/bin.
- Управление логированием по Java Management Extensions.
Используются ли еще где-то в реальной разработке JSP, или это уже устаревшая технология? Заменит ли ее JSF (https://javatalks.ru/topics/38037)?
JSF и JSP- разные ниши и задачи. JSP- шаблонизатор, JSF- МVС фреймворк. Из моего опыта- с JSP сталкивался в 60% проектов. Его прямая замена: http://www.thymeleaf.org (в Spring-Boot по умолчанию), но в уже запущенных проектах встречется достаточно редко. JSP не умирает, потому что просто и дешево. Кроме того включается в большнство веб-контейнеров (в Tomcat его реализация Jasper)
JSF- sun-овский еще фреймворк, с которым я ни разу не сталкивался и особого желания нет. Вот он как раз, по моему мнению, активно замещается хотя бы javascript фреймворками (angular, ember, react).
А зачем мы использовали logback? Почему SLF4J нас не устроило? Почему реализация логирования не log4j?
SLF4J-API это API. Там есть только пустая реализация org.slf4j.helpers.NOPLogger (можно посмотреть в исходниках). Logback для новых проектов стал стандарт. spring-petclinic и spring-boot используют его.
Домашнее задание HW01 (накатывает патчи урока, коммитим/пушим в master и после делаем ветку HW01 от последнего патча):
- По аналогии с
UserServletдобавитьMealServletиmealList.jsp.- Задеплоить приложение (war) в Tomcat c
applicationContext=topjava(приложение должно быть доступно по http://localhost:8080/topjava) - Попробовать разные деплои в Tomcat, remote и local debug
- Задеплоить приложение (war) в Tomcat c
- Сделать отображения списка еды в jsp, цвет записи в таблице зависит от параметра
isExceeded(красный/зеленый).- Время выводить без 'T', список выводим БЕЗ фильтрации, поле
userв классMealНЕ добавляем. - Вариант реализации:
- из сервлета преобразуете еду в памяти в
List<MealWithExceeded>; - кладете список в запрос (
request.setAttribute); - делаете forward на jsp для отрисовки таблицы (при redirect аттрибуты теряются).
- из сервлета преобразуете еду в памяти в
- Деплоиться лучше как
war exploded: нет упаковки в war и при нажатой кнопкеUpdate Resources on Frame Deactivationможно обновляться css, html, jsp без передеплоя. При измененииweb.xml, добавлении методов, классов необходим redeploy. - В
JSPдля цикла можно использоватьJSTL tag forEach. Для подключенияJSTLвpom.xmlи шапку JSP нужно добавить:
- Время выводить без 'T', список выводим БЕЗ фильтрации, поле
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
- Интернет-приложения на JAVA
- HTTP 1.0 vs 1.1
- JSP
- JSTL для написания JSP страниц
- JSTL: Шаблоны для разработки веб-приложений в java
- JSTL LocalDateTime format
- Хранение в памяти будет одна из наших CRUD реализаций (позже будет JDBC, JPA и DATA-JPA).
- Работать с реализацией через интерфейс, который не должен ничего знать о деталях реализации (Map, DB или что-то еще).
- Добавить поле
idвMeal/ MealWithExceedи реализовать генерацию счетчика, учитываем многопоточность сервелтов! - Сделать форму редактирования в JSP: AJAX/JavaScript использовать НЕ надо, делаем через
<form method="post">иdoPost()в сервлете. - Для ввода дат и времени можно использовать html5 типы, хотя они поддерживаются не всеми браузерами (протестировать свой браузер). В конце курса мы добавим DateTimePicker jQuery plugin, который будет работать на всех браузерах.
- Simple CRUD using Servlet/JSP
- Обзор java.util.concurrent.*
После выполнения ДЗ обязательно проверьте решение на ошибки
Не попадаю на страничку/брекпойнт в сервлете.
- внимательно проверь url и applicationContext (Application Context должен быть тот же, что и url приложения: wiki IDEA)
- посомтрите в task manager: возможно запущено несколько JVM и они мешают друг другу. Лишние java приложения убить.
Приложение не видит TOPJAVA_ROOT.
После выставления переменной окружения IDEA нужно рестартовать. Проверить, видит ли java переменную окружения можно так: System.getenv("TOPJAVA_ROOT"). Еще вариант: добавить -DTOPJAVA_ROOT=... в опции запуска приложения, тогда она доступна из java как System.getProperty("TOPJAVA_ROOT").
Проблемы с кодировкой в POST (кракозябры).
Возможное решение - выставьте кодироку ДО первого чтения из request:
protected void doPost(HttpServletRequest request, ...) {
request.setCharacterEncoding("UTF-8");
Если сервлет тыкают несколько пользователей / несколько браузеров, какого должно быть поведение? Нужно ли что-то делать с сессиями?
Нужно делать реализацию хранения (в Optional) многопоточной (оно одно на всех и шарится между пользователями). Cессии пока не используем (начнутся, когда будет прикручивать авторизацию).
Предпочтительнее ли создавать новый объект
Mealпри каждом update?
Обычно так, особенно если используется Spring MVC. Если при обновлении не создавать копию, то нам сохраненный в памяти объект могут попортить. Вопрос скорее доверия к коду- если проект большой и людей над ним трудится много, то обычно нужно копировать.
Почему теряются атрибуты при передаче на сервлет:
http://localhost:8080/topjava/meals?action=add&...иreq.getAttribute("action")= null ?
См. Difference between getAttribute() and getParameter(). Отсюда также следует, что при редиректе что аттрибуты теряются.
- Хранить нужно
Mealи конвертировать ее вMealWithExceedкогда отдаем список на отображение в JSP. Иначе при редактировании любой записи или изменении юзером своей нормыcaloriesPerDayнужно будет пересчитывать все записи юзера. - Стили
colorможно применять ко всей строке таблицыtr, а не каждой ячейке. DateTimeFormatterможно сделать один заранее (он потокобезопасный в отличии отSimpleDateFormatter), а не создавать новый при каждом запросе.- Реализаций интерфейса хранения будет несколько. Нужно учитывать это в названии класса.
- Если в названии класса есть
Meal, не нужно использовать слово meal в методах класса. - В
web.xmlпринято группировать сервлет со своим маппингом - Не размещайте никакую логику (форматирование, счетчики) в бинах, где хранятся только данные (
Meal, MealWithExceed) - Еще раз- детали реализации в памяти не должны быть никому видны. Те НЕ НАДО счетчик размещать в
MealилиMealServletилиMealsUtil, в базе же он будет по другому генерится. Иvolatileпри ++ не помогает от многопоточности. Почему? Обратите также внимание на то, чтобы реализация вашей коллекции для хранения еды была также многопоточной. - Не делайте дублирование кода
MealsUtil. Возможно вам пригодятся константыLocalTime.MINиLocalTime.MAX - Не дублируйте строки в
jsp. Посмотрите на тернарный оператор.


