-
Notifications
You must be signed in to change notification settings - Fork 35
Lesson 9
Онлайн проекта 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_DAYtoru.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.
- на стороне сервера формируется
i18nJavaScript массив с значениями, который затем используется для интернационализации в браузере- в модальном окне заголовок подменяется через
$('#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(), его нужно тоже поправить
Правка
Разбор домашнего задания HW8
Вопрос: