개발 환경 : STS(3.9.5), spring(5.1.2), mybatis, openjdk1.8, mariaDB 등


sts에서 spring legacy project중에 spring mvc project를 생성한다.


pom.xml 사용 라이브러리 : 

- jstl : jsp에서 jstl 태그를 사용하기 위함

- mariadb-java-clien : mariaDB와 connnection을 맺기 위함

- mybatis-spring  : Spring에서 연동을 지원하는 mybatis

- mybatis              

- spring-jdbc : Spring에서 지원하는 JDBC

- commons-dbcp : 커넥션풀을 담당하는 Apache Commons DBCP

- commons-lang3 : 문자열 라이브러리를 apache commons lang으로 통일하기 위함

- log4jdbc-remix : mybatis 로그를 출력하기 위함

- lombok : @data, @slf4 어노테이션 등을 사용하기 위함

- springloaded : java 소스 수정 시 tomcat을 자동으로 reload해주기 위함(tomcat restart를 안해도 된다)


<pom.xml 소스>

		<dependency>
		    <groupId>jstl</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>
		<dependency>
		    <groupId>org.mariadb.jdbc</groupId>
		    <artifactId>mariadb-java-client</artifactId>
		    <version>1.1.7</version>
		</dependency>
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis-spring</artifactId>
		    <version>1.3.2</version>
		</dependency>
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis</artifactId>
		    <version>3.4.6</version>
		</dependency>
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-jdbc</artifactId>
		    <version>5.1.4.RELEASE</version>
		</dependency>
		<dependency>
		    <groupId>commons-dbcp</groupId>
		    <artifactId>commons-dbcp</artifactId>
		    <version>1.4</version>
		</dependency><dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-lang3</artifactId>
		    <version>3.0</version>
		</dependency>
		<dependency>
		    <groupId>org.lazyluke</groupId>
		    <artifactId>log4jdbc-remix</artifactId>
		    <version>0.2.7</version>
		</dependency>
		<dependency>
		    <groupId>org.projectlombok</groupId>
		    <artifactId>lombok</artifactId>
		    <version>1.18.4</version>
		    <scope>provided</scope>
		</dependency>
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>springloaded</artifactId>
		    <version>1.2.8.RELEASE</version>
		</dependency>


위와 같이 셋팅 한 후에 mybatis 설정을 위해 config파일들을 추가해야 한다.

추가 경로(이클립스 경로) : src/main/webapp/WEB-INF/spring/

추가 경로 하위에 mybatis-config-base.xml와 mybatis-context.xml을 추가한다.


<mybatis-context.xml 소스 코드>

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd"> <bean id="jdbcProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:META-INF/jdbc.properties" /> </bean> <bean id="dataSourceSpied" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource"> <constructor-arg ref="dataSourceSpied" /> <property name="logFormatter"> <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter"> <property name="loggingType" value="MULTI_LINE" /> <property name="sqlPrefix" value="SQL : "/> </bean> </property> </bean> <bean id="sqlSessionFactory" class="com.spring.test.util.RefreshableSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="typeAliasesPackage" value="com.spring.test"/> <property name="configLocation" value="WEB-INF/spring/mybatis-config-base.xml" /> <property value="classpath:com/spring/**/dao/mapper/*Mapper.xml" name="mapperLocations" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.spring.test" /> <property name="annotationClass" value="org.springframework.stereotype.Repository"/> </bean> </beans>

기본적인 mybatis셋팅에서 dataSource를 셋팅하는 부분이 살짝 바뀌었다. 이는 mybatis 로그를 출력하기 위한 셋팅이다.

또한 sqlSessionFactory 부분에서 RefreshableSqlSessionFactoryBean.java를 참조하여 셋팅하였는데 mapper 수정 시 tomcat restart를 하지 않고 바로 적용되도록 하기 위함이다.


<RefreshableSqlSessionFactoryBean.java 소스코드>

