개발 환경 : 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 소스>
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | < 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 소스 코드>
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | < p ><? xml version = "1.0" encoding = "UTF-8" ?> 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 > </ p > |
기본적인 mybatis셋팅에서 dataSource를 셋팅하는 부분이 살짝 바뀌었다. 이는 mybatis 로그를 출력하기 위한 셋팅이다.
또한 sqlSessionFactory 부분에서 RefreshableSqlSessionFactoryBean.java를 참조하여 셋팅하였는데 mapper 수정 시 tomcat restart를 하지 않고 바로 적용되도록 하기 위함이다.
<RefreshableSqlSessionFactoryBean.java 소스코드>
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | <p> 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(); } }</p> |
<mybatis-config-base.xml 소스코드>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | < p ><? xml version = "1.0" encoding = "UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" < 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 >< br ></ p > |
위의 소스는 mybatis 설정 정보 파일로 필요한 옵션을 추가해서 사용하면 되겠다.(mybaits.org 또는 구글링)에서 참조
위의 파일을 추가한 후 설정을 읽어오기 위해 root-context.xml파일을 수정한다.
<root-context.xml 소스 코드>
1 2 3 4 5 6 7 8 9 | < p ><? xml version = "1.0" encoding = "UTF-8" ?> 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 > </ p > |
root-context.xml의 소스를 수정한 후 mybatis-context.xml에서 설정한 dataSource 정보를 읽어오기 위해 jdbc.properties 파일을 추가한다.
추가 경로 : src/main/resource/META-INF/
<jdbc.properties 소스 코드>
1 2 3 4 5 | < p ># Maria DB jdbc.driverClassName=org.mariadb.jdbc.Driver jdbc.username = javaboja jdbc.password = javaboja</ p > |
마지막으로 mybatis 쿼리 로그를 출력하기 위해 log4j.xml을 수정하자.
<log4j.xml 소스 코드>
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <? xml version = "1.0" encoding = "UTF-8" ?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <!-- 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 |