Home » Учебник по созданию веб-приложений на Java для начинающих
Учебник по созданию веб-приложений на Java для начинающих

Учебник по созданию веб-приложений на 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 хороша для долгосрочных проектов, где важна стабильность и производительность. Если планируешь серьёзный проект, не экономь на сервере — бери сразу нормальное железо, потом будет сложнее мигрировать.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked