Push 163 file(s) from Obsidian
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
#java #SpringBoot
|
||||
|
||||
Сценарий: В приложении есть и традиционные веб-эндпоинты с Thymeleaf, и REST API.
|
||||
Нужно централизовать обработку ошибок (например, перехват ResourceNotFoundException):
|
||||
|
||||
Как вернуть страницу 404 для обычных web-эндпоинтов?
|
||||
|
||||
Как вернуть JSON с ошибкой 404 для REST API?
|
||||
|
||||
→
|
||||
@ControllerAdvice — используется с @Controller, возвращает view.
|
||||
@RestControllerAdvice — сочетает @ControllerAdvice + @ResponseBody (для REST API).
|
||||
@@ -0,0 +1,67 @@
|
||||
#java #абстракции
|
||||
|
||||
Одна из ключевых концепций ООП – абстракция. Мы постоянно используем её в [[Java]], даже не задумываясь. Но давайте разберёмся, зачем она нужна и как правильно применять.
|
||||
|
||||
📌 Что такое абстракция?
|
||||
Абстракция – это процесс выделения существенных характеристик объекта, скрывая при этом детали реализации. Это позволяет нам работать с объектами через их интерфейсы, а не конкретные реализации.
|
||||
|
||||
Пример из жизни:
|
||||
Когда вы едете на машине, вам не нужно знать, как работает двигатель. Достаточно уметь жать на газ, тормозить и поворачивать руль. Вот это и есть абстракция – вам доступен только необходимый интерфейс, а детали скрыты.
|
||||
|
||||
🔹 Как реализуется абстракция в Java?
|
||||
В Java абстракция достигается двумя способами:
|
||||
1. Абстрактные классы (abstract class)
|
||||
2. Интерфейсы (interface)
|
||||
|
||||
🚀 Абстрактные классы
|
||||
Абстрактный класс может содержать как реализованные, так и абстрактные (без реализации) методы. Его нельзя создать через new, он служит основой для дочерних классов.
|
||||
```java
|
||||
abstract class Vehicle {
|
||||
abstract void start(); // абстрактный метод, без реализации
|
||||
|
||||
void stop() {
|
||||
System.out.println("Машина остановилась");
|
||||
}
|
||||
}
|
||||
|
||||
class Car extends Vehicle {
|
||||
@Override
|
||||
void start() {
|
||||
System.out.println("Запуск двигателя...");
|
||||
}
|
||||
}
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Vehicle car = new Car();
|
||||
car.start();
|
||||
car.stop();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
💡 Тут start() – это абстрактный метод, его реализация будет в Car. А вот stop() реализован в базовом классе.
|
||||
|
||||
🚀 Интерфейсы
|
||||
Интерфейсы содержат только сигнатуры методов (до Java 8), а с Java 8 можно добавлять default и static методы.
|
||||
|
||||
```java
|
||||
interface Engine {
|
||||
void start();
|
||||
}
|
||||
|
||||
class ElectricCar implements Engine {
|
||||
@Override
|
||||
public void start() {
|
||||
System.out.println("Электродвигатель включен!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
📌 Разница между интерфейсом и абстрактным классом в том, что интерфейсы описывают, что класс ДОЛЖЕН делать, а абстрактные классы – как он МОЖЕТ это делать.
|
||||
|
||||
🎯 Где применять абстракцию?
|
||||
- Если у вас иерархия классов с общими методами – используйте абстрактный класс.
|
||||
- Если вам нужно гибкое поведение без наследования – используйте интерфейсы.
|
||||
|
||||
👉 Абстракция позволяет писать гибкий, расширяемый и поддерживаемый код, уменьшая зависимость от конкретных реализаций.
|
||||
@@ -0,0 +1,8 @@
|
||||
#java #SpringBoot
|
||||
|
||||
Сценарий: Ты добавил в проект стороннюю библиотеку (например, кастомный логгер) и просто положил её JAR в classpath.
|
||||
Без написания конфигурационных классов Spring автоматически подхватывает нужные бины.
|
||||
Объясни, как Spring Boot определяет и подключает их при старте.
|
||||
|
||||
→
|
||||
Использует SpringFactoriesLoader, который читает META-INF/spring.factories и конфигурирует бины в зависимости от содержимого classpath.
|
||||
@@ -0,0 +1,18 @@
|
||||
#java #поиск
|
||||
```java
|
||||
public class BinarySearch {
|
||||
public static int binarySearch(int[] arr, int target) {
|
||||
int left = 0, right = arr.length - 1;
|
||||
|
||||
while (left <= right) {
|
||||
int mid = (left + right) / 2;
|
||||
|
||||
if (arr[mid] == target) return mid;
|
||||
if (arr[mid] < target) left = mid + 1;
|
||||
else right = mid - 1;
|
||||
}
|
||||
|
||||
return -1; // элемент не найден
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,17 @@
|
||||
#java #коллекции
|
||||
|
||||
Коллекции [[Java]] и производительность
|
||||
🍩List (Списки)
|
||||
🟣ArrayList – быстрый доступ к элементам и их обход, но вставка/удаление в середине списка требует сдвига элементов.
|
||||
🟣LinkedList – удобен для вставки и удаления, но случайный доступ медленный, так как элементы обходятся с начала или конца.
|
||||
|
||||
🍩Set (Множества)
|
||||
🟣HashSet – быстрые операции добавления, удаления и поиска (за O(1)), но не сохраняет порядок элементов.
|
||||
🟣LinkedHashSet – сохраняет порядок вставки и быстрее перебирается, чем HashSet.
|
||||
🟣TreeSet – поддерживает сортировку, но операции добавления, удаления и поиска имеют логарифмическую сложность O(log n).
|
||||
|
||||
🍩Map (Словари/Отображения)
|
||||
🟣HashMap – обеспечивает O(1) доступ по ключу, но не сохраняет порядок. Возможны коллизии, которые могут замедлить работу.
|
||||
🟣LinkedHashMap – сохраняет порядок вставки и перебирается быстрее, чем HashMap.
|
||||
🟣TreeMap – хранит ключи в отсортированном порядке, но операции выполняются за O(log n).
|
||||
![[collection.jpg]]
|
||||
@@ -0,0 +1,23 @@
|
||||
#docker
|
||||
`docker compose up -d` Запуск всех сервисов в фоновом режиме.
|
||||
`docker compose down` Остановка и удаление контейнеров, сетей и служебных ресурсов проекта.
|
||||
`docker compose restart` Перезапуск всех сервисов проекта.
|
||||
`docker compose stop` Остановка сервисов без удаления контейнеров.
|
||||
`docker compose start` Запуск ранее остановленных контейнеров.
|
||||
`docker ps` Просмотр запущенных контейнеров.
|
||||
`docker ps -a` Просмотр всех контейнеров, включая остановленные.
|
||||
`docker compose ps` Просмотр состояния контейнеров текущего проекта.
|
||||
`docker stats` Мониторинг потребления CPU, RAM и сетевых ресурсов контейнерами в реальном времени.
|
||||
`docker compose logs` Просмотр журналов всех сервисов проекта.
|
||||
`docker compose logs -f` Просмотр журналов в режиме реального времени.
|
||||
`docker compose logs <service>` Просмотр журналов конкретного сервиса.
|
||||
`docker logs <container>` Просмотр журналов конкретного контейнера.
|
||||
`docker inspect <container>` Получение полной информации о контейнере (сеть, тома, переменные окружения и др.).
|
||||
`docker exec -it <container> bash` Подключение к оболочке контейнера для диагностики и выполнения команд.
|
||||
`docker exec -it <container> sh` Аналогично для контейнеров без Bash.
|
||||
`docker top <container>` Просмотр процессов внутри контейнера.
|
||||
`docker images` Список локальных Docker-образов.
|
||||
`docker image inspect <image>` Информация об образе.
|
||||
`docker system df` Статистика использования диска Docker.
|
||||
`docker volume ls` Список томов Docker.
|
||||
`docker network ls` Список сетей Docker.
|
||||
@@ -0,0 +1,7 @@
|
||||
#java #SpringBoot
|
||||
|
||||
Сценарий: Твой публичный API перегружен — один клиент шлет слишком много запросов, мешая остальным.
|
||||
Какой практичный, независимый от технологий подход можно применить для ограничения, например, 100 запросов в минуту на клиента, и где обычно реализуется такая логика?
|
||||
|
||||
→
|
||||
Bucket4j / Resilience4j, счетчики в Redis, лимитирование на уровне API Gateway.
|
||||
@@ -0,0 +1,11 @@
|
||||
```java
|
||||
public class MaxInArray {
|
||||
public static int findMax(int[] arr) {
|
||||
int max = arr[0];
|
||||
for (int num : arr) {
|
||||
if (num > max) max = num;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
#java
|
||||
|
||||
Потому что интерфейс описывает контракт, а не состояние. Все поля интерфейса — это константы, доступные без создания экземпляра. Они автоматически public static final, даже без явного указания.
|
||||
@@ -0,0 +1,15 @@
|
||||
```java
|
||||
public class PalindromeCheck {
|
||||
public static boolean isPalindrome(String str) {
|
||||
int left = 0, right = str.length() - 1;
|
||||
|
||||
while (left < right) {
|
||||
if (str.charAt(left++) != str.charAt(right--)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
#java #SpringBoot
|
||||
|
||||
Сценарий: В микросервисной архитектуре оформление заказа включает два шага — списание товара в Inventory Service и списание денег через Payment Service.
|
||||
Если списание товара прошло успешно, а оплата — нет, какой шаблон проектирования поможет откатить изменения в Inventory и обеспечить согласованность данных?
|
||||
|
||||
→
|
||||
Шаблон Saga (хореография или оркестрация), либо двухфазный коммит (2PC, но редко используется на практике).
|
||||
@@ -0,0 +1,10 @@
|
||||
#java #SpringBoot
|
||||
|
||||
Сценарий: У тебя есть OrderService с методом createOrder(), помеченным @Transactional.
|
||||
Внутри он вызывает updateInventory() (тоже в OrderService и тоже с @Transactional).
|
||||
Если updateInventory() выбрасывает runtime-исключение, что произойдет с транзакцией, начатой в createOrder()?
|
||||
Как изменить дизайн, если нужно, чтобы оба метода выполнялись в отдельных, независимых транзакциях?
|
||||
|
||||
→
|
||||
Транзакция не будет распространяться (прокси не сработает при внутреннем вызове).
|
||||
Решение — self-injection (внедрение самого себя как зависимости) или использование AOP.
|
||||
@@ -0,0 +1,8 @@
|
||||
#java #SpringBoot
|
||||
|
||||
Сценарий: Нужно хранить товары пользователя в корзине и управлять временным списком поисковых фильтров, который очищается после каждого HTTP-запроса.
|
||||
Какой скоуп ты выберешь для ShoppingCart и какой — для SearchFilter, и почему?
|
||||
|
||||
→
|
||||
@SessionScope — для корзины (привязано к пользовательской сессии),
|
||||
@RequestScope — для поискового фильтра (новый бин на каждый HTTP-запрос).
|
||||
@@ -0,0 +1,17 @@
|
||||
```java
|
||||
public class BubbleSort {
|
||||
public static void bubbleSort(int[] arr) {
|
||||
int n = arr.length;
|
||||
for (int i = 0; i < n - 1; i++) {
|
||||
for (int j = 0; j < n - i - 1; j++) {
|
||||
if (arr[j] > arr[j + 1]) {
|
||||
// обмен
|
||||
int temp = arr[j];
|
||||
arr[j] = arr[j + 1];
|
||||
arr[j + 1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,10 @@
|
||||
#Java #SpringBoot
|
||||
|
||||
Сценарий: Представь, что ты проектируешь сложную e-commerce платформу. Где ты используешь интерфейс с аннотацией
|
||||
@Repository, а где — с аннотацией @Service? Приведи конкретный пример, какую роль каждая из этих аннотаций играет в процессе оформления заказа пользователем.
|
||||
|
||||
→
|
||||
@Component — универсальный бин,
|
||||
@Service — бизнес-логика,
|
||||
@Repository — DAO + перевод исключений в DataAccessException,
|
||||
@Controller — контроллер уровня MVC.
|
||||
@@ -0,0 +1,8 @@
|
||||
```java
|
||||
public class Factorial {
|
||||
public static long factorial(int n) {
|
||||
if (n <= 1) return 1;
|
||||
return n * factorial(n - 1);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
Ключевое слово final в [[Java]] — это модификатор, который может применяться к переменным, методам и классам. Когда оно используется с переменной, это делает её неизменяемой, другими словами — константой. Например, переменная PI объявлена как final в классе ниже:
|
||||
```java
|
||||
public class CircleCalculator {
|
||||
private final double PI = 3.14159;
|
||||
public double calculateArea(double radius) {
|
||||
return PI * radius * radius;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
#java #SpringBoot
|
||||
|
||||
Сценарий: Коллега добавил новую фичу, и теперь твое Spring-приложение не стартует, выдавая BeanCurrentlyInCreationException из-за циклической зависимости между ServiceA и ServiceB.
|
||||
Предположим, что быстро переработать бизнес-логику невозможно. Какое минимальное изменение кода ты бы предложил, чтобы приложение хотя бы запустилось, и почему это считается временным решением?
|
||||
|
||||
→
|
||||
Spring по умолчанию может использовать проксирование и конструкторную/сеттерную инъекцию.
|
||||
Лучшее решение — перепроектировать зависимости или использовать @Lazy.
|
||||
@@ -0,0 +1,3 @@
|
||||
#java
|
||||
Объект - это объединение данных и кода, который эти данные обрабатывает ()
|
||||
Класс - это шаблон описания объектов. В классе могут описываться поля, методы, конструкторы и другие классы.
|
||||
@@ -0,0 +1,81 @@
|
||||
#PostgreSQL #PostgreSQL #SQL
|
||||
|
||||
-- ***********************************
|
||||
-- Редактирование таблиц, расширенные возможности SELECT, функции
|
||||
-- ***********************************
|
||||
|
||||
-- Добавление поля в таблицу
|
||||
```sql
|
||||
ALTER TABLE table_name ADD COLUMN new_field
|
||||
BOOLEAN NOT NULL DEFAULT TRUE;
|
||||
```
|
||||
|
||||
-- добавление поля с автоинкрементом и primary key в таблицу
|
||||
```sql
|
||||
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
|
||||
```
|
||||
|
||||
-- Удаление поля из таблицы
|
||||
```sql
|
||||
ALTER TABLE table_name DROP COLUMN new_field;
|
||||
```
|
||||
|
||||
-- переименовать поле
|
||||
```sql
|
||||
ALTER TABLE table_name RENAME old_field TO new_field;
|
||||
```
|
||||
|
||||
-- сменить тип данных
|
||||
```sql
|
||||
ALTER TABLE table_name ALTER COLUMN any_field SET
|
||||
DATA TYPE VARCHAR(255);
|
||||
```
|
||||
|
||||
-- изменить значение по умолчанию
|
||||
```sql
|
||||
ALTER TABLE table_name ALTER COLUMN any_field SET
|
||||
DEFAULT 'new value';
|
||||
```
|
||||
|
||||
-- добавить/удалить constraint NOT NULL
|
||||
```sql
|
||||
ALTER TABLE table_name ALTER COLUMN any_field
|
||||
SET|DROP NOT NULL;
|
||||
```
|
||||
|
||||
-- переименовать таблицу
|
||||
```sql
|
||||
ALTER TABLE table_name RENAME TO new_table_name;
|
||||
```
|
||||
|
||||
-- Расширенные возможности SELECT
|
||||
```sql
|
||||
SELECT * FROM table WHERE field1 LIKE 'value'; -- field1 = 'value'
|
||||
SELECT * FROM table WHERE field1 LIKE 'val%'; -- field1 начинается с 'val'
|
||||
SELECT * FROM table WHERE field1 LIKE '%lue'; -- field1 заканчивается на 'lue'
|
||||
SELECT * FROM table WHERE field1 LIKE '%e%'; -- field1 содержит 'e'
|
||||
```
|
||||
несколько условий
|
||||
```sql
|
||||
SELECT * FROM table WHERE field1 = 'value' AND field2 > 'value2';
|
||||
SELECT * FROM table WHERE field1 = 'value' OR field2 > 'value2';
|
||||
```
|
||||
|
||||
|
||||
-- вывод уникальных записей
|
||||
```sql
|
||||
SELECT DISTINCT field1 FROM table;
|
||||
```
|
||||
|
||||
-- группирование записей
|
||||
```sql
|
||||
SELECT field1, COUNT(field1) FROM table GROUP BY field1;
|
||||
```
|
||||
|
||||
|
||||
-- сгруппирует записи таблицы table по полю field и выведет уникальные значения field и количество повторений
|
||||
```sql
|
||||
```
|
||||
SELECT field1, COUNT(field1) FROM table GROUP BY field1
|
||||
HAVING COUNT(field) > 3;
|
||||
-- сгруппирует записи таблицы table по полю field и выведет уникальные значения field и количество повторений, где количество повторений больше 3
|
||||
@@ -0,0 +1,107 @@
|
||||
#PostgreSQL #PostgreSQL #SQL
|
||||
|
||||
Перенес в my-mans
|
||||
|
||||
-- подключиться к postgres (утилита psql)
|
||||
```bash
|
||||
psql -U postgres
|
||||
```
|
||||
|
||||
-- команды помощи
|
||||
help
|
||||
\h -- помощь по командам SQL
|
||||
\? -- помощь по командам psql
|
||||
|
||||
-- выход из консоли postgres
|
||||
\q
|
||||
|
||||
-- создать базу
|
||||
```sql
|
||||
CREATE DATABASE my_database;
|
||||
```
|
||||
|
||||
-- подключиться к базе
|
||||
```
|
||||
\connect my_database;
|
||||
```
|
||||
|
||||
-- создать таблицу my_table с полями field1 (тип целочисленный, обязательное для заполнения), field2 (тип строка 255 символов)
|
||||
```sql
|
||||
CREATE TABLE my_table (field1 INT NOT NULL, field2 VARCHAR(255));
|
||||
```
|
||||
|
||||
-- вывести все таблицы
|
||||
```sh
|
||||
\d
|
||||
```
|
||||
|
||||
-- удалить таблицу my_table
|
||||
```sql
|
||||
DROP TABLE my_table;
|
||||
```
|
||||
|
||||
-- внести в таблицу запись
|
||||
```sql
|
||||
INSERT INTO my_table(field1, field2) VALUES(1,'Any text value');
|
||||
```
|
||||
|
||||
-- вывести записи
|
||||
```sql
|
||||
SELECT * FROM my_table; -- все записи
|
||||
SELECT * FROM my_table WHERE field1 = 1; -- все, где field1 = 1
|
||||
SELECT * FROM my_table WHERE field1 != 1; -- и т д
|
||||
SELECT * FROM my_table WHERE field1 > 1;
|
||||
SELECT * FROM my_table LIMIT 100; -- первые 100 записей;
|
||||
SELECT * FROM my_table LIMIT 100 OFFSET 200; -- запись с 201 по 300;
|
||||
```
|
||||
|
||||
-- сортировка при выводе
|
||||
```sql
|
||||
SELECT * FROM my_table ORDER BY field1 ASC; -- вывести отсортировав в возрастающем порядке
|
||||
SELECT * FROM my_table ORDER BY field1 DESC; -- вывести отсортировав в убывающем порядке
|
||||
```
|
||||
|
||||
-- изменить запись таблицы (поле field2 строки, где field1 = 1);
|
||||
```sql
|
||||
UPDATE my_table SET field2 = 'Other text value' WHERE field1 = 1;
|
||||
```
|
||||
|
||||
-- удаление данных
|
||||
```sql
|
||||
DELETE FROM my_table; -- удалить все записи;
|
||||
DELETE FROM my_table WHERE field1 = 1; -- удалить запись где field1 = 1;
|
||||
```
|
||||
|
||||
|
||||
-- ***********************************
|
||||
-- нормализация (разбиение таблиц на несколько)
|
||||
-- ***********************************
|
||||
|
||||
-- Constraints - ограничения типов данных
|
||||
```sql
|
||||
CREATE TABLE my_table (
|
||||
field1 INT NOT NULL, -- запись обязательна
|
||||
field2 VARCHAR(255) NOT NULL UNIQUE, -- запись должна быть уникальной
|
||||
field3 BOOLEAN NOT NULL DEFAULT TRUE -- значение по умолчанию - true
|
||||
...
|
||||
);
|
||||
```
|
||||
|
||||
-- Первичный и внешние ключи
|
||||
-- при создании записи таблицы с отсутствующим внешним ключом выведется запись об ошибке. будут выводится ошибки и в иных случаях, когда будут нарушаться связи.
|
||||
CREATE TABLE IF NOT EXISTS my_table ( -- ключ IF NOT EXISTS проверяет, существует ли таблица.
|
||||
field1 SERIAL INT PRIMARY KEY, -- при добавлении PRIMARY KEY поле автоматически наследует ограничения NOT NULL и UNIQUE, и создается индекс. SERIAL тип данных являющийся автоматически увеличивающимся счетчиком (аналог ключа AUTOINCREMENT в Sqlite)
|
||||
field2 VARCHAR(255) NOT NULL UNIQUE,
|
||||
field3 INT NOT NULL,
|
||||
FOREIGN KEY(field3) REFERENCES other_table(field_name) -- поле ссылается на внешнюю таблицу other_table на поле field_name, которое обязательно должно быть с PRIMARY KEY
|
||||
);
|
||||
|
||||
-- вывод данных из нескольких таблиц со связанными полями
|
||||
```sql
|
||||
SELECT * FROM table_1 LEFT JOIN table_2 ON (table_2.field = table_1.field);
|
||||
```
|
||||
|
||||
-- алиасы, нужны для удобства. Также, при выводе наименование таблиц или полей выводится алиасом, при его наличии.
|
||||
```sql
|
||||
SELECT * FROM table_1 as tab1 LEFT JOIN table_2 as tab2 ON (tab1.field = tab2.field);
|
||||
```
|
||||
Reference in New Issue
Block a user