Whiteship's Note


[Spring Web Flow] booking 예제 분석 2 - Resources Servlet

Spring Web Flow/etc : 2009.10.15 16:05


<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <!-- The master configuration file for this Spring web application -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/config/web-application-config.xml
        </param-value>
    </context-param>
   
    <!-- Enables Spring Security -->
     <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
      <filter-name>springSecurityFilterChain</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
   
    <!-- Loads the Spring web application context -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

      <!-- Serves static resource content from .jar files such as spring-faces.jar -->
    <servlet>
        <servlet-name>Resources Servlet</servlet-name>
        <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>
       
    <!-- Map all /resources requests to the Resource Servlet for handling -->
    <servlet-mapping>
        <servlet-name>Resources Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>
   
    <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
       
    <!-- Map all *.spring requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>

web.xml에서 눈여볼만한 부분은 먼저, 스프링 JS가 제공하는 ResourceServlet 입니다.
JAR 파일에 들어있는 정적인 자원들(이미지, javascript, css)을 효율적으로 가져오기 위한 서블릿입니다. (JAR 파일에 없으면 로컬에 있는 파일을 참조합니다.

standard.jsp 파일에 있는 헤더를 보죠.

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Spring Travel: Spring MVC and Web Flow Reference Application</title>
    <link type="text/css" rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css" />" />
    <style type="text/css" media="screen">
        @import url("<c:url value="/resources/css-framework/css/tools.css" />");
        @import url("<c:url value="/resources/css-framework/css/typo.css" />");
        @import url("<c:url value="/resources/css-framework/css/forms.css" />");
        @import url("<c:url value="/resources/css-framework/css/layout-navtop-localleft.css" />");
        @import url("<c:url value="/resources/css-framework/css/layout.css" />");
        @import url("<c:url value="/resources/styles/booking.css" />");
    </style>
    <script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js" />"></script>
    <script type="text/javascript" src="<c:url value="/resources/spring/Spring.js" />"></script>
    <script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js" />"></script>
</head>

저기서 보면 /resources로 시작하는 url들이 보입니다. css와 js를 찹조하고 있군요. spring js JAR 파일을 볼까요.


위에서 참조하는 리소스들이 이 JAR 파일에 들어있네요. 그럼 JAR 파일에 들어있지 않은 자원들은 어찌할까요.

...
        <div id="branding" class="spring">
            <a href="<c:url value="/" />"><img src="<c:url value="/resources/images/header.jpg"/>" alt="Spring Travel" /></a>
        </div>
    </div>
    <div id="content" class="clearfix spring">
        <div id="local" class="spring">
            <a href="http://www.thespringexperience.com">
                <img src="<c:url value="/resources/images/diplomat.jpg"/>" alt="generic hotel" />
            </a>
            <a href="http://www.thespringexperience.com">
                <img src="<c:url value="/resources/images/tse.gif"/>" alt="The Spring Experience" />
            </a>
...

이것도 standard.jsp 파일의 일부입니다. 위에 보시면 /resources 로 시작하기 때문에 ResourceServlet이 요청을 처리할겁니다. 그러나 JAR 파일에는 저런 이미지들이 들어있지 않습니다. 그때는 프로젝트의 웹 폴더를 기준으로 /resources를 잘라낸 나머지 부분을 가지고 경로 탐색을 해서 찾아줍니다.


이렇게 보시다시피, /resoruces/images/header.jsp 라는 리소스 URL을 ResourceServelt이 받아서 프로젝트에 위치한 web/images/header.jsp를 찾아서 돌려줍니다.

마지막으로 ResourceServlet의 속성을 살펴보죠.

public void setGzipEnabled(boolean gzipEnabled)
public void setAllowedResourcePaths(java.lang.String allowedResourcePaths)
public void setCompressedMimeTypes(java.lang.String compressedMimeTypes)
public void setJarPathPrefix(java.lang.String jarPathPrefix)
public void setCacheTimeout(int cacheTimeout)

흠.. 뭐 이런 것들이 있군요.

다음..DispatcherServlet 설정이 뭔가 좀 낯설게 느껴집니다. 봄싹같은 경우는.

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

    <servlet-mapping>
        <servlet-name>springsprout</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

이렇게 설정했습니다. 저렇게 해두면, springsprout-servlet.xml 파일을 찾아서 WebApplicationContext의 설정파일로 사용합니다.

그런데 지금 저 예제에서는

    <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
    </servlet-mapping>

이렇게 설정했지요. 아무래도 설정을 간단하게 하고자.. 보통 ApplicationContext의 설정파일로 쓰는 것에 웹과 관련 된 설정까지 다 해놓고, 저기서는 별다른 설정 파일을 읽지 않도록, 기본 설정 파일을 찾지 않게 그냥 빈 문자열로 설정한 듯 합니다.

봄싹의 경우 기본 네임스페이스가 springsprout기 때문에 init-param으로 contextConfigLocation 속성을 설정하지 않아도 springsprout-servlet.xml 파일을 찾도록 되어 있습니다. 몾찾으면 에러가 납니다.

그런데, <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> 이녀석은 지금 기본 네임스페이스가 Spring MVC Dispatcher Servlet 이게 되고 따라서 그냥 두면 Spring MVC Dispatcher Servlet-servlet.xml 이 파일을 찾다가 몾찾아서 에러가 날 겁니다. 그래서 contextConfigLocation을 null로 설정해서 설정 파일이 필요없도록 해둔거네요.

굳이 Web 설정이랑 App 설정을 구분할 필요가 없다면, 저렇게 해도 괜찮긴 하겠네요. 흠..

web.xml 분석은 이만~







top


[Spring Web Flow] booking 예제 분석 1 - 예제 실행하기

Spring Web Flow/etc : 2009.10.15 14:59



위 코드를 받아서 메이븐 플젝 import를 해서 Run on server로 돌리거나, Spring 사이트에서 Spring Web Fow를 다운 받은 다음 projects 폴더에 가셔서 booking-mvc 폴젝을 메이븐을 플젝 import 하셔도 됩니다.

막상 실행해 보고나니 너무 간단한 예제라서 조금 아쉽네요. 적어도 멀티 폼 정도의 예제는 만들어줘어야 하는가 아닌가 싶기도 합니다. 그렇치만, 스프링 MVC 연동, 스프링 시큐리티 연동, 스프링 EL, ConversionService 등록, 스프링 JS 등을 눈여겨 볼 수 있는 좋은 예제입니다.

실행은 별거 없으니 여기서 마무리?

혹시 Run On Server로 실행할 때 ClassNotFound 예외가 발생한다면 mvn war:inplace를 한 번 해주고 다시 하면 될 겁니다.



top