Хочешь уверенно проходить IT-интервью?

Мы понимаем, как сложно подготовиться: стресс, алгоритмы, вопросы, от которых голова идёт кругом. Но с AI тренажёром всё гораздо проще.
💡 Почему Т1 тренажёр — это мастхэв?
- Получишь настоящую обратную связь: где затык, что подтянуть и как стать лучше
- Научишься не только решать задачи, но и объяснять своё решение так, чтобы интервьюер сказал: "Вау!".
- Освоишь все этапы собеседования, от вопросов по алгоритмам до диалога о твоих целях.
Зачем листать миллион туториалов? Просто зайди в Т1 тренажёр, потренируйся и уверенно удиви интервьюеров. Мы не обещаем лёгкой прогулки, но обещаем, что будешь готов!
Реклама. ООО «Смарт Гико», ИНН 7743264341. Erid 2VtzqwP8vqy
Архитектура Web-приложений

Архитектура современных приложений состоит из отдельных модулей, как показано на рисунке выше. Эти модули часто называют Frontend и Backend. Frontend – это модуль, который отвечает за юзер-интерфейс и логику, которые предоставляется приложением при использовании. Так, например когда мы заходим в соцсети через браузер, мы взаимодействуем именно с FrontEnd-модулем приложения. То, как отображаются наши посты в виде сторисов или карточек, сообщения и другие активности реализуются именно в FrontEnd-модуле. А все данные, которые мы видим, хранятся и обрабатываются в Backend или серверной части приложения. Эти модули обмениваются между собой посредством разных архитектурных стилей: REST, GRPC и форматов сообщений – JSON и XML.
В этой статье мы напишем примитивную серверную часть социальной сети с использованием Spring Boot, запустим свой сервер, рассмотрим разные типы HTTP запросов и их применение.
Необходимое требование к читателю: умение писать на Java и базовые знания Spring Framework. Данная статья познакомит вас со Spring Boot и даст базовые понятия данного фреймворка.
Инициализация проекта
Чтобы создать Spring Boot проект, перейдем на страницу https://start.spring.io/ и выберем необходимые зависимости: в нашем случае Spring Web. Чтобы запустить проект, необходима минимальная версия Java 17. Скачиваем проект и открываем в любом IDE (в моем случае – Intellij Idea)

Spring Web
– зависимость, которая предоставляет контейнер сервлетов Apache Tomcat (является дефолтным веб-сервером). Проще говоря, сервлеты – это классы, которые обрабатывают все входящие запросы.
Открываем проект и запускаем.

Мы видим, что проект запустился и готов обрабатывать запросы на порту 8080 – Tomcat started on port(s): 8080 (http)
.
Теперь создадим свой первый класс – GreetingController
. Controller-классы ответственны за обработку входящих запросов и возвращают ответ.
Чтобы сделать наш класс Controller
, достаточно прописать аннотацию @RestController
. @RequestMapping
указывает, по какому пути будет находиться определённый ресурс или выполняться логика.
package io.proglib;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/greet")
public class GreetingController {
@GetMapping
public String greet() {
return "Hello";
}
}
Перезапускаем проект, и сервер готов уже обрабатывать наши запросы.
Открываем браузер по адресу http://localhost:8080/greet
и получаем следующий вывод.

Если отправить запрос по адресу http://localhost:8080/
, мы получим ошибку, т. к. по этому пути не определены логика обработки запроса и ресурсы.
Request Params
При отправке запросов мы часто используем переменные в запросе, чтобы передавать дополнительную информацию или же делать запросы гибкими. Параметр в запросе передаётся в конце адреса (=url
) сервера и указывается после вопросительного знака (=?
).
Например, http://localhost:8080/greet?name=Alice
. Параметр запроса является = name
cо значением = Alice
.
Чтобы обрабатывать переменную запроса, используется аннотация @RequestParam
. Параметры запроса могут быть опциональными или же обязательными. @RequestParam("name")
означает следующее: взять ту переменную из запроса, название которого равно name
.
@RestController
@RequestMapping("/greet")
public class GreetingController {
@GetMapping
public String greet(@RequestParam("name") String name) {
return "Hello, " + name;
}
}

Вдобавок, запрос может содержать несколько параметров.
Например, http://localhost:8080/greet/full?name=John&surname=Smith
. Параметры выделяются знаком &
. В этом запросе два параметра: name=John
и surname=Smith
.
Чтобы обработать каждый параметр запроса, нужно пометить каждую переменную @RequestParam
.
package io.proglib;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/greet")
public class GreetingController {
@GetMapping
public String greet(@RequestParam("name") String name) {
return "Hello, " + name;
}
@GetMapping("/full")
public String fullGreeting(@RequestParam("name") String name,
@RequestParam("surname") String surname) {
return "Nice to meet you, " + name + " " + surname;
}
}

Path Variable
PathVariable
по применению похож на @Request Param
. @PathVariable
также является параметром запроса, но используются внутри адреса запроса. Например,
RequestParam
– http://localhost:8080/greet/full?name=John&surname=Smith
PathVariable
– http://localhost:8080/greet/John
. В этом случае John
является PathVariable.
В запросе можно указывать несколько PathVariable, как и в случае RequestParam
package io.proglib;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/greet")
public class GreetingController {
@GetMapping
public String greet(@RequestParam("name") String name) {
return "Hello, " + name;
}
@GetMapping("/full")
public String fullGreeting(@RequestParam("name") String name, @RequestParam("surname") String surname) {
return "Nice to meet you, " + name + " " + surname;
}
@GetMapping("/{name}")
public String greetWithPathVariable(@PathVariable("name") String name) {
return "Hello, " + name;
}
}
Чтобы протестировать, открываем браузер и переходим по адресам: http://localhost:8080/greet/John/Smith
и http://localhost:8080/greet/John

