이전에 Hello World 출력하기에서 살펴보았듯이..

Spring에서는 MVC 프레임워크를 제공한다..

다시 한 번 Spring MVC의 동작이 어떻게 되는지 살펴보자...

 

1. 클라이언트의 요청

2. DispatcherServlet 시작

3. HanderMapping을 이용하여 해당 Controller 검색

4. 해당 Controller가 요청 처리 후 ModelAndView 리턴

5. ViewResolver를 이용하여 View 검색

6. View에 출력

 

Spring MVC에서 C에 해당하는 부분이 바로 DispatcherServlet이다...

이 녀석이 클라이언트의 요청을 받아 Controller를 검색하고...

Controller의 처리 결과인 ModelAndView를 전달 받아 View를 출력해주는 역할을 한다...

우리가 할 일은 실제 요청을 처리할 Controller를 만들고..

처리한 결과를 출력해 줄 View를 만드는 것뿐이다..

물론 DB 정보가 필요하다면 Model을 만드는 것도 우리가 할 일이다...

자... 그렇다면 이제 이전 HelloWorld 출력하기에서 했던 내용을 좀 더 자세히 알아보자..

 

DispatcherServlet은 기본적으로 /WEB-INF/ 디렉토리에 서블릿이름-servlet.xml 파일을 설정파일로 사용한다...

아래와 같이 설정했다면 cuvic-servlet.xml 파일로 저장하면 된다...

 

<servlet>
   <servlet-name>cuvic</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

 

가끔 설정 파일을 한 개 이상 사용하고 싶은 경우가 있다...

그런 경우 <init-param>으로 contextConfigLocation을 설정해준다...

 

<servlet>
   <servlet-name>cuvic</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

   <init-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>/WEB-INF/appContext.xml, /WEB-INF/sqlContext.xml</param-value>

   </init-param>

</servlet>

 

위와 같이 하면 appContext.xml과 sqlContext.xml 파일을 설정 파일로 사용하게 된다...

설정 파일은 콤마(,)나 공백문자 또는 탭과 세미콜론(;) 중 하나로 구분한다..

 

Spring MVC에서는 1개 이상의 DispatcherServlet을 설정할 수 있다..

 

<servlet>
   <servlet-name>cuvic1</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

   <init-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>/WEB-INF/app1Context.xml</param-value>

   </init-param>

</servlet>

 

<servlet>
   <servlet-name>cuvic2</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

   <init-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>/WEB-INF/app2Context.xml</param-value>

   </init-param>

</servlet>

 

위와 같이 2개의 DispatcherServlet을 설정할 수 있다..

하지만 위와 같이 설정을 하게 되면 cuvic1과 cuvic2는 서로 독립적인 서블릿이 되버린다..

따라서 서로의 빈 객체를 사용할 수가 없게 된다..

대부분 동일한 서비스 객체와 퍼시스턴트 객체를 사용하므로 따로 사용할 필요가 없다...

이처럼 공통으로 사용할 빈 객체가 필요한 경우 ContextLoaderListener를 사용하면 된다...

 

<context-param>

   <param-name>contextConfigLocation</param-name>

   <param-value>/WEB-INF/app.xml, /WEB-INF/sql.xml</param-value>

</context-param>

 

<listener>

   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

 

위와 같이 설정해주면 app.xml과 sql.xml 에 있는 빈들은 모든 서블릿에서 공통으로 사용할 수 있게 된다...

 

이번에는 자바를 하게 되면 항상 발생하는 인코딩 문제를 해결해보자...

이전에 살펴봤듯이 한글을 제대로 표현하기 위해서는 UTF-8 형식으로 보내는 것이 현명한 방법이다..

하지만 대부분 기본으로 8859_1이나 EUC_KR을 많이 사용하곤 한다...

따라서 request.setCharacterEncoding("UTF-8") 메소드를 이용해서 변경해주는데...

모슨 소스 코드에 이를 해주는 것은 매우 번거롭고 귀찮은 일이다..

아래와 같이 서블릿 필터를 등록하면 쉽게 인코딩을 설정할 수 있다...

 

<filter>

   <filter-name>encoder</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>encoding</filter-name>

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

</filter-mapping>

 

이번에는 해당 요청을 처리하는 Controller를 검색하기 위한 HandlerMapping을 살펴보자...

Spring에서 제공하는 HandlerMapping 클래스는 4가지가 있다...

 

SimpleUrlHandlerMapping : URL 패턴에 매칭되는 지정된 Controller를 사용

BeanNameUrlHandlerMapping : URL과 일치하는 이름을 갖는 빈을 Controller로 사용

ControllerClassNameHandlerMapping : URL과 일치하는 클래스 이름을 갖는 빈을 Controller로 사용

DefaultAnnotationHandlerMapping : @RequestMapping Annotation을 이용

 

위의 4가지 클래스는 AbstractUrlHandlerMapping 클래스를 상속한다..

Annotation을 이용하는 방법은 다음에 알아보도록 하고 나머지 3개 먼저 알아보도록 하자...

이 클래스는 요청 URL의 서블릿 컨텍스트까지를 기준으로 Controller를 매핑한다...

즉 서블릿 컨텍스트가 test이고 아래와 같은 URL 요청이 있다면..

 

http://localhost/test/hello/HelloWorld.cmd

 

/hello/HelloWorld.cmd를 사용하여 Controller를 찾게 된다..

 

