Spring Properties Dosyası Kullanımı ve Değer Okuma
Properties dosyaları, uygulamanızı farklı konfigürasyon ayarlarıyla ayrı ayrı yapılandırılabilir ve güncellenebilir hale getirir. Uygulamanızda birden fazla properties dosyası tanımlayabilirsiniz ve kullanabilirsiniz. Bu yazımızda properties dosyalarını nasıl tanımlayacağınızı ve içindeki değerleri uygulamanızda nasıl elde edebileceğinizi göstereceğiz.
Properties kullanımı tanımlama ve değer alma olarak başlıklandırarak anlatmaya başlayalım.
1. Properties Dosyaları
Spring, projenin classpath
ve resources
dizininde bulunan .properties
dosyalarını kullanarak konfigürasyonlarınızı haricileştirmenin bir yolunu sağlar. Bu, konfigürasyonlarınızın ortam bazlı dinamik olarak yapılandırılabilmesi ve çoklu ortam kurulumları için çok kullanışlıdır.
resources
dizini Spring tarafından değil, Maven ve Gradle dizin yapısı tarafından sağlanan bir özelliktir. Build adımı sırasında Maven ve Gradle dosyaları buradan alacak ve bunları runtime classpath'inde kullanmanız için uygun yere yerleştirecektir (Ör: Java'nın -cp seçeneğiyle). src/main/resources/
dizininde bulunan application.properties
dosyasıdır. Yeni bir Spring Boot projesi oluşturduğunuzda bu varsayılan properties dosyasının içi boş olarak oluşturulur.Aşağıda örnek bir .properties
dosya içeriği gösterilmektedir:
spring.datasource.username=user
logging.level.root=INFO
Bu örnek dosya, bir data source için kullanıcı adı ve uygulamanın root log kaydı düzeyi için değerler içerir. Properties dosyaları key=value
sözdizimi ile oluşturulur.
2. YAML Properties Dosyaları
Alternatif olarak, varsayılan .properties
sözdizimi yerine Spring, YAML formatındaki properties dosyalarını da destekler. Dolayısıyla, varsayılan application.properties
dosyası yerine, özelliklerinizi YAML biçiminde tercih ederseniz, application.yml
adlı yeni bir özellik dosyası oluşturabilirsiniz:
spring:
datasource:
username: user
logging:
level:
root: INFO
Bunun gerektireceği tek fark, dosya içindeki içeriğin biçimlendirilmesidir, bu nedenle seçim yalnızca tercihe bağlıdır.
3. Properties Dosyalarındaki Değerlere Erişme
Şimdi ana konuya, yani yukarıda bahsedilen properties dosyalarındaki değerlere nasıl ulaşabileceğimize geçiyoruz. Fakat başlıkları incelerken Spring Framework ve Spring Boot projeleri için farklı kullanım şekillerine dikkat ediniz!
3.1. @Value Anotasyonunu Kullanarak
Spring Boot projenizde, varsayılan properties dosyası olan application.properties
dosyasında tanımladığınız key'lere erişebilmek için direkt @Value
anotasyonunu kullanabilirsiniz. Örneği test edebilmek için bu properties dosyasına blog.name
key'ini ekleyelim.
blog.name=Kerteriz Blog
Ardından Blog
sınıfımızda yer alan name
değişkenine bu değeri @Value
anotasyonu ile atayalım.
@Getter
@Component
public class Blog {
@Value("${blog.name}")
private String name;
}
Şimdi, TestController
sınıfımızda Blog
sınıfımızı inject edelim ve /test
endpointi açarak name
değişkenini return edelim.
@RestController
public class TestController {
private final Blog blog;
public TestController(Blog blog) {
this.blog = blog;
}
@GetMapping("/test")
public String test() {
return blog.getName();
}
}
Hızlıca GET isteği atalım ve sonucu kontrol edelim.
GET http://localhost:8080/test
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 13
Date: Sat, 21 May 2022 19:07:07 GMT
Keep-Alive: timeout=60
Connection: keep-alive
Kerteriz Blog
Response code: 200; Time: 151ms; Content length: 13 bytes
Response body içinde application.properties
dosyası içinde verdiğimiz değeri görüyoruz.
Bu uyarıyı daha net hale getirelim. Yukarıdaki örnekte name
değişkenine application dosyanızdaki blog.name
değerini enjekte etmek için Blog
sınıfınızın Spring Context içinde yer alması gerekmektedir. Bir sınıfın ise Spring Context'e eklenebilmesi için şunlardan birine uyması gerekmektedir;
@Configuration
anotasyonu ile işaretlenmiş sınıflarda@Bean
anotasyonu ile instance'ının üretilmesi- Stereo-type anotasyonlardan (
@Component
,@Controller
,@Repository
) biriyle işaretlenmiş olması
Bu konuda daha detaylı bir bilgi için önceki yazımızı okuyabilirsiniz:
User
sınıfının instance'ını Spring Context'ten alarak değil de direkt kendiniz üreterek kullanırsanız name
değişkenine herhangi bir değer atanmayacaktır.Küçük bir örnekle bunu da ispatlayalım:
@SpringBootApplication
public class PureSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(PureSpringBootApplication.class, args);
Blog blog = new Blog();
System.out.println("==>" + blog.getName());
}
}
Konsola bakarsanız ==>null
satırını göreceksiniz.
Eğer Spring Framework projeniz ile @Value
anotasyonunu kullanmak istiyorsanız, properties dosyanızın konumunu @PropertySource
anotasyonu ile belirtmelisiniz. Çünkü application.properties
dosyası Spring Boot projesinde varsayılan olarak atanır. Spring Framework projeniz için bu properties dosyalarını siz seçmelisiniz.
Benzer olarak, Spring Boot projesinde de application.properties
dışında başka bir properties dosyası kullanmak istiyorsanız yine aynı şekilde @PropertySource
anotasyonu ile bu dosyayı belirtmelisiniz.
Öyleyse @PropertySource
kullanımına bakalım.
3.1.1 @PropertySource Anotasyonu Kullanımı
Spring @PropertySource
anotasyonu, Spring Environment'a properties dosyası sağlamak için kullanılır. Bu anotasyon, @Configuration
sınıflarıyla birlikte veya @Value
anotasyonu kullandığınız sınıflarla birlikte kullanılır.
@PropertySource
anotasyonunu şu durumlarda kullanmak istiyoruz:
- Spring Boot projesinde
application.properties
dosyası haricinde properties dosyaları tanımlayacaksınız. - Spring Framework projesinde properties dosyaları tanımlayacaksınız.
Örneğimizde, resources
dizininde blog.properties
dosyasını oluşturarak blog.name
isimli key'i buraya taşıyoruz. Ardından Blog
isimli sınıfımıza @PropertySource
anotasyonunu ekliyoruz.
@Getter
@Component
@PropertySource("classpath:blog.properties")
public class Blog {
@Value("${blog.name}")
private String name;
}
Başka bir User
isimli sınıf daha ekleyelim ve aynı şekilde user.name
değerine erişelim.
@Getter
@Component
@PropertySource("classpath:user.properties")
public class User {
@Value("${user.name}")
private String name;
@Value("${blog.name}")
private String blogName;
}
Örnekte dikkat edeceğiniz üzere, User
sınıfımızda sadece user.properties
dosyasını ayarlasak bile Blog
sınıfında ayarladığımız blog.properties
dosyasının içindeki key'lere erişebiliyoruz.
@PropertySource
anotasyonunu sınıf tanımları üzerinde ayrı ayrı kullanmak programınızın karmaşıklığını artırıp bu gibi unutacağınız durumlara neden olabileceği için @Configuration
anotasyonlu sınıflarda @PropertySource
kullanmak daha iyi olacaktır.
@Configuration
@PropertySource(value = "classpath:user.properties")
@PropertySource(value = "classpath:blog.properties")
public class AppProperties {
}
3.2. @ConfigurationProperties Anotasyonunu Kullanarak
@ConfigurationProperties
anotasyonu, @Value
anotasyonundan daha kapsamlı bir yaklaşım sunar.
Bu yöntem, özelliklere ayrı ayrı erişilen önceki çözümün aksine, properties dosyası içinde yer alan bütün keyleri bir POJO'da depolayarak değerlere erişmek için kullanılır.
@ConfigurationProperties
anotasyonunu kullanabilmek için maven veya gradle dosyanıza spring-boot-configuration-processor
bağımlılığını eklemelisiniz.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
Ardından Spring Boot veya Spring Framework projelerimizde örneğimiz için blog.properties
dosyamızın içini şu şekilde ayarlayalım. Tabi bu properties dosyasını belirtmek için bir üstteki başlıkta anlattığımız gibi @PropertySource
anotasyonunu kullanmayı unutmayınız:
blog.name=Kerteriz Blog
blog.url=kerteriz.net
blog.author=Ismet BALAT
Şimdi Blog
sınıfımızı @ConfigurationProperties
anotasyonu ile işaretleyelim. Ayrıca tüm keyler blog
prefixi içerdiğinden, prefix
parametresi ile bunu belirtelim.
@Data
@Component
@ConfigurationProperties(prefix = "blog")
public class Blog {
private String name;
private String url;
private String author;
}
Şimdi, TestController
sınıfımızda Blog
sınıfımızı inject edelim ve /test
endpointi açarak User
sınıfımızın tüm fieldlarını toString
methodu ile return edelim.
@RestController
public class TestController {
private final Blog blog;
public TestController(Blog blog) {
this.blog = blog;
}
@GetMapping("/test")
public String test() {
return blog.toString();
}
}
Hızlıca GET isteği atalım ve sonucu kontrol edelim.
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 62
Date: Sat, 21 May 2022 20:41:38 GMT
Keep-Alive: timeout=60
Connection: keep-alive
Blog(name=Kerteriz Blog, url=kerteriz.net, author=Ismet BALAT)
Response code: 200; Time: 5ms; Content length: 62 bytes