Каждая HTTP-сессия определяется двумя вещами:
- Запросом от клиента (браузера)
- Ответом от сервера
Во фреймворках запрос и ответ обычно представляются двумя объектами — request
и response
.
Javalin тут пошел немного другим путем и объединил все в объекте ctx
, который передается каждому обработчику. Через этот объект можно получить любую информацию из HTTP-запроса или добавить данные в HTTP-ответ. В этом уроке вы узнаете, как работать с объектом ctx
и разберетесь, как устроена HTTP-сессия в этом случае.
Response
Метод ctx.result()
формирует тело ответа:
app.get("/", ctx -> {
ctx.result("Hello World");
});
По умолчанию данные отдаются с заголовком Content-Type: text/plain. Даже если мы передадим в ответе HTML, тип контента все равно не поменяется. Дело в том, что Javalin не анализирует, что мы отдаем. Поэтому нам придется поменять тип:
app.get("/", ctx -> {
ctx.contentType("text/html");
ctx.result("<h1>Hello Hexlet</h1>");
});
Если данные нужно отдать в виде JSON, то можно использовать метод ctx.json()
. Он формирует JSON и устанавливает Content-Type со значением, равным json:
app.get("/", ctx -> {
// Какой-то код формирования object
ctx.json(object);
});
Кроме тела ответа, можно еще установить заголовки и поменять код ответа:
app.get("/", ctx -> {
ctx.status(403);
ctx.header("KEY", "value");
});
Еще мы можем выполнить редирект:
app.get("/admin", ctx -> {
// Указываем статус вторым параметром
ctx.redirect("/", HttpStatus.forStatus(302));
});
Request
Данные запроса можно извлечь множеством методов. Обычно такие вещи смотрят по необходимости, поэтому заучивать их смысла нет. Рассмотрим несколько самых базовых методов:
app.get("/", ctx -> {
ctx.body(); // Тело запроса
ctx.bodyAsClass(clazz); // Тело запроса, сконвертированное из JSON в объект
ctx.header("Content-Type"); // Заголовок
ctx.uploadedFile("name"); // Загруженный файл
ctx.queryParamMap(); // Все параметры запросов
ctx.queryParam("name"); // Параметр запроса
ctx.formParamMap(); // Все параметры формы
ctx.formParam("name"); // Параметр формы
});
Параметры запроса
Параметры запроса не считаются частью маршрута и не влияют на выбор обработчика.
Это связано с тем, что они используются для разных вспомогательных целей — например, параметр page
обозначает страницу просматриваемого списка. В такой ситуации обработчик один и тот же, а вот данные — разные. Представим, что у нас есть вот такой код:
app.get("/users", ctx -> {
// Отдаем обратно url + query params
ctx.result(ctx.fullUrl());
});
А теперь посмотрим, что он выводит в лог в ответ на разные запросы из браузера:
/users
Request: GET [/users]
Matching endpoint-handlers: [GET=/users]
QueryString: null
QueryParams: {}
Response: [200 OK], execution took 2.34 ms
http://localhost:7070/users
/users?page=3
Request: GET [/users]
Matching endpoint-handlers: [GET=/users]
QueryString: page=3
QueryParams: {page=[3]}
Response: [200 OK], execution took 0.29 ms
http://localhost:7070/users?page=3
Во всех этих случаях фреймворк вызовет один и тот же обработчик, связанный с маршрутом /users. Фреймворк автоматически разбирает эти параметры и дает к ним удобный доступ через методы контекста:
app.get("/users", ctx -> {
var page = ctx.queryParam("page");
});
Параметры запроса не связаны с методом HTTP. Они могут приходить как на GET-запросы, так и на все остальные:
// post
app.post("/users", ctx -> {
var page = ctx.queryParam("page");
});
Автоматическая конвертация
В примере ниже вы видите переменную page
типа строка:
app.get("/users", ctx -> {
var page = ctx.queryParam("page");
});
С точки зрения HTTP, все переданные через него данные — это строки. Но с точки зрения внутренней логики все работает по-другому. На самом деле, параметры, которые мы передаем через HTTP-протокол, в большинстве случаев строками не являются.
Поэтому их нужно преобразовывать в строки. Для удобства работы Javalin предоставляет механизм для автоматической конвертации в нужный тип данных:
app.get("/users", ctx -> {
var page = ctx.queryParamAsClass("page", Integer.class).get();
});
Но даже этого бывает мало. Для примера представим, что страница не установлена. В таком случае мы должны задать значение по умолчанию, равное единице. Javalin позволяет это сделать:
app.get("/users", ctx -> {
var page = ctx.queryParamAsClass("page", Integer.class).getOrDefault(1);
});
Самостоятельная работа
- Откройте свой проект hexlet-javalin
- Добавьте туда обработчик, который будет обрабатывать GET-запросы по адресу /hello и выводить приветствие. Обработчик должен использовать параметр запроса
name
и приветствовать пользователя по имени. Например, при запросеGET /hello?name=John
нужно вывести Hello, John! или Hello, World!, если параметра нет - Запустите приложение и откройте страницу в браузере
- Поэкспериментируйте с разными значениями параметра запроса
- Залейте изменения на GitHub
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.