반응형

Let's take a lookt at spring-boot!


한 줄로만 요약할 수는 없겠지만 굳이 이야기 한다면 '좀 더 쉽게 스프링을 관리하여 스프링을 빠르게 개발하는데 도움을 주는 도구' 이지 않을까 합니다.


A. spring-boot 를 사용하는데 있어서 핵심요소들이 있습니다. 

1. @SpringBootApplication 을 통한 기본적인 Auto-Configuration 을 활성화 할 수 있습니다. 

2. spring-boot 의 starter 들을 통해 이전에 비해 spring 의 설정들을 간소화 및 관련된 의존성들을 쉽게 관리할 수 있게 됬습니다.

3. spring-boot CLI(Commnand Line Interface) 를 통해서 간결한 스프링 개발 방식을 제공합니다.

4. Actuator 를 통해서 애플리케이션의 내부 작동을 살펴볼 수 있습니다.


B. 다음으로 spring-boot 애플리케이션 프로젝트를 생성하는 방법들을 확인해 보겠습니다.

1. Maven 으로 프로젝트를 생성할 수 있습니다.

mvn archetype:generate -B\

  -DarchetypeGroupId=am.ik.archetype\

  -DarchetypeArtifactId=spring-boot-blank-archetype\

  -DarchetypeVersion=1.0.6\

  -DgroupId=com.example\

  -DartifactId=hajiboot\

  -Dversion=1.0.0-SNAPSHOT

2. Sping Initializer의 웹 인터페이스를 사용합니다.

- http://start.spring.io

3. 개발도구들을 활용해서 프로젝트를 생성합니다.

- IntelliJ, SpringToolSuite

4. Spring Boot CLI 에서 Initializer 를 사용 합니다.

- spring init

- spring init -dweb,jpa,security --build gradle -p jar -x (현재디렉토리에 풀기를 원하면 --extract 나 -x 사용)

spring init -d=web,thymeleaf,data-jpa,h2 --groupId=com.example  --artifactId=mylotto --name="My Lotto Service" --package-name=mylotto --description="My Lotto Service" --build maven mylotto


참고) spring-boot 의 실행.

1. mvn spring-boot:run

2. mvn package 실행 후 java -jar *.jar


참고) spring-boot-cli 설치.

1. spring-boot-cli 라이브러리를 직접 설치 및 환경설정을 한다.

2. SDKMAN(http://sdkman.io) 를 설치하여 spring-boot-cli 를 설치한다.(bashrc 가 수정되는 바람에 나중에 삭제할 때 헤맬 수 있다.)

3. Homebrew 로 설치한다.(https://brew.sh)

4. 맥포트로 설치한다.(https://www.macports.org/install.php)


C. DB

1. JDBC 연결.

a) pom.xml 에 spring-boot-starter-data-jdbc 또는 spring-boot-starter-data-jpa(jdbc를 포함) 그리고 mysql-connector 를 추가한다.

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jdbc</artifactId>

</dependency>

<!-- jpa 안에 jdbc 포함 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>


b) application.properties 에 설정값들을 추가한다.

spring.datasource.dirver-class-name=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://*******:3306/my_lotto

spring.datasource.connectionProperties=useSSL=false;characterEncoding=UTF-8;zeroDateTimeBehavior=convertToNull;useAffectedRows=true

spring.datasource.username=

spring.datasource.password=

spring.datasource.initSQL=SELECT 1

spring.datasource.tomcat.max-wait=3000

spring.datasource.tomcat.mac-active=2

spring.datasource.tomcat.test-on-borrow=true


c) JdbcTemplate 으로 CRUD 를 한다.

@Autowired JdbcTemplate jdbcTemplate;


public List<MyLotto> selectList() {

String query = "SELECT * FROM mylotto ORDER BY seq desc LIMIT 10";

return jdbcTemplate.query(query, new BeanPropertyRowMapper<MyLottoVO>(MyLottoVO.class));

}


2. MyBatis 연동.

a) mybatis-spring-boot-starter 를 추가한다.(1.2.0 이 있지만... parent version 1.5.2에선 안 되는 듯)

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.1.1</version>

</dependency>


b) using simple mapper 

- dependency 를 추가하고, datasource에 대한 application.properties 설정이 되어 있단면 아래의 interface Mapper 만 있으면 동작한다.

@Mapper

public interface MyLottotMapper {

@Select("SELECT * FROM mylotto WHERE key = #{key}")

MyLotto selectOne(@Param("key") Integer key);


@Select("SELECT NOW() FROM DUAL")

String selectCurrentDateTime();

}


c) using SqlSession

- Dao, Repository 역할을 가지는 클래스를 만든다.

@Repository

public class MyLottoRepository {

private final SqlSession sqlsession;


public MyLottoRepository(SqlSession sqlsession) {

this. sqlsession = sqlsession;

}


public MyLotto selectOne() {

return (MyLotto) this.sqlSession.selectOne("com.joochang.lotto.selectOne"); 

}

}

- mapper.xml 을 만든다.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.joochang.lotto">

<resultMap id="myLotto" type="com.joochang.lotto.MyLotto">