package com.spring.test.util; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.DisposableBean; import org.springframework.core.io.Resource; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class RefreshableSqlSessionFactoryBean extends SqlSessionFactoryBean implements DisposableBean { private static final Log log = LogFactory.getLog(RefreshableSqlSessionFactoryBean.class); private SqlSessionFactory proxy; private int interval = 500; private Timer timer; private TimerTask task; private Resource[] mapperLocations; /** * 파일 감시 쓰레드가 실행중인지 여부. */ private boolean running = false; private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); public void setMapperLocations(Resource[] mapperLocations) { super.setMapperLocations(mapperLocations); this.mapperLocations = mapperLocations; } public void setInterval(int interval) { this.interval = interval; } /** * @throws Exception */ public void refresh() throws Exception { if (log.isInfoEnabled()) { log.info("refreshing sqlMapClient."); } w.lock(); try { super.afterPropertiesSet(); } finally { w.unlock(); } } /** * 싱글톤 멤버로 SqlMapClient 원본 대신 프록시로 설정하도록 오버라이드. */ public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); setRefreshable(); } private void setRefreshable() { proxy = (SqlSessionFactory) Proxy.newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSessionFactory.class}, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // log.debug("method.getName() : " + method.getName()); return method.invoke(getParentObject(), args); } }); task = new TimerTask() { private Map<Resource, Long> map = new HashMap<Resource, Long>(); public void run() { if (isModified()) { try { refresh(); } catch (Exception e) { log.error("caught exception", e); } } } private boolean isModified() { boolean retVal = false; if (mapperLocations != null) { for (int i = 0; i < mapperLocations.length; i++) { Resource mappingLocation = mapperLocations[i]; retVal |= findModifiedResource(mappingLocation); } } return retVal; } private boolean findModifiedResource(Resource resource) { boolean retVal = false; List<String> modifiedResources = new ArrayList<String>(); try { long modified = resource.lastModified(); if (map.containsKey(resource)) { long lastModified = ((Long) map.get(resource)) .longValue(); if (lastModified != modified) { map.put(resource, new Long(modified)); modifiedResources.add(resource.getDescription()); retVal = true; } } else { map.put(resource, new Long(modified)); } } catch (IOException e) { log.error("caught exception", e); } if (retVal) { if (log.isInfoEnabled()) { log.info("modified files : " + modifiedResources); } } return retVal; } }; timer = new Timer(true); resetInterval(); } private Object getParentObject() throws Exception { r.lock(); try { return super.getObject(); } finally { r.unlock(); } } public SqlSessionFactory getObject() { return this.proxy; } public Class<? extends SqlSessionFactory> getObjectType() { return (this.proxy != null ? this.proxy.getClass() : SqlSessionFactory.class); } public boolean isSingleton() { return true; } public void setCheckInterval(int ms) { interval = ms; if (timer != null) { resetInterval(); } } private void resetInterval() { if (running) { timer.cancel(); running = false; } if (interval > 0) { timer.schedule(task, 0, interval); running = true; } } public void destroy() throws Exception { timer.cancel(); } }


<mybatis-config-base.xml 소스코드>

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="false"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25000"/> </settings> <typeHandlers> <!-- java.sql.Timestamp 를 java.util.Date 형으로 반환 --> <typeHandler javaType="java.sql.Timestamp" handler="org.apache.ibatis.type.DateTypeHandler"/> <typeHandler javaType="java.sql.Time" handler="org.apache.ibatis.type.DateTypeHandler"/> <typeHandler javaType="java.sql.Date" handler="org.apache.ibatis.type.DateTypeHandler"/> </typeHandlers> </configuration>

위의 소스는 mybatis 설정 정보 파일로 필요한 옵션을 추가해서 사용하면 되겠다.(mybaits.org 또는 구글링)에서 참조


위의 파일을 추가한 후 설정을 읽어오기 위해 root-context.xml파일을 수정한다.

<root-context.xml 소스 코드>

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Root Context: defines shared resources visible to all other web components --> <import resource="mybatis-context.xml" /> </beans>


root-context.xml의 소스를 수정한 후 mybatis-context.xml에서 설정한 dataSource 정보를 읽어오기 위해 jdbc.properties 파일을 추가한다.

추가 경로 : src/main/resource/META-INF/

<jdbc.properties 소스 코드>

# Maria DB jdbc.driverClassName=org.mariadb.jdbc.Driver jdbc.url=jdbc:mariadb://localhost:3306/javaboja?useUnicode=true&characterEncoding=utf-8&interactiveClient=true&autoReconnect=true&autoReconnectForPools=true&zeroDateTimeBehavior=convertToNull jdbc.username = javaboja jdbc.password = javaboja

마지막으로 mybatis 쿼리 로그를 출력하기 위해 log4j.xml을 수정하자.

<log4j.xml 소스 코드>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	<!-- Appenders -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p: %c - %m%n" />
		</layout>
	</appender>
	
	<!-- Application Loggers -->
	<logger name="com.spring.test">
		<level value="info" />
	</logger>
	 <!-- Query Loggers -->
    <logger name="jdbc.sqlonly" additivity="false">
        <level value="INFO" />
        <appender-ref ref="console-infolog" />
    </logger>
    <logger name="jdbc.resultsettable" additivity="false">
        <level value="INFO" />
        <appender-ref ref="console" />
    </logger>
	<!-- 3rdparty Loggers -->
	<logger name="org.springframework.core">
		<level value="info" />
	</logger>
	
	<logger name="org.springframework.beans">
		<level value="info" />
	</logger>
	
	<logger name="org.springframework.context">
		<level value="info" />
	</logger>

	<logger name="org.springframework.web">
		<level value="info" />
	</logger>

	<!-- Root Logger -->
	<root>
		<priority value="warn" />
		<appender-ref ref="console" />
	</root>
	
</log4j:configuration>

위 소스 코드에서 각 패키지를 입력하는 부분은 자기 자신의 프로젝트 패키지 명에 맞게 수정해줘야 한다.

여기까지 진행했다면 셋팅은 끝났다. 이제 게시판을 만들어 보자.

'spring' 카테고리의 다른 글

spring quartz 스케쥴링 java config  (3) 2019.02.15
spring 스케쥴링 설정  (0) 2019.02.12
view에서 특정 함수 반복 실행 방지  (0) 2019.02.12
spring mybatis 게시판  (1) 2019.02.12

+ Recent posts