← Назад к вопросам

Какие знаешь виды конфигураций?

1.6 Junior🔥 121 комментариев
#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Виды конфигураций в Java

Конфигурация приложения — критически важна для запуска одного кода в разных окружениях (dev, test, prod). Разберу основные подходы, которые использую в практике.

1. Properties файлы

Классический и простейший способ конфигурации:

// application.properties
app.name=MyApplication
app.version=1.0.0
server.port=8080
server.servlet.context-path=/api
database.url=jdbc:mysql://localhost:3306/mydb
database.username=root
database.password=secret

// Чтение в коде
import java.io.FileInputStream;
import java.util.Properties;

public class PropertiesConfigExample {
    public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        
        // Способ 1: из файла
        try (FileInputStream fis = new FileInputStream("application.properties")) {
            props.load(fis);
        }
        
        String appName = props.getProperty("app.name");
        int port = Integer.parseInt(props.getProperty("server.port"));
        
        System.out.println("App: " + appName + " on port: " + port);
        
        // Способ 2: со значением по умолчанию
        String timeout = props.getProperty("request.timeout", "30");
    }
}

В Spring Boot автоматически загружается application.properties:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class AppConfig {
    @Value("${app.name}")
    private String appName;
    
    @Value("${server.port:8080}")
    private int port;
    
    @Value("${database.url}")
    private String dbUrl;
}

2. YAML конфигурация

Более читаемый формат чем properties:

# application.yml
app:
  name: MyApplication
  version: 1.0.0
  settings:
    timeout: 30
    retries: 3

server:
  port: 8080
  servlet:
    context-path: /api

database:
  url: jdbc:mysql://localhost:3306/mydb
  username: root
  password: secret
  pool:
    max-size: 20
    min-idle: 5
    timeout: 30

logging:
  level:
    root: INFO
    com.myapp: DEBUG
    org.springframework: WARN

Чтение YAML в Java:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;

@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private String name;
    private String version;
    private Settings settings;
    
    public static class Settings {
        private int timeout;
        private int retries;
        
        // getters/setters
    }
}

@Component
@ConfigurationProperties(prefix = "database")
public class DatabaseProperties {
    private String url;
    private String username;
    private String password;
    private Pool pool;
    
    public static class Pool {
        private int maxSize;
        private int minIdle;
        private int timeout;
    }
}

3. Environment Variables (переменные окружения)

Для конфигурации в Docker/Kubernetes:

// Linux/Mac
export APP_NAME="MyApp"
export SERVER_PORT=9000
export DATABASE_URL="jdbc:mysql://db-server:3306/mydb"
java -jar app.jar

// Windows
set APP_NAME=MyApp
set SERVER_PORT=9000
java -jar app.jar

// Docker
# Dockerfile
ENV APP_NAME=MyApp
ENV SERVER_PORT=8080

Чтение в коде:

public class EnvironmentConfigExample {
    public static void main(String[] args) {
        // Читаем из переменных окружения
        String appName = System.getenv("APP_NAME");
        String port = System.getenv("SERVER_PORT");
        
        System.out.println("App: " + appName + " Port: " + port);
        
        // Если не установлена, использовать default
        String dbUrl = System.getenv("DATABASE_URL");
        if (dbUrl == null) {
            dbUrl = "jdbc:mysql://localhost:3306/default";
        }
    }
}

// Spring Boot автоматически читает env variables
@Component
public class EnvConfig {
    @Value("${APP_NAME:DefaultApp}")
    private String appName;
    
    @Value("${SERVER_PORT:8080}")
    private int port;
}

4. Command Line Arguments (параметры командной строки)

public class CommandLineExample {
    public static void main(String[] args) {
        // java -jar app.jar --server.port=9000 --app.name=MyApp
        
        for (String arg : args) {
            System.out.println("Argument: " + arg);
        }
    }
}

// Spring Boot парсит автоматически
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        // Вызов: java -jar app.jar --spring.config.location=config/app.properties
    }
}

5. System Properties (системные свойства JVM)

public class SystemPropertiesExample {
    public static void main(String[] args) {
        // Установить свойство
        System.setProperty("app.mode", "production");
        
        // Прочитать свойство
        String mode = System.getProperty("app.mode");
        
        // Встроенные свойства
        System.out.println("OS: " + System.getProperty("os.name"));
        System.out.println("Java version: " + System.getProperty("java.version"));
        System.out.println("User dir: " + System.getProperty("user.dir"));
    }
}

// Запуск с системными свойствами
// java -Dapp.mode=production -Dserver.port=9000 -jar app.jar

6. Configuration Classes (Java-based конфигурация)

Spring конфигурация через Java классы:

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Value;

@Configuration
public class AppConfiguration {
    @Value("${database.url}")
    private String dbUrl;
    
    @Value("${database.username}")
    private String username;
    
    @Value("${database.password}")
    private String password;
    
    // Создание bean'а с конфигурацией
    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(dbUrl);
        config.setUsername(username);
        config.setPassword(password);
        config.setMaximumPoolSize(20);
        return new HikariDataSource(config);
    }
    
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    }
}

// Использование
@Component
public class MyService {
    private final DataSource dataSource;
    
    public MyService(DataSource dataSource) {
        this.dataSource = dataSource;
    }
}

7. .env файлы (для локальной разработки)

# .env
APP_NAME=MyApplication
SERVER_PORT=8080
DATABASE_URL=jdbc:mysql://localhost:3306/mydb
DATABASE_USERNAME=root
DATABASE_PASSWORD=secret
JWT_SECRET=my-secret-key-very-long
ACTIVE_PROFILE=dev
import io.github.cdimascio.dotenv.Dotenv;

public class DotEnvExample {
    public static void main(String[] args) {
        // Зависимость: io.github.cdimascio:java-dotenv:0.3.0
        Dotenv dotenv = Dotenv.load();
        
        String appName = dotenv.get("APP_NAME");
        String dbUrl = dotenv.get("DATABASE_URL");
        
        System.out.println("App: " + appName);
        System.out.println("DB: " + dbUrl);
    }
}

8. Конфигурация для разных профилей (Dev/Test/Prod)

# application.yml (основной)
app:
  name: MyApplication

spring:
  profiles:
    active: dev

---
# application-dev.yml
spring:
  config:
    activate:
      on-profile: dev

server:
  port: 8080
  
database:
  url: jdbc:mysql://localhost:3306/mydb_dev
  username: root
  password: secret

logging:
  level:
    root: DEBUG

---
# application-prod.yml
spring:
  config:
    activate:
      on-profile: prod

server:
  port: 443
  ssl:
    enabled: true
    key-store: classpath:keystore.jks
  
database:
  url: jdbc:mysql://prod-db-server:3306/mydb_prod
  username: ${DATABASE_USERNAME}
  password: ${DATABASE_PASSWORD}

logging:
  level:
    root: WARN

Активация профилей:

# Запуск с профилем dev
java -jar app.jar --spring.profiles.active=dev

# Или через переменную окружения
export SPRING_PROFILES_ACTIVE=prod
java -jar app.jar

# Или через application.properties
spring.profiles.active=prod

9. ConfigMap и Secrets в Kubernetes

# kubernetes-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  application.yml: |
    server:
      port: 8080
    app:
      name: MyApplication
---
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
stringData:
  database-password: secret123
  jwt-secret: my-secret-key
---
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: config
      mountPath: /etc/config
    env:
    - name: DATABASE_PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secrets
          key: database-password
  volumes:
  - name: config
    configMap:
      name: app-config

10. JSON конфигурация

{
  "app": {
    "name": "MyApplication",
    "version": "1.0.0"
  },
  "server": {
    "port": 8080,
    "threads": 20
  },
  "database": {
    "url": "jdbc:mysql://localhost:3306/mydb",
    "username": "root",
    "password": "secret",
    "pool": {
      "maxSize": 20,
      "minIdle": 5
    }
  }
}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.file.Files;
import java.nio.file.Paths;

public class JsonConfigExample {
    static class AppConfig {
        public String name;
        public String version;
        public Server server;
        public Database database;
        
        static class Server {
            public int port;
            public int threads;
        }
        
        static class Database {
            public String url;
            public String username;
            public String password;
        }
    }
    
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String json = new String(Files.readAllBytes(Paths.get("config.json")));
        AppConfig config = mapper.readValue(json, AppConfig.class);
        
        System.out.println("App: " + config.name);
        System.out.println("Port: " + config.server.port);
    }
}

Сравнение методов конфигурации

МетодПростотаФлексибильностьДля productionПримечания
Properties✓✓✓Классический способ
YAML✓✓✓✓✓✓✓Более читаемо
Env Variables✓✓✓✓✓✓✓✓Docker/Kubernetes стандарт
Command Line✓✓Для override'ов
Java Config✓✓✓✓✓✓Типизировано
.env файлы✓✓✓Только для dev
Профили✓✓✓✓✓✓✓✓Разные окружения
ConfigMap✓✓✓✓✓✓Kubernetes только

Лучшие практики

public class ConfigBestPractices {
    /**
     * 1. НИКОГДА не хардкодь пароли, API ключи, секреты
     */
    // ❌ НЕПРАВИЛЬНО
    private String dbPassword = "secret123";
    
    // ✅ ПРАВИЛЬНО
    @Value("${database.password}")
    private String dbPassword;
    
    /**
     * 2. Используй environment variables для продакшена
     * - Совместимо с Docker/Kubernetes
     * - Безопаснее чем файлы
     * - Проще управлять
     */
    
    /**
     * 3. Разделяй конфигурацию по профилям
     * - Dev, Test, Prod конфиги отдельно
     * - Меньше ошибок при деплое
     */
    
    /**
     * 4. Типизируй конфигурацию
     * - Используй ConfigurationProperties
     * - Валидируй значения
     * - IDE подсказки
     */
    
    /**
     * 5. Документируй все конфигурационные параметры
     * - Какие есть
     * - Какие обязательные
     * - Какие значения по умолчанию
     */
}

Рекомендованный подход для production

# 1. Основные настройки в application.yml
# 2. Специфичные настройки в application-{profile}.yml
# 3. Секреты и sensitive данные только через Environment Variables
# 4. Переопределение через Command Line при необходимости

java -Dspring.profiles.active=prod \
  -Dserver.port=443 \
  -jar app.jar

Этот подход даёт максимальную флексибильность и безопасность.

Какие знаешь виды конфигураций? | PrepBro