Liigu peamise sisu juurde

Konfiguratsioonifailid (.properties)

Sissejuhatus

Rakendused vajavad sageli erinevaid konfiguratsiooniväärtusi, olgu nendeks näiteks andmebaasiandmed, pordid, tokenid, salasõnad jne. Sellised väärtusi ei tohiks kunagi eales koodi kirjutada, kuna see võimaldab, kellel iganes koodile ligipääs on, neid väärtusi ja nende taga olevaid teenuseid kuritarvitada. Lisaks nende väärtuse muutumisel peaks terve koodibaasi uuesti kompileerima.

Javasse on sisseehitatud eraldi failivorming konfiguratsioonifailide jaoks - .properties. See on võti-väärtus paaridest koosnev tekstifail, mida rakendus käivitamisel loeb. Nende failide käsitlemiseks on Java standardteegis olemas Properties klass.

.properties fail

.properties fail on tekstifail, kus iga rida määratleb võti-väärtus paari, kus need on eraldatud võrdlusmärgiga (=). Kommentaare saab sinna jätta trellide (#) kaudu.

Näiteks:

# Application configuration
app.name=Library Manager
app.version=1.0

# Server settings
server.host=localhost
server.port=8080

# File paths
data.books=data/books.txt
data.authors=data/authors.txt

Võtmed tavaliselt kirjutatakse väikeste tähtedega ning kategooriad eraldatakse punktidega (ehk server sätete alla kuuluvad alamsätted host ja port näiteks). Väärtused on alati sõned ehk nende teisendamise eest teistesse tüüpidesse (täisarvud, tõeväärtused) vastutab rakendus ise.

Konfiguratsiooni mällu laadimine

java.util pakis on Properties klass, mis oskab lugeda ja endasse salvestada nendest failidest tulevaid võti-väärtus paare.

Properties config = new Properties();

try (InputStream input = Files.newInputStream(Path.of("app.properties"))) {
config.load(input);
} catch (IOException e) {
throw new RuntimeException("Could not load configuration", e);
}

String host = config.getProperty("server.host");
String port = config.getProperty("server.port");

System.out.println("Connecting to " + host + ":" + port);

getProperty(key) meetod tagastab väärtuse sõnena, null tagastatakse siis kui sellist võtit ei eksisteeri.

Vaikeväärtused

getProperty võtab vastu ka teist argumenti, mis võimaldab määrata vaikeväärtuse olukorras, kus võtit võib mitte eksisteerida:

String host = config.getProperty("server.host", "localhost");
int port = Integer.parseInt(config.getProperty("server.port", "8080"));

See on kasulik olukorras, kus võime eeldada, et mingil sättel on vaikeväärtus olemas.

Konfiguratsioonifailide salvestamine

Properties objekti sisu on võimalik ka faili tagasi kirjutada. Selleks on olemas store meetod, mis võtab argumentidena sisse faili, kuhu sisu kirjutada, ning ka kommentaari:

Properties config = new Properties();
config.setProperty("app.name", "Library Manager");
config.setProperty("server.host", "localhost");
config.setProperty("server.port", "8080");

try (OutputStream output = Files.newOutputStream(Path.of("app.properties"))) {
config.store(output, "Application configuration");
} catch (IOException e) {
throw new RuntimeException("Could not save configuration", e);
}

Tulemusena tekib selline fail:

#Application configuration
#Mon Apr 21 12:00:00 UTC 2026
server.port=8080
server.host=localhost
app.name=Library Manager

Pane tähele, et store lisab ajatempliga kommentaari ega säilita võtmete algset järjekorda. Inimese poolt hallatavate konfiguratsioonifailide puhul on see sageli ebasoovitav - lihtsam on faili otse muutmine ja selle lugemine load meetodiga.

classpath'ist laadimine

Suuremates rakendustes on levinud muster, kus vaikimisi konfiguratsioon pakitakse rakendusega kaasa ning vajadusel väline fail kirjutab selle üle. getResourceAsStream meetod võimaldab laadida faile, mis on rakendusse endasse pakitud:

Properties config = new Properties();

try (InputStream input = AppConfig.class.getResourceAsStream("/app.properties")) {
if (input == null) throw new RuntimeException("Configuration file not found on classpath");
config.load(input);
} catch (IOException e) {
throw new RuntimeException("Could not load configuration", e);
}

Gradle’i projektidess lisatakse src/main/resources kausta paigutatud failid automaatselt classpath’ile. Tavalistes Java projektides sellist kokkulepet ei ole. Ressursse võib hoida suvalistes kaustades tingimusel, et rakenduse käivitamisel on need lisatud classpath'i (nt -cp parameetriga käsurealt).

Praktiline nõuanne

Praktikas on soovituslik luua eraldi konfiguratsiooniklass, mis mähib endasse Properties objekti ja hoiab endas meetodeid sätetele ligipääsemiseks:

public class AppConfig {
private final Properties properties;

public AppConfig(Path configFile) throws IOException {
properties = new Properties();
try (InputStream input = Files.newInputStream(configFile)) {
properties.load(input);
}
}

public String getAppName() {
return properties.getProperty("app.name", "Unknown App");
}

public String getServerHost() {
return properties.getProperty("server.host", "localhost");
}

public int getServerPort() {
return Integer.parseInt(properties.getProperty("server.port", "8080"));
}

public Path getBooksFilePath() {
return Path.of(properties.getProperty("data.books", "data/books.txt"));
}
}

Kasutajad kasutavad AppConfig-i, teadmata konfiguratsioonifaili vormingut või võtmete nimesid:

AppConfig config = new AppConfig(Path.of("app.properties"));
BookDao dao = new FileBookDao(config.getBooksFilePath());

Selle eelis on see, et see hoiab toored võtmed ühes kohas ning pakub ülejäänud koodibaasile selgesõnaliselt määratletud meetodeid.