아키텍처와 함께

블로그 이미지
by gregorio
  • Total hit
  • Today hit
  • Yesterday hit

'분류 전체보기'에 해당되는 글 56건

  1. 2018.08.13
    [Spring Boot] Properties Configuration
  2. 2018.08.13
    [Spring Boot] Transaction AOP 설정
  3. 2018.08.13
    [Spring Boot] Mybatis 적용
  4. 2018.08.13
    [Spring Boot] Intercepor 적용
  5. 2018.08.13
    [Spring Boot] Filter 적용

Spring Boot에서 Properties를 구성하는 방법이다.


먼저 Spring MVC에서는 XML 파일을 이용하여 다양하게 Property를 bean으로 정의할 수 있다.


■ properties-context.xml


 

<bean id="app" class="org.springframework.beans.factory.config.PropertiesFactoryBean">

<property name="location" value="classpath:properties/app.properties" />

</bean>


<bean id="system" class="org.springframework.beans.factory.config.PropertiesFactoryBean">

<property name="location" value="classpath:properties/system.properties" />

</bean>

<!-- system.properties, common.properties의 모든 항목을 Load  -->

<!-- 응용에서는 Property의 설정값을 가지고 오기 위해 PropertiesUtil을 사용함 -->

<bean id="PropertiesUtil" class="batch.web.util.PropertiesUtil">

  <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />

  <property name="locations">

  <list>

  <value>classpath:properties/system.properties</value>

  <value>classpath:properties/app.properties</value> 

  </list>

  </property>

  </bean>


여기서 PropertiesUtil bean은 Context Load 시 app.properties와 system.properties를 모두 읽어 소스에서 모든 properties를 읽을 수 있도록 구성되어 있다.


 Spring Boot에서 Properties를 bean으로 생성하기 위해서는 PropertySourcesPlaceholderConfigurer를 이용하여 bean으로 설정한다.



■PropertyConfig.java


import java.io.IOException;


import org.springframework.beans.factory.config.PropertiesFactoryBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.Resource;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;


@Configuration

public class PropertyConfig {


@Bean(name="app")

public static PropertiesFactoryBean app() throws IOException {

PropertiesFactoryBean pspc = new PropertiesFactoryBean();

Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:properties/app.properties");

pspc.setLocations(resources);

return pspc;

}

@Bean(name="system")

public static PropertiesFactoryBean system() throws IOException {

PropertiesFactoryBean pspc = new PropertiesFactoryBean();

Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:properties/system.properties");

pspc.setLocations(resources);

return pspc;

}

}


PropertiesFactoryBean 를 bean으로 설정 시 location을 classpath의 properties/app.properties와 system.properties를 사용하여 각각을 app bean과 system bean으로 설정하였다.


app bean과 system bean을 사용하기 위해서는 bean이 동일하게 PropertiesFactoryBean를 bean으로 등록하기 때문에 어떤 bean을 사용할지 정의하여야 한다.


■ 사용 예


  @Autowired

@Qualifier("system")

private PropertiesFactoryBean system;



LOGGER.debug("Message Test :: {}::{}", msg,system.getObject().get("jndi.datasource.name"));



PropertiesFactoryBean으로 정의된 system bean을 사용하기 위해 Qualifier Annotation을 이용하여 system bean을 정의하였다.


이렇게 하지 않는 경우 Spring boot가 실행시 다음과 같은 오류 메세지가 발생한다.


Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed 






위에서 정의한 PropertiesUtil을 bean으로 정의하기 위해 다음과 같이 개발이 필요하다.


■PropertiesUtil.java


import java.util.HashMap;

import java.util.Map;

import java.util.Properties;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

import org.springframework.core.io.Resource;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import org.springframework.stereotype.Component;



@Component

public class PropertiesUtil extends PropertyPlaceholderConfigurer implements InitializingBean{

/**LOGGER SET **/

private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesUtil.class);


private static Map<String, String> propertiesMap;



   @Override

    protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {

        super.processProperties(beanFactory, props);

//         String[] activeProfiles = environment.getActiveProfiles();

//

//         if (LOGGER.isDebugEnabled()) {

//         for (String activeProfile : activeProfiles) {

//         LOGGER.debug("Active Profile :: {}", activeProfile);

//         }

//         }

        propertiesMap = new HashMap<String, String>();

        for (Object key : props.keySet()) {

            String keyStr = String.valueOf(key);

            String valueStr = resolvePlaceholder(keyStr, props, SYSTEM_PROPERTIES_MODE_OVERRIDE);

            propertiesMap.put(keyStr, valueStr);

            if (LOGGER.isDebugEnabled()) {

            LOGGER.debug("Load Properties :" +  keyStr + ":" + valueStr);

            }

        }

    }


    /**

     * This method return value with the name from properties map

     * @param name propertiy name

     * @return

     */

    public static String getString(String name)  {

        return propertiesMap.get(name) != null ? propertiesMap.get(name).toString() : "";

    }


    public static int getInt(String name) {

    return propertiesMap.get(name) != null ? Integer.parseInt(String.valueOf(propertiesMap.get(name))) : 0;

    }


    public static long getLong(String name) {

    return propertiesMap.get(name) != null ? Long.parseLong(String.valueOf(propertiesMap.get(name))) : 0L;

    }


@Override

public void afterPropertiesSet() throws Exception {

Resource[] locations  = new PathMatchingResourcePatternResolver().getResources("classpath:properties/*.properties");

LOGGER.debug("Locations :: {}", locations.toString());

super.setLocations(locations);

}

}



소스에서는 PropertyPlaceholderConfigurer의 processProperties 메소드를 재정의하였으며, 본 메소드에서는 Properties를 파라미터로 받아 해당 Properties를 Load한다.



InitializingBean의 afterPropertiesSet  메소드를 재정할 때 PropertyPlaceholderConfigurer의 location을 읽어들일 Properties 파일을 정의하여 사용한다.




'Spring Framrwork' 카테고리의 다른 글

[Spring Boot] JsonView 설정  (0) 2018.08.14
[Spring Boot] Exception Resolver  (0) 2018.08.14
[Spring Boot] Transaction AOP 설정  (0) 2018.08.13
[Spring Boot] Mybatis 적용  (0) 2018.08.13
[Spring Boot] Intercepor 적용  (0) 2018.08.13
AND

Spring Boot에서 Transaction AOP 설정하는 방법이다.


먼저 Spring MVC에서는 Transaction에 AOP를 설정하기 위해 XML을 이용하여 Tranaction AOP를 설정한다.


■transction-context.xml


  <tx:annotation-driven transaction-manager="txManager"/>


<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"/>

</bean>


<tx:advice id="txAdvice" transaction-manager="txManager">

<tx:attributes>

<tx:method name="retrieve*" read-only="true" />

<tx:method name="select*" read-only="true" />

<tx:method name="insert*" rollback-for="Exception" />

<tx:method name="update*" rollback-for="Exception" />

<tx:method name="delete*" rollback-for="Exception" />

<tx:method name="save*" rollback-for="Exception" />

<tx:method name="process*" propagation="REQUIRES_NEW" rollback-for="Exception" />

</tx:attributes>

</tx:advice>

    

<aop:config>

<aop:pointcut id="requiredTx" expression="execution(* batch..service.impl.*Impl.*(..))"/>

<aop:advisor advice-ref="txAdvice" pointcut-ref="requiredTx" />

</aop:config>


</beans>


Transaction Manager bean을 설정한 후 transaction advice를 이용하여 Transaction을 적용할 Method를 설정한다.



Spring Boot에서는 TransactionInterceptor와 AspectJExpressionPointcut를 이용하여 bean을 설정함으로써 Transaction을 제어할 수 있다.


■TransactionConfig.java


import java.util.ArrayList;

import java.util.List;

import java.util.Properties;


import org.aspectj.lang.annotation.Aspect;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.aop.Advisor;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;

import org.springframework.aop.support.DefaultPointcutAdvisor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import org.springframework.transaction.TransactionDefinition;

import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

import org.springframework.transaction.interceptor.RollbackRuleAttribute;

import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;

import org.springframework.transaction.interceptor.TransactionInterceptor;


@Aspect

@Configuration

public class TransactionConfig {

private static final Logger LOGGER = LoggerFactory.getLogger(TransactionConfig.class);

    private static final int TX_METHOD_TIMEOUT = 3;

    private static final String AOP_POINTCUT_EXPRESSION = "execution(* webapp.sample.service..*.*(..))";


//    @Autowired

//    private PlatformTransactionManager transactionManager;


    @Autowired

    private DataSourceTransactionManager transactionManager;


    @Bean

    public TransactionInterceptor txAdvice() {

        

    TransactionInterceptor txAdvice = new TransactionInterceptor();

    Properties txAttributes = new Properties();

   

    List<RollbackRuleAttribute> rollbackRules = new ArrayList<RollbackRuleAttribute>();

   

    rollbackRules.add(new RollbackRuleAttribute(Exception.class));

    /** If need to add additionall exceptio, add here **/

   

    DefaultTransactionAttribute readOnlyAttribute = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED);

    readOnlyAttribute.setReadOnly(true);

    readOnlyAttribute.setTimeout(TX_METHOD_TIMEOUT);

   

        RuleBasedTransactionAttribute writeAttribute = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, rollbackRules);

        writeAttribute.setTimeout(TX_METHOD_TIMEOUT);

   

String readOnlyTransactionAttributesDefinition = readOnlyAttribute.toString();

String writeTransactionAttributesDefinition = writeAttribute.toString();

LOGGER.info("Read Only Attributes :: {}", readOnlyTransactionAttributesDefinition);

LOGGER.info("Write Attributes :: {}", writeTransactionAttributesDefinition);

// read-only

txAttributes.setProperty("retrieve*", readOnlyTransactionAttributesDefinition);

txAttributes.setProperty("select*", readOnlyTransactionAttributesDefinition);

txAttributes.setProperty("get*", readOnlyTransactionAttributesDefinition);

txAttributes.setProperty("list*", readOnlyTransactionAttributesDefinition);

txAttributes.setProperty("search*", readOnlyTransactionAttributesDefinition);

txAttributes.setProperty("find*", readOnlyTransactionAttributesDefinition);

txAttributes.setProperty("count*", readOnlyTransactionAttributesDefinition);

// write rollback-rule

txAttributes.setProperty("*", writeTransactionAttributesDefinition);

txAdvice.setTransactionAttributes(txAttributes);

txAdvice.setTransactionManager(transactionManager);

   


        return txAdvice;

    }


    @Bean

    public Advisor txAdviceAdvisor() {

        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();

        pointcut.setExpression("(execution(* *..*.service..*.*(..)) || execution(* *..*.services..*.*(..)))");

        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);

        return new DefaultPointcutAdvisor(pointcut, txAdvice());

    }

}




TransactionInterceptor bean 생성 시 readOnlyAttribute와 wirtheOnlyAttribute를 DefaultTransactionAttribute와 RuleBasedTransactionAttribute를 이용하여 생성한다.


Transaction Attribute에 ReadOnlyAttribute와 writeOnlyAttribute를 메소드의 유형에 따라 설정한 후 TransactionInterceptor에 정의한다.



그리고 Advisor를 bean으로 설정할 때 pointCut을 생성하여 expression을 정의한다.

'Spring Framrwork' 카테고리의 다른 글

[Spring Boot] Exception Resolver  (0) 2018.08.14
[Spring Boot] Properties Configuration  (0) 2018.08.13
[Spring Boot] Mybatis 적용  (0) 2018.08.13
[Spring Boot] Intercepor 적용  (0) 2018.08.13
[Spring Boot] Filter 적용  (0) 2018.08.13
AND

Spring Boot에서 Mybatis를 적용하는 방법이다.


Spring MVC에서는 Mybatis를 적용하기 위해 DataSource에 Mybatis Configuration 파일과 Mapper Location을 정의해주어야 한다.



■context-datasource.xml


  <beans profile="sqlite">

<!-- SQLIITE  -->

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">

<property name="jndiName" value="batchweb" />

<property name="resourceRef" value="true" />

</bean>

</beans>



<beans>

     <!-- SqlSession setup for MyBatis Database Layer -->

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="configLocation" value="classpath:/sqlmap/config/mybatis-config.xml" />

<property name="mapperLocations">

<list>

<value>classpath:/sqlmap/cmn/*SQL.xml</value>

<value>classpath:/sqlmap/#{system['database.type']}/**/*SQL.xml</value>

</list>

</property>

</bean> 


    <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

<property name="dataSource" ref="dataSource" />

</bean>

    

    <bean id="baseDao" class="batch.web.base.BaseDao">

    <property name="sqlSessionFactory" ref="sqlSession" />

    </bean>




먼저 JndiObjectFactoryBean을 이용하여 dataSource bean을 설정한다.

다음으로 SqlSessionFactoryBean에 configLocation과 mapperLocations에 Mybatis configuration 파일 위치를 정의하고, mapperLocation에 Mybatis에서 사용하는 SQL 파일의 위치를 정의한다.



BaseDao를 사용하기 위해 bean으로 정의한다. 이때 BaseDao SqlSessionFactory를 sqlSession을 주입한다. 


bean 설정이 완료된 후 DAO를 생성한다.


■ BaseDao.java


 import org.mybatis.spring.support.SqlSessionDaoSupport;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.InitializingBean;


import batch.web.mybatis.JobParamResultHandler;


public class BaseDao extends SqlSessionDaoSupport implements InitializingBean {

private static  Logger LOGGER = LoggerFactory.getLogger(BaseDao.class);

/**

*<pre>

* 1.Description: Insert Data

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param params

* @return

* @throws Exception

*/

public <T> int insert(String sqlId, T params) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().insert(sqlId, params);

}

/**

*<pre>

* 1.Description: Update Data

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param params

* @return

* @throws Exception

*/

public <T> int update(String sqlId, T params) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().update(sqlId, params);

}


/**

*<pre>

* 1.Description: Delete Data

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param params

* @return

* @throws Exception

*/

public <T> int delete(String sqlId, T params) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().delete(sqlId, params);

}


/**

*<pre>

* 1.Description: Select data for one row

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param param

* @return

* @throws Exception

*/

public <T, V> T select(String sqlId, V param) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().selectOne(sqlId, param);

}


/**

*<pre>

* 1.Description: select data for one row without parameter

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @return

* @throws Exception

*/

public <T, V> T select(String sqlId) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().selectOne(sqlId);

}


/**

*<pre>

* 1.Description: Select data list with parameter 

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param param

* @return

* @throws Exception

*/

@SuppressWarnings("unchecked")

public <T, V> T selectList(String sqlId, V param) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return (T) getSqlSession().selectList(sqlId, param);

}

/**

*<pre>

* 1.Description: Select list without parameter

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @return

* @throws Exception

*/

@SuppressWarnings("unchecked")

public <T, V> T selectList(String sqlId) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return (T) getSqlSession().selectList(sqlId);

}

/**

*<pre>

* 1.Description: Select data with Result Handler

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param job

* @param handler

* @throws Exception

*/

public <T> void selectListWithHandler(String sqlId, Object job, JobParamResultHandler<T> handler) throws Exception {

getSqlSession().select(sqlId, job, handler);

}

}




Spring Boot에서는 sqlSessionFactory를 bean으로 정의한다.


■ DatasourceConfig.java


import javax.sql.DataSource;


import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.mybatis.spring.SqlSessionTemplate;

import org.mybatis.spring.annotation.MapperScan;

import org.mybatis.spring.support.SqlSessionDaoSupport;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.Resource;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;


@Configuration

//@MapperScan(value ="dynm.demo.mapper1", sqlSessionFactoryRef="db1SqlSessionFactory")

//@EnableTransactionManagement

public class DatasourceConfig {


@Bean(name="sqlSessionFactory")

    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();

        factoryBean.setDataSource(dataSource);

Resource[] sqlResources = new PathMatchingResourcePatternResolver().getResources("classpath:sqlmap/**/*SQL.xml");

Resource configLocation = new PathMatchingResourcePatternResolver().getResource("classpath:sqlmap/config/mybatis-config.xml");

factoryBean.setConfigLocation(configLocation);

factoryBean.setMapperLocations(sqlResources);


        return factoryBean.getObject();

    }



    @Bean(name="sqlSessionTemplate")

    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {

        return new SqlSessionTemplate(sqlSessionFactory);

    }

    

}



SqlSesionFactroy를 bean으로 생성하기위해 SqlSessionFactoryBean을 생성한 후 configurationLocation과 mapperLocations을 정의한다.


BaseDao를 bean으로 사용하기 위해 다음과 같이 BaseDao를 개발한다.


■BaseDao.java


import javax.annotation.PostConstruct;


import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.support.SqlSessionDaoSupport;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;


@Repository("baseDao")

public class BaseDao extends SqlSessionDaoSupport implements InitializingBean {

private static  Logger LOGGER = LoggerFactory.getLogger(BaseDao.class);

@Autowired

private SqlSessionFactory sqlSessionFactory;

/**

*<pre>

* 1.Description: Insert Data

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param params

* @return

* @throws Exception

*/

public <T> int insert(String sqlId, T params) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().insert(sqlId, params);

}

/**

*<pre>

* 1.Description: Update Data

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param params

* @return

* @throws Exception

*/

public <T> int update(String sqlId, T params) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().update(sqlId, params);

}


/**

*<pre>

* 1.Description: Delete Data

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param params

* @return

* @throws Exception

*/

public <T> int delete(String sqlId, T params) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().delete(sqlId, params);

}


/**

*<pre>

* 1.Description: Select data for one row

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param param

* @return

* @throws Exception

*/

public <T, V> T select(String sqlId, V param) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().selectOne(sqlId, param);

}


/**

*<pre>

* 1.Description: select data for one row without parameter

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @return

* @throws Exception

*/

public <T, V> T select(String sqlId) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return getSqlSession().selectOne(sqlId);

}


/**

*<pre>

* 1.Description: Select data list with parameter 

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @param param

* @return

* @throws Exception

*/

@SuppressWarnings("unchecked")

public <T, V> T selectList(String sqlId, V param) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return (T) getSqlSession().selectList(sqlId, param);

}

/**

*<pre>

* 1.Description: Select list without parameter

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @param sqlId

* @return

* @throws Exception

*/

@SuppressWarnings("unchecked")

public <T, V> T selectList(String sqlId) throws Exception {

if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Excuted SQL ID :: {}", sqlId);

}

return (T) getSqlSession().selectList(sqlId);

}

/** 

*<pre>

* 1.Description: When using spring boot, SqlSessionFactory should be set in SqlSessionDaoSupport

*                If you use spring MVC, no need to set sqlsessionfactory, because baseDao should be set bean 

* 2.Biz Logic:

* 3.Author : LGCNS

*</pre>

* @throws Exception

*/

@PostConstruct

public void postConstruct() throws Exception {

  super.setSqlSessionFactory(sqlSessionFactory);

}

}



먼저 BaseDao를 Repository Annotation을 이용하여 bean형식으로 로 정의한다.

여기서 BaseDao에 SqusessionFactory를 주입하기 위해 bean으로 정의한 SqlSessionFactory를 Autowired Annotation을 이용하여 Filed로 정의한다.


BaseDao에 SqlSessionFactory를 PostConstruct Annotation을 이용하여  SqlSessionDaoSupport sqlSessionFactory를 주입한다.



'Spring Framrwork' 카테고리의 다른 글

[Spring Boot] Properties Configuration  (0) 2018.08.13
[Spring Boot] Transaction AOP 설정  (0) 2018.08.13
[Spring Boot] Intercepor 적용  (0) 2018.08.13
[Spring Boot] Filter 적용  (0) 2018.08.13
[Spring Boot] welcome-file-list 적용  (0) 2018.08.13
AND

Spring Boot에서 Interceptor를 적용하는 방법이다.


먼저 Spring MVC에서는 Interceptor를 적용하기 위해서 HandlerInterceptorAdapter를 상속받아 Interceptor를 개발한다.


■SessionInterceptor.java


 import java.util.List;

import java.util.Map;


import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.stereotype.Component;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;


import dymn.demo.base.BaseConstants;

import dymn.demo.exception.BizException;

import dymn.demo.util.NetUtil;

import dymn.demo.util.NullUtil;

import dymn.demo.util.PatternUtil;

import dymn.demo.util.SessionUtil;


public class SessionInterceptor extends HandlerInterceptorAdapter implements InitializingBean{

private static final Logger LOGGER = LoggerFactory.getLogger(SessionInterceptor.class);

// private static final String sApiKey = "B69FAF368B184727E89A";

/** Login Check Skip URIs **/

private List<String> skipUris;

/** LOGIN URL **/

private String loginURI;


public void setSkipUris(List<String> skipUris) {

this.skipUris = skipUris;

}


public void setLoginURI(String loginURI) {

this.loginURI = loginURI;

}


/**

* Return boolean

* @param request HttpServletRequest

* @param response HttpServletResponse

* @param Object handler

* @return boolean

* @see 

*/


@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String requestURI = request.getRequestURI();


long startTime = System.currentTimeMillis();

request.setAttribute("startTime", Long.valueOf(startTime));

request.setAttribute("requestURI", requestURI);

request.setAttribute("clientIP", NetUtil.getClinetIP());

/** Session Vo Check if null create new session Vo **/

boolean isSkipUri = false;

if (requestURI.equals("/") ) {

isSkipUri = true;

}

else {

if (!NullUtil.isNull(skipUris)) {

isSkipUri = PatternUtil.isPatternMatch(skipUris, requestURI);

}

}

/** Login Check **/

if (!isSkipUri) {

/** Get session value from HTTP Session **/

Map<String, Object> session = SessionUtil.getSession(BaseConstants.DEFAULT_SESSION_NAME);

/** Move to Login Page **/

if (NullUtil.isNull(session)) {

String contentType = request.getHeader("Content-Type") != null ? request.getHeader("Content-Type") : "";

if (!contentType.contains("json")) {

response.sendRedirect(loginURI);

}

LOGGER.error("You shoud logon the system to use the system(session is null) :: {}", requestURI);

throw new BizException("You shoud logon the system to use the system(session is null)");

}

else {

if (NullUtil.isNull(session.get("userId"))) {

String contentType = request.getHeader("Content-Type");

if (!contentType.contains("json")) {

response.sendRedirect(loginURI);

}

LOGGER.error("You shoud logon the system to use the system(userId is null) :: {}", requestURI);

throw new BizException("You shoud logon the system to use the system(userId is null)");

}

}

}

return super.preHandle(request, response, handler);

}


/**

* Return void

* @param request HttpServletRequest

* @param response HttpServletResponse

* @paeam Object handler

* @return void

* @see

*/

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) throws Exception {


}


/**

*/

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {


String requestURI = request.getAttribute("requestURI").toString();


if (LOGGER.isDebugEnabled()) {

LOGGER.debug("Session Interceptor is called : {}", requestURI);

}

/** If request URI is login or logout, set host name, host address  to session information 

*  When logout, session information is invalidated

* */



long startTime = (Long) request.getAttribute("startTime");

long endTime = System.currentTimeMillis();

LOGGER.info("Request URL::{} Request ClinetIP::{} Response Code::{} Start Time::{} End Time::{}  Elapse Time::{}(ms)",

requestURI, request.getAttribute("clientIP"), response.getStatus(), startTime, endTime, (endTime - startTime));

}



@Override

public void afterPropertiesSet() throws Exception {

}


}



코드 개발이 완료되면 mvc-servlet-context.xml에 Interceptor를 등록한다.


■mvc-servlet-context.xml


     <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">

        <property name="interceptors">

            <list>

                <ref bean="localeChangeInterceptor" />

                <ref bean="sessionInteceptor" />

            </list>

        </property>

    </bean>



<!-- Set the login check, block service and authorization for menu -->

<bean id="sessionInteceptor" class="batch.web.interceptor.SessionInterceptor">

<property name="skipUris">

<list>

<value>/login/*</value>

</list>

</property>

<property name="loginURI" value="/main/mainpage.do" />

<!-- The beans are configured in context-beans.xml file  -->

<!-- This is blocking service  -->

<!-- property name="blockServiceName" value="blockService" /-->

<!-- This is checking for unauthorized url -->

<!-- property name="authCheckServiceName" value="authCheckService" /-->

</bean>



Spring Boot에서 Interceptor 개발은 동일하며, @Component Annotation을 이용하여 bean으로 등록한다.


bean으로 등록하는 이유는 해당 Interceptor를 bean으로 사용하기 위해서 이다.


■WebConfig.java


import java.util.ArrayList;

import java.util.List;

import java.util.Locale;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.support.ReloadableResourceBundleMessageSource;

import org.springframework.core.Ordered;

import org.springframework.web.servlet.LocaleResolver;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

import org.springframework.web.servlet.i18n.SessionLocaleResolver;

import org.springframework.web.servlet.view.json.MappingJackson2JsonView;


import dymn.demo.filter.ABCFilter;

import dymn.demo.interceptor.SessionInterceptor;

import dymn.demo.util.PropertiesUtil;


@Configuration

// @EnableWebMvc

// public class WebConfig extends WebMvcConfigurerAdapter {

// public class WebConfig extends WebMvcConfigurationSupport {

public class WebConfig implements WebMvcConfigurer {


@Autowired

private SessionInterceptor sessionInterceptor;


@Autowired

private ABCFilter abcFilter;



/** Register intercepter **/

@Override

public void addInterceptors(InterceptorRegistry registry) {

List<String> skipUris = new ArrayList<String>();


String[] uris = PropertiesUtil.getString("session.skip.uri").split(",");

;

for (String uri : uris) {

skipUris.add(uri);

}

sessionInterceptor.setSkipUris(skipUris);

registry.addInterceptor(sessionInterceptor);

// .addPathPatterns("/*");

// .excludePathPatterns(skipUris);

}

}

 


Spring MVC에서 sessionInterceptor bean 등록 시 skipUrl 주입하였으나, Spring Boot에서는 Properties 파일에 session.skip.uri 값을 읽어 sessionInterceptor에 주입한다.


그리고 InterceptorRegistry를 이용하여 sessionItnerceptor를 Interceptor로 등록한다.



AND

Spring Boot에서 Filter를 적용하는 방법이다.


먼저 Spring MVC에서는 Filter를 적용하기 위해 web.xml 파일에 다음과 같이 등록한다.


■web.xml


  <filter>

<filter-name>abcFilter</filter-name>

<filter-class>xxx.yyyy.ABCFilter</filter-class>

</filter>


<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/</url-pattern>

</filter-mapping>



ABCFilter를 적용하며, 모든 요청 URI에 ABCFilter를 적용하는 예제이다.



Spring Boot에서는 Filter를 적용하기 위해 먼저 Filter를 생성한다.


■ABCFilter


import java.io.IOException;


import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.core.Ordered;

import org.springframework.core.annotation.Order;

import org.springframework.stereotype.Component;


@Order(Ordered.LOWEST_PRECEDENCE -1)

@Component

public class ABCFilter implements Filter{


private static final Logger LOGGER = LoggerFactory.getLogger(ABCFilter.class);

@Override

public void init(FilterConfig filterConfig) throws ServletException {

}

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;

LOGGER.info("Inside ABCFilter: "+ req.getRequestURI());

chain.doFilter(request, response);

}

@Override

public void destroy() {

}



@Order Annotation을 이용하여 Filter적용 순서를 결정한다. 적용할 Filter가 많을 경우 Filter의 적용 순서를 정의할 수 있다.


다음로 FilterRegistrationBean을 이용하여 Filter를 적용한다.


■WebConfig.java


import java.util.ArrayList;

import java.util.List;

import java.util.Locale;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.support.ReloadableResourceBundleMessageSource;

import org.springframework.core.Ordered;

import org.springframework.web.servlet.LocaleResolver;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

import org.springframework.web.servlet.i18n.SessionLocaleResolver;

import org.springframework.web.servlet.view.json.MappingJackson2JsonView;


import dymn.demo.filter.ABCFilter;

import dymn.demo.interceptor.SessionInterceptor;

import dymn.demo.util.PropertiesUtil;


@Configuration

// @EnableWebMvc

// public class WebConfig extends WebMvcConfigurerAdapter {

// public class WebConfig extends WebMvcConfigurationSupport {

public class WebConfig implements WebMvcConfigurer {


@Autowired

private ABCFilter abcFilter;


/** Register Filter **/

/** If you want to register other filer, Add Bean for other fileter **/

@Bean

public FilterRegistrationBean<ABCFilter> getFilterRegistrationBean() {

FilterRegistrationBean<ABCFilter> registrationBean = new FilterRegistrationBean<>();

registrationBean.setFilter(abcFilter);

registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 1);

registrationBean.addUrlPatterns("/*");

return registrationBean;

}




FilterRegistrationBean의 Generic Type을 ABCFilter로하여 FilterRegistrationBean을 생성한다.

Filter Mapping은 addUrlPatterns를 이용하여 Fillter이 필요한 URI를 정의한다.








AND

ARTICLE CATEGORY

분류 전체보기 (56)
Spring Framrwork (33)
Linux (1)
APM (1)
Java (8)
python (0)
ant (1)
chart (1)
OS (1)
tomcat (1)
apache (1)
database (0)

RECENT ARTICLE

RECENT COMMENT

CALENDAR

«   2024/10   »
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

ARCHIVE

LINK