Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발자 되버리기

yml에서 데이터 가져오기 및 스프링부트 디비 2개 이상 연결하는 법 본문

개발/Spring_Boot

yml에서 데이터 가져오기 및 스프링부트 디비 2개 이상 연결하는 법

구본익 2020. 10. 11. 18:05

application.yml

 

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.lang.Nullable;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
        Properties propertiesFromYaml = loadYamlIntoProperties(resource);
        String sourceName = name != null ? name : resource.getResource().getFilename();
        return new PropertiesPropertySource(sourceName, propertiesFromYaml);
    }

    private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException {
        try {
            YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
            factory.setResources(resource.getResource());
            factory.afterPropertiesSet();
            return factory.getObject();
        } catch (IllegalStateException e) {
            // for ignoreResourceNotFound
            Throwable cause = e.getCause();
            if (cause instanceof FileNotFoundException)
                throw (FileNotFoundException) e.getCause();
            throw e;
        }
    }
}

└ 제일먼저 YalmPropertySourceFactory 코드를 만들어 줍니다.

 

 

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
//value를 통해 값이 있는 위치를 명시해준다.
@PropertySource(value = "classpath:application.yml", factory = YamlPropertySourceFactory.class)
// yml 파일에서 가져올 변수 이름을 명시해준다.
@ConfigurationProperties(prefix = "test")
@Setter
@Getter
public class ApplicationYamlRead {
    private String data_1;
    private String data_2;
}

└ 이후 ApplicationYamlRead.java 파일을 만들어주면 됩니다.

 

 

 

@Test
    void geyDatas(){
        System.out.println(applicationYamlRead.getData_1());
        System.out.println(applicationYamlRead.getData_2());
    }

이후 테스트 코드를 작성후 확인해봅니다.

 

성공적으로 데이터가 출력되었습니다!

 

추가적으로 규칙된 데이터를 넣게된다면 이런식으로 작성 할 수도 있습니다.

 

db:
  datasource_1:
    driver: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:/127.0.0.1:3306/local_db_schema?serverTimezone=UTC&characterEncoding=UTF-8
    username: username
    password: password
  datasource_2:
    driver: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:/127.0.0.1:3306/product_db_schema?serverTimezone=UTC&characterEncoding=UTF-8
    username: username
    password: password

└ 위처럼 yml 파일이 있다고 가정합시다.

 

 

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class DBSource {
    private String driver;
    private String url;
    private String username;
    private String password;
}

이제 위에 datasource_n 에 해당하는 클래스를 만듭니다.

 

 

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
// value를 통해 값이 있는 위치를 명시해준다.
@PropertySource(value = "classpath:application.yml", factory = YamlPropertySourceFactory.class)
// yml 파일에서 가져올 변수 이름을 명시해준다.
@ConfigurationProperties(prefix = "db")
@Setter
@Getter
public class ApplicationDBRead {
    private DBSource datasource_1;
    private DBSource datasource_2;
}

└ 위와같이 클래스를 선언해면 사용이 가능합니다.

 

 

위와같이 클래스의 변수명과 yml의 속성값이 서로 매핑되야 합니다.

 

이제 실제로 잘 작동되는지 url만 받아오는 테스트 코드를 작성해보겠습니다.

@Autowired
    private ApplicationDBRead applicationDBRead;
    @Test
    void ymlDBGetter(){
        System.out.println(applicationDBRead.getDatasource_1().getUrl());
        System.out.println(applicationDBRead.getDatasource_2().getUrl());
    }

성공적으로 값이 잘 출력되는것을 확인할 수 있습니다!

 

 

추가적으로 List 형식으로 받는것도 가능합니다

db:
  hello:
    - 참 쉬운
    - yml에서 데이터
    - 가져오기!

 

public class ApplicationDBRead {
    private DBSource datasource_1;
    private DBSource datasource_2;
    List<String> hello;
}
@Test
    void ymlDBGetter(){
        for(String hello : applicationDBRead.getHello()){
            System.out.println(hello);
        }
    }

 

 

이런식으로  외부에 노출되면 안되는 값(ex 비밀번호)등을 yml파일에는 넣고 필요할 때에만 SFTP 등을 사용하여 서버로 전송해야 합니다.

 

 

이런걸 응용해서 디비에도 접근할 수 있는 Configration을 작성할 수 있습니다.

 

 

 

사실 스프링부트는 이미 간단하게 하나의 디비에 연결할 수 있게 해주지만

개발을 하다보면 여러곳의 디비를 써야할 경우가 있습니다.

 

'ABC' 와 'ABCDEF' 두개의 스키마 있다.

 

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "myServiceNameEntityManager",
        transactionManagerRef = "myServiceNameTransactionManager",
        basePackages = "com.myServiceName.model"
)
public class DBConfig {
    @Autowired
    private ApplicationYamlRead applicationYamlRead;

    @Bean
    public DataSource mysqlDataSource() {
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setDriverClassName(applicationYamlRead.getmyServiceName_driver_class_name());
        hikariDataSource.setJdbcUrl(applicationYamlRead.getmyServiceName_url());
        hikariDataSource.setUsername(applicationYamlRead.getmyServiceName_username());
        hikariDataSource.setPassword(applicationYamlRead.getmyServiceName_password());
        return hikariDataSource;
    }


    @Bean(name = "myServiceNameEntityManager")
    public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        Map<String, Object> properties = new HashMap<String, Object>();
        // yml이나 properties에서도 써줄 수 있지만 여러 디비를 관리하다보면 밑에와같이 쓸 수 있습니다.
        // properties.put("hibernate.hbm2ddl.auto", "create");
        // properties.put("hibernate.hbm2ddl.auto", "update");
        // properties.put("hibernate.hbm2ddl.auto", "none");
        properties.put("show-sql", "true");
        return builder
                .dataSource(mysqlDataSource())
                .properties(properties)
                //.packages(TestModel.class)
                .packages("com.myServiceName.model")
                .persistenceUnit("userPU")
                .build();
    }


    @Bean(name = "myServiceNameTransactionManager")
    public PlatformTransactionManager mysqlTransactionManager(@Qualifier("myServiceNameEntityManager") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

 

application.yml 파일에는 알맞는 변수값을 넣어주고

ApplicationYamlRead 클래스에 알맞게 변수를 선언해주고 Getter로 받아주면 끝!

 

Comments