...

</resultMap>

<select id="selectOne" resultMap="myLotto">

<![CDATA[

SELECT * FROM mylotto LIMIT 1

]]>

</select>

</mapper>


3. JPA 연동.

a) JPA 를 MySql과 함께 사용하려면 먼저 아래와 같이 pom.xml 에 dependency 를 추가해 줍니다.

<!-- jpa 안에 jdbc 포함 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

b) application.properties 에 JPA와 관련된 설정을 추가합니다.

spring.jpa.databas=MYSQL

spring.jpa.show-sql=true

# 테스트할 때 유용할 것 같은 기능. #실환경에서 돌린다면 지옥을 경험한다..

# spring.jpa.hibernate.ddl-auto=create # create or create-drop

c) Entity 클래스를 생성합니다.

@Entity

public class MyLotto {

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private int id;

private String name;


(생략)...

}

d) Dao, Repository 역할을 가지는 interface 를 만들어야 합니다.

public interface MyLottoJPA extends CrudRepository<MyLotto, Integer> {

MyLotto findById(Integer id);

}

또는

public interface MyLottoJPA extends JpaRepository<MyLotto, Integer> {

MyLotto findById(Integer id);

}


D. Logger

spring-boot는 모든 내부 로깅에 대해서 Commons-Loggins-API 를 사용합니다. 기본 구성은 Java-Util-Logging, Log4j2logback 입니다. 기본적으로 spring-boot 'Starters' 를 사용하면 logback 이 사용될 것인데, Java-Util-Logging, Commons-Logging, Log4j 또는 SLF4J 를 사용하는 의존적인 라이브러리들이 모두 올바르게 동작하도록 적절한 logback 라우팅이 포함됩니다.


a) spring-boot는 콘솔에 INFO 레벨 로그를 표시하려고 로그백(http://logback.qos.ch)으로 로깅을 설정합니다. 로깅 구성을 완전히 제어하려면 클래스패스 루트(src/main/resources)에 logback.xml 파일을 생성해야 합니다. logback.xml 이 존재하면 우선적으로 파일의 내용이 적용됩니다. 다르게 하려면 logback.xml 의 이름을 변경하고 (logback-spring.xml) application.properties 에 로그설정들을 추가하면 됩니다.

참고) applcation.properties

logging.config=classpath:logback-spring.xml

logging.exception-conversion-word=

logging.file=

logging.level=

logging.path=

logging.pattern.console=


b) 만약 logback 대신 log4j2 를 사용하고 싶다면 다음과 같이 해야 합니다.

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter</artifactId>

<exclusions>

<exclusion>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-logging</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-log4j2</artifactId>

</dependency>


references of loggers)

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html


E. Profile

 스프링 프레임워크는 스프링 3.1부터 Profile-Based Configuration을 지원했습니다. 이것은 애플리케이션의 환경설정을 분리하는 방법이면서 특정한 환경을 구성하기도 합니다. @Component나 @Configuration 은 @Profile 과 함께 쓰여 애플리케이션의 로딩을 제한할 수 있습니다.

 spring-boot를 빌드 및 실행 시 "no profiles are currently active" 라는 메시지를 마주칠 수 있는데요. 에러는 spring.profiles.active 값을 설정하면 해결할 수 있습니다. pom.xml 과 src/main/resrouce 의 application.properties 에 대한 설정을 다음과 같이 합니다.


참고) pom.xml

<properties>

<activeProfile>local</activeProfile>

</properties>

<profiles>

<profile>

<id>local</id>

<activation>

<activationByDefault>true</activationByDefault>

</activation>

<properties>

<activeProfile>local</activeProfile>

</properties>

</profile>

<profile>

<id>release</id>

<properties>

<activeProfile>release</activeProfile>

</properties>

</profile>

</profiles>


참고) application.properties

spring.profiles.active=@activeProfiles@

위와 같이 설정 후 application-{profile}.properties 형태의 입맛에 맞는 파일들을 생성하여 사용할 수 있으며, 실행은 아래와 같이 합니다.

java -jar -Dspring.profiles.active=local target/lotto-0.0.1-SNAPSHOT.jar

또는 각 서버에서 환경변수 설정을 통해 사용할 수 있습니다.

export SPRING_PROFILES_ACTIVE=release


references of profiles)

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

- https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html

https://groups.google.com/forum/#!topic/ksug/BBaO3y8hSaU



Spring-boot-profiles

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html


Common-Application-Properties

http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html


Etc...

http://www.mybatis.org/spring-boot-starter/

https://github.com/spring-projects/spring-boot

https://www.slideshare.net/madvirus/spring-boot-42817314

https://www.slideshare.net/whiteship/ss-47273947



반응형
반응형

Spring4 + myBatis 환경에서 트랜잭션 설정하기.

트랜잭션 위주로 정리해 봅니다. mybatis 는 뭐 정보가 많으니 패스하겠습니다.


1. 기본 설정.

transaction 범위와 관련하여, dispatch-servlet 에서와  applicaitonContext.xml 에서의  component-scan 설정을 수정해 줘야 합니다.

mvc-config.xml

<context:component-scan base-package="com.slowstarter" use-default-filters="false">

<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />

</context:component-scan>


applicationContext.xml

<context:component-scan base-package="com. slowstarter">

<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />

</context:component-scan>


poll(dbcp2, c3po), mybatis 등 필요한 dependency 설정들 추가하기. 

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.4.0</version>

</dependency>


<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjweaver</artifactId>

<version>1.8.1</version>

</dependency>


2. aop 를 통한 설정.


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

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

</bean>


<tx:annotation-driven transaction-manager="transactionManager" mode="proxy"/>


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

<tx:attributes>

<tx:method name="createTest"

    isolation="REPEATABLE_READ"

    propagation="REQUIRED"

    rollback-for"RuntimeException" />

</tx:attributes>

</tx:advice>


<aop:config>

<aop:pointcut id="servicePublicMethod"

                expression="execution(* com.joochang.service.*Service.*(..))" />

<aop:adviser id="transactionAdvisor"

               pointcut-ref="servicePubicMethod" advice-ref="txAdvice" />

</aop:config>


- 스프링AOP 대신 AspectJ-AOP를 사용하는 방법도 있다. AspectJ는 프록시 대신 클래스 바이트코드를 직접 변경해서 부가기능을 추가하기 때문에 타깃 오브젝트의 자기 호출 중에도 트랜잭션 부가기능이 잘 적용된다. 굳이 자신의 메소드를 호출하는 경우에도 트랜잭션 속성이 정확히 적용되기를 원한다면 AspectJ를 사용하는편이 좋다. <tx:annotation-driven mode="aspectj" /> 처럼 설정하면 된다. (Spring AOP 는 기본적으로 JDK프록시이고, AspectJ는 클래스기반 프록시)


3. annotation 을 통한 설정. 

 MySql 은 기본 isolation 이 repeatable_read  인데, spring  의 default 가 알아서 맞춰주는지 알아볼 필요도 있고 명확하게 해당 타입을 지정해 주는게 더 와 닿는 것 같습니다.


@Transactional(propagation = Propagarion.REQUIRED,

                  isolation = Isolation.REPEATABLE_READ,

                  rollbackFor = RuntimeException.class)

public MyTestResult createTest() throws RuntimeException {

...

}


 선언적 트랜잭션에서는 런타입 예외가 발생하면 롤백합니다. 반면에 예외가 전혀 발생하지 않거나 checked-exception이 발생하면 commit 합니다.  스프링에서 data-access-exception은 Runtime-Exception으로 전환돼서 던져지므로 Runtime-Exception만 롤백대상이 됩니다. 하지만 롤백대상으로 삼아야 한다면 rollbackFor 를 사용해서 등록합니다. 반대로 기본적인 롤백대상인 Runtime-Exception을 트랜잭션 커밋 대상으로 해 주려면 noRollbackFor 를 사용하면 됩니다.


 그리고 rollback 시 createTest() 에서 만약 try catch 쓸 경우 statement 안에서 예외를 잡더라도 throw new RuntimeException  하지 않으면 롤백되지 않습니다. 또한 finally 로 뭔가 동작을 하길 바래서 사용한다면 ㅠㅠ rollback 이 되지 않습니다.


4. 기타 사항. 

 스프링의 Proxy 는 2가지 타입이 있습니다.  JDK Reflection API 를 사용한 JDK다이내믹프록시 와 CBLIB(Code Generator Library) 인데요. JDK프록시는 인터페이스를 구현한 클래스에 적용이되고, CBLIB은 spring 3.2부터 기본적용이 되어있어서 인터페이스를 사용하지 않은 클래스에 대해 적용이 됩니다.

 스프링AOP는 기본적으로 JDK Reflection API를 사용하여 Spring에 의해 생성 된 다이내믹 프록시 기법을 이용해 동작합니다. 다이내믹 프록시를 적용하려면 인터페이스가 있어야 하지만 스프링 내부의 ProxyFactoryBean 클래스나 CGLIB 라이브러리가 제공해주는 클래스 레벨의 프록시도 사용할 수 있습니다. AspectJ를 사용해 트랜잭션을 적용할 때는 앞에서 설명한 것처럼 @Transactional을 클래스레벨과 클래스 메소드 레벨에 부여해야 한다는 점을 주의해야합니다. AspectJ 모드를 사용하면서 인터페이스에만 @Transactional을 부여하면 트랜잭션이 적용되지 않습니다. 그래서 클래스프록시 모드에서는 Service 코드에 인터페이스를 Implements 해야한다는니 이런 거 필요없습니다.


명확하게 CGLIB을 사용하려면 proxy-target-class=true 옵션을 아래의 설정에 추가 해야만 합니다.

<tx:annotation-driven proxy-target-class="true">

또는 <aop:config proxy-targer-class="true"> </aop:config>

또는 <aop:aspectj-autoproxy proxy-target-class="true"> //  aspectj는 기본이 클래스모드

또는 @EnableAspectJAutoProxy(proxyTargetClass=true)

또는 spring.aop.proxy-target-class=true // application.properties 




반응형

+ Recent posts