- Home »

Учебник по созданию веб-приложений на Java для начинающих
Помню, как лет 10 назад мучался с первым Java-приложением — куча XML-конфигов, Tomcat, который упорно не хотел стартовать, и Spring, который казался чёрной магией. Сейчас всё намного проще, но новичкам по-прежнему сложно разобраться в экосистеме. Если ты системный администратор, девопс или просто любишь ковыряться с серверами, то Java веб-приложения — это то, с чем придётся работать постоянно. Банки, энтерпрайз, микросервисы — везде Java.
Эта статья поможет тебе пройти путь от пустого сервера до работающего веб-приложения. Без воды, с конкретными командами и примерами. Покажу, как избежать типичных граблей и настроить всё так, чтобы потом не было больно за потраченное время.
Как это работает под капотом
Java веб-приложение — это не просто код, а целая экосистема. В основе лежит Java Virtual Machine (JVM), поверх которой крутится веб-сервер (например, Tomcat или Jetty). Твоё приложение упаковывается в WAR-файл и разворачивается на сервере.
Классическая архитектура выглядит так:
- HTTP-запрос → веб-сервер (Nginx/Apache)
- Прокси → сервер приложений (Tomcat)
- Обработка → Java-код (Spring Boot/servlet)
- База данных → PostgreSQL/MySQL
- Ответ → обратно клиенту
Современный подход — Spring Boot с встроенным Tomcat. Получается fat JAR, который можно запустить одной командой. Намного проще для деплоя и администрирования.
Быстрая настройка окружения
Для начала нужен сервер. Рекомендую взять VPS на 2-4 ГБ RAM — Java прожорливая к памяти. Для продакшна лучше сразу выделенный сервер.
Ставим базовое окружение на Ubuntu 22.04:
sudo apt update && sudo apt upgrade -y
sudo apt install openjdk-17-jdk maven nginx postgresql -y
# Проверяем версию Java
java -version
# Должно показать: openjdk version "17.0.x"
# Устанавливаем переменную JAVA_HOME
echo 'export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"' >> ~/.bashrc
source ~/.bashrc
Создаём простейшее Spring Boot приложение:
mkdir ~/webapp && cd ~/webapp
mvn archetype:generate -DgroupId=com.example -DartifactId=webapp \
-DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
cd webapp
Теперь правим pom.xml
, добавляем Spring Boot:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>webapp</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Создаём основу приложения
Создаём структуру проекта:
mkdir -p src/main/java/com/example/webapp
mkdir -p src/main/resources
# Главный класс приложения
cat > src/main/java/com/example/webapp/Application.java << 'EOF'
package com.example.webapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
EOF
# Простой контроллер
cat > src/main/java/com/example/webapp/HelloController.java << 'EOF'
package com.example.webapp;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/")
public String hello() {
return "Hello, World! Server time: " + java.time.LocalDateTime.now();
}
@GetMapping("/health")
public String health() {
return "OK";
}
}
EOF
Конфигурируем подключение к базе:
cat > src/main/resources/application.properties << 'EOF'
# Настройки базы данных
spring.datasource.url=jdbc:postgresql://localhost:5432/webapp
spring.datasource.username=webuser
spring.datasource.password=webpass
spring.jpa.hibernate.ddl-auto=create-drop
# Настройки сервера
server.port=8080
server.servlet.context-path=/api
# Логирование
logging.level.com.example.webapp=DEBUG
logging.file.name=webapp.log
EOF
Настройка базы данных
Создаём базу и пользователя:
sudo -u postgres psql
CREATE DATABASE webapp;
CREATE USER webuser WITH PASSWORD 'webpass';
GRANT ALL PRIVILEGES ON DATABASE webapp TO webuser;
\q
Создаём простую Entity для работы с БД:
cat > src/main/java/com/example/webapp/User.java << 'EOF'
package com.example.webapp;
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false, unique = true)
private String email;
// Конструкторы, геттеры и сеттеры
public User() {}
public User(String name, String email) {
this.name = name;
this.email = email;
}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
EOF
Примеры использования и сравнение подходов
Подход | Плюсы | Минусы | Когда использовать |
---|---|---|---|
Spring Boot + embedded Tomcat | Быстрый старт, простой деплой, автоконфигурация | Больше RAM, меньше контроля | Микросервисы, стартапы |
Traditional WAR + Tomcat | Гибкость настройки, меньше памяти | Сложнее настройка, больше конфигов | Enterprise, монолиты |
Spring Boot + Docker | Изоляция, масштабируемость | Overhead Docker, сложность отладки | Kubernetes, CI/CD |
Пример расхода памяти на моём тестовом сервере:
# Spring Boot приложение
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head -10
# Типичное потребление:
# - Spring Boot: ~300-500 MB
# - Tomcat standalone: ~200-300 MB
# - Nginx: ~10-20 MB
# - PostgreSQL: ~50-100 MB
Сборка и запуск
Собираем проект:
mvn clean package
# Запускаем локально для тестирования
java -jar target/webapp-1.0.0.jar
# Или через Maven
mvn spring-boot:run
Тестируем работу:
curl http://localhost:8080/api/
curl http://localhost:8080/api/health
# Должны получить ответы
Настройка production окружения
Создаём systemd сервис для автозапуска:
sudo tee /etc/systemd/system/webapp.service > /dev/null << 'EOF'
[Unit]
Description=Java Web Application
After=network.target
[Service]
Type=simple
User=webapp
WorkingDirectory=/opt/webapp
ExecStart=/usr/bin/java -jar -Xmx512m -Xms256m webapp-1.0.0.jar
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Создаём пользователя для приложения
sudo useradd -r -s /bin/false webapp
sudo mkdir -p /opt/webapp
sudo cp target/webapp-1.0.0.jar /opt/webapp/
sudo chown -R webapp:webapp /opt/webapp
# Включаем и запускаем сервис
sudo systemctl daemon-reload
sudo systemctl enable webapp
sudo systemctl start webapp
sudo systemctl status webapp
Настраиваем Nginx как reverse proxy:
sudo tee /etc/nginx/sites-available/webapp > /dev/null << 'EOF'
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Таймауты
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
# Статические файлы (если есть)
location /static/ {
alias /opt/webapp/static/;
expires 30d;
}
# Мониторинг
location /health {
proxy_pass http://localhost:8080/api/health;
access_log off;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/webapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Мониторинг и отладка
Полезные команды для мониторинга:
# Логи приложения
sudo journalctl -u webapp -f
# Потребление ресурсов
sudo htop
sudo iotop
# Подключения к базе
sudo netstat -tulpn | grep :5432
# HTTP соединения
sudo ss -tuln | grep :8080
# Проверка работы JVM
jps -v
jstat -gc [PID]
Настройка логирования с ротацией:
sudo tee /etc/logrotate.d/webapp > /dev/null << 'EOF'
/opt/webapp/webapp.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
copytruncate
}
EOF
Альтернативные решения и инструменты
Если Spring Boot кажется избыточным, есть несколько альтернатив:
- Micronaut — быстрый старт, меньше памяти, компиляция в native
- Quarkus — от Red Hat, ориентирован на cloud-native
- Vert.x — реактивный подход, высокая производительность
- Play Framework — если нравится Scala/функциональщина
Ссылки на документацию:
Автоматизация и CI/CD
Простой деплой скрипт:
#!/bin/bash
# deploy.sh
echo "Building application..."
mvn clean package -DskipTests
echo "Stopping service..."
sudo systemctl stop webapp
echo "Backing up current version..."
sudo cp /opt/webapp/webapp-1.0.0.jar /opt/webapp/webapp-backup.jar
echo "Deploying new version..."
sudo cp target/webapp-1.0.0.jar /opt/webapp/
sudo chown webapp:webapp /opt/webapp/webapp-1.0.0.jar
echo "Starting service..."
sudo systemctl start webapp
echo "Waiting for startup..."
sleep 10
echo "Health check..."
if curl -f http://localhost:8080/api/health; then
echo "✅ Deployment successful!"
else
echo "❌ Deployment failed, rolling back..."
sudo systemctl stop webapp
sudo cp /opt/webapp/webapp-backup.jar /opt/webapp/webapp-1.0.0.jar
sudo systemctl start webapp
fi
Для продакшна рекомендую настроить Blue-Green deployment или использовать Docker с Kubernetes.
Нестандартные способы использования
Несколько интересных кейсов из практики:
- Embedded база данных — H2 для прототипов и тестирования
- Websocket для real-time — чаты, уведомления, мониторинг
- Scheduled задачи — @Scheduled для cron-like функций
- Интеграция с Redis — кэширование, сессии
- Metrics с Micrometer — интеграция с Prometheus/Grafana
Пример интеграции с Redis:
# В pom.xml добавляем
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
# В application.properties
spring.redis.host=localhost
spring.redis.port=6379
spring.cache.type=redis
Заключение и рекомендации
Java веб-приложения — это не так страшно, как кажется. Spring Boot убрал большую часть боли с настройкой, а современные инструменты позволяют быстро получить работающий результат.
Мои рекомендации:
- Начинай с Spring Boot — меньше головной боли
- Используй PostgreSQL для БД — надёжнее MySQL
- Обязательно настрой мониторинг и логирование
- Автоматизируй деплой с самого начала
- Не экономь на RAM — Java любит память
Когда использовать Java:
- Enterprise приложения с высокой нагрузкой
- Микросервисы в корпоративной среде
- Интеграция с legacy системами
- Когда нужна типизация и стабильность
Когда лучше выбрать что-то другое:
- Простые CRUD приложения — лучше Python/Django
- Real-time системы — Node.js эффективнее
- Прототипы и MVP — Ruby on Rails быстрее
Помни: лучший стек — тот, который знает твоя команда. Java хороша для долгосрочных проектов, где важна стабильность и производительность. Если планируешь серьёзный проект, не экономь на сервере — бери сразу нормальное железо, потом будет сложнее мигрировать.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.