Controller's in Spring. Разбираем создание и устройство.
Встреча от 18.05.2025
Запись встречи -
YOUTUBE
RUTUBE
На сегодняшней встрече мы разобрали важную тему в Spring Java - Controller.
Что мы успели:
➡️ Зачем нам вообще нужны контроллеры.
➡️ Какие существуют основные принципы REST при написании контроллеров.
➡️ Основные аннотации Spring для написания контроллеров и их настройку.
➡️ Все это посмотрели на примере кода.
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Спасибо всем кто пришел, респект 🫡
Встреча от 18.05.2025
Запись встречи -
YOUTUBE
RUTUBE
На сегодняшней встрече мы разобрали важную тему в Spring Java - Controller.
Что мы успели:
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Спасибо всем кто пришел, респект 🫡
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
"Масштабируемость — это искусство упрощения."
Джефф Дин, инженер Google, сказал это в 2012 году на конференции по системам, обсуждая архитектуру больших систем.
Шутки про Джеффа (из статьи):
«Когда Джефф Дин разрабатывает программу, то сначала создаёт бинарник, а потом пишет исходный код как документацию».
«Джефф Дин однажды не прошёл тест Тьюринга, потому что правильно установил 203-е число Фибоначчи менее чем за секунду».
«Джефф Дин родился 31 декабря 1969 года в 23:48. Ему потребовалось 12 минут, чтобы запустить свой первый счётчик времени».
Почитать статью хааабр
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
От распределённого бэкенда — к сильному ИИ. Чем сейчас занимается легендарный Джефф Дин?
На Хабре иногда рассказывают про выдающихся программистов современности, таких как Линус Торвальдс , Фабрис Беллар и Джефф Дин . Про этих людей ходят легенды. Особенно выделяется последний, которого в...
👍2
Работа с коллекциями, вложенными объектами и generic-типами в Gson
1. Работа с коллекциями
Сериализация/десериализация списков (List<T>)
Пример с List<String>:
Проблема: При использовании List.class тип элементов стирается. Для generic-типов нужен TypeToken.
Использование TypeToken для generic-типов
Пример с массивами
Работа с Map<String, Object>
2. Вложенные объекты и сложные структуры
Объекты внутри объектов
Пример JSON с вложенностью:
Соответствующие Java-классы:
Десериализация вложенного объекта
Сериализация сложного объекта
Как обрабатываются вложенности
Gson рекурсивно обходит все поля объекта.
Для каждого вложенного объекта создается новый экземпляр.
Поддерживается любая глубина вложенности.
Пример с коллекцией вложенных объектов
JSON:
Java-классы:
Десериализация:
#Java #middle #Gson
1. Работа с коллекциями
Сериализация/десериализация списков (List<T>)
Пример с List<String>:
Gson gson = new Gson();
// Сериализация списка в JSON
List<String> languages = Arrays.asList("Java", "Kotlin", "Python");
String json = gson.toJson(languages);
System.out.println(json); // ["Java","Kotlin","Python"]
// Десериализация JSON обратно в List
List<String> parsedList = gson.fromJson(json, List.class);
System.out.println(parsedList.get(0)); // Java
Проблема: При использовании List.class тип элементов стирается. Для generic-типов нужен TypeToken.
Использование TypeToken для generic-типов
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
// Создаем Type для List<String>
Type listType = new TypeToken<List<String>>() {}.getType();
// Десериализация с сохранением типа
String json = "[\"Apple\", \"Banana\"]";
List<String> fruits = gson.fromJson(json, listType);
System.out.println(fruits.get(0).toUpperCase()); // APPLE (без TypeToken был бы Object!)
Пример с массивами
// Сериализация массива
int[] numbers = {1, 2, 3};
String numbersJson = gson.toJson(numbers);
System.out.println(numbersJson); // [1,2,3]
// Десериализация обратно в массив
int[] parsedNumbers = gson.fromJson(numbersJson, int[].class);
System.out.println(parsedNumbers[0]); // 1
Работа с Map<String, Object>
// Сериализация Map
Map<String, Object> data = new HashMap<>();
data.put("name", "John");
data.put("age", 30);
data.put("skills", Arrays.asList("Java", "SQL"));
String mapJson = gson.toJson(data);
System.out.println(mapJson);
// {"skills":["Java","SQL"],"name":"John","age":30}
// Десериализация Map
Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> parsedMap = gson.fromJson(mapJson, mapType);
System.out.println(parsedMap.get("name")); // John
2. Вложенные объекты и сложные структуры
Объекты внутри объектов
Пример JSON с вложенностью:
{
"name": "Alice",
"address": {
"city": "New York",
"street": "5th Avenue"
}
}
Соответствующие Java-классы:
class Address {
private String city;
private String street;
// Конструктор, геттеры и сеттеры
public Address(String city, String street) {
this.city = city;
this.street = street;
}
public String getCity() { return city; }
public String getStreet() { return street; }
}
class Person {
private String name;
private Address address;
// Конструктор, геттеры и сеттеры
}
Десериализация вложенного объекта
String personJson = """
{
"name": "Alice",
"address": {
"city": "New York",
"street": "5th Avenue"
}
}
""";
Gson gson = new Gson();
Person person = gson.fromJson(personJson, Person.class);
System.out.println(person.getName()); // Alice
System.out.println(person.getAddress().getCity()); // New York
Сериализация сложного объекта
Address address = new Address("Berlin", "Main Street");
Person person = new Person("Bob", address);
String json = gson.toJson(person);
System.out.println(json);
// {"name":"Bob","address":{"city":"Berlin","street":"Main Street"}}
Как обрабатываются вложенности
Gson рекурсивно обходит все поля объекта.
Для каждого вложенного объекта создается новый экземпляр.
Поддерживается любая глубина вложенности.
Пример с коллекцией вложенных объектов
JSON:
{
"team": "Developers",
"members": [
{
"name": "John",
"role": "Backend"
},
{
"name": "Anna",
"role": "Frontend"
}
]
}
Java-классы:
class TeamMember {
private String name;
private String role;
// конструктор и геттеры
}
class Team {
private String teamName;
private List<TeamMember> members;
// конструктор и геттеры
}
Десериализация:
Type teamType = new TypeToken<Team>() {}.getType();
Team team = gson.fromJson(jsonString, teamType);
#Java #middle #Gson
👍3
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Что выведет код?
#Tasks
public class Task190525 {
public static void main(String[] args) {
String s1 = "Java";
String s2 = s1.concat('\u00A9');
System.out.println(s2);
}
}
#Tasks
👍1
👍1
"Стартапы — это марафон, а не спринт."
Джастин Кан, основатель Twitch, сказал это в 2014 году в интервью Y Combinator, подчеркивая терпение в разработке успешного стартапа.
Биография
хааабр
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Justin Kan
Justin Kan (born July 16, 1983) is an American internet entrepreneur and investor. He is the co-founder of live video platforms Justin.tv and Twitch, as well as the mobile social video application Socialcam. He was also the co-founder and former CEO of law…
👍1
Глубокое изучение типа данных short в Java: сравнение с byte и int
Тип short в Java — это примитивный тип, представляющий собой 16-битное целое число со знаком. Он занимает 2 байта памяти и служит компромиссным решением между компактным byte и универсальным int. Несмотря на то, что short используется относительно редко, его понимание важно при оптимизации памяти и взаимодействии с внешними системами.
Диапазон и внутреннее представление
Тип short может хранить значения от -32 768 до 32 767. Как и все знаковые целочисленные типы в Java, short использует формат дополнительного кода (two’s complement). Самый старший (16-й) бит используется для знака: 0 — положительное число, 1 — отрицательное.
Это значит, что в 16 бит можно закодировать 2¹⁶ различных значений: половина для положительных чисел (включая 0), половина для отрицательных.
Для сравнения:
byte — 8 бит, диапазон: -128 до 127
short — 16 бит, диапазон: -32 768 до 32 767
int — 32 бита, диапазон: примерно -2.1 млрд до 2.1 млрд
Такой диапазон делает short пригодным для хранения небольших чисел, например, размеров, координат, портов, идентификаторов, когда byte мал, а int избыточен.
Память и размещение
short занимает 2 байта, в отличие от byte (1 байт) и int (4 байта). Это может быть важно при работе с большими массивами. Например, массив из миллиона short займёт 2 МБ, а массив int — уже 4 МБ.
Как и другие примитивные типы, short:
хранится в стеке, если это локальная переменная;
размещается в куче, если это поле объекта;
автоматически удаляется при выходе переменной из области видимости или при сборке мусора (если внутри объекта).
Арифметика и повышение типов
Важный момент: при любом арифметическом выражении, даже если оба операнда имеют тип short, результат всегда приводится к int. Это правило относится ко всем типам, младше int.
Например:
Чтобы код компилировался, нужно сделать явное приведение:
Это также относится к byte. int, в отличие от них, участвует в арифметике напрямую без преобразований, так как int — тип по умолчанию для целых чисел в Java.
Переполнение и поведение при выходе за диапазон
short, как и другие примитивные типы, не защищён от переполнения. Если результат выходит за диапазон [-32 768; 32 767], значение просто оборачивается — без исключений или предупреждений.
Это может быть источником трудноуловимых ошибок:
Беззнаковость
Как и byte, short — только знаковый тип. В Java нет беззнакового short. Если необходимо работать с диапазоном 0–65535, используется int и маска & 0xFFFF:
Применение и область использования
Оптимизация памяти. Если у вас есть массив, содержащий значения, которые гарантированно не выходят за диапазон short, можно заменить int на short и вдвое сократить объём памяти.
Работа с файлами и сетевыми протоколами. Некоторые форматы (например, WAV, BMP) и сетевые протоколы используют 16-битные поля. Для точного отражения структуры лучше использовать short, чтобы избежать лишних преобразований.
Ограничение диапазона. Как и в случае с byte, использование short может служить сигналом другим разработчикам: переменная не может иметь произвольное значение int.
Сравнение: byte vs short vs int
byte — минимальный по размеру, экономичен, но быстро переполняется. Подходит для работы с бинарными потоками, кодировками, цветовыми компонентами.
short — компромисс между byte и int. Используется реже, но уместен в структурированных форматах, при массовой обработке чисел с ограниченным диапазоном.
int — тип по умолчанию. Безопасный, удобный, редко переполняется. Но при массовой обработке больших объёмов данных может оказаться избыточным по памяти.
Пример: обрезка типа при записи
#Java #для_новичков #beginner #short
Тип short в Java — это примитивный тип, представляющий собой 16-битное целое число со знаком. Он занимает 2 байта памяти и служит компромиссным решением между компактным byte и универсальным int. Несмотря на то, что short используется относительно редко, его понимание важно при оптимизации памяти и взаимодействии с внешними системами.
Диапазон и внутреннее представление
Тип short может хранить значения от -32 768 до 32 767. Как и все знаковые целочисленные типы в Java, short использует формат дополнительного кода (two’s complement). Самый старший (16-й) бит используется для знака: 0 — положительное число, 1 — отрицательное.
Это значит, что в 16 бит можно закодировать 2¹⁶ различных значений: половина для положительных чисел (включая 0), половина для отрицательных.
Для сравнения:
byte — 8 бит, диапазон: -128 до 127
short — 16 бит, диапазон: -32 768 до 32 767
int — 32 бита, диапазон: примерно -2.1 млрд до 2.1 млрд
Такой диапазон делает short пригодным для хранения небольших чисел, например, размеров, координат, портов, идентификаторов, когда byte мал, а int избыточен.
Память и размещение
short занимает 2 байта, в отличие от byte (1 байт) и int (4 байта). Это может быть важно при работе с большими массивами. Например, массив из миллиона short займёт 2 МБ, а массив int — уже 4 МБ.
Как и другие примитивные типы, short:
хранится в стеке, если это локальная переменная;
размещается в куче, если это поле объекта;
автоматически удаляется при выходе переменной из области видимости или при сборке мусора (если внутри объекта).
Арифметика и повышение типов
Важный момент: при любом арифметическом выражении, даже если оба операнда имеют тип short, результат всегда приводится к int. Это правило относится ко всем типам, младше int.
Например:
short a = 1000;
short b = 2000;
short c = a + b; // Ошибка компиляции
Чтобы код компилировался, нужно сделать явное приведение:
short c = (short)(a + b);
Это также относится к byte. int, в отличие от них, участвует в арифметике напрямую без преобразований, так как int — тип по умолчанию для целых чисел в Java.
Переполнение и поведение при выходе за диапазон
short, как и другие примитивные типы, не защищён от переполнения. Если результат выходит за диапазон [-32 768; 32 767], значение просто оборачивается — без исключений или предупреждений.
Это может быть источником трудноуловимых ошибок:
short s = 32_767;
s++; // теперь s = -32_768
Беззнаковость
Как и byte, short — только знаковый тип. В Java нет беззнакового short. Если необходимо работать с диапазоном 0–65535, используется int и маска & 0xFFFF:
short s = -1;
int unsigned = s & 0xFFFF; // результат: 65535
Применение и область использования
Оптимизация памяти. Если у вас есть массив, содержащий значения, которые гарантированно не выходят за диапазон short, можно заменить int на short и вдвое сократить объём памяти.
Работа с файлами и сетевыми протоколами. Некоторые форматы (например, WAV, BMP) и сетевые протоколы используют 16-битные поля. Для точного отражения структуры лучше использовать short, чтобы избежать лишних преобразований.
Ограничение диапазона. Как и в случае с byte, использование short может служить сигналом другим разработчикам: переменная не может иметь произвольное значение int.
Сравнение: byte vs short vs int
byte — минимальный по размеру, экономичен, но быстро переполняется. Подходит для работы с бинарными потоками, кодировками, цветовыми компонентами.
short — компромисс между byte и int. Используется реже, но уместен в структурированных форматах, при массовой обработке чисел с ограниченным диапазоном.
int — тип по умолчанию. Безопасный, удобный, редко переполняется. Но при массовой обработке больших объёмов данных может оказаться избыточным по памяти.
Пример: обрезка типа при записи
short s = (short) 40000;
System.out.println(s); // Выведет -25536
Потому что 40000 не помещается в short, и лишние биты отбрасываются.
#Java #для_новичков #beginner #short
👍3
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что выведет код?
#Tasks
public class Main {
public static void main(String[] args) {
short a = 10;
short b = 20;
short c = a + b;
System.out.println(c);
}
}
#Tasks
👍1
👍4
А вы знали, что первый "цифровой кошелёк" появился в 1990 году?
Корни цифровых кошельков уходят корнями в 1990-е годы, когда Дэвид Чаум представил DigiCash, одну из первых цифровых валют, для транзакций которых требовался цифровой кошелек (DigiCash, 1990). Новаторская работа Чаума в области криптографических методов заложила основу для безопасных онлайн-транзакций.
proof
#facts
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
"Хороший продукт решает одну проблему лучше всех."
Тони Фаделл, создатель iPod, сказал это в 2015 году на конференции TED, описывая философию дизайна.
Биография
#Citation #Biography
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Фаделл, Тони
Тони Фаделл (англ. Anthony M. Fadell; род. , ) — американский топ-менеджер. Бывший старший директор департамента по разработке и выпуску плеера iPod от Apple.
👍1
Кастомизация и адаптеры в Gson
1. Кастомные сериализаторы и десериализаторы
Gson позволяет переопределять стандартное поведение сериализации и десериализации с помощью интерфейсов JsonSerializer<T> и JsonDeserializer<T>.
1.1. Создание кастомного сериализатора (JsonSerializer<T>)
Используется, когда нужно изменить стандартное преобразование объекта в JSON.
Пример: Сериализация объекта User с особым форматированием поля email.
1.2. Создание кастомного десериализатора (JsonDeserializer<T>)
Используется, когда нужно изменить стандартное преобразование JSON в объект.
Пример: Десериализация JSON с дополнительной валидацией email.
1.3. Регистрация адаптеров через GsonBuilder
Чтобы применить кастомные сериализаторы и десериализаторы, их нужно зарегистрировать в GsonBuilder:
1.4. Пример: Кастомный формат даты
Если стандартный формат даты (Date) не подходит, можно задать свой:
#Java #middle #Gson #JsonSerializer #JsonDeserializer
1. Кастомные сериализаторы и десериализаторы
Gson позволяет переопределять стандартное поведение сериализации и десериализации с помощью интерфейсов JsonSerializer<T> и JsonDeserializer<T>.
1.1. Создание кастомного сериализатора (JsonSerializer<T>)
Используется, когда нужно изменить стандартное преобразование объекта в JSON.
Пример: Сериализация объекта User с особым форматированием поля email.
public class User {
private String name;
private String email;
// Конструкторы, геттеры и сеттеры
}
public class UserSerializer implements JsonSerializer<User> {
@Override
public JsonElement serialize(User user, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("name", user.getName());
jsonObject.addProperty("email", user.getEmail().toLowerCase()); // Приводим email к нижнему регистру
return jsonObject;
}
}
1.2. Создание кастомного десериализатора (JsonDeserializer<T>)
Используется, когда нужно изменить стандартное преобразование JSON в объект.
Пример: Десериализация JSON с дополнительной валидацией email.
public class UserDeserializer implements JsonDeserializer<User> {
@Override
public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
String name = jsonObject.get("name").getAsString();
String email = jsonObject.get("email").getAsString();
if (!email.contains("@")) {
throw new JsonParseException("Invalid email format");
}
return new User(name, email);
}
}
1.3. Регистрация адаптеров через GsonBuilder
Чтобы применить кастомные сериализаторы и десериализаторы, их нужно зарегистрировать в GsonBuilder:
Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserSerializer()) // Сериализатор
.registerTypeAdapter(User.class, new UserDeserializer()) // Десериализатор
.create();
// Сериализация
User user = new User("John", "John@Example.com");
String json = gson.toJson(user); // {"name":"John","email":"john@example.com"}
// Десериализация
User parsedUser = gson.fromJson(json, User.class);
1.4. Пример: Кастомный формат даты
Если стандартный формат даты (Date) не подходит, можно задать свой:
public class DateSerializer implements JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
@Override
public JsonElement serialize(Date date, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(dateFormat.format(date));
}
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new DateSerializer())
.create();
Date now = new Date();
String json = gson.toJson(now); // "12.05.2025"
#Java #middle #Gson #JsonSerializer #JsonDeserializer
👍4
2. Настройка Gson через GsonBuilder
GsonBuilder позволяет гибко настраивать поведение Gson.
2.1. Основные методы настройки
.setPrettyPrinting(): Форматирует JSON с отступами для читаемости
.serializeNulls(): Сериализует поля со значением null (по умолчанию они пропускаются)
.excludeFieldsWithoutExposeAnnotation(): Игнорирует поля без аннотации @Expose
Пример:
2.2. Использование @Expose для выборочной сериализации
Поля без @Expose игнорируются, если включена соответствующая настройка.
2.3. Полный пример кастомной конфигурации Gson
#Java #middle #Gson #GsonBuilder
GsonBuilder позволяет гибко настраивать поведение Gson.
2.1. Основные методы настройки
.setPrettyPrinting(): Форматирует JSON с отступами для читаемости
.serializeNulls(): Сериализует поля со значением null (по умолчанию они пропускаются)
.excludeFieldsWithoutExposeAnnotation(): Игнорирует поля без аннотации @Expose
Пример:
Gson gson = new GsonBuilder()
.setPrettyPrinting() // Красивый вывод JSON
.serializeNulls() // Включает null-поля
.excludeFieldsWithoutExposeAnnotation() // Только помеченные @Expose
.create();
2.2. Использование @Expose для выборочной сериализации
Поля без @Expose игнорируются, если включена соответствующая настройка.
public class User {
@Expose
private String name; // Будет сериализовано
private String password; // Не будет сериализовано
}
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
User user = new User("John", "secret");
String json = gson.toJson(user); // {"name":"John"}
2.3. Полный пример кастомной конфигурации Gson
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.setDateFormat("dd.MM.yyyy") // Формат даты по умолчанию
.registerTypeAdapter(User.class, new UserSerializer())
.excludeFieldsWithoutExposeAnnotation()
.create();
#Java #middle #Gson #GsonBuilder
👍5
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что выведет код?
#Tasks
public class Task210525 {
public static void main(String[] args) {
String s1 = new String("Java");
String s2 = s1.intern();
String s3 = "Java";
System.out.println(s1 == s2);
System.out.println(s2 == s3);
}
}
#Tasks
👍1
👍2
В чем разница между public, private, protected и default модификаторами доступа? 🤓
Ответ:Модификаторы доступа определяют видимость элементов класса:
🔜 public: доступен отовсюду.
🔜 private: доступен только внутри класса.
🔜 protected: доступен в пакете и в подклассах (даже в других пакетах).
🔜 default (без модификатора): доступен только внутри пакета.
#собеседование
Ответ:
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5