Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Spring MVC로 애노테이션(Annotation)을 사용하여 Hello World 예제

공부하고 있는 Toby's 스프링 3는 아직 Spirng MVC까지 진도를 나가지 않았지만 MVC 설정을 해야할 필요가 있었던 관계로 항상 다른 사람들이 셋팅해준거 쓰다가 처음으로 한번 셋팅해 보았습니다. 아무래도 스프링은 개발자에게 너무나도 다양한 선택권을 주고 있기 때문에 전체적인 원리를 이해하고 있지 못하는 상황에서는 초기 셋팅은 꽤나 어려움으로 다가왔습니다. 여러가지 접근법이 있지만 개인적으로는 이제 패러다임이 애노테이션으로 넘어갔다고 생각하기 때문에 애노테이션을 이용해서 프로젝트를 설정했습니다. 기본부터 차근차근....

아직 스프링에 대한 이해도가 높지 못하기 때문에 설정에 일부 불필요한 부분이 있을 수 있고 자세한 설명은 (저도 잘 모르는 관계로) 어느정도 생략하고 넘어갑니다.


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>outsider.ne.kr</groupId>
    <artifactId>helloworld</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>helloworld</name>
    <url>http://maven.apache.org</url>

    <properties>
        <java.version>1.6</java.version>
        <spring.version>3.0.5.RELEASE</spring.version>
        <org.slf4j.version>1.6.1</org.slf4j.version>
        <downSource>true</downSource>
        <downJavadoc>true</downJavadoc>
        <wtpContextName>helloworld</wtpContextName>
    </properties>

    <dependencies>
        <!-- Spring dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>org.springframework.spring-library</artifactId>
            <type>libd</type>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion>  <!-- declare the exclusion here -->
                    <groupId>javax.servlet</groupId>
                      <artifactId>com.springsource.javax.servlet</artifactId>
                </exclusion>
            </exclusions> 
        </dependency>
    </dependencies>     <repositories>         <repository>             <id>com.springsource.repository.bundles.release</id>             <name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</name>             <url>http://repository.springsource.com/maven/bundles/release</url>         </repository>         <repository>             <id>com.springsource.repository.bundles.external</id>             <name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>             <url>http://repository.springsource.com/maven/bundles/external</url>         </repository>         <repository>             <id>com.springsource.repository.libraries.release</id>             <name>SpringSource Enterprise Bundle Repository - SpringSource Library Releases</name>             <url>http://repository.springsource.com/maven/libraries/release</url>         </repository>         <repository>             <id>com.springsource.repository.libraries.external</id>             <name>SpringSource Enterprise Bundle Repository - External Library Releases</name>             <url>http://repository.springsource.com/maven/libraries/external</url>         </repository>     </repositories> </project>

Maven을 사용하고 있는 관계로 프로젝트 관리를 위한 pom.xml입니다.(필요없는 부분은 지웠습니다.) pom.xml의 양이 많기 때문에 다 설명하기는 어렵기 때문에 간단히 설명하면 Spring 3.0.5.RELEASE 버전을 사용하며 간단한 Hello World코드이기 때문에 스프링프레임워크가 전부 필요하진 않지만 차후 확장을 위한 기본 골격이기에(일일이 의존성까지 맞추기도 어렵고 해서) SpringSource Enterprise Bundle Repository에서 Spring 3.0.5 RELEASE를 모두 가져오도록 했으며 EBR에서 라이브러리를 가져오도록 <repository>를 추가했습니다.


<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>HelloWorld</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext*.xml</param-value>
    </context-param>
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.properties</param-value>
    </context-param>
  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

web/WEB-INF/web.xml 파일입니다. <context-param>을 이용해서 스프링의 applicationContext.xml를 설정하고(여러가지 applicationContext를 사용하도록 applicationContext*.xml과 같이 작성하였습니다.) log4j에 대한 프로퍼티 파일을 지정하였습니다. vaule에 classpath:를 지정하였기 때문에 해당 파일을 클래스패스에서 찾게 되기 때문에 소스폴더인 src폴더 바로 아래에 위 파일들을 위치해두면 컴파일시에 클래스패스에 포함되게 됩니다. 리스너는 ContextLoaderListener를 지정하고 요청을 처리하기 위해서 DispatcherServlet을 spring이라는 이름으로 등록해주고 이 서블릿은 /app/*에 매핑합니다.


<?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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <context:component-scan base-package="kr.ne.outsider.helloworld.web" />

    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

web/WEB-INF/spring-servlet.xml 파일입니다. web.xml에서 DispatcherServlet을 spring이라는 이름으로 등록했기 때문에 spring-servlet.xml이라는 파일명을 사용했습니다. 다른 파일명을 사용하려면 web.xml에서 서블릿을 등록할 때 contextConfigLocation를 이용하여 파일을 지정해 주어야 합니다.

<context:component-scan>에서는 annotation을 찾을 패키지명을 지정합니다. 여러개를 지정할 경우에는 콤마(,)를 이용합니다. DefaultAnnotationHandlerMapping는 type레벨에서 @RequestMapping을 처리하고  AnnotationMethodHandlerAdapter는 메서드레벨에서 처리하는데 사용합니다. 이 2가지는 DispatcherServlet을 사용할 경우 디폴트로 사용되지만 다른 핸들러맵핑을 합께 사용하려고 하면 지정하여야 합니다. InternalResourceViewResolver에서 prefix와 suffix를 주어서 Controller에서 이름만 지정해주고 뷰로 사용할 JSP를 찾도록 하였습니다.


// HelloWorldController.java
package kr.ne.outsider.helloworld.web;

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

@Controller
public class HelloWorldController {
    
    @RequestMapping(value="/helloworld", method=RequestMethod.GET)
    public ModelAndView example() {
        return new ModelAndView("helloworld", "message", "Hello World");
    }
    
}

헬 로월드를 출력할 컨트롤러 파일입니다. 로직은 필요없기 때문에 소스는 컨트롤러만 구성했으며 컨트롤러를 사용하기 위해서 @Controller를 지정하고 /helloworld에 대한 GET요청을 받아서 Hello World를 출력하도록 @RequestMapping를 설정했습니다.


<!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>Hello World</title>
    </head>
    <body>
        ${message}
    </body>
</html>

web/WEB-INF/views/helloworld.jsp 파일입니다. 여기서 HelloWorldController에서 message에 지정한 "Hello World"를 출력합니다. 이제 http://localhost:8080/helloworld/app/helloworld에 접근하면 Hello World가 찍히는 페이지를 볼 수 있습니다.(context명때문에 URL이 이쁘진 않군요 ㅎㅎ) 혹 참고용으로 프로젝트 소스를 함께 올려놓습니다.


스프링소스에서 제공하는 샘플을 참고해도 많이 도움이 될 것 같습니다.
2011/01/12 01:52 2011/01/12 01:52