Онлайн проекта Topjava
- Браузер кэширует javascript и css. Если изменения не работают, обновите приложение в браузере по Ctrl+F5
- При удалении файлов не забывайте делать clean:
mvn clean package
- Из за баги в FireFox при пустом ответе от Ajax в консоль браузера выводится:
Ошибка синтаксического анализа XML: корневой элемент не найден
. Лечится@ResponseStatus(value = HttpStatus.NO_CONTENT)
.- Уменьшил отступы у навигационной панели. См. Bootstrap Spacing
1. HW8
Поправка к видео: в гриде bootstrap 12 колонок
- Все события сделал через
onlick
- Фильтр еды сделал в Bootstrap 4 Cards
- Удалил лишние классы, JSP и i18N
- Вместо глабальных переменных
ajaxUrl
,datatableApi
и одинаковой функции обновления таблицыupdateTable()
задаю их в объекте контекст, который передаю вmakeEditable()
как параметр
Можно ли было удаление делать без перезагрузки таблицы (удалением строки) и для редактирования брать данные со страницы, а не с сервера?
В многопользовательском приложении принято при изменении данных подтягивать все изменения с базы, иначе может быть несогласованность базы и UI (например когда пользователей редактируют несколько администраторов одновременно). В таблице еды наши пользователи видят только свои записи, но лучше для всех таблиц делать общий подход. Дополнительная нагрузка на базу тут совсем небольшая.
Добавил сброс фильтра
- Перенес метод
enable
вtopjava.users.js
и сделал стиль для пользователей через атрибутdata-userEnabled
- Меняю стиль
<tr>
ПОСЛЕ успешной обработки запроса черезdata-userEnabled
, при ошибке возвращаюchecked
в прежнее состояние- Убрал
init()
. При переводе таблицы на Ajax вместо него будетcreatedRow
. Атрибутыdata-userEnabled
добавляются при отрисовки таблицы в JSP
Move
ru.javawebinar.topjava.util.MealsUtil.DEFAULT_CALORIES_PER_DAY
toru.javawebinar.topjava.util.UserUtil
- Сделал интерфейс
HasId
от которого наследуютсяBaseTo
иAbstractBaseEntity
- Сделал проверку
id
вValidationUtil
на основеHasId
- Сделал в
ProfileRestController
обновление своего профиля черезUserTo
(нельзя изменять себе роли) и поправил тест
responseJSON
не выводится в случае его отсутствия (например при попытке добавить пользователья с дублирующимся email)- сделал конкатенацию ошибок через
StringJoiner
- при неверном формате email делается проверка
startsWith
, чтобы поле email не дублировалось в сообщении
- Spring Validation.
- Bean Validation
- Валидация формы по AJAX.
- JSR-303, 349
- @Valid @RequestBody + Error handling
- Java Bean Validation Basics
- Перешли на параметры Datatables в формате 1.10
- В
makeEditable()
больше нет манипуляций c DOM, которые требуются делать ПОСЛЕ отработки плагинаdatatable
, поэтому нам не обязательно вызывать ее в коллбэкеinitComplete
.
Что за дополнительный параметр (который каждый раз инкрементируется) появляется при запросе datatables данных по ajax (например
http://localhost:8080/topjava/ajax/admin/users/?_=1496156621129
) ?
Это защита datatables
от кэширования запроса браузером (например в IE).
- Добавил простую интернационализацию в JavaScript.
- на стороне сервера формируется
i18n
JavaScript массив с значениями, который затем используется для интернационализации в браузере- в модальном окне заголовок подменяется через
$('#modalTitle').html(..title)
Для тестирования локали можно поменять Accept-Language
. Для хрома в chrome://settings/languages
перетащить нужную локаль наверх.
Добавил функциональность logout
- Почему при логине как admin еда отдаются для user?
- Почему при логине как user не отображается список пользователей?
- Почему еда не редактируется?
Подсказка: поглядите вкладку Network в браузере.
Рефакторинг
- В
login.jsp
вместо атрибутов достаю параметры запроса (param.error/message
).- Закрыл доступ к
/login
для уже авторизованных в приложении пользователей (вspring-security.xml
изменилpermitAll
наisAnonymous
)- При нажании кнопок
Зайти как ...
сделал вход в приложение
- Принцип работы Spring Security
- Типы проксирования
- Dynamic Proxy API
- Конфликт проксирования Data Repository
- Security фильтры
- Cделал "честную" авторизацию в
RootControllerTest
(черезauthentication
в утильном методеTestUtil
)- Cделал
mockAuthorize
дляSpringMain
, в который не попадают фильтры
- Spring Security Test
- Интеграция со Spring MVC Test
- HttpBasic авторизация
- Тестирование контроллеров с помощью MockMvc (без spring-security-test)
11. Cookie. Session.
В куки попадает обычная строка JSESSIONID. Куда сериалиуется объект User?
Для хранения сосотяния сессии (например корзины покупателя) в Servlet API есть механизм хранения объектов сессии (грубо- мультимапмапа, которая достается из хранилища по ключу). При создании сессии на стороне сервера (через request.getSession
) создается кука JSESSIONID
, которая передается между клиентом и сервером и является ключом в хранилище объектов сессий. См. обработка сессий с помощью сервлетов
В
login.jsp
есть форма<form:form action="spring_security_check" ..>
Где такой url используется?
Это стандартный url для авторизации в spring-security
. Он его и обрабатывает.
Если не пользовать js, а писать UI на JSP, сообщения между ui и сервером будут в формате json? Это же будет JSON API?
Есть данные, которые передаются между клиентом и сервером в формате json или get/post с параметрами, есть стили взаимодействия клиента и сервера (REST, JSON API, JSON-RPC) и есть отрисовка UI: JSP, Javascript фреймворк, Thymleaf и пр. Не надо эти вещи путать между собой.
По умолчанию спринг работает с
UserDetailsService
, который должен возвращатьUserDetails
. Но мы не хотим стандартные, мы хотим свои, поэтому просто наследуем нашиUserServiceImpl
иAuthorizedUser
от соответствующих интерфейсов и реализуем недостающие методы, которые spring security и будет использовать?
Да. Сервис аутентификации конфигурится в spring-security.xml
<authentication-manager>
и должен реализовывать интерфейс UserDetailsService
. В spring-security есть его стандартные реализации, которые использовались до нашей кастомной UserServiceImpl
, например jdbc-user-service
использует реализацию JdbcUserDetailsManager
- 1: Реализовать для meal Binding/ Update/ Validation. Проверить работу при пустом значении
calories
. - 2: Перевести
meals.jsp
на работу по ajax. Стиль строки таблицы сделать в зависимости отexcess
, время отображать безT
. Добавить i18n. - 3: Починить meals тесты, добавить тест на неавторизованный доступ
-
4: Подключить datetime-picker к фильтрам и модальному окну добавления/редактирования еды
-
Попробуйте при запросах по REST оставить стандартный ISO формат (с разделителем
T
). То есть:- Отображение и редактирование еды на UI происходит без
T
(формат значений на UI можно увидеть во вкладке браузера Network) - Когда мы работаем по REST, в json и запросах формат даты ISO (с разделителем
T
) - Напомню, что параметры методов контроллера (даже собранные в объекты через Binding) парсятся конверторами спринга (
@DateTimeFormat
), а объекты json парсится Jackson и они никак не влияют друг на друга.
- Отображение и редактирование еды на UI происходит без
- 1: Проверьте, что при добавлении и редактировании пользователя и еды у вас корректно отображаются заголовки модального окна: "Добавить/Редактировать еду пользователя"
- 2: Не дублируйте
<c:forEach var='key' ...
i18n['${key}'] = ...
- 3: Для подключения css и js datetimepicker-а посмотрите в его jar (или поищите в проекте по Ctrl+Shift+N:
datetimepicker
) - 4: datetimepicker работает корректно в Хроме, если убрать в
type
в<input type="date/time/datetime-local" ..
- 5: Если появляются проблемы с JS типа
... is not defined
- обратите внимание на порядок загрузки скриптов и атрибутdefer
. Скрипты должны идти в нужном порядке. Если определяете скрипт прямо в jsp, он выполняется доdefer
скриптов. - 6: Не дублируйте обработку ошибок в
BindingResult
в ajax контроллерах - 7: Проверьте редактирование еды: открыть на редактирование и сохранить не должно приводить к ошибкам с форматом времени.
- 8: Проверьте в
RootController.meals()
, его нужно тоже поправить