Пул строк в Java не является пустым при старте JAR файла. Он изначально содержит несколько предопределенных строковых литералов, которые JVM использует для своей внутренней работы, а также строковые литералы, используемые в загруженных классах и стандартных библиотеках.
JVM и стандартные библиотеки Java используют различные строковые литералы для своей работы. Эти строки добавляются в пул строк при запуске JVM. Примеры таких строк включают имена основных классов и пакетов (например,
"java/lang/Object", "java/lang/String").Когда классы загружаются JVM, все строковые литералы, используемые в этих классах, добавляются в пул строк. Это включает строки, используемые в JAR файле, а также строки из стандартных библиотек Java, которые загружаются при старте.
Для демонстрации этого можно написать простой код, который проверяет, присутствуют ли определенные строки в пуле строк при старте программы.
public class StringPoolDemo {
public static void main(String[] args) {
// Проверка стандартных строк, которые могут быть в пуле строк
String str1 = "java";
String str2 = "lang";
String str3 = "Object";
// Вывод строк
System.out.println("str1: " + str1);
System.out.println("str2: " + str2);
System.out.println("str3: " + str3);
// Проверка строк в пуле строк
System.out.println("Is 'java' in pool: " + (str1 == "java"));
System.out.println("Is 'lang' in pool: " + (str2 == "lang"));
System.out.println("Is 'Object' in pool: " + (str3 == "Object"));
}
}При запуске JVM загружаются системные классы, такие как
java.lang.Object, java.lang.String, java.lang.System, и другие. Строковые литералы, используемые в этих классах, добавляются в пул строк.Когда JVM загружает пользовательские классы из JAR файла, все строковые литералы в этих классах также добавляются в пул строк.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🤔2
1. Фильтры (Filters):
- Создайте фильтр, который проверяет, существует ли активная сессия, и перенаправляет на страницу входа, если сессия недействительна.
2. Настройка безопасности в web.xml:
- Используйте <security-constraint> и роли для ограничения доступа к сервлетам.
3. Проверка в коде:
- Проверяйте сессию непосредственно в сервлете с помощью request.getSession(false).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Это два интерфейса в JDBC, которые используются для выполнения SQL-запросов к базе данных. Основные различия между ними касаются производительности, безопасности и удобства использования.
Statement используется для выполнения простых SQL-запросов. Запросы формируются и передаются в базу данных в виде строки. Подходит для простых запросов. Не оптимизирован для повторного выполнения. Каждый раз, когда запрос передается в базу данных, он компилируется и выполняется заново. Уязвим к SQL-инъекциям. Поскольку запрос формируется путем конкатенации строк, злоумышленники могут внедрять вредоносный SQL-код.
Statement stmt = connection.createStatement();
String query = "SELECT * FROM employees WHERE department = 'HR'";
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println("ID: " + id + ", Name: " + name);
}
stmt.close();
PreparedStatement используется для выполнения предварительно скомпилированных SQL-запросов. Это позволяет повысить производительность и безопасность. Оптимизирован для повторного выполнения. Запрос компилируется только один раз, а затем может многократно выполняться с разными параметрами, что повышает производительность. Защита от SQL-инъекций. Использует параметризованные запросы, которые помогают избежать уязвимостей, связанных с SQL-инъекциями. Удобство работы с параметрами. Позволяет устанавливать значения параметров с использованием методов setInt(), setString() и других.
String query = "SELECT * FROM employees WHERE department = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, "HR");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println("ID: " + id + ", Name: " + name);
}
pstmt.close();
Statement: Каждый запрос компилируется заново, что снижает производительность при многократном выполнении одного и того же запроса.PreparedStatement: Запрос компилируется один раз и может многократно выполняться с разными параметрами, что повышает производительность.Statement: Уязвим к SQL-инъекциям, поскольку запросы формируются путем конкатенации строк.PreparedStatement: Использует параметризованные запросы, что защищает от SQL-инъекций.Statement: Подходит для простых, одноразовых запросов.PreparedStatement: Удобен для многократного выполнения запросов с разными параметрами.Оба интерфейса могут выполнять запросы типа
SELECT, INSERT, UPDATE, DELETE, но PreparedStatement более удобен для запросов с параметрами.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1
- Установите SSL-сертификат на сервер (например, через Let’s Encrypt).
- Настройте сервер (Apache, Nginx) для принудительного использования HTTPS.
2. Редирект HTTP → HTTPS:
- Настройте перенаправление на уровне сервера или используйте фильтры.
3. Установите безопасные атрибуты куки:
- Используйте Secure и HttpOnly, чтобы защитить куки от утечки.
4. Шифрование данных:
- Передавайте конфиденциальные данные только через HTTPS.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥7
JSP страница переводится в сервлетный Java-код. JSP контейнер анализирует содержимое JSP страницы и создает соответствующий сервлетный исходный код (.java файл).
Сервлетный исходный код компилируется в байт-код, создавая .class файл (сервлет). Этот этап аналогичен компиляции обычного Java-кода.
Скомпилированный класс сервлета загружается в память. Контейнер загружает класс сервлета, чтобы он мог быть выполнен.
Контейнер вызывает метод
jspInit(). Этот метод вызывается один раз при первом создании сервлета или при перезапуске сервера и предназначен для выполнения инициализационных задач (например, настройка ресурсов).Для каждого HTTP-запроса вызывается метод
jspService(). Этот метод обрабатывает входящий запрос и генерирует соответствующий ответ. Основная работа по генерации динамического содержимого происходит на этом этапе.Когда JSP страница выводится из эксплуатации (например, при остановке сервера), контейнер вызывает метод
jspDestroy(). Этот метод используется для освобождения ресурсов (например, закрытие соединений с базой данных).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯3🔥2👾1
1. Подключение к базе данных:
- Используйте пул соединений (например, HikariCP или Apache DBCP) для повышения производительности.
- Настройте подключение через файл конфигурации (web.xml или context.xml).
2. Журналирование:
- Интегрируйте библиотеку логирования (например, Log4j, SLF4J).
- Логируйте SQL-запросы, ошибки и основные действия пользователя для отладки и аналитики.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
- Поддержка асинхронных запросов для улучшения производительности.
2. Аннотации:
- Упрощение конфигурации сервлетов, фильтров и слушателей через
3. Сканирование компонентов:
- Автоматическое обнаружение сервлетов и фильтров без необходимости указывать их в web.xml.
4. Поддержка загрузки файлов:
- Упрощенная работа с файлами через многочастные запросы (MultipartConfig).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
- Простой метод аутентификации с передачей имени и пароля в HTTP-заголовках.
2. Form-Based Authentication:
- Пользователь вводит логин и пароль в HTML-форме, данные проверяются сервером.
3. Digest Authentication:
- Более безопасный метод, где пароль хэшируется перед передачей.
4. Client Certificate Authentication:
- Использование SSL-сертификатов клиента для аутентификации.
5. Кастомная аутентификация:
- Реализация пользовательской логики проверки сессии и токенов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥5
Чтобы написанная на Java программа заработала, необходимо выполнить несколько шагов, начиная с написания кода и заканчивая его запуском.
Напишите Java-код в текстовом редакторе или интегрированной среде разработки (IDE), такой как IntelliJ IDEA, Eclipse или NetBeans.
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}Убедитесь, что на вашем компьютере установлен JDK (Java Development Kit). JDK включает в себя компилятор (javac) и виртуальную машину Java (JVM). Скачайте и установите последнюю версию JDK с сайта Oracle или OpenJDK.
Компилируйте Java-код в байт-код, который будет выполняться на JVM. Для этого используйте команду
javac. После компиляции появится файл HelloWorld.class, содержащий байт-код.javac HelloWorld.java
Запустите скомпилированный байт-код с помощью виртуальной машины Java (JVM), используя команду
java. java HelloWorld
Вывод должен быть:
Hello, World!
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19😁8
Это объектно-ориентированный, кроссплатформенный язык с автоматическим управлением памятью. Он предоставляет мощную библиотеку, высокую производительность и надежную модель многопоточности. Java поддерживает строгую типизацию, что помогает избежать многих ошибок на этапе компиляции. Код Java компилируется в байт-код, который выполняется виртуальной машиной Java (JVM).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14😁2👀1
Оптимизация запросов в базе данных (БД) — это процесс улучшения их производительности, чтобы они выполнялись быстрее и использовали меньше ресурсов. Рассмотрим основные способы оптимизации SQL-запросов.
Индексы ускоряют поиск данных, создавая структуру, похожую на оглавление книги. Вместо полного перебора таблицы (Full Table Scan), БД быстро находит нужные строки по индексу.
CREATE INDEX idx_user_name ON users(name);
Избегайте
SELECT *, так как это нагружает систему избыточными данными. Плохо
SELECT * FROM users;
Хорошо
SELECT id, name FROM users;
Перед оптимизацией полезно посмотреть, как БД выполняет запрос.
EXPLAIN SELECT * FROM users WHERE name = 'Ivan';
Если вам нужно получить только первые N строк, используйте
LIMIT, чтобы БД не грузила лишние данные. SELECT * FROM users ORDER BY id LIMIT 10;
Соединение (
JOIN) таблиц может быть дорогостоящим. Вот несколько рекомендаций: - Используйте индексы на полях, участвующих в
JOIN. - Если возможно, замените сложные
JOIN на подзапросы (EXISTS, IN). CREATE INDEX idx_orders_user_id ON orders(user_id);
Часто повторяющиеся запросы можно кэшировать на уровне БД (
QUERY CACHE в MySQL) или в приложении (Redis, Memcached). SET GLOBAL query_cache_size = 1000000;
Нормализация уменьшает дублирование данных, разбивая таблицы.
Денормализация может ускорить работу, дублируя данные и уменьшая количество
JOIN. Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🤯2🔥1
В Spring действительно можно создать два синглтона, но тут важно понимать, что Spring использует паттерн Singleton на уровне контейнера, а не на уровне JVM. Давайте разберёмся, как это возможно.
В Spring синглтон означает, что в рамках одного контекста (
ApplicationContext) создаётся один экземпляр бина. @Component
public class MySingletonBean {
public MySingletonBean() {
System.out.println("Создан экземпляр MySingletonBean");
}
}
Есть несколько способов создать два синглтона.
Создание двух контекстов (
ApplicationContext) Spring гарантирует синглтонность только в одном контексте. Если создать два контекста, можно получить два независимых синглтона.
AnnotationConfigApplicationContext context1 = new AnnotationConfigApplicationContext(AppConfig.class);
AnnotationConfigApplicationContext context2 = new AnnotationConfigApplicationContext(AppConfig.class);
MySingletonBean bean1 = context1.getBean(MySingletonBean.class);
MySingletonBean bean2 = context2.getBean(MySingletonBean.class);
System.out.println(bean1 == bean2); // false! Два разных объекта
Определение двух бинов одного типа
Можно создать два разных бина, просто давая им разные имена в конфигурации.
@Configuration
public class AppConfig {
@Bean
public MySingletonBean firstSingleton() {
return new MySingletonBean();
}
@Bean
public MySingletonBean secondSingleton() {
return new MySingletonBean();
}
}
Теперь оба метода создадут разные объекты.
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MySingletonBean bean1 = context.getBean("firstSingleton", MySingletonBean.class);
MySingletonBean bean2 = context.getBean("secondSingleton", MySingletonBean.class);
System.out.println(bean1 == bean2); // false
Изменение области (
scope) бина Если изменить область (
@Scope), можно получить два экземпляра в одном контексте, но тогда это уже не будет синглтон. @Component
@Scope("prototype")
public class MyBean {
public MyBean() {
System.out.println("Создан новый экземпляр MyBean");
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28
- Куча используется для объектов и динамической памяти.
- Стек содержит локальные переменные и вызовы методов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23🔥4🤔2❤1
В MySQL (и других реляционных БД) типы данных
DATETIME и TIMESTAMP используются для хранения даты и времени, но у них есть несколько ключевых отличий. Используйте
DATETIME, если: Нужно хранить фиксированное значение даты и времени, не зависящее от часового пояса.
Работаете с датами за пределами 1970-2038 гг.
Требуется удобочитаемый формат (без конверсий).
Используйте
TIMESTAMP, если: Нужно учитывать часовой пояс (например, хранить время в UTC, а при запросе автоматически конвертировать в локальное).
Важно автоматическое обновление при изменении строки (
ON UPDATE CURRENT_TIMESTAMP). Нужно экономить память (занимает в 2 раза меньше места, чем
DATETIME). DATETIME (Фиксированная дата и время)
CREATE TABLE events (
id INT PRIMARY KEY,
event_time DATETIME NOT NULL
);
INSERT INTO events VALUES (1, '2025-02-17 12:30:00');
TIMESTAMP (Автообновление + Часовые пояса)
CREATE TABLE logs (
id INT PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Если изменим
time_zone, TIMESTAMP отобразится в новом часовом поясе. SET time_zone = 'Europe/Moscow';
SELECT created_at FROM logs;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤1
Каждый бин (компонент) проходит через жизненный цикл, который начинается с его создания и заканчивается уничтожением. Этот цикл включает в себя ряд этапов, на которых он предоставляет различные точки для настройки поведения бина. Вот основные этапы жизненного цикла:
Создает экземпляр бина из класса определения бина.
Внедряет значения и ссылки на другие бины в свойства текущего бина, используя конфигурацию, заданную в XML, аннотациях или конфигурации.
Если бин реализует один из Aware интерфейсов, он вызывает соответствующие методы, передавая экземпляру бина ссылку на контекст, фабрику бинов и т.д.
Перед инициализацией бина, он дает возможность BeanPostProcessor'ам обработать объект. Это может быть использовано для проксирования бинов или для иной предварительной обработки.
Если для бина определен метод инициализации (через аннотацию
@PostConstruct, интерфейс InitializingBean или атрибут init-method в XML-конфигурации), он вызывает его после того, как все свойства бина были установлены.После вызова метода инициализации бин полностью инициализирован и готов к использованию в приложении.
Когда контекст приложения закрывается, и бины должны быть уничтожены, он вызывает метод уничтожения для бинов, которые определяют его (через аннотацию
@PreDestroy, интерфейс DisposableBean или атрибут destroy-method в XML-конфигурации).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20🔥3
Методы
Thread.sleep() и Thread.yield() в Java используются для управления потоком, но работают по-разному. Метод
Thread.sleep(milliseconds) приостанавливает выполнение текущего потока на указанное время. Поток уходит в состояние "ожидания" (TIMED_WAITING).
Операционная система не даёт ему процессорное время в течение заданного времени.
После завершения паузы поток снова становится готовым к выполнению (RUNNABLE).
public class SleepExample {
public static void main(String[] args) {
System.out.println("Начало работы...");
try {
Thread.sleep(2000); // Пауза на 2 секунды
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Прошло 2 секунды");
}
}Результат
Начало работы...
(пауза 2 секунды)
Прошло 2 секунды
Метод
Thread.yield() даёт возможность другим потокам выполнить работу. Текущий поток передаёт управление планировщику (scheduler).
Если есть другие потоки с таким же или более высоким приоритетом, они получат процессорное время.
Если таких потоков нет, то текущий поток продолжит выполняться.
public class YieldExample {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
Thread.yield(); // Позволяет другим потокам выполняться
}
};
Thread t1 = new Thread(task, "Поток-1");
Thread t2 = new Thread(task, "Поток-2");
t1.start();
t2.start();
}
}Результат (примерный, зависит от планировщика ОС)
Поток-1 - 1
Поток-2 - 1
Поток-1 - 2
Поток-2 - 2
...
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19