جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی

در این بخش به بحث چگونگی استفاده از Property ها در Spring و نحوه کانفیگ کردن آنها با PropertySource@ و روش XML ای آن و نحوه کارکرد آن در Spring Boot میپردازیم.


نحوه ثبت یک Property فایل توسط Annotation : در یک کلاس Configuration@ میتوان از PropertySource@ استفاده کنیم و آدرس فایل property را به عنوان آرگومان ارسال کنیم :

@Configuration
@PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
    //...
}

میتوانیم با استفاده از placeholder بصورت داینامیک آدرس property file را بدهیم اینطوری نیازی نیست که آدرس property فایل ثابت باشد :

@PropertySource({ 
  "classpath:persistence-${envTarget:mysql}.properties"
})
...

برای معرفی چندین property فایل به این صورت میتوان اقدام کرد :

//java 8 feature
@PropertySource("classpath:foo.properties")
@PropertySource("classpath:bar.properties")
public class PropertiesWithJavaConfig {
    //...
}
@PropertySources({
    @PropertySource("classpath:foo.properties"),
    @PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
    //...
}

در این حالت اگر یک مقداری در فایل های property دوبار استفاده شود آخرین آنها در نظر گرفته میشود و الویت بالاتری دارد



طریقه تعریف توسط xml :

<context:property-placeholder location="classpath:foo.properties" />

در این حالت فایل foo.properties باید در مسیر /src/main/resources موجود باشد


حالت تعریف چند تایی در xml :

<context:property-placeholder location="classpath:foo.properties, classpath:bar.properties"/>


خواندن و استفاده کردن از مقادیر Property ها :


روش اول با استفاده از Value@ میتوانیم مقادیر موجود در property ها را خوانده و در متغییری تزریق کنیم

@Value( "${jdbc.url}" )
private String jdbcUrl;

خواندن مقادیر و در صورت عدم وجود آن، با یک مقدار پیش فرض پر میشود :

@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;

خواندن مقادیر در xml فایل ها :

<bean id="dataSource">
  <property name="url" value="${jdbc.url}" />
</bean>


روش دوم با استفاده از Environment API در Spring :

@Autowired
private Environment env;
...
dataSource.setUrl(env.getProperty("jdbc.url"));



استفاده از property در Spring Boot :

Spring Boot در ابتدای اجرا دنبال یک فایل بصورت پیش فرض بنام application.properties در مسیر src/main/resources میگردد و بصورت اتوماتیک آنرا شناسایی و استفاده میکند و ما نیز میتوانیم تنظیمات خود را در داخل این فایل قرار دهیم و دیگر نیازی نداریم که فایل property خودمان را به Spring معرفی کنیم 


همینطور میتوانیم فایل property تنظیمات را در خط فرمان موقع اجرا کد به عنوان آرگومان ارسال کنیم :

java -jar app.jar --spring.config.location=classpath:/another-location.properties

همچنین ما میتوانیم برای هر profile موجود یک فایل property مجزا در مسیر src/main/resources داشته باشیم که نیاز دارد الگوی زیر را داشته باشد. در صورت وجود این تنظیمات جانبی همچنان فایل application.properties به عنوان پیش فرض خوانده میشود

application-[environment].properties

مثل : application-dev.properties 


اگر نیاز باشد کد با شرایط تستی تست شود و تنظیمات مختص خود را داشته باشد نیاز است که تنظیمات مربوطه در مسیر src/test/resources گذاشته شود



TestPropertySource@ : اگر در شرایط تست نیاز داریم که ادرس فایل تنظیمات property را بصورت دستی ارسال کنیم میتوانیم با این annotation این کار را بکنیم :

@ContextConfiguration
@TestPropertySource("/my-test.properties")
public class IntegrationTests {
    // tests
}

حتی میتوانیم بدون ادرس دهی فایل، مقادیر و نام های property ها را بصورت دستی و hardcode ارسال کنیم :

@ContextConfiguration
@TestPropertySource("foo=bar", "bar=foo")
public class IntegrationTests {
    // tests
}

همچنین میتوانیم مقادیر بالا را با کمک SpringBootTest@ وارد کنیم :

@SpringBootTest(properties = {"foo=bar", "bar=foo"})
public class IntegrationTests {
    // tests
}


ConfigurationProperties@ : زمانی که property فایل های سلسله مراتبی داشته باشیم میتوانیم از این annotation استفاده کنیم 


استفاده از yaml به جای properties فایل ها :

در Spring میتوانیم از فایل و ساختار yaml هم استفاده کنیم و تمامی شرایط آن با properties مشابه است و تنها فرق آن در ساختار آن و ساپورت نکردن PeropertySource@ از آن است حالا نگاهی کنیم به ساختار داخلی yaml :


مدل properties : 

database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar
secret=foo

مدل yaml :

database:
  url: jdbc:postgresql:/localhost:5432/instance
  username: foo
  password: bar
secret: foo


ارسال مقادیر property از طریق خط فرمان :

java -jar app.jar --property="value"

همچنین میتوانید از طریق سویچ سیستمی آنرا انجام دهیم :

java -Dproperty.name="value" -jar app.jar

از طریق متغییر های سیستمی هم میتوان نام و مقادیری را اعمال کنیم :

export name=value
java -jar app.jar


تولید مقادیر تصادفی :

random.number=${random.int}
random.long=${random.long}
random.uuid=${random.uuid}


تعریف یک property  خام با استفاده از کلاس PropertyPlaceholderConfigurer بصورت دستی:

این روش کاربرد زیادی ندارد ولی شاید شرایطی بوجود آید که نیاز باشد باید یک bean ایجاد کنیم که مقدار برگشتی آن از جنس کلاس PropertySourcesPlaceholderConfigurer باشد و اینطوری مقادیر property بصورت اتوماتیک ثبت خواهند شد :

@Bean
public static PropertySourcesPlaceholderConfigurer properties(){
    PropertySourcesPlaceholderConfigurer pspc
      = new PropertySourcesPlaceholderConfigurer();
    Resource[] resources = new ClassPathResource[ ]
      { new ClassPathResource( "foo.properties" ) };
    pspc.setLocations( resources );
    pspc.setIgnoreUnresolvablePlaceholders( true );
    return pspc;
}

روش تعریف یک property خام بصورت دستی با xml : 

این روش هم کاربرد زیادی ندارد 

<bean
  class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:foo.properties</value>
        </list>
    </property>
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>



Context to Context - Parent Child : 

حالتی پیش میاد که (بیشتر در وب) که برنامه اینقدر بزرگ است که یک Context بزرگ چند Context داخلی در خودش دارد و اینجا مقادیر property چطور در Context پدر و فرزند قابل دسترس است ؟


- حالتی که property ها در فرمت xml و با استفاده از <property-placeholder> تعریف شده باشند :

اگر فایل در پدر تعریف شده باشد دسترسی ها به این نحو است :

@Value works in Child context: NO
@Value works in Parent context: YES

اگر فایل در فرزند تعریف شده باشد دسترسی ها به این نحو است :

@Value works in Child context: YES
@Value works in Parent context: NO

در مورد Environment API همانطور که قبلا توضیح دادیم چون با استفاده از xml و <property-placeholder> تعریف شده است دسترسی بکل وجود نخواهد داشت: 

environment.getProperty works in either context: NO


- حالتی که property ها از طریق PropertySource@ تعریف شده باشند :

اگر فایل در پدر تعریف شده باشد دسترسی ها به این نحو است :

@Value works in Child context: YES
@Value works in Parent context: YES
environment.getProperty in Child context: YES
environment.getProperty in Parent context: YES


اگر فایل در فرزند تعریف شده باشد دسترسی ها به این نحو است :

@Value works in Child context: YES
@Value works in Parent context: NO
environment.getProperty in Child context: YES
environment.getProperty in Parent context: NO





نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی