ParkJongin Blog

ParkJongin Blog

All posts in one long list


제주도 중문 VADADA (바다다) 방문기

VADADA

제주도 중문 대포포구 바로옆에 VADADA라는 비치라운지가 있습니다. 저는 제주도에가서 마침 펜션이 걸어서 10분 걸리는 곳에 잡게 되어서 걸어서 가봤습니다. 술을 먹겠다는 생각으로 가서 걸어갔는데요..
진짜 풍경이 어마어마하게 좋습니다. 하지만 술을 많이 먹지는 못했습니다.. 이유는 가격이 조금 비싸게 느껴져서 그랬습니다. 제가 많이 비싼 칵테일을 못먹어봐서 그런거일 수 있지만 제 기준으로는 강남보다 칵테일가격이 더 비싸게 느껴졌습니다. 하지만 경치는 엄청좋으니 제주도 놀러간김에 한번쯤은 가볼만 한 곳 같습니다. 술을 못드시는 분들은 제기억에는 노알콜도 있던것 같구요.. 개인적인 생각으로는 낮에 커피한잔 마시러 가면 딱 좋을것 같습니다. 커피도 팝니다. 저는 밤에가서 밤바다 경치를 보며 칵테일을 먹었습니다. 물론 밤에도 바다쪽으로 환하게 불을 켜놔서 바다 경치가 멋있게 보이긴합니다. 그치만.. 낮에가면 더 멋질것 같았습니다.

VADADA에서 찍은 사진..



VADADA 건물 모습
  • VADADA 건물은 정말 이쁘게 생겼습니다. 저렇게 지어져있고 야외에 테이블과 누울수도 있는 침대?같은 쇼파가 있습니다.
VADADA에서 바라본 밤바다
  • VADADA 야외 테이블에서 바라본 밤바다 입니다. 정말 멋있지만 낮에가면 더 멋질 것 같다는 생각을 했습니다.
VADADA에서 먹은 칵테일과 안주
  • VADADA에서 미도리샤워랑 하나는 깔루아밀크였던 것 같습니다. 안주는 과일말린것을 시켰는데요. 저렇게 3개 해서 대충 5만원정도 나왔던 것 같습니다.

펜션에서 바라본 VADADA
  • 펜션에서 멀리 하얗게 보이는 건물이 VADADA 입니다. 혹시 걸어서 가실분은 제가 묵은 펜션도 괜찮으실 것 같습니다. 바로 보이는 항구는 대포항구 입니다.

마치며

VADADA는 한번쯤 가볼만한곳 입니다. 낮에 갈 때는 상관없지만.. 저는 밤에 갔을때 정말 찾기가 힘들었습니다.
정말 가로등도 없고 시골 거외길을 걷는 기분으로 걸어가셔야 합니다. 노래소리는 들리지만 정말 이 길로 가면 나올까? 라는 생각으로 가시다보면 딱 나옵니다. 밤 12시에 VADADA는 문을 닫습니다. 마감할때쯤 나왔는데 아쉬웠을만큼 좋았습니다.

웹 어플리케이션?

WebApplication

‘하위에 WEB-INF 디렉토리를 갖고 최상위 디렉토리는 해당 웹 컨텍스트의 최상위 문서 루트가 된다.’ 와 ‘WEB-INF 디렉토리 밑에 web.xml에 서블릿 설정이 포함된다’가 일반적인 답변이라고 한다.
서블릿 명세에서 웹 어플리케이션을 정의할 때 디렉토리 구조를 위와 같은 내용으로 결정하고 WAR포맷로 정의한 것은 하나의 독립적인 어플리케이션으로 취급하려는 의도입니다.
서블릿명세는 서블릿컨테이너와 서블릿의 기능이 모두 정의되어 있고 각 각의 서블릿컨테이너(예를들면 톰캣과 같은…또한 여러종류의 톰캣과 같은 서블릿컨테이너가 존재합니다.)의 성능 차이가 있을 뿐 기능적인것은 모두 동일하게 동작하게 된다.
서블릿컨테이너가 웹 어플리케이션을 내부로 끌어들이는 과정을 배치라고 하고 서블릿 컨테이너는 웹 어플리케이션마다 독자적인 클래스로더를 유지해서 우연히도 같은 클래스를 사용하는 서로다른 웹 어플리케이션이 있는 경우에도 간섭이 발생하지 않게 유지합니다.

조금 부족한것 같지만.. 일반적인 답변과 웹어플리케이션과 서블릿컨테이너와의 서블릿명세에 의한 관계를 정리해보았습니다. 제 생각이지만 서블릿컨테이너는 우리가 흔히 아는 운영체제(OS)라고 생각하면 될 것이고 웹 어플리케이션은 운영체제에서 동작하는 일반적인 어플리케이션같이 생각하면 편할 것 같습니다. 이 글은 서블릿 컨테이너의 이해라는 책을 공부하며 정리해 보았습니다. 부족한것은 피드백 주시면 감사하겠습니다.

Servlet이란?

들어가기전에.. 그냥 주저리..

막연하게 스프링을 공부해야지.. 하고나서 스프링을 공부하려고 보니 너무 어려웠다. 그 이유가 무엇인가 생각을 해보니 기본적으로 servlet, jsp 웹프로그래밍에 대해 경험도 없고 지식도 없었던 것이 큰 장애물 이었던 것 같다. 더하기를 모르고 곱하기를 하려고 했던 느낌이랄까.. 아무튼 내가 느끼기엔 그랬다. 지금도 잘 아는 것은 아니지만… 서블릿 컨테이너의 이해라는 책을 보고 간략하게 제 생각과 정리할 것을 적어봤습니다.

서블릿이란?

1997년 SUN사에서 웹 서비스를 위한 기본 인터페이스로 서블릿을 제안했다. 서블릿을 배치, 서비스하는 구조로 서블릿 컨테이너의 개념도 전파했다.
서블릿은 javax.servlet.Servlet 인터페이스를 구현한 것이 서블릿이라고 한다.
나의 생각으로는 web application 이라는 생각을 하고 있다. Servlet 자체가 web application 이라기 보다는 Servlet을 이용해서 웹 서비스를 하고 내부적인 비지니스 로직과 같은 부가적인 기능을 더하면 Web application이라고 생각한다. 이러한 생각을 하는 이유는 또 있다.
Servlet은 기본적으로 우리가 자바 응용프로그램을 만들때 public static void main에서 프로그램이 시작한다면 Servlet은 서블릿 컨테이너에 의해 생성, 호출, 소멸이 이루어진다. 또한 서블릿 컨테이너가 네트워크 통신, 생명주기 관리, 스레드 기반의 병렬처리를 대행해 주기도 한다. 이렇게 보면 Servlet은 서블릿 컨테이너에서 돌아가는 일종의 프로그램이라고 할 수 있다. 그렇게 따지면 서블릿 컨테이너는 서블릿을 관리하는 작은 os와 같이 생각을 할 수 있다고 생각한다.(os가 해주는 역할을 다 하지는 않겠지만..)

서블릿과 서블릿 컨테이너(tomcat)

앞서 말했듯이 서블릿은 서블릿 컨테이너에서 관리된다. 서블릿 컨테이너는 bootstrap.jar와 tomcat-juli.jar 이렇게 2개만 classpath에 지정되어 있다.
이 2개는 서블릿 컨테이너가 서버를 띄우기 위해 필요한 것이다. 서버가 정상적으로 작동되고 나면 우리가 작성한 서블릿은 어떻게 올라가게 되는 것일까?
우리가 만든 서블릿을 서버위에서 동작시키려면 우리가 만든 서블릿class를 서블릿 컨테이너가 찾을 수 있어야 한다. 또한 어떠한 url로 요청이 들어 왔을때 우리가 만든 서블릿을 실행해야 한다는 사실을 알려줘야 한다. 이러한 과정을 배치라고 한다. 배치를 하기 위해 우리가 만든 서블릿을 서블릿 컨테이너가 알 수 있도록 해야 한다.

서블릿 컨테이너가 서블릿을 탐색하는 방법

서블릿 컨테이너는 웹 애플리케이션의 구조를 보고 탐색하게 된다. 그 구조는 web-inf 폴더내의 클래스 파일과 web.xml을 보고 판단하게 된다.
url은 web.xml에 정의된 url 패턴에 따라 처리할 서블릿이 결정이 된다. 서블릿 컨테이너는 public static void main을 통해 실행 됩니다.
여기서 command에 따라 분기를 나누어 각 상태에 맞는 로직을 실행합니다. 서블릿 컨테이너가 서블릿(웹 애플리케이션을 실행하는 단계를 요약해 보면 다음과 같습니다.)

  • 서블릿 컨테이너가 서블릿이 포함된 웹 애플리케이션을 동작시키기 위해 클래스 로더를 생성하고
  • 클래스 로더는 서블릿 명세에 미리 약속된 특정 위치 web-inf/lib, web-inf/classes에 있는 jar나 class 파일을 로딩 합니다.
  • 모든 서블릿은 javax.servlet.Servlet 인터페이스를 구현한 것이므로 사용자가 작성한 다양한 형태의 서블릿을 Servlet.service 메소드로 호출 할 수 있습니다. 따라서 서블릿 컨테이너는 클래스 로더와 인터페이스를 이용해서 우리가 만든 서블릿을 호출하게 됩니다.

간략하게.. 제 생각이 섞여서 어떻게 보면 뒤죽박죽일 수 있는 내용입니다. 혹시나 궁금한 점, 틀린 점이 있으시면 댓글 달아주시면 감사하겠습니다.

POJO란 무엇일까..?

POJO

스프링의 핵심이 POJO 프로그래밍이다. 스프링의 주요 기술인 IoC/DI, AOP와 PSA는 애플리케이션을 POJO로 개발할 수 있게 해주는 가능기술이라고 불린다.
POJO는 Plain Old Java Object의 약자로 Martin Fowler가 컨퍼런스 발표를 준비하다가 만들어낸 용어라고 한다.
POJO는 그냥 순수 자바 오브젝트이다. 이를 위해서는 몇 가지 조건이 있다.

  • 특정 규약에 종속되지 않는다. POJO는 자바언어와 꼭 필요한 API 외에는 종속되지 않아야 한다. 별다른 가치를 주지도 못하는 규약 따위에 종속되지 않아야 하고, 객체지향 설계의 자유로운 적용이 가능한 오브젝트여야만 POJO라고 불릴 수 있다.
  • 특정 환경에 종속되지 않는다. 특정 환경에 종속적이어야만 동작하는 오브젝트도 POJO라고 볼 수 없다. 특정 환경이 의존 대상 검색에 종속적이면 POJO라고 할 수 없다. 예를 들면 어떤 특정 서버에서만 동작하는 API를 직접 쓴 코드를 갖고 있거나 특정 OS에서 제공하는 기능을 직접 호출하도록 만들어진 오브젝트와 같은 케이스다.
    하지만 특정 기술규약과 환경에 종속되지 않다고 모두 POJO라고 말할 수도 없다.
    진정한 POJO란 객체지향적인 원리에 충실하면서, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 말한다. 그런 POJO에 애플리케이션의 핵심 로직과 기능을 담아 설계하고 개발하는 방법을 POJO프로그래밍이라고 할 수 있다.

스프링에서는 POJO프로그래밍을 DI, IoC, AOP, PSA를 이용하여 가능하게 했다. PSA는 서비스 추상화 인데 이것은 DI를 통해 가능하다.

마치며…

이 글은 토비의 스프링 3.0을 공부하면서 적은 글 입니다.
아직은 부족함이 많은 글 입니다. 부족한 점, 더 채워나가고 공부해야겠습니다.

IOC컨테이너, ApplicationContext, BeanFactory Spring

IOC컨테이너, ApplicationContext, BeanFactory

IoC컨테이너와 ApplicationContext, BeanFactory가 의미하는 것은 비슷하다. IoC컨테이너는 BeanFactory라고 불리기도 한다. BeanFactory는 빈의 생성과 제어의 관점에서 이야기를 하는 것이고 ApplicationContext는 스프링이 제공하는 Application 지원 기능을 모두 포함해서 이야기 하는 것이다. 스프링에서 핵심기능은 ApplicationContext이다. 우리가 흔히 xml로 정의하는 ApplicationContext(RootContext)를 설정정보로 참조한다. ApplicationContext에서 Bean의 생성, 조회, 등록 등을 담당한다. BeanFactory를 상속받는다. 따라서 BeanFactory의 중요 기능인 Bean 생성, 조회, 등록을 그대로 받고 여기에 스프링에 제공하는 부가기능을 추가로 제공한다.

ApplicationContext 동작방식
  • ApplicationContext는 @Configuration 어노태이션이 붙은 자바 파일이나, xml로 만든 <beans로 시작하는 appcontext를 설정정보로 등록하고 @Bean이 붙은 메소드의 이름을 가져와 빈 목록을 만든다.
  • 클라이언트가 ApplicationContext의 getBean() 메소드를 호출하면 자신의 빈 목록에서 요청한 이름이 있는지 찾고, 있다면 빈을 생성하는 메소드를 호출해서 오브젝트를 생성시킨 후 클라이언트에 돌려준다.

ApplicationContext와 BeanFactory

ApplicationContext를 사용하면 BeanFactory사용보다 더 범용적이고 유연하게 IoC기능을 확장해서 사용할 수 있다.

장점

  • 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
  • 종합 IoC 서비스를 제공해 준다.
  • 빈을 검색하는 다양한 방법을 제공한다.

토비의 Spring 3.0을 참고하여 작성하였습니다.

스프링 IoC, 스프링 DI

제어의 역전(IoC)

  • 제어의 역전이라는 개념. 일반적으로 프로그램의 흐름은.
    1. main()메소드와 같이 시작지점에서..
    2. 사용할 오브젝트를 결정하고..
    3. 오브젝트를 생성하고..
    4. 메소드를 호출하고..
    5. 메소드안에서 사용할 것을 결정하고 호출 하는 식의 반복..
      으로 이루어 진다.

제어의 역전은 이러한 흐름의 개념을 거꾸로 뒤집는 것이다.
제어의 역전에서는 오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않고, 생성하지도 않는다. 또 자신이 어디서 만들어지고 어디서 사용되는지도 알 수 없다.
모든 제어 권한을 자신이 아닌 다른 대상에게 위임한다.(서블릿또한 서블릿 컨태이너에 의해 관리되므로 제어의 역전 개념이 들어가 있다.)

  • 스프링 IoC 스프링에서는 오브젝트 팩토리를 이용해서 IoC를 한다. 스프링이 직접 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트(대상)이 Bean이라고 불리며 BeanFactory에서 빈의 생성, 관계 설정등과 같은 제어를 담당한다.

의존성 주입(DI)

말그대로 의존성이 있는 오브젝트를 외부로 부터 제공 받는다는 의미이다.
의존성이 있다는 것은 예를들면, A가 B에 의존하고 있다고 하면 A는 B의 변화 상태에 따라 영향을 받는 다는 의미이다.
스프링 DI는 세가지 조건을 충족해야 한다.

  • 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스에만 의존하고 있어야 한다.
  • 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제3의 존재가 결정한다.
  • 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.

의존관계 검색은 꼭 스프링의 bean일 필요는 없지만 애플리캐이션 기동시점에서 한번은 관계검색을 해줘야한다.
의존관계 주입은 꼭 스프링의 baen이어야 한다. 컨테이너가 관리해주기 위함이다.

위에 스프링IoC에서 BeanFactory가 스프링 Bean을 생성할때 DI를 같이 관리 해준다.

스프링 AOP

Spring AOP

AOP는 관점지향프로그래밍의 약자입니다. Spring에서 AOP를 할때에는 Dynamic Proxy를 이용해서 하게 됩니다. Dynamic Proxy는 동적으로 타겟의 Proxy를 만들어서 Proxy를 통해 AOP를 가능하게 하는 방법입니다. Aspectj는 java가 bytecode로 변환되고 나서 코드를 끼워넣습니다. 하지만 spring은 동적으로 proxy를 통해 접근하므로 많이 어려운점이 없지만 속도가 느리다는 단점이 있습니다.

AOP의 용어

  • Aspect : Aspect는 어던 부가적인 기능을 정의 한다는 의미 입니다. 보통 AOP를 사용하는 곳은 로그, 데이터 처리 속도 등 반복적인 코드가 계속적으로 쓰일 경우 사용합니다. Aspect는 이러한 반복적인 코드가 하는 기능을 정의한다는 의미 입니다.(공통적으로 관심이 있는 사항들..)

  • JoinPoint : JoinPoint는 어떤 부가적인 기능을 삽입할 특정 위치를 말합니다.

  • PointCut : PointCut은 어떤 클래스의 어느 조인트포인트를 사용할 것인가를 정의합니다.

  • Advise : Advise는 각 JointPoint에 삽입되어져 동작할 수 있는 코드를 말합니다.

아래 코드 예제를 보겠습니다.

@Aspect
public class ChronometryImpl implements Chronometry{

	long startTime;
	
	@Override
	@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
	public void start() {
		// TODO Auto-generated method stub
		System.out.println("start input");
	}

	@Override
	@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
	public void end() {
		// TODO Auto-generated method stub
		
	}
	
	@Before("@annotation(org.springframework.transaction.annotation.Transactional)")
	public void start_before(){
		startTime = System.currentTimeMillis();
	}
	
	@After("start()")
	public void start_after(){
		System.out.println("처리 시간 : " + (System.currentTimeMillis() - startTime)/1000.0 + "sec");	
	}
	
	
	
}

 
aspect 코드

위 코드는 처리시간을 측정하기 위한 코드 입니다. @Aspect는 위 ChronometryImpl이 Aspect(어떤 부가적인 기능 정의)로 사용될 것임을 나타냅니다. 그리고 나서 @Pointcut은 어느 조인트 포인트를 사용할 것인가를 정의합니다.(복수 가능) 위 코드에서 조인트 포인트는 @annotation(org.springframework.transaction.annotation.Transactional) 이것이 됩니다. start()는 @Pointcut(“@annotation(org.springframework.transaction.annotation.Transactional)”)를 재정의한 것입니다. advise는 각 조인트포인트에 삽입되어져 동작할 코드들을 나타냅니다. 위 코드에서 보면 @Before(“@annotation(org.springframework.transaction.annotation.Transactional)”)와 @After(“start()”)가 있는 것을 확인할 수 있습니다. @Before는 “@annotation(org.springframework.transaction.annotation.Transactional)” 이거 자체가 PointCut이 되어서 따로 PointCut을 정의할 필요가 없습니다. @After@Pointcut(“@annotation(org.springframework.transaction.annotation.Transactional)”)으로 재정의된 start()를 사용하므로 따로 Pointcut을 정의해줘야 합니다.

Spring AOP

Spring 에서 IBatis 설정 방법

들어가기전에..

ibatis를 사용하기 위해서는 ibatis 관련 라이브러리를 설치해줘야 한다. maven 프로젝트인 경우 pom.xml에서 maven repository를 이용해서 받아주면 된다. maven 프로젝트가 아닌경우 lib파일을 받아서 직접 넣어줘야 한다. 또한 mysql, oracle등 사용할 디비접속에 필요한 jdbc 라이브러리를 받아줘야 한다.

MVC SPRING

스프링 프래임워크는 MVC 패턴을 따르고 있다. ibatis를 이용해서 db에 접근하는 것은 MVC패턴에서 M과 C의 관계가 아닐까 생각한다. 이 말은.. MODEL을 만들고 CONTROLLER 혹은 SERVICE에서 실제 데이터 처리를 위한 로직을 만들게 되는데, 데이터 처리를 하기 위해 필요한 데이터는 MODEL에서 가져오게 된다. 이 MODEL은 일종의 데이터를 담는 그릇이고 중간에 DAO(Data Access Object)를 둬서 Database에 접근, 제어를 하게되고 결과값을 리턴받아 MODEL에 넣게 된다. 이 데이터 MODEL을 갖고 CONTROLLER나 SERVICE에서 처리를 한다. 아래 그림이 예를 들어 설명한 것이다.

spring 데이터 처리 과정

DAO를 통해 DB의 데이터를 이용하고 데이터 반환과 SERVICE나 CONTROLLER에서 MODEL에 저장된 반환값을 이용한다.

IBATIS 사용하기

JDBC API와 SQL의 조합으로는 엔터프라이즈 애플리캐이션의 거대한 데이터를 처리하는 데에 제약과 문제점이 있다. 좀 더 효과적인 방식으로 사용가능하도록 추상화하고 개선하기 위해 나온것이 IBATIS 와 같은것이 있다. 스프링에서는 DATASOURCE라는 하나의 독립된 빈으로 등록하도록 강력하게 권장하고 있다. DB CONNECTION에 관련된 정보를 담고 있는것 같다. 스프링에서 IBATIS를 사용하기 위해서는 root-context(app-context)와 sqlmap, sqlmapconfig, dao, model 등이 필요하다. 먼저 IBATIS를 이용하기 위한 환경설정을 위해 root-context를 수정해보자.

model 만들기

먼저 어떤 모델을 만들어서 데이터를 처리할 것인지 정하는 것이 필요하다. 나는 article이라는 모델을 만들고 처리해 보았다. model을 만들때 데이터를 담는 VO와 DAO가 필요하다. VO는 순수 모델에 관련된 데이터를 담기위한 클래스이다. DAO는 디비를 제어할 때 필요한 중간자 역할을 해주는 것이다.

public class Article {

	Integer	id;
	String	title;
	String	author;
	String	link;
	String	description;
	String	content;
	String	date;

	// getter, setter 메소드는 자동 generate기능을 이용했다.
}
Article 클래스(모델)

위 코드는 Article 모델 클래스를 정의한 것이다. 이 모델에 맞는 데이터를 데이터베이스에서 가져와야 하는데 컨트롤러에서나 서비스에서 DAO를 통해 접근을 할 것이다. DAO를 통해 접근해서 얻은 결과 데이터를 Article모델에 담아서 반환해 줄 것이다.

	@Repository()
	public class ArticleDAO extends SqlMapClientDaoSupport{
		
		public ArrayList<Article> selectArticleList(){
		 
			ArrayList<Article> articleList = null;
			articleList = (ArrayList<Article>)this.getSqlMapClientTemplate().queryForList("ArticleDAO.getArticleList");
			return articleList;
		}
	}
ArticleDAO 코드

위 코드는 ArticleDAO 코드이다. SqlMapClientDaoSupport를 상속받는 것이 중요하다. 나중에 밑에 ibatis 설정을 하고 나서 articleDAO에 DI를 해줘야 하기 때문이다. @Repository는 스프링 빈으로 등록하기 위해서 @Component대신 더 스코프를 좁힌 개념으로 DAO, DB와 관련된 일을 한다고 명시해주기 위해 Repository를 붙여줬다.

이제 모두 모델은 준비가 되었다. ibatis - rootcontext 설정을 해보자.

ibatis - rootcontext(appcontext).xml 수정

	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
	    <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"/>
	    <property name="username" value="root"/>
	    <property name="password" value="root"/>
	</bean>
	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
	    <property name="configLocation" value="/WEB-INF/ibatis/config/sqlMapConfig.xml"/>
	    <property name="dataSource" ref="dataSource"/>
	</bean>
	<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
	    <property name="sqlMapClient" ref="sqlMapClient"/>
	</bean>		
	
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  		<property name="dataSource" ref="dataSource"></property>
 	</bean>
 
ibatis application context에서 설정
  • 먼저 제일 중요한 dataSource를 빈으로 등록해 준다. driverClassName에는 사용할 db의 드라이버 클래스 이름을 적어준다. 그 외 DB의 주소, 아이디, 패스워드 등을 설정해준다.
  • 다음 sqlMapClient에 sqlmap(실제 sql을 작성하는 xml문서) 환경설정 파일이 있는 경로 설정과 dataSource를 DI 해준다. configLocation에서 경로는 classPath를 등록해줘야 하는데 이것은 맨 아래에서 설명하겠다.
  • sqlMapClient는 iBatis의 핵심 API의 인터페이스가 담겨져 있다. 이를 이용하려면 sqlMapClient가 구현된 오브젝트가 실제 있어야 하는데 이 것을 sqlMapClientFactoryBean에서 해준다. sqlMapClientFactoryBean을 이용해서 sqlMapClient를 싱글톤 빈으로 등록한다.
  • sqlMapClientTemplate은 sqlMapClient를 DI받아서 ibatis의 기능을 이용한다. sqlMapClient를 직접 이용하는 대신 sqlMapClientTemplate을 이용하는 것이 좋은데, 그 이유는 sqlMapClientTemplate에서 기본적으로 예외변환, 스프링 트랜잭션, 동기화 등이 지원되기 때문이다.

이렇게 root context 설정이 끝나고 나면 sqlmapconfig와 sqlmap이 필요하다.

ibatis - sqlmapconfig, sqlmap 설정

이제 실제적으로 우리가 쿼리를 작성해야 하는 부분이다. sqlmapconfig는 sqlmap설정과 실제 sqlmap파일이 있는 경로를 적어주게 된다.

<?xml version="1.0" encoding="UTF-8"?>
 
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" 
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
 
<sqlMapConfig>
 	<settings enhancementEnabled="true" maxTransactions="5"
        maxRequests="32" maxSessions="10" useStatementNamespaces="true"/>
    <sqlMap resource="./app/sqlMap.xml"/>
</sqlMapConfig>
 
sqlmapconfig 설정
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">
 
<sqlMap namespace="ArticleDAO">
 
    <typeAlias alias="Article" type="com.pji.article.Article" />
 
    <select id="getArticleList" resultClass="com.pji.article.Article">
        SELECT * 
        FROM article
        ORDER BY date ASC;
    </select>
     
</sqlMap>
sqlmap 설정
  • 모두 설정이 되어있으면 이제 사용할때 주의해야 할 부분이 있다. DAO에서 queryForList(“ArticleDAO.getArticleList”) 메소드를 이용해서 쿼리를 요청하고 싶을때 naspace.selectid로 파라메터를 넘겨줘야한다. 또한 resultClass와 parametaClass를 작성해서 만약 쿼리내에서 변수를 사용하고 싶을때는 parametaClass를 이용해서 받아야 한다. resultClass는 결과 반환을 어떤 형식으로 할지 정한다. 우리는 아까 정의한 article모델로 데이터를 반환한다.

이제 다했다. Controller 혹은 Service에서 @Autowired나 직접 bean으로 등록한 후 ArticleDAO를 DI해주고 ArticleDAO.selectArticleList()로 호출하면 된다. 아래 코드는 사용 예시이다.

@Service
public class ArticleService {
	
	@Autowired
	ArticleDAO articleDAO;

	public void articleService(){
		
		Article article = null;	
		article = articleDAO.getArticleList().get(id);
	}
}
Service에서 articleDAO 사용 예시

configLocation에서 classpath 적용하기.

먼저 ibatis map혹은 config.xml 파일을 넣을 폴더를 생성한다. 그리고 나서 아래 그림과 같이 한다.

classpath설정 1

properties를 선택해주고,

classpath설정 1

java build path -> source -> add folder… 을 눌러서 방금 생성한 폴더를 선택한 후 ok를 누르면 classpath가 된다.

JAVA Reflection

리플렉션이란?

‘컴퓨터 프로그램에서 런타임 시점에 사용되는 자신의 구조와 행위를 관리(type introspection)하고 수정할 수 있는 프로세스를 의미한다. (type introspection)은 객체 지향 프로그램언어에서 런타임에 객체의 형(type)을 결정할 수 있는 능력을 의미한다.’ 라고 위키에 되어 있다.

자바는 컴파일 과정 다음 바이트코드로 생성된 클래스 정보를 이용해서 reflection을 하게 된다. 동적으로 인스턴스를 생성하게되는 것이다. reflection을 이용하면 클래스 이름을 알면 동적으로 인스턴스를 생성할 수 있고, 메소드호출 및 멤버변수도 알 수 있다. private멤버변수 또한 접근 가능하다.

reflection기술은 보통 라이브러리를 만들 때 사용할 수 있다. 예를 들면 자료형에 상관없이 json객체로 만들어주는 기능이 필요하다고 생각해보자. 자료형에는 우리가 모델로 정의한 클래스가 있을 수도 있고 형태가 다양할 것이다. 이럴경우 자바 리플렉션을 이용해서 json객체로 만들어줄 수 있다.

JAVA Reflection을 이용한 JSON객체 생성

public class Album {
	Integer id;
	String title;
	String nation;

	public Integer getId() {
		return id;
	}
	public void setId(Integer album_id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getNation() {
		return nation;
	}
	public void setNation(String nation_cd) {
		this.nation = nation;
	}
}
model class file
  • album이라는 클래스를 정의하고 멤버변수와 메소드를 정의했다.
	public String generateJsonAndToString(Object obj){
		JSONObject json = new JSONObject();
		char[] methodNameArr = null;
		String methodName = null;
		Method method = null;
		
		for (Field field : obj.getClass().getDeclaredFields()){ 
			// reflection을 이용해서 멤버변수의 이름을 구한다.
			try {
				methodNameArr = field.getName().toCharArray(); 
				//메소드 이름이 멤버변수 이름의 첫 알파벳이 대문자로 바뀐 것이라고 가정하고 필드이름을 구해서 넣어준다.
				methodNameArr[0] = (char)((methodNameArr[0] - 'a') + 'A'); 
				// 첫 알파벳을 대문자로 바꿔준다.
				methodName = "get" + new String(methodNameArr); 
				// 앞에 get을 추가해서 getMethod가 되도록 한다.

					try {
						method = obj.getClass().getMethod(methodName); 
						// 메소드 오브젝트에 reflection을 이용해서 메소드객체를 담는다.
						json.put(field.getName(), method.invoke(obj)); 
						// 메소드 실행
					} catch (NoSuchMethodException | SecurityException | IllegalAccessException | InvocationTargetException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}


			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		return json.toString(); json 스트링 형태로 반환.
	}
리플렉션을 이용해서 object를 json string으로 변환하는 함수코드
  • 매개변수를 Object형으로 받고 어떠한 자료형이 오더라도 사용이 가능하도록 한다. Object 클래스에서 getClass 메소드를 이용해서 reflection한다.(주석참고)

IBatis에서 꺽쇠( < 또는 > ) 사용할 때..

방법

	 <![CDATA[ 내용 ]]> 으로 감싸준다. 그리고 &lt; &gt; 이러한 방법으로도 가능하다...끄읏..

Application Context와 Servlet Context

Root Context와 Servlet Context

Servlet Context는 서블릿이 서블릿 컨테이너와 통신하기 위한 메서드들을 기록한 클래스 입니다. Root Context(Application Context) 또한 같은 역할을 한다고 생각합니다. Root Context는 Servlet Context의 부모 자식 관계입니다. Root Context가 Servlet Context의 부모 위치에 있으며, Root Context를 상속받아 Servlet Context가 생성됩니다. 따라서 Root Context는 Servlet Context의 자원을 사용할 수 없지만 Servlet Context는 Root Context의 자원을 사용할 수 있습니다. Root Context는 web.xml에서 listener를 통해 부모 Context로 등록할 수 있습니다. Context 로드 순서는 root->servlet 순으로 진행됩니다. 보통 Controller를 제외한 Component를 Root Context에 등록해서 사용하고 Controller류의 Component는 Servlet에 등록해서 사용합니다. 그 이유는 여러가지가 있지만 제가 겪은것(아직 추측입니다.)은 각 서블릿마다 컨트롤러를 따로 가지고 있어야 하고 만약 Root Context와 중복된 bean을 정의하면 우선순위는 servlet이 됩니다. 하지만 Context 로드 순서는 Root Context가 먼저 로드 되기 때문에 Root Context에 있는 bean은 DI가 되어 있지만 나중에 로드되는 Servlet Context는 이미 Root Context 에서 등록된 중복 bean을 상속받아 override하는 과정에서 DI가 제대로 되지 않는 결과가 나지 않았나 싶습니다. 제대로 DI가 되지 않은 Servelt Context의 bean이 막상 호출되었을때 Root Context의 bean보다 우선순위에서 앞서기 때문에 제대로 DI가 되지 않은 bean이 호출되어서 오류가 났던 것 같습니다. 아직은 추측단계 이지만 auto component scan과정에서 에러가 발생한 것을 서블릿에만 controller등록을 해주어 해결을 했던 경험이 있습니다. 확실한 이유를 아시는 분은 알려주세요.

Spring에서 자바 bean 메타설정, xml bean 메타설정

Bean

자바 인스턴스

Spring Bean Factory

Spring에서는 Bean을 기본적으로 싱글톤으로 인스턴스를 생성해서 관리한다. IoC컨테이너, 스프링컨테이너로 불리기도 하는것 같다. java reflection 기술을 이용해서 등록을 해준다.

JAVA Bean

@Configuration
public class bean{
	@Bean
	public classType dataSource(){
		classType dataSource = new classType();
		dataSource.setid("id");
		dataSource.setpw("pw");
		dataSource.setDriverClass(com.db.driver.class);
		
		return dataSource;
	}
}
spring java bean 메타설정 예
  • Java에서는 @Configuration 어노태이션과 @Bean 어노태이션이 함께 사용되면 빈 메타정보를 자바로 작성할 수 있게된다.

XML Bean

<beans>
	<bean id="datasource" class=classpath:bean>
		<property name="driverClass" value="com.db.driver.class"/>
		<property name="pw" value="pw"/>
		<property name="id" value="id"/>
	</bean>
</beans>
spring xml bean 메타설정 예
  • XML에서는 bean태그로 빈 메타정보를 작성할 수 있다.

The server does not support version 3.1 of the J2EE Web module specification. 에러가 나는 경우

에러 해결 방법

The server does not support version 3.1 of the J2EE Web module specification. 에러는 현재 Dynamic Web Application 프로젝트를 생성 했을시 Dynamic Web module 버전이 tomcat에서 지원하는 버전과 맞지 않을 경우 발생한다.(이 경우엔 3.1을 지원하지 않는다. 톰캣버전은 7) 이 경우 프로젝트 생성시 tomcat(버전에따라)이 지원하는 Dynamic Web module(톰캣7일 경우 3.0버전)을 선택해주면 된다.

에러 화면

에러 화면

에러 해결

에러 해결

스프링 Dispatcher Servlet

서블릿, 디스패쳐서블릿

자바 서블릿 이란 자바를 이용해서 동적으로 웹페이지를 생성해주는 서버 프로그램이다. 톰캣과 같은 서블릿 컨테이너 아래에서 동작하게 된다. 디스패쳐서블릿은 스프링 프레임워크의 핵심역할을 하는 서블릿이다. 예전에 서블릿을 여러개 만들어서 요청을 처리했다고 하는데 나는 시작한지가 얼마 안되어서 잘 모르겠다. 이렇게 서블릿을 여러개 두고 처리하는 방식과 반대로 디스패쳐서블릿과 비슷하게 서블릿 하나를 두고 앞에서 모든 요청을 받고 요청에 따라 처리 로직을 실행하는 것이 있다. 프론트 컨트롤러 패턴이라고 불리는 것이다. 디스패쳐서블릿도 프론트 컨트롤러 패턴의 일종같다.

디스패쳐서블릿 처리 과정

디스패쳐서블릿의 클라이언트 요청 처리과정
  • Client에서 요청을 하면 디스패쳐서블릿에서 요청을 받는다.(web.xml에 servlet-mapping을 통해 디스패쳐서블릿이 요청받을 URL패턴을 정의한다.)
  • 디스패쳐서블릿은 핸들러 매핑을 통해 어떤 컨트롤러에서 요청을 처리할 것인지를 결정한다. 디스패쳐서블릿은 핸들러 매핑을 통해 컨트롤러 요청을 처리할 때 컨트롤러 호출방법이 컨트롤러 타입에 따라 다르기 때문에 어떤 컨트롤러를 호출해야 할지 모른다. 따라서 중간에 핸들러 어댑터를 두어 적합한 어댑터를 가져다가 호출한다. @RequestMapping@Controller 어노태이션을 적용할 경우 DefaultAnnotationHandlerMapping에 의해 핸들러가 결정되고, 그에 대응되는 AnnotationMethodHandlerAdapter에 의해 호출이 일어난다.
  • 컨트롤러에서 처리된 결과를 뷰로 보여줘야한다. 결과를 디스패쳐 서블릿이 가져간 후 View Resolver를 통해 어떤 뷰에 보여줄지 결정하게 된다. 컨트롤러가 리턴한 뷰 이름을 참고해서 뷰 오브젝트를 찾아주며, 뷰 오브젝트의 종류는 다양하다. 뷰 오브젝트를 찾아서 결과를 출력하면 이를 다시 디스패쳐서블릿에 보내고 디스패쳐서블릿은 결과를 다시 요청받은 클라이언트에 돌려준다.

스프링 설정 및 스프링 프로젝트 간보기(maven 없이)

스프링 설정

스프링 프레임워크를 사용하기 위해서는 스프링 프레임워크 라이브러리를 받아서 설치해야 한다. 제일 간단한 방법으로는 STS를 설치해서 사용하는 방법이 있다. 또 다른 방법으로는 이클립스를 이용해서 하는 방법이 있다. 이클립스를 이용하는 방법은 help -> eclipse marketplace에서 spring ide를 받고 스프링 프레임워크 라이브러리 파일을 추가시키는 방법이 있다. STS를 이용해서 하는 방법은 maven 빌드 툴을 이용해서 하는 방법과 그냥 하는 방법이 있다. maven을 이용하게 되면 스프링 프레임워크에 필요하거나 프로젝트 진행에 있어서 필요한 라이브러리들을 쉽고 간편하게 관리할 수 있다. maven을 사용하지 않는 경우에는 스프링 프레임워크 라이브러리 파일을 모두 내려받아서 추가해주면 된다. maven을 사용하지 않고 하는 경우에는 직접 라이브러리 파일을 찾아서 추가해줘야 한다는 번거로운점이 있다.

maven을 사용하지 않는 경우

Dynamic Web Project 생성
  • maven을 사용하지 않는 경우에는 STS를 기준으로 Package Explorer에서 오른쪽 마우스를 누른 후 new -> others에서 web 폴더에 있는 Dynamic Web Project를 생성한다.
  • 생성하게 되면 아무것도 없는 Dynamic Web Project가 생성이 된다.
Add Spring Project Nature 추가
  • 위 그림과 같이 add spring project nature를 해준다. 그러면 스프링 프로젝트로 변하고 프로젝트 폴더 그림 옆에 S가 생긴것을 볼 수 있다.

그 다음 남은 것은 Spring Framework 추가, web.xml, servlet-context, application-context(root-context)를 생성해주고 view(jsp파일)와 Controller 자바 파일을 생성해주기가 남았다.

  • 먼저 Spring Framework를 추가해보자. http://maven.springframework.org/release/org/springframework/spring/ 왼쪽의 링크에서 원하는 스프링 프레임워크 버전을 선택해서 라이브러리 파일을 다운로드 받는다.(최신버전일 경우 현재 자신의 컴퓨터에 깔린 JAVA버전을 확인해봐야 한다.) 다운 받은 후 아래 경로와 같은 곳에 받은 라이브러리 파일을 추가한다. 또한 추가로 commons-logging.jar(누르면 다운로드 됩니다.) 파일을 받아서 넣어줘야 한다. commons-logging.jar 가 없을 경우 tomcat 에러가 난다.
SpringFramework를 프로젝트에 추가
  • 위 그림과 같이 Spring Framework 라이브러리를 추가하고, 다음으로 web.xml을 만들어 준다. WebContent -> WEB-INF 폴더 안에 만들어 준다. web.xml을 추가하고 나서 아래 코드를 복사 붙여넣기 해서 넣어준다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
id="your_id" version="3.0">

  <display-name>your_display_name</display-name>


	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/root-context.xml</param-value>
	</context-param>
	
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>pji</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/pji-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		


<servlet-mapping>

    <servlet-name>pji</servlet-name>

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

</servlet-mapping>

  
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  	</welcome-file-list>
  
</web-app>
web.xml
  • 위 web.xml 코드에서 신경써줘야 할 부분이 있다.

맨 위에 id = your_id 는 web_app의 id를 넣는 부분이므로 아무거나 넣고싶은 것을 넣어준다. 다음으로 <display-name> 부분은 DD파일의 title정도 이다. 보통 프로젝트 이름이 들어가게 되며 수정가능하다. (톰캣에서 DD파일은 web.xml 로 웹 어플리캐이션의 환경설정을 담당한다.) 다음으로 <context-param>은 <param-name>, <param-value>를 입력해줘서 application context의 설정파일의 경로를 입력해준다. 다음으로 <servlet-name>은 디스패쳐서블릿의 이름을 입력해주면 된다.(하고싶은 이름을 아무거나 넣으면 된다.) 그리고나서 <init-param>을 이용해서 <param-name>과 <param-value>를 입력해줘서 servlet context의 설정파일 경로를 입력해준다.(보통은 servletName-servlet)으로 xml이 설정된다.

<servlet-mapping> 부분은 <servlet-name>을 위에 <servlet>에서 설정했던 이름과 동일하게 설정해주고 <url-pattern>을 설정해준다. <welcome-file>은 첫 화면에 노출될 뷰 파일을 적어준다. 위에서는 index.jsp로 설정했다.

  • 이제 servlet-context와 root-context를 설정해보자. servlet-context와 root-context을 xml로 작성할 것이다.
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"  
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
  	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		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.xsd">
  	
  	<mvc:annotation-driven />

	
	<bean id="annotationMapper" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
	
		<property name="order" value="0" /> 
	
	</bean> 
	
	
	<bean id="viewResolver"  
		
		class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
		
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />  
		
		<property name="prefix" value="/WEB-INF/viewFolder/" />  
		
		<property name="suffix" value=".jsp" />  
		
	</bean>  

	<context:component-scan base-package="com.test" />	
	
	
	
</beans>  
servlet-context.xml

viewResolver 설정에서 <property name=”prefix” value=”/WEB-INF/viewFolder/” /> 는 앞 경로를 의미한다. 디스패쳐 서블릿이 컨트롤러로 부터 결과값을 받아서 viewResolver로 연결해 줄 때 /WEB-INF/veiwFolder/로 경로가 이동되고 <property name=”suffix” value=”.jsp” /> 를 통해 확장자가 .jsp로 끝나는 뷰 파일을 호출할 것이라고 property설정을 해주는 것이다. 위에서 viewFolder와 .jsp는 자신이 원하는 것으로 해도 된다. 위 예제 에서는 jstlView를 사용했으므로 추가로 jstl.jar(누르면 다운로드 됩니다.)를 받아서 lib폴더에 넣어줘야 한다. 또한 <context:component-scan base-package=”com.test” /> 에서 base-package 경로를 자신의 프로젝트 패키지에서 controller.java파일이 있는 패키지 경로로 입력해주면 된다. 만약 component-scan을 사용하지 않을 경우 따로 bean을 등록해주고 DI를 해줘야 한다. 그렇지 않고 @autowired를 사용할 것이라면 <context:component-scan base-package=”com.test” />에서 경로를 알맞게 바꿔주자. 현재 예제에서는 component-scan을 사용했다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
  	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="
	   	http://www.springframework.org/schema/mvc 		http://www.springframework.org/schema/mvc/spring-mvc.xsd
		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.xsd">



  	<mvc:annotation-driven />


</beans>
root-context.xml

root-context에는 위와같이 기본적인 것만 해주면 된다.

  • 이제 다음으로 view파일을 만들어줄 차례다. view파일은 두가지를 만들것이다. 하나는 index.jsp와 helloSpring.jsp를 만들것이다. 아까 web.xml에서 welcome-file로 index.jsp를 지정하였으므로 index.jsp가 기본 페이지가 될 것이고 index.jsp에서 helloSpring에 링크를 걸어주어 helloSpring이 화면에 출력되도록 해볼것이다.
index.jsp와 helloSpring.jsp 파일 경로
  • 위와 같이 추가해 주고 index.jsp와 helloSpring.jsp를 아래 코드와 같이 작성한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>TestProject - Hello Spring World</title>
</head>
<body>
<a href="helloSpring">Enter Spring World</a>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>TestProject - Hello Spring World</title>
</head>
<body>
${helloWorld}
</body>
</html>
helloSpring.jsp
  • 마지막으로 컨트롤러를 추가할 차례다.
SpringTestController.java
  • com.test.controller 패키지를 추가하고 SpringTestController.java를 추가했다.
package com.test.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class SpringTestController {
	@RequestMapping("/helloSpring")
	public ModelAndView TestController(){
		ModelAndView mv = new ModelAndView();
		
		mv.addObject("helloWorld", "hello~ Spring World");
		mv.setViewName("helloSpring");
		return mv;
	}
}
SpringTestController.java
  • 컨트롤러를 추가해서 index.jsp에서 helloSpring으로 링크가 걸려서 넘어오게 되면 디스패쳐서블릿에서 핸들러매핑을 통해 TestController()로 넘어오게 된다. 비지니스 로직을 TestController()에서 수행하고 mv.addObject를 통해 메시지를 담고, setViewName를 통해 view 값을 넘겨준다. 그러면 아래 그림과 같이 실행이 된다.
index.jsp 출력
  • index.jsp 를 출력한 화면. 위 링크를 누르면 아래 그림과 같이 된다.
helloSpring 출력
  • helloSpring.jsp 를 출력한 화면.