그렇다면 BeanNameUrlHandlerMapping을 이용한 설정을 살펴보자...

 

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

 

<bean id="/hello/HelloWorld.cmd" class="org.test.web.HelloController"/>

 

<servlet>
   <servlet-name>test</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>
  
<servlet-mapping>
   <servlet-name>test</servlet-name>
   <url-pattern>*.cmd</url-pattern>
</servlet-mapping>

 

<servlet-mapping>
   <servlet-name>test</servlet-name>
   <url-pattern>/hello/*</url-pattern>
</servlet-mapping>

 

위와 같은 경우에는 확장자가 cmd이거나 /hello/로 들어오는 모든 요청을 DispatcherServlet에 보내게 된다...

즉 위의 URL 요청인 경우 *.cmd 패턴은 /hello/HelloWorld.cmd로 검색하게 되고 /hello/* 패턴은 /HelloWorld.cmd로 검색한다...

따라서 위의 예제에서는 빈의 이름이 /hello/HelloWorld.cmd 혹은 /HelloWorld.cmd인 Controller를 선택되게 된다...

만약 항상 서블릿 컨텍스트 이후의 전체 경로를 사용하고자 한다면...

아래와 같이 alwaysUseFullPath를 true로 지정해준다...

 

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">

   <property name="alwaysUseFullPath" value="true"/>

</bean>

 

또한 위에서 살펴보았듯이 BeanNameUrlHandlerMapping은 빈의 이름을 Ant 경로 패턴을 사용하게 된다..

Ant 경로 패턴은 다음과 같은 규칙이 있다...

 

? : 1개의 문자와 매칭

* : 0개 이상의 문자와 매칭

** : 0개 이상의 디렉토리와 매칭

 

예를 들어 /hello/**/*.cmd 라고 하면..

/hello/hello.cmd, /hello/1/hello.cmd, /hello/1/2/hello.cmd 등의 값이 매핑될 수 있다...

 

이번에는 HelloWorld 출력하기에서 살펴보았던 SimpleUrlHandlerMapping에 대해서 알아보자..

가장 많이 사용되는 HandlerMapping으로 패턴 매칭을 이용하여 Controller를 매핑한다...

위의 예제는 아래와 같이 사용될 수 있다..

 

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

   <property name="mappings">

      <props>

         <prop key="*.cmd">helloController</prop>

         <prop key="/hello/*">helloController</prop>

   </property>

</bean>

 

<bean id="helloController" class="org.test.web.HelloController"/>

 

<servlet>
   <servlet-name>test</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>
  
<servlet-mapping>
   <servlet-name>test</servlet-name>
   <url-pattern>*.cmd</url-pattern>
</servlet-mapping>

 

그리고 Spring에서는 다수의 HandlerMapping을 사용할 수 있다..

만약 아래와 같이 위의 2가지를 모두 사용한다면...

 

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"/>

   <property name="mappings">

      <props>

         <prop key="*.cmd">helloController</prop>

         <prop key="/hello/*">helloController</prop>

   </property>

</bean>

 

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

 

과연 어떤 HandlerMapping을 먼저 사용하게 될까...

order 프로퍼티를 사용하지 않는다면 설정 파일에 입력된 순서대로 Controller를 검색하게 되고...

만약 order 프로퍼티를 주게 되면 낮은 순서에 따라 Controller를 검색하게 된다...

즉 위의 예제는 order 속성이 없으므로 먼저 설정한 SimpleUrlHandlerMapping이 먼저 적용되고...

아래의 예제와 같은 경우 order가 1로 설정된 BeanNameUrlHandlerMapping을 먼저 적용하게 된다...

 

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

   <property name="order" value="2">

   <property name="mappings">

      <props>

         <prop key="*.cmd">helloController</prop>

         <prop key="/hello/*">helloController</prop>

   </property>

</bean>

 

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">

   <property name="order" value="1">

</bean>

 

마지막으로 ControllerClassNameHandlerMapping을 한 번 알아보자...

 

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>

 

<bean id="helloController" class="org.test.web.HelloController"/>

 

위와 같이 설정해주면 알아서 Controller의 이름 패턴으로 매핑을 시켜준다...

즉 HelloController는 다음 URL 패턴과 매핑된다...


/helloController*

 

만약 MultiActionController를 상속하여 구현하였다면 다음 URL 패턴과 매핑된다...


/helloController/*

 

상당히 편리한 기능이 아닐 수 없다...

MultiActionController는 무엇인지 모르지만 일단은 저렇게 사용된다고 기억해두도록 하자...

HandlerMapping은 여기까지 알아보고... 실제 Controller 만드는 방법은 다음에 다시 알아보도록 하자...

 

 

[출처] http://blog.naver.com/inho1213/80052729536

'프레임워크 > Spring' 카테고리의 다른 글

어노테이션을 이용한 설정  (0) 2015.11.06
@Autowired 와 @Resource  (0) 2015.11.06
Spring MVC 기초  (0) 2015.10.16
Spring HelloWorld! 띄우기  (0) 2015.10.16
Spring 강좌 웹개발자 샤쿠  (0) 2015.10.16
블로그 이미지

532

처음 프로그래밍을 시작한 개발자들은 Hello World!를 기억 할 것이다. Hello world가 Hell World가 될 줄 몰랐던 한 개발자의 이야기. 게시글의 출처를 표기하며, 출처를 남기지 않고 펌을 하는것에 대해 법적 책임을 묻지 않습니다.

,