Skip to content

Latest commit

 

History

History
191 lines (137 loc) · 20.4 KB

lesson09.md

File metadata and controls

191 lines (137 loc) · 20.4 KB

Онлайн проекта Topjava

  • Браузер кэширует javascript и css. Если изменения не работают, обновите приложение в браузере по Ctrl+F5
  • При удалении файлов не забывайте делать clean: mvn clean package

error Правка

Apply 9_0_fix.patch

  • Из за баги в FireFox при пустом ответе от Ajax в консоль браузера выводится: Ошибка синтаксического анализа XML: корневой элемент не найден. Лечится @ResponseStatus(value = HttpStatus.NO_CONTENT).
  • Уменьшил отступы у навигационной панели. См. Bootstrap Spacing

hw Разбор домашнего задания HW8

video 1. HW8

Поправка к видео: в гриде bootstrap 12 колонок

Apply 9_01_HW8.patch

  • Все события сделал через onlick
  • Фильтр еды сделал в Bootstrap 4 Cards
  • Удалил лишние классы, JSP и i18N
  • Вместо глабальных переменных ajaxUrl, datatableApi и одинаковой функции обновления таблицы updateTable() задаю их в объекте контекст, который передаю в makeEditable() как параметр

question Вопрос:

Можно ли было удаление делать без перезагрузки таблицы (удалением строки) и для редактирования брать данные со страницы, а не с сервера?

В многопользовательском приложении принято при изменении данных подтягивать все изменения с базы, иначе может быть несогласованность базы и UI (например когда пользователей редактируют несколько администраторов одновременно). В таблице еды наши пользователи видят только свои записи, но лучше для всех таблиц делать общий подход. Дополнительная нагрузка на базу тут совсем небольшая.

Apply 9_02_HW8_clear_filter.patch

Добавил сброс фильтра

Apply 9_03_HW8_enable_disable.patch

  • Перенес метод enable в topjava.users.js и сделал стиль для пользователей через атрибут data-userEnabled
  • Меняю стиль <tr> ПОСЛЕ успешной обработки запроса через data-userEnabled, при ошибке возвращаю checked в прежнее состояние
  • Убрал init(). При переводе таблицы на Ajax вместо него будет createdRow. Атрибуты data-userEnabled добавляются при отрисовки таблицы в JSP

Занятие 9:

Apply 9_04_binding.patch

Move ru.javawebinar.topjava.util.MealsUtil.DEFAULT_CALORIES_PER_DAY to ru.javawebinar.topjava.util.UserUtil

Apply 9_05_update.patch

  • Сделал интерфейс HasId от которого наследуются BaseTo и AbstractBaseEntity
  • Сделал проверку id в ValidationUtil на основе HasId
  • Сделал в ProfileRestController обновление своего профиля через UserTo (нельзя изменять себе роли) и поправил тест

Apply 9_06_validation.patch

  • responseJSON не выводится в случае его отсутствия (например при попытке добавить пользователья с дублирующимся email)
  • сделал конкатенацию ошибок через StringJoiner
  • при неверном формате email делается проверка startsWith, чтобы поле email не дублировалось в сообщении

Apply 9_07_datatable_via_ajax.patch

  • Перешли на параметры Datatables в формате 1.10
  • В makeEditable() больше нет манипуляций c DOM, которые требуются делать ПОСЛЕ отработки плагина datatable, поэтому нам не обязательно вызывать ее в коллбэке initComplete.

question Вопрос:

Что за дополнительный параметр (который каждый раз инкрементируется) появляется при запросе datatables данных по ajax (например http://localhost:8080/topjava/ajax/admin/users/?_=1496156621129) ?

Это защита datatables от кэширования запроса браузером (например в IE).

Apply 9_08_js_i18n.patch

  • Добавил простую интернационализацию в JavaScript.
    • на стороне сервера формируется i18n JavaScript массив с значениями, который затем используется для интернационализации в браузере
    • в модальном окне заголовок подменяется через $('#modalTitle').html(..title)

Для тестирования локали можно поменять Accept-Language. Для хрома в chrome://settings/languages перетащить нужную локаль наверх.

Apply 9_09_min_form_login.patch

Добавил функциональность logout

question Мои вопросы:

  • Почему при логине как admin еда отдаются для user?
  • Почему при логине как user не отображается список пользователей?
  • Почему еда не редактируется?

Подсказка: поглядите вкладку Network в браузере.

Apply 9_10_jsp_form_login.patch

Рефакторинг

  • В login.jsp вместо атрибутов достаю параметры запроса (param.error/message).
  • Закрыл доступ к /login для уже авторизованных в приложении пользователей (в spring-security.xml изменил permitAll на isAnonymous)
  • При нажании кнопок Зайти как ... сделал вход в приложение

Apply 9_11_auth_via_user_service.patch

Apply 9_12_spring_security_test.patch

Apply 9_13_test_fix.patch

  • Cделал "честную" авторизацию в RootControllerTest (через authentication в утильном методе TestUtil)
  • Cделал mockAuthorize для SpringMain, в который не попадают фильтры

question Ваши вопросы

В куки попадает обычная строка 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

hw Домашнее задание HW9

  • 1: Реализовать для meal Binding/ Update/ Validation. Проверить работу при пустом значении calories.
  • 2: Перевести meals.jsp на работу по ajax. Стиль строки таблицы сделать в зависимости от excess, время отображать без T. Добавить i18n.
  • 3: Починить meals тесты, добавить тест на неавторизованный доступ

Optional

  • 4: Подключить datetime-picker к фильтрам и модальному окну добавления/редактирования еды

  • Попробуйте при запросах по REST оставить стандартный ISO формат (с разделителем T). То есть:

    • Отображение и редактирование еды на UI происходит без T (формат значений на UI можно увидеть во вкладке браузера Network)
    • Когда мы работаем по REST, в json и запросах формат даты ISO (с разделителем T)
    • Напомню, что параметры методов контроллера (даже собранные в объекты через Binding) парсятся конверторами спринга (@DateTimeFormat), а объекты json парсится Jackson и они никак не влияют друг на друга.

error Проверка в HW09

  • 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(), его нужно тоже поправить