[ 스프링 환경 설정 정리 ]
1. [ index.jsp 메인 화면 띄우기 ]
1) WEB-INF/views 폴더 아래에 메인페이지로 쓸 index.jsp 페이지를 생성한다.
2) root 패키지에서 controller 패키지를 추가한 뒤, MyController.java 처럼 앞으로 컨트롤러로 이용할 자바 클래스를 만들고 아래처럼 소스코드를 작성한다.
@Controller // 스프링 웹 설정파일인 WEB-INF/spring/appServlet/servlet-context.xml 에서 <contextcomponent scan package로 지정된 패키지에서 탐색을 해 @Controller가 있는 클래스를 컨트롤러 클래스로 인식한다.
public class MyController {
// 메인 페이지 임으로 http://127.0.0.1:80/ 으로 요청시 index.jsp가 뜰 수 있도록 RequestMapping을 / 로 지정한다.
@RequestMapping(value="/")
public String homePage(){
return "index"; // servlet-context.xml 파일에서 ViewResolver에 매칭되는 부분으로 띄워줄 뷰 이름을 적는다.
}
}
3) 여기까지 작업시, http://localhost:80/root패키지/ 이렇게 해야 index.jsp가 뜨게 됨으로 http://localhost:80/ 만으로 뜨게하기 위해서 servers 탭의 서버를 더블클릭해 서버 설정창으로 들어가 modules 탭을 누르고 Edit를 눌러 Path 에 / 가 되도록 수정해 준다.
4) web.xml에 들어가 <welcome-file-list>index.jsp</welcome-file-list>를 추가해준다.
5) 앞으로 우리가만든 MyController로 쓸 것임으로 기존에 있던 HomeController 지워버리자.
: 결과) http://localhost:80/ 만으로 index.jsp 페이지가 뜨게 된다.
-----------------------------------------------------------
2. [ 한글 설정하기 ]
: JSP에서 filter를 이용해 controller로 들어가기 전에 request.setCharacterEncoding("UTF-8")을 해줬던 것처럼 스프링에선 이러한 역할을 하는 클래스를 제공한다. 이 클래스를 filter에 등록하고 url 매핑을 해주자.
1) web.xml에
<!-- [한글처리] -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
코드를 추가해주자. 단! 주의할 점은, 반드시 servlet 태그 위에 위치해야한다.!! 서블릿보다 필터가 먼저 와야함!!
-----------------------------------------------------------
3. [ DB 설정하기 ]
1) [ DB DataSource 객체 생성 및 JUnit 단위 테스트하기]
a) pom.xml에 아래 라이브러리를 추가시킨다.
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- spring-jdbc : datasource 객체 가져올 때 쓰임 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- spring-test : Junit을 이용해 스프링 코드를 테스트할 때 필요하다. -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
+ JUnit 버전을 4.10 이상으로 올려준다.!!
b) 스프링 환경설정 파일에 datasource 빈 객체를 등록해주어야 하는데 스프링에는 환경설정 파일이 두개가 있다.
- WEB-INF/spring/appServlet/servlet-context.xml
: 웹과 관련된 환경설정을 담당한다.
- WEB-INF/spring/root-context.xml
: 웹이외의 환경설정을 담당
ex) DB설정, 트랜잭션 설정 등등...
따라서, root-context.xml에 아래의 코드를 추가시킨다.
<!-- [데이터베이스 DataSource설정] -->
<bean id="datasource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/book_ex?useSSL=false&serverTimezone=Asia/Seoul"></property>
<property name="username" value="root"></property>
<property name="password" value="dudfhd13"></property>
</bean>
c) 데이터 베이스에 연결이 잘 되어 Connection 객체가 잘 얻어지는지 JUnit테스트를 진행하자!
: 스프링에서 test를 진행할 때는 src/test 폴더에서 작업을 해야한다.
: src/test/패키지경로/ 에다가 DataSourceTest.java 클래스를 하나 만들고
: 다음의 코드를 작성한다.
// JUnit은 WAS 구동없이 테스트를 빠르게 할 수 있기 때문에 단위테스트에 적합하다. 또한, 스프링은 많은 작업을 하고 테스트하려면 오류를 잡기 어려움으로 단위테스트에 신경을 쓰자.
// 스프링 관련 테스트임으로 이 작업을하려면 pom.xml에 spring-test 라이브러리가 추가되어 있어야한다.
@RunWith(SpringJUnit4ClassRunner.class) // 스프링을 로딩한다.
@ContextConfiguration(locations ={"file:src/main/webapp/WEB-INF/spring/**/*.xml"}) // 스프링 설정파일을 로딩한다.
public class DataSourceTest {
@Inject // byType으로 스프링 환경설정파일에 생성해둔 타입이 같은
// 녀석을 자동으로 주입한다.
private DataSource ds;
@Test // 단위테스트할 메서드에 작성한다.
public void testConection()throws Exception{
try(Connection con = (Connection) ds.getConnection()){
// datasource로부터 Connection 객체를 얻어 로그를 찍어보자.
// 메서드를 더블클릭하고 오른쪽 클릭->Run as->Junit Test를 클릭해 Connection 객체가 정상적으로 생성되었다면 DB연결에 성공한 것이다.
System.out.println("테스트 : " + con);
}catch(Exception e){
e.printStackTrace();
}
}
}
2. datasource 객체를 등록했음으로 [ MyBatis(마바) 설정을 하자 ]
a) pom.xml에 아래 라이브러리를 추가한다.
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
b) classpath경로인 src/resources 에 mapper 폴더를 만들고 그 안에 MyBatisMapper.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">
<!-- namespace는 mapper를 구분하는 역할을 함으로 고유한 값으로 지정하지만 보통 프로젝트의 패키지명으로 짓지만 여기선 간단히 작성했다. -->
<mapper namespace="MapperNameSpace">
</mapper>
c) src/resources 아래에 mybatis-config.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>
<typeAliases>
<package name="org.zerock.domain"/>
<!--
typeAliases에 패키지 속성으로 지정해 놓으면 mapper에서 resultType시 일일이 패키지명을 다 기재하지 않고 클래스명만
기재해 사용할 수 있다. import와 유사함
-->
</typeAliases>
</configuration>
d) 스프링 환경설정 파일 root-context.xml에 가서 다음의 코드를 작성한다.
<!-- MyBatis의 SqlSessionFactory 빈을 등록한다. -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"></property>
<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mapper/**/*Mapper.xml"></property>
// 여기서 **는 어떠한 폴더가 와도 괜찮다는 의미 파일명 앞에 *는 아무거나 파일명와도 대고 끝에 Mapper.xml로 끝나는 파일 모두를 의미한다.
</bean>
<!-- MyBatis에서 실질적으로 우리가 사용하게 될 sqlSessionTemplate 빈을 등록하자. -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
e) JUnit 테스트 코드를 작성하.....자....라 하고 싶은데 너무 귀찮아서 생략하겠다.(잘될거다..)
-----------------------------------------------------------
4. [ AOP와 Transaction 설정 ]
: AOP란?
: OOP(객체지향)에서 기능별로 클래스를 나누었지만, 그럼에도 불구하고 나누어진 클래스들 안에서도 공통으로 사용되는 코드가 중복되기 때문에 여전히 한계점을 지니고 있다. 따라서, 이러한 비지니스 로직이 아닌 공통관심사(횡단관심사)를 proxy(대리자)에게 실행시점에 너가 대신해서 저 비지니스 로직을 실행하는 메서드 앞이나 뒤 혹은 앞 뒤 에 넣어줘!(주입해줘) 처럼 작동하는 방식을 AOP(Aspect Object Programming : 관점지향 프로그래밍)이라고 한다.
ex) 로그, 트랜잭션, 수행성능 테스트 메서드 등..
: AOP 필수 용어
- Advice : 공통관심사, 즉 공통으로 수행할 코드 자체를 의미한다.
- PointCut : 구체적으로 비지니스 로직의 어디에 들어갈지를 지정한다.(앞,뒤 혹은 둘다)
- JoinPoint : PointCut의 묶음이라고 생각하면 쉽다. Advice가 적용될 메서드들
- Aspect : AOP의 하나의 단위라고 보면 된다. 즉, Advice + PointCut을 의미함
- Target : Aspect가 적용될 클래스를 가리킨다.
- Proxy : AOP를 대신 적용하는 대신자 객체
- Weaving : AOP를 적용하는 것을 위빙이라 한다.
여튼... 여기까진 상식적인 얘기고... 설정하는 방법은
Transaction을 어노테이션을 사용하면 저절로 AOP가 적용이 된다. 따라서 트랜잭션을 사용한다는 건, AOP를 사용하는 것과 마찬가지임으로 AOP에서 필요로하는 라이브러리도 필요하다.
즉, AspectJ와 spring-tx를 추가해야한다.
1) pom.xml에
<!-- 트랜잭션을 위한 spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
가 추가 되어 있는지 확인하자. 일반적으로 legacy project로 생성시 aspectj는 있으니까 spring-tx만 추가해주도록 하자.
-----------------------------------------------------------
5. [ REST 설정 ]
: REST 방식
특정 url이 구체적인 특정 데이터를 의미하는 방식이다.
ex) /replies/123 + DELETE 방식 => 123번 댓글을 지운다.
ex) /replies/ + JSON 데이터 + POST 방식 => 댓글을 추가한다.
이러한 REST 방식은 AJAX와 연동되어서 자주 사용된다.
AJAX?
: 비동기적 통신 방법인데 JSP 화면처리가 싱글쓰레드 기반으로 동작하기 때문에 처리를 할 때 화면이 깜빡이는 것을 우리는 경험했을 것이다.
하지만, 좋아요 버튼 등을 클릭할 때 화면이 깜빡 거린다면...? 극혐
따라서, 싱글 쓰레드처럼 순차적으로 처리하는게 아니라 멀티쓰레드처럼 동시적으로 처리되는 것처럼 느껴지게 하는 방식인데 사실 동시적으로 처리된다기보단, 여유가 될 때 처리를 하도록 해놓고 그 작업을 기다리지 않고 다른 작업을 하다가 그 작업이 처리되면 그 결과를 받는 방식이다.
여튼간.... 서두가 길었고...
설정을 위해서는... JSON 객체를 자동으로 일반 객체로 일반 객체를 반환시
JSON 객체로 자동으로 변환해주기 위해서 필요한 라이브러리가 있다.
1) pom.xml에 jackson-databind 라이브러리를 추가하자.
<!-- REST, AJAX를 위한 라이브러리 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>
-----------------------------------------------------------
6. [ jdbc용 로그 설정해주기 ]
: 우리가 MyBatis를 이용해 작업을 할 때 최대 단점은?
console에 찍히는 것만 바서는 어떤 변수에 어떤 값이 set되는지 정확히 파악하기가 너무 어렵다. 인정??
따라서, log4jdbc log4j2 라이브러리를 이용하면 이러한게 친절히 다 나온다...
1) pom.xml에
<!-- jdbc log를 위한 라이브러리 -->
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
<version>1.16</version>
</dependency>
를 추가하자.
2) 이때 반드시!!!!!!,
- log4jdbc.log4j2.properties
- logback.xml
이 두 파일을 src/resources 아래에 넣어주어야 한다.
이 두 파일은 인터넷에서 구글링해서 찾던지... 기존에 환경설정 되있던대에서 가져와라
-----------------------------------------------------------
6. [ 스프링 MVC 파일 업로드 설정 ]
: 이미지 파일의 경우 이미지를 깨끗하게 축소할 수 있는 imgScalr 라이브러리를 사용한다. 이 라이브러리는 큰 이미지 파일을 고정된 크기로 변환할 때 편리하다.
1) pom.xml에 아래의 라이브러리를 추가한다.
<!-- 파일 업로드 관련 라이브러리 -->
<dependency>
<groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
2) 웹에서 파일 업로드는 multipart/form-data라는 방식으로 데이터를 여러 조각으로 나누어서 전송한다. 이때, 스프링 MVC에서 파일 업로드를 처리하기 위해서 파일 업로드로 들어오는 데이터를 처리하는 객체가 필요한데 이 객체를 "multipartResolver"라고 한다.
이 객체는 웹 설정과 관련이 있기 때문에 root-context.xml이 아니라 servlet-context.xml에 아래의 빈을 등록해 주어야 한다.
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="maxUploadSize" value="10485760"></beans:property>
</beans:bean>
파일 사이즈는 최대 10M정도로 설정했다.
-----------------------------------------------------------7. [ Spring MVC "인터셉터" 설정 ]
: 인터셉터는 JSP의 필터와 거의 유사하다. Controller로 요청이 들어가기 전에 한번 걸려주는 역할로
게시물 작성할 때 로그인이 필요하듯 게시글 접근 전에 로그인이 되어 있는지 유무등을 검사할 때 자주 사용된다.
하지만, Filter는 웹 애플리케이션 내에서 동작하므로 스프링의 Context를 접근하기 어렵지만, 인터셉터는 Spring의 Context내에서 존재함으로 Context 내의 모든 객체를 활용할 수 있다는 장점이 있다.
설정 방법)
1) 패키지에 SampleInterceptor 클래스를 하나 만들고 HandlerInterceptorAdapter를 extends(상속)한다.
package com.configure.javaStudy.interceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class SampleInterceptor extends HandlerInterceptorAdapter{
}
2) WEB-INF/spring/appServlet/servlet-context.xml에 다음 코드를 추가한다.
<!-- 인터셉터를 쓰기 위해 만들어논 SampleInterceptor 클래스를 객체 등록해놓자. -->
<!-- 인터셉터 등록하려면 Namespaces 탭에서 mvc 가 체크 되어 있어야만 함! -->
<!-- interceptor 태그 부분에는 mapping에 원하는 URI를 지정한다. 이 설정은 web.xml의 필터나 servlet의 설정과
동일함으로 필요한 경로를 직접 지정하거나, **, * 와 같은 패턴을 적용할 수 있다.
-->
<!-- 아래처럼 작성하면 현재 프로젝트의 /doA 경로와 /doB 경로를 호출할 때 SampleInterceptor 클래스가 동작하도록 되어 있는 것! -->
<beans:bean id="sampleInterceptor"
class="com.configure.javaStudy.interceptor.SampleInterceptor">
</beans:bean>
<interceptors>
<interceptor>
<mapping path="/doA" />
<mapping path="/doB" />
<beans:ref bean="sampleInterceptor" />
</interceptor>
</interceptors>
-----------------------------------------------------------
여기까지가 스프링 기본 설정입니다.!! 수고하셨습니다.
- 작성자 : 황영롱 2017-04-28