Запрос с двумя параметризованными PathVariable.

HTTP-методы
Когда мы говорим о запросах, мы также подразумеваем HTTP-метод, который используется при отправке этого запроса. Каждый запрос представляет собой некий HTTP-метод. Например, когда мы переходим в браузере по адресу http://localhost:8080/greet/John/Smith
, наш браузер отправляет GET-запрос на сервер.
Большая часть информационных систем обмениваются данными посредством HTTP-методов. Основными HTTP-методами являются – POST
, GET
, PUT
, DELETE
. Эти четыре запроса также называют CRUD-запросами.
- POST-метод – используется при создании новых ресурсов или данных. Например, когда мы загружаем новые посты в соцсетях, чаще всего используется POST-запросы. POST-запрос может иметь тело запроса.
- GET-метод – используется при получении данных. Например, при открытии любого веб-приложения, отправляется именно GET-запрос для получения данных и отображения их на странице. GET-запрос не имеет тела запроса.
- PUT-метод – используется для обновления данных, а также может иметь тело запроса, как и POST.
- DELETE-метод – используется для удаления данных.
Реализация основных методов
Давайте создадим сущности и реализуем методы, чтобы наш сервер принимал все четыре запроса. Для этого создадим сущности User
и Post
, и будем проводить операции над ними.
Для простоты User
имеет только два поля: username
и список постов posts
, а сущность Post
имеет поле description
и imageUrl
.
Сущность User
:
package io.proglib;
import java.util.ArrayList;
import java.util.List;
public class User {
private String username;
private List<Post> posts;
public User() {
posts = new ArrayList<>();
}
public User(String username, List<Post> posts) {
this.username = username;
this.posts = posts == null ? new ArrayList<>() : posts;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<Post> getPosts() {
return posts;
}
public void setPosts(List<Post> posts) {
this.posts = posts;
}
}
Сущность Post
:
package io.proglib;
public record Post(
String description,
String imageUrl
) {
}
Создаем новый класс контроллер – UserActivityController
, который будет обрабатывать наши запросы – POST, GET, PUT, DELETE.
Наш контроллер: UserActivityController.
Будем использовать список – List<User> users
в качестве локальной базы данных, где будем хранить все наши данные.
package io.proglib;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserActivityController {
private final static List<User> users = new ArrayList<>();
}
POST-запрос: добавление нового пользователя
Чтобы указать, что метод принимает POST-запросы используем аннотацию – @PostMapping
. Так как запрос имеет тело запроса, где мы передаем пользователя, нужно пометить переменную user
аннотацией @RequestBody
.
@PostMapping("")
public User addUser(@RequestBody User user) {
users.add(user);
return user;
}
GET-запрос: получение пользователей
@GetMapping("")
public List<User> getUsers() {
return users;
}
@GetMapping("/{username}")
public User getUserByUsername(@PathVariable("username") String username) {
return users.stream().filter(user -> user.getUsername().equals(username))
.findFirst().get();
}
@Getmapping("")
указывает, что методы обрабатывают GET-запросы. Значение, которое передаётся внутри аннотации, является частью url или адреса. Например, запрос http://localhost:8080/users/baggio
обработается методом getUserByUsername()
, а запрос http://localhost:8080/users/
обработается методом http://localhost:8080/users
.
PUT-запрос: обновление данных
@PutMapping("/{username}")
public Post update(@PathVariable("username") String username, @RequestBody Post post) {
users.stream().filter(user ->
user.getUsername().equals(username))
.findAny()
.ifPresent(user -> user.getPosts().add(post));
return post;
}
@PutMapping("/{username}")
указывает, что метод принимает PUT-запросы. В нашем примере в запросе мы передаем параметр запроса, а также тело запроса – post
. Метод принимает – username
, ищет юзера из списка с таким username
и добавляем новый пост к его списку постов.
Delete-запрос: удаление данных
@DeleteMapping("/{username}")
public String deleteUser(@PathVariable("username") String username) {
users.stream().filter(user ->
user.getUsername().equals(username))
.findAny()
.ifPresent(users::remove);
return "User with username: " + username + " has been deleted";
}
@DeleteMapping("/{username}")
– указывает, что метод принимает DELETE-запросы.
Данный метод получает параметр username
из запроса и удаляет из списка пользователя с таким username.
Запуск приложения и тестирование
Чтобы убедиться, что все работает, мы можем отправить каждый вид запроса и протестировать. Для этого нам необходим API-client, который может посылать запросы. В примерах я использую POSTMAN.
Post-запрос: создание нового пользователя.
Тело запроса отправляется в виде JSON.

GET-запрос: получение пользователей

PUT-запрос: обновление списка постов пользователя

DELETE-запрос: удаление пользователя по username

В этой статье мы рассмотрели архитектуру современных web-приложений, а также написали свою серверную часть приложения, получив поверхностные знания по Spring Boot
, HTTP запросы
и параметры запросов.
Комментарии