SPRING
2017.05.30 / 18:56

'Spring Web Flow'¿¡ ÇØ´çµÇ´Â ±Û 16°Ç

Secutiry
Ãßõ ¼ö 426

[Spring Web Flow] booking ¿¹Á¦ ºÐ¼® 3 - webmvc-config.xml ¼³Á¤

Spring Web Flow/etc : 2009.10.16 20:28


<?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"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <!-- Scans for application @Components to deploy -->
    <context:component-scan base-package="org.springframework.webflow.samples.booking" />

    <!-- Imports the configurations of the different infrastructure systems of the application -->
    <import resource="webmvc-config.xml" />
    <import resource="webflow-config.xml" />
    <import resource="data-access-config.xml" />
    <import resource="security-config.xml" />

</beans>

web.xml¿¡ À¯ÀÏÇÏ°Ô µî·ÏµÇ¾î ÀÖ´Â ºó ¼³Á¤ÆÄÀÏÀ̾ú´Âµ¥, ¿­¾îº¸´Ï ³× °³ÀÇ ´Ù¸¥ ºó ¼³Á¤ ÆÄÀϵéÀ» import ÇÏ°í ÀÖ½À´Ï´Ù. ÀÌ Áß¿¡¼­ webmvc-config.xml ÆÄÀÏÀ» º¸°Ú½À´Ï´Ù. 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->
    <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
        <property name="order" value="0" />
    </bean>

    <!-- Maps request paths to @Controller classes; e.g. a path of /hotels looks for a controller named HotelsController -->
    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
        <property name="order" value="1" />
        <property name="defaultHandler">
            <!-- If no @Controller match, map path to a view to render; e.g. the "/intro" path would map to the view named "intro" -->    
            <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
        </property>
    </bean>

    <!-- Resolves logical view names returned by Controllers to Tiles; a view name to resolve is treated as the name of a tiles definition -->
    <bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTilesView"/>
    </bean>

    <!-- Configures the Tiles layout system -->
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/layouts/layouts.xml</value>
                <value>/WEB-INF/views.xml</value>
                <value>/WEB-INF/hotels/views.xml</value>
                <value>/WEB-INF/hotels/booking/views.xml</value>
            </list>
        </property>
    </bean>
    
    <!-- Dispatches requests mapped to POJO @Controllers implementations -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

    <!-- Dispatches requests mapped to org.springframework.web.servlet.mvc.Controller implementations -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

    <!-- Dispatches requests mapped to flows to FlowHandler implementations -->
    <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
        <property name="flowExecutor" ref="flowExecutor"/>
    </bean>

    <!-- Custom FlowHandler for the hotel booking flow -->
    <bean name="hotels/booking" class="org.springframework.webflow.samples.booking.BookingFlowHandler" />    
        
</beans>

1. org.springframework.webflow.mvc.servlet.FlowHandlerMapping

ÀÌ Å¬·¡½º´Â (FlowUrlHandler¸¦ »ç¿ëÇÏ¿©) URLÀ» ºÐ¼®ÇÏ¿© ÇØ´ç URLÀ» ó¸®ÇÒ FlowHandler¸¦ ã¾Æ¼­ ¹ÝȯÇØÁÖ´Â ¿ªÇÒÀ» ÇÕ´Ï´Ù. 

¸ÕÀú, ApplicationContext¿¡¼­ ã°í, ´ÙÀ½Àº FlowRegistry¿¡¼­ ã¾Æº¸°í, ±×·¡µµ ¾øÀ¸¸é nullÀ» ¹ÝȯÇÕ´Ï´Ù. ±×·³ ÀÌÁ¦ ÀÌ ´ÙÀ½ Çڵ鷯 ¸ÊÇΠüÀÎÀ» Ÿ°Ô µÇ°ÚÁÒ.

µû¶ó¼­ ÀÌ Å¬·¡½º¿¡ ¼³Á¤ÇÒ ¼ö ÀÖ´Â ÁÖ¿ä ¼Ó¼ºÀº FlowUrlHandler¿Í FlowRegistryÀÔ´Ï´Ù. ÇÏÁö¸¸ ÀÌÁß¿¡¼­ FlowUrlHandler´Â ½ºÇÁ¸µÀÌ ±âº»À¸·Î Á¦°øÇÏ´Â DefaultFlowHandler¸¦ »ç¿ëÇÏ´Â°Ô ÀϹÝÀûÀÏ °Í °°±º¿ä.

2. org.springframework.webflow.mvc.servlet.FlowHandlerAdapter

ÀÌ ³à¼®Àº FlowHandler°¡ ´ã´çÇϱâ·Î ÇÑ ¿äûÀ» FlowExecutor¸¦ ÀÌ¿ëÇؼ­ ó¸®ÇÏ´Â ÀÏ·ÃÀÇ ¿öÅ© Ç÷ο쿡 µû¶ó ½ÇÇà½ÃÄÑÁÖ´Â °÷ÀÔ´Ï´Ù. ½ÇÁúÀûÀÎ ÀÛ¾÷µéÀº »ó´ç ºÎºÐÀ» À§ÀÓÇÏ°í ÀÖÀ¸¸é¼­ ±× °ñ°ÝÀ» ¸¸µé¾îµÐ °÷ÀÔ´Ï´Ù. 

Ç÷οì id¿¡ ÇØ´çÇÏ´Â Ç÷οì Á¤ÀǸ¦ °¡Á®¿À°í, Ç÷οì Á¤ÀÇ·Î ÇÃ·Î¿ì ½ÇÇà °´Ã¼(FlowExecution)À» ¸¸µé°í, FlowUrlHandler·Î ÇÊ¿äÇÑ execution ¸Å°³º¯¼öµµ ¸¸µé´Â µî.. ÇÑ ¹øÀÇ Äڵ帮ºä·Î ÆľÇÇϱ⿡´Â ºÐ·®ÀÌ ¸¹´õ±º¿ä. ƯÈ÷ FlowExecutor ÂÊÀ¸·Î µé¾î°¡¸é.. Å©Çä.. Ŭ·¡½º°¡ ÆÅÆÅ ´Ã¾î³³´Ï´Ù.

3. org.springframework.webflow.mvc.servlet.FlowHandler

ƯÁ¤ Ç÷οì Á¤ÀÇ¿¡ Á¢±ÙÇÏ´Â °ÍÀ» Ä¿½ºÅ͸¶ÀÌ¡ ÇÒ ¶§ ÀÌ ³à¼®À» ±¸ÇöÇÑ´Ù°í ÇÕ´Ï´Ù.
- Launch executions of that flow with data in the execution input map
- ÇÃ·Î¿ì °á°ú´Â ¸¾´ë·Î ó¸®ÇÏ°í ½ÍÀ» ¶§.
- Ç÷ο쿡¼­ ´Ù·çÁö ¾ÊÀº ¿¹¿Ü¸¦ ¸¾´ë·Î ´Ù·ç°í ½ÍÀ» ¶§.

À§ ¿¹Á¦¿¡¼­ BookingFlowHandler À̳༮ÀÌ ±¸ÇöÇÑ °Ç µÎ °³. 
- String handleExecutionOutcome: ½ÇÇàÀÌ ³¡³µÀ» ¶§ °¥ À§Ä¡
- String handleException: ¿¡·¯°¡ ¹ß»ýÇßÀ» ¶§ °¥ À§Ä¡



½Å°í
top

[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

SWF 12Àå JSF ÅëÇÕ



12.1. µµÀÔ

½ºÇÁ¸µ Faces´Â ½ºÇÁ¸µÀÇ JSF ÅëÇÕ ¸ðµâ·Î ½ºÇÁ¸µ¿¡¼­ JSF »ç¿ëÀ» °£ÆíÇÏ°Ô ÇØÁØ´Ù. JSF UI ÄÄÆ÷³ÍÆ® ¸ðµ¨À» ½ºÇÁ¸µ MVC¿Í ½ºÇÁ¸µ À¥ Ç÷οì ÄÁƲ·Î·¯¿Í ÇÔ²² »ç¿ëÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù.

½ºÇÁ¸µ Faces´Â ¶ÇÇÑ Ajax¿Í Ŭ¸®À̾ðÆ®ÂÊ °ËÁõ ±â´ÉÀ» Á¦°øÇÏ´Â Àڱ׸¶ÇÑ Faceletsµµ Á¦°øÇÑ´Ù. ÀÌ ÄÄÆ÷³ÍÆ® ¶óÀ̺귯¸®´Â ½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®¸¦ ±â¹ÝÀ¸·Î ¸¸µé¾ú´Ù. ½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®´Â Dojo¸¦ ±â¹Ý UI ÅøŶÀ¸·Î ÅëÇÕÇÑ ÀÚ¹Ù½ºÅ©¸³Æ® Ãß»óÈ­ ÇÁ·¹ÀÓ¿öÅ©µå´Ù.

12.2. ½ºÇÁ¸µ-Á᫐ ÅëÇÕ ¹æ¹ý

½ºÇÁ¸µ Faces´Â JSFÀÇ UI ÄÄÆ÷³ÍÆ® ¸ðµ¨ ÀåÁ¤À» ½ºÇÁ¸µÀÇ ÄÁÆ®·Ñ·¯¿Í ¼³Á¤ ¸ðµ¨ ÀåÁ¡°ú °áÇÕÇØÁØ´Ù. ¾Æ¹«·± ¾àÁ¡¾øÀÌ JSFÀÇ ¸ðµç ÀåÁ¡À» È°¿ëÇÒ ¼ö ÀÖ´Ù.

½ºÇÁ¸µ Faces´Â Ç¥ÁØ JSF ±â´É¿¡ ´ÙÀ½°ú °°Àº °­·ÂÇÑ º¸¿ÏÀ縦 Á¦°øÇÑ´Ù.

  1. managed bean facility
  2. scope management
  3. event handling
  4. navigation rules
  5. easy modularization and packaging of views
  6. cleaner URLs
  7. model-level validation
  8. client-side validation and UI enhancement
  9. Ajax partial page updates and full navigation
  10. progressive enhancement and graceful degradation

ÀÌ ±â´ÉÀ» »ç¿ëÇϸé faces-config.xml¿¡ ÇÊ¿äÇÑ ¼³Á¤ ºÐ·®À» Çö°ÝÇÏ°Ô ÁÙ¿©ÁÙ °ÍÀÌ¸ç ºä¿Í ÄÁÆ®·Ñ·¯ °èÃþÀ» º¸´Ù ±ò²ûÇÏ°Ô ºÐ¸®ÇØÁÖ¸ç ¾ÖÇø®ÄÉÀ̼ÇÀÇ ±â´É Ã¥ÀÓ ¸ðµâÈ­¸¦ º¸´Ù Àß Áö¿øÇÑ´Ù. ÀÌ ±â´ÉµéÀÇ »ç¿ë¹ýÀº ´ÙÀ½ Àý¿¡¼­ »ìÆ캸°Ú´Ù. ÀÌ ±â´Éµé ´ëºÎºÐÀº ½ºÇÁ¸µ À¥ Ç÷οìÀÇ Ç÷οì Á¤ÀÇ ¾ð¾î¸¦ ±â¹ÝÀ¸·Î ÇÑ´Ù. ¿©·¯ºÐÀÌ Ç÷οì Á¤ÀÇÇϱ⿡ ³ª¿ÍÀÖ´Â ±âº»À» ÀÌÇØÇÏ°í ÀÖ´Ù°í °¡Á¤ÇÑ´Ù.

12.3. web.xml ¼³Á¤Çϱâ

½ºÇÁ¸µ Faces¸¦ »ç¿ëÇϴ ù ¹ø° ´Ü°è´Â ¿äûÀ» web.xml ÆÄÀÏ¿¡ ÀÖ´Â DispatcherServletÀ¸·Î ¶ó¿ìÆÃÇÏ´Â °ÍÀÌ´Ù. À̹ø ¿¹Á¦¿¡¼­, ¿ì¸®´Â /spring/À¸·Î ½ÃÀÛÇÏ´Â ¸ðµç URLÀ» ¼­ºí¸´À¸·Î ¸ÊÇÎÇÑ´Ù. ¼­ºí¸´À» ¼³Á¤ÇØ¾ß ÇÑ´Ù. init-paramÀ» »ç¿ëÇÏ¿© ¼­ºí¸´¿¡ contextConfigLocationÀ» ³Ñ°ÜÁØ´Ù. ÀÌ °ÍÀº ¾ÖÇø®ÄÉÀ̼ÇÀÇ ½ºÇÁ¸µ ¼³Á¤ ÆÄÀÏ À§Ä¡´Ù.

<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>/WEB-INF/web-application-config.xml</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>
        
JSF¸¦ ÀûÀýÇÏ°Ô µ¿ÀÛ½ÃÅ°·Á¸é, FacesServletÀ» web.xml¿¡ ¼³Á¤ÇØ¾ß ÇÑ´Ù. ½ºÇÁ¸µ Faces¸¦ »ç¿ëÇÒ ¶§´Â ±×°ÍÀ» »ç¿ëÇÏ¿© ¿äûÀ» ¶ó¿ìÆÃÇÒ ÇÊ¿ä°¡ ¾ø´Ù.

<!-- Just here so the JSF implementation can initialize, *not* used at runtime -->
<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
    
<!-- Just here so the JSF implementation can initialize -->
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
</servlet-mapping>
        
½ºÇÁ¸µ Faces  ÄÄÆ÷³ÍÆ®¸¦ »ç¿ëÇÒ ¶§¿¡µµ ½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ® ResourceServletÀ» ¼³Á¤ÇÏ¿© ÄÄÆ÷³ÍÆ®¿¡¼­ CSS¿Í ÀÚ¹Ù½ºÅ©¸³Æ® ¸®¼Ò½º¸¦ Á¦´ë·Î Ãâ·ÂÇÒ ¼ö ÀÖ°Ô ÇÒ ÇÊ¿ä°¡ ÀÖ´Ù. ÀÌ ¼­ºí¸´Àº ¹Ýµå½Ã /resources/*·Î ¸ÊÇÎÇØ¾ß ÄÄÆ÷³ÍÆ®¿¡¼­ ·£´õ¸µÇÑ URL¿¡ ´ëÇØ Á¦´ë·Î µ¿ÀÛÇÑ´Ù.

<!-- Serves static resource content from .jar files such as spring-faces.jar -->
<servlet>
    <servlet-name>Resource 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>Resource Servlet</servlet-name>
    <url-pattern>/resources/*</url-pattern>
</servlet-mapping>
        
½ºÇÁ¸µ Faces ÄÄÆ÷³ÍÆ®´Â JSP ´ë½Å¿¡ FaceletÀ» »ç¿ëÇØ¾ß ÇÑ´Ù. µû¶ó¼­ À̵é ÄÄÆ÷³ÍÆ®¸¦ »ç¿ëÇÏ·Á¸é ÀϹÝÀûÀÎ Facelet ¼³Á¤À» ¹Ýµå½Ã Ãß°¡ÇØ¾ß ÇÑ´Ù.

!-- Use JSF view templates saved as *.xhtml, for use with Facelets -->
<context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.xhtml</param-value>
</context-param>
        
12.4. JSF ºä ·£´õ¸µ Çϵµ·Ï À¥ ÇÃ·Î¿ì ¼³Á¤Çϱâ

The next step is to configure Web Flow to render JSF views. To do this, in your Spring Web Flow configuration include the faces namespace and link in the faces flow-builder-services :

´ÙÀ½ ´Ü°è´Â JSF ºä¸¦ ·£´õ¸µ Çϵµ·Ï À¥ Ç÷ο츦 ¼³Á¤ÇÏ´Â °ÍÀÌ´Ù. ±×·¸°Ô ÇÏ·Á¸é ½ºÇÁ¸µ À¥ ÇÃ·Î¿ì ¼³Á¤¿¡ faces ³×ÀÓ½ºÆäÀ̽º¸¦ Ãß°¡ÇÏ°í 

<?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:webflow="http://www.springframework.org/schema/webflow-config"
       xmlns:faces="http://www.springframework.org/schema/faces"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/webflow-config
           http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
           http://www.springframework.org/schema/faces
           http://www.springframework.org/schema/faces/spring-faces-2.0.xsd">

    <!-- Executes flows: the central entry point into the Spring Web Flow system -->
    <webflow:flow-executor id="flowExecutor" />

    <!-- The registry of executable flow definitions -->
    <webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices" base-path="/WEB-INF">
        <webflow:flow-location-pattern value="**/*-flow.xml" />
    </webflow:flow-registry>

    <!-- Configures the Spring Web Flow JSF integration -->
    <faces:flow-builder-services id="facesFlowBuilderServices" />

</beans>
        
faces:flow-builder-services ű״ JSF ȯ°æ¿¡ ÀûÀýÇÑ ´Ù¸¥ ±âº» °ªµéµµ ¼³Á¤ÇÑ´Ù. ƯÈ÷ Unified ELÀ» ±âº» EL·Î ¼³Á¤ÇÑ´Ù.

¿ÏÀüÈ÷ µ¿ÀÛÇÏ´Â ¿¹Á¦´Â ¹èÆ÷ÆÇ¿¡¼­ swf-booking-faces ·¹ÆÛ·±½º ¾ÖÇø®ÄÉÀ̼ÇÀ» Âü°íÇ϶ó.

12.5. faces-config.xml ¼³Á¤Çϱâ

faces-config.xml¿¡ À¯ÀÏÇÏ°Ô ¼³Á¤ÇÒ ÇÊ¿ä°¡ ÀÖ´Â °ÍÀº Facelet »ç¿ë¿¡ ´ëÇÑ °ÍÀÌ´Ù. ¸¸¾à ½ºÇÁ¸µ Faces ÄÄÆ÷³ÍÆ®¸¦ »ç¿ëÇÏÁö ¾Ê°í JSP¸¦ »ç¿ëÇÏ°í ÀÖ´Ù¸é, ¾î¶°ÇÑ ½ºÇÁ¸µ Faces °ü·Ã ¼³Á¤µµ faces-config.xml¿¡ Ãß°¡ÇÏÁö ¾Ê¾Æµµ µÈ´Ù.

<faces-config>
    <application>
        <!-- Enables Facelets -->
        <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>  
    </application>
</faces-config>
        
12.6. JSF°¡ °ü¸®ÇÏ´Â ºó ±â´É ±³Ã¼Çϱâ

½ºÇÁ¸µ Faces´Â JSF°¡ °ü¸®ÇÏ´Â ºó ±â´ÉÀ» Ç÷ο찡 °ü¸®ÇÏ´Â º¯¼ö¿Í ½ºÇÁ¸µÀÌ °ü¸®ÇÏ´Â ºóÀ¸·Î ¿ÏÀüÈ÷ ±³Ã¼ÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ±×·¸°Ô ÇÏ¿© ¿©·¯ºÐÀÌ °ü¸®ÇÏ´Â °´Ã¼¸¦ Àß Á¤ÀǵǾî ÀÖ´Â ÃʱâÈ­ ÈÄÅ©¿Í µµ¸ÞÀÎ °´Ã¼ ½ÇÇà ÈÄÅ©·Î »ý¸í Áֱ⸦ º¸´Ù Àß °ü¸®ÇÒ ¼ö ÀÖ´Ù. °Ô´Ù°¡, ¿©·¯ºÐÀÌ ÀÌ¹Ì ºñÁî´Ï½º °èÃþ¿¡¼­ ½ºÇÁ¸µÀ» »ç¿ëÇغôٴ °¡Á¤ÇÑ´Ù¸é, µÎ °³ÀÇ ´Ù¸¥ ºó °ü¸® ¸ðµ¨À» À¯ÁöÇÏ´Â °Í¿¡ ´ëÇÑ °³³äÀûÀÎ ¿À¹öÇìµå¸¦ ÁÙÀÏ ¼ö ÀÖ´Ù.

¼ø¼ö JSF °³¹ßÀ» ÇÒ ??´Â request ½ºÄÚÇÁ·Î´Â º¹ÀâÇÑ À̺¥Æ®-±â¹Ý ºä¸¦ ´Ù·ç´Â ´ëÈ­Çü ¸ðµ¨ °´Ã¼¸¦ ÀúÀåÇϱ⿡´Â Àû´çÇÏÁö ¾Ê´Ù´Â °ÍÀ» ±Ý¹æ ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¿ÀÁ÷ »ç¿ëÇÒ ¼ö ÀÖ´Â ¿É¼ÇÀº session ½ºÄÚÇÁ¿¡ ¸ðµç °ÍµéÀ» ³Ö´Â °ÍÀÌ´Ù. ¾ÖÇø®ÄÉÀ̼ÇÀÇ ´Ù¸¥ ºä ¶Ç´Â ±â´ÉÀûÀÎ ºÎºÐÀ» ó¸®ÇÒ ¶§ °´Ã¼µéÀ» û¼ÒÇØÁà¾ß ÇÑ´Ù´Â Ãß°¡ ÀÛ¾÷ÀÌ »ý±ä´Ù. Á¤¸»·Î ÇÊ¿äÇÑ °ÍÀº request¿Í session ½ºÄÚÇÁ Áß°£ Âë µÇ´Â ¾î¶² ½ºÄÚÇÁ°¡ ÇÊ¿äÇÏ´Ù. ¿ì´© ÁÁ°Ôµµ À¥ Ç÷οì´Â ±×·¯ÇÑ È®Àå ±â´ÉÀ» Á¦°øÇÑ´Ù.

12.6.1. ÇÃ·Î¿ì º¯¼ö »ç¿ëÇϱâ

°¡Àå °£´ÜÇÏ°í ÀÚ¿¬½º·´°Ô ¸ðµ¨À» ¼±¾ðÇÏ°í °ü¸®ÇÏ´Â °ÍÀº ÇÃ·Î¿ì º¯¼ö¸¦ »ç¿ëÇÏ´Â °ÍÀÌ´Ù. ÀÌ º¯¼öµéÀ» ÇÃ·Î¿ì ½ÃÀ۽ÿ¡ ¼±¾ðÇÒ ¼ö ÀÖ´Ù.

<var name="searchCriteria" class="com.mycompany.myapp.hotels.search.SearchCriteria"/>
            
±×·± ´ÙÀ½ ÀÌ º¯¼ö¸¦ Ç÷οì Áß ¾î¶² JSF ºä ÅÛÇø´¿¡ ELÀ» ÅëÇؼ­ ÂüÁ¶ÇÑ´Ù.

<h:inputText id="searchString" value="#{searchCriteria.searchString}"/>
            
(Á» ´õ ±¸Ã¼ÀûÀÏ ÇÊ¿ä°¡ ÀÖ´Ù¸é ±×·¸°Ô ÇÒ ¼öµµ ÀÖÁö¸¸)ÅÛÇø´¿¡¼­ º¯¼ö¸¦ ÂüÁ¶ÇÒ ¶§ ±× ½ºÄÚÇÁ·Î Á¢µÎ¾î¸¦ ºÙÀÌÁö ¾Ê¾Æµµ µÈ´Ù´Â °Í¿¡ ÁÖ¸ñÇ϶ó. Ç¥ÁØ JSF ºóÀ¸·Î ´ëÀÀÇÏ´Â º¯¼ö¿¡ ´ëÇØ ¸ðµç »ç¿ë °¡´ÉÇÑ ½ºÄÚÇÁ¿¡¼­ ã¾Æº¼ °ÍÀÌ´Ù. µû¶ó¼­ EL Ç¥Çö½ÄÀ» ¼öÁ¤ÇÏÁö ¾Ê°íµµ Ç÷οì Á¤ÀÇ¿¡¼­ ±×°ÍÀ» ÂüÁ¶ÇÏ´Â º¯¼öÀÇ ½ºÄÚÇÁ¸¦ º¯°æÇÒ ¼ö ÀÖ´Ù.

¶ÇÇÑ ºä ÀνºÅϽº º¯¼ö¸¦ ÇöÀç ºä·Î ¹üÀ§¸¦ Á¦ÇÑÇÏ°í ´Ù¸¥ ºä·Î À̵¿Çϸé ÀÚµ¿À¸·Î ºñ¿ö¹ö¸®°Ô Á¤ÀÇÇÒ ¼ö ÀÖ´Ù. ÀÌ·¸°Ô ÇÏ´Â °ÍÀº º¸Åë ÆäÀÌÁö ³»¿¡¼­ ´Ù¸¥ ºä·Î ÀüÀÌÇϱâ Àü¿¡ ¿©·¯ ¿©·¯ ¿äû¿¡ °ÉÃÄ À̺¥Æ®¸¦ ó¸®ÇÏ´Â JSF ºä¿¡¼­ ¸Å¿ì À¯¿ëÇÏ´Ù.

ºä ÀνºÅϽº º¯¼ö¸¦ Á¤ÀÇÇÒ¶§ var ¿¤¸®¸ÕÆ®¸¦ view-state Á¤ÀÇ ³»ºÎ¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

<view-state id="enterSearchCriteria"> 
    <var name="searchCriteria" class="com.mycompany.myapp.hotels.search.SearchCriteria"/> 
</view-state>
            

12.6.2. ½ºÄÚÇÁ¸¦ °¡Áø ½ºÇÁ¸µ ºó »ç¿ëÇϱâ

ºñ·Ï ÀÚµ¿ ¿¬°á Ç÷οì ÀνºÅͽº º¯¼ö°¡ ±¦ÂúÀº ¸ðµâÈ­¿Í °¡µ¶¼ºÀ» Á¦°øÇÏÁö¸¸ °¡²û ¿©·¯ºÐÀº AOP °°Àº ½ºÇÁ¸µ ÄÁÅ×À̳ÊÀÇ ±â´ÉÀ» È°¿ëÇÏ°í ½ÍÀ» ¼ö ÀÖ´Ù. ±×·± °æ¿ì ¿©·¯ºÐÀº ½ºÇÁ¸µ ¾ÖÇø®ÄÉÀ̼ÇÄÁÅؽºÆ® ³»ºÎ¿¡ ÀÖ´Â ºó¿¡ ƯÁ¤ À¥ ÇÃ·Î¿ì ½ºÄÚÇÁ¸¦ ÁÙ ¼ö ÀÖ´Ù.

<bean id="searchCriteria" class="com.mycompany.myapp.hotels.search.SearchCriteria" scope="flow"/>
            
ÀÌ·± Á¢±Ù ¹æ¹ýÀÇ °¡Àå Å« Â÷ÀÌÁ¡Àº EL Ç¥Çö½Ä¿¡ ÀÇÇØ Á¢±ÙµÉ ¶§ ºñÀ» ÃʱâÈ­ ÇÑ´Ù´Â °ÍÀÌ´Ù. ELÀ» ÅëÇÑ ÀÌ·± Á¾·ùÀÇ »ý¼º Áö¿¬Àº JSF°¡ °ü¸®ÇÏ´Â ºóÀÌ ÇÒ´çµÇ´Â °Í°ú ¸Å¿ì ºñ½ÁÇÏ´Ù.

12.6.3. ¸ðµ¨ Á¶ÀÛÇϱâ

ºä ·£Å͸µ Çϱâ Àü¿¡ (µ¥ÀÌÅͺ£À̽º¿¡¼­ ¿µ¼Ó ¿£Æ¼Æ¼¸¦ ·ÎµùÇÏ´Â °Í °°Àº)¸ðµ¨ ÃʱâÈ­°¡ ÇÊ¿äÇÑ °ÍÀº ¸Å¿ì ÈçÇÑ ÀÏÀÌÁö¸¸ JSF ÀÚü·Î´Â ÀÌ·¯ÇÑ ÃʱâÈ­¿¡ »ç¿ëÇÒ ÆíÀǼº ÈÄÅ©(hook)¸¦ Á¦°øÇÏÁö ¾Ê´Â´Ù. Ç÷οì Á¤ÀÇ ¾ð¾î´Â ¾×¼Ç(Action)À» ÅëÇؼ­ ÀÌ¿Í °ü·ÃµÈ ÀÚ¿¬½º·¯¿î ±â´ÉÀ» Á¦°øÇÑ´Ù. ½ºÇÁ¸µ Faces´Â ¾×¼ÇÀÇ °á°ú¸¦ JSF-°ü·Ã µ¥ÀÌÅÍ ±¸Á¶·Î º¯°æÇØÁÖ´Â Ãß°¡ÀûÀÎ ÆíÀǼºÀ» Á¦°øÇÑ´Ù. ¿¹Á¦¸¦ º¸ÀÚ.

<on-render>
    <evaluate expression="bookingService.findBookings(currentUser.name)" 
              result="viewScope.bookings" result-type="dataModel" />
</on-render>
          
ÀÌ·¸°Ô Çϸé bookingService.findBookings ¸Å¼­µå °á°ú¸¦ ÃëÇÏ°í ±×°ÍÀ» Ç¥ÁØ JSF DataTable ÄÄÆ÷³ÍÆ®¿¡¼­ ÇØ´ç ¸ñ·ÏÀ» »ç¿ëÇÒ ¼ö ÀÖµµ·Ï Ä¿½ºÅÒ JSF DataModel·Î °¨½Ñ´Ù.

<h:dataTable id="bookings" styleClass="summary" value="#{bookings}" var="booking" 
             rendered="#{bookings.rowCount > 0}">
    <h:column>
        <f:facet name="header">Name</f:facet>
        #{booking.hotel.name}
    </h:column>                   
    <h:column>
    <f:facet name="header">Confirmation number</f:facet>
        #{booking.id}
        </h:column>
    <h:column>
        <f:facet name="header">Action</f:facet>
        <h:commandLink id="cancel" value="Cancel" action="cancelBooking" />
    </h:column>
</h:dataTable>
            
Ä¿½ºÅÒ DataModelÀº request ½ºÄÚÇÁ ¿ÜÀÇ ÀúÀåÀ» À§ÇÑ Á÷·ÄÈ­¿Í EL¿¡¼­ ÇöÀç ¼±ÅÃÇÑ ÁÙ¿¡ ´ëÇÑ Á¢±Ù µî ¸î¸î Ãß°¡ÀûÀÎ ÆíÀǼºÀ» Á¦°øÇÑ´Ù. ¿¹¸¦ µé¾î, DataTable ³»ÀÇ ÄÄÆ÷³ÍÆ®¿¡ ÀÇÇØ ¾×¼Ç À̺¥Æ®°¡ ¹ß»ýÇÑ ºä¿¡¼­ Æ÷½ºÆ®¹é ÇÒ ¶§, ¿©·¯ºÐÀº ¼±ÅÃÇÑ ÁÙÀÇ ¸ðµ¨ ÀνºÅϽº¸¦ °¡Áú ¼ö ÀÖ´Ù.

<transition on="cancelBooking">
    <evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />            
</transition>
            
12.7. ½ºÇÁ¸µ À¥ Ç÷οì·Î JSF À̺¥Æ® ó¸®Çϱâ

½ºÇÁ¸µ À¥ Ç÷οì´Â ³·Àº °áÇÕµµ¸¦ À¯ÁöÇϸ鼭 JSF ¾×¼Ç À̺¥Æ®¸¦ ó¸®ÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÀÚ¹Ù Äڵ忡¼­ JSF API¿¡ ÀÇÁ¸ÇÏÁö ¾Ê¾Æµµ µÈ´Ù. À̺¥Æ®¸¦ Ä¿½ºÅÒ ÀÚ¹Ù ¾×¼Ç Äڵ带 ÀüÇô »ç¿ëÇÏÁö ¾Ê°í Ç÷οì Á¤ÀÇ ¾ð¾î¸¦ »ç¿ëÇÏ¿© ¿ÏÀüÇÏ°Ô Ã³¸®ÇÒ ¼ö ÀÖ´Ù. ÀÌ·¸°Ô Çϸé (JSF ºä ÅÛÇø´°ú SWF Ç÷οì Á¤ÀÇ) À̺¥Æ®¸¦ ¿¬°áÇÒ ¶§ ¸¸µé¾îÁö´Â ±¸¼º¹°µéÀ» Àüü ¾ÖÇø®ÄÉÀ̼ÇÀ» ºôµåÇÏ°í ´Ù½Ã ¹èÆ÷ÇÒ ÇÊ¿ä ¾øÀÌ Áï½Ã ¸®ÇÁ·¡½Ã µÇ±â ¶§¹®¿¡ º¸´Ù ±â¹ÎÇÑ °³¹ß ÇÁ·Î¼¼½º°¡ °¡´ÉÇØÁø´Ù.

12.7.1. JSF In-page ¾×¼Ç À̺¥Æ® ó¸®Çϱâ

°£´ÜÇÏÁö¸¸ JSF¿¡¼­ °¡Àå ÈçÇÑ °æ¿ì°¡ ¸ðµ¨À» Á¶ÀÛÇÏ´Â À̺¥Æ®¸¦ ¹ß»ý½ÃÅ°°í µ¿ÀÏÇÑ ºä·Î ¸ðµ¨ÀÇ º¯°æµÈ »óŸ¦ º¸¿©ÁÖ´Â °ÍÀÌ´Ù. Ç÷οì Á¤ÀÇ ¾ð¾î´Â transition ¿¤¸®¸ÕÆ®¿¡¼­ ÀÌ°ÍÀ» Áö¿øÇÑ´Ù.

ÀÌ °Í¿¡ ´ëÇÑ ÁÁÀº ¿¹Á¦´Â ÆäÀÌ¡ 󸮸¦ ÇÏ´Â ¸ñ·Ï Ç¥´Ù. °Å´ëÇÑ °á°ú ¸ñ·Ï ÁßÀÇ ÀϺθ¸ Àоî¿À°í º¸¿©ÁÖ°í ½Í´Ù°í °¡Á¤Çغ¸ÀÚ. ±×¸®°í »ç¿ëÀÚ´Â ±× °á°ú¸¦ ÆäÀÌ¡ÇÒ ¼ö ÀÖ´Ù. ¸ñ·ÏÀ» Àоî¿À°í º¸¿©ÁÖ´Â Ãʱâ view-state Á¤ÀÇ´Â ´ÙÀ½°ú °°´Ù.
 
<view-state id="reviewHotels">
    <on-render>
        <evaluate expression="bookingService.findHotels(searchCriteria)" 
                  result="viewScope.hotels" result-type="dataModel" />
    </on-render>
</view-state>
            

JSF DataTable·Î ÇöÀç È£ÅÚ ¸ñ·ÏÀ» º¸¿©ÁÖµµ·Ï ÇÒ ¼ö ÀÖ´Ù. ±×·± ´ÙÀ½ Ç¥ ÇÏ´Ü¿¡ "More Results" ¸µÅ©¸¦ Á¦°øÇÑ´Ù.
 
<h:commandLink id="nextPageLink" value="More Results" action="next"/>
            
ÀÌ Ä¿¸Çµå¸µÅ©´Â action ¼Ó¼º¿¡¼­ "next" À̺¥Æ®¸¦ º¸³½´Ù. ±×·³ ¿©·¯ºÐÀº À̺¥Æ®¸¦ view-state Á¤ÀÇ¿¡ Ãß°¡ÇÏ·Á ó¸®ÇÒ ¼ö ÀÖ´Ù.
 
<view-state id="reviewHotels">
    <on-render>
        <evaluate expression="bookingService.findHotels(searchCriteria)" 
            result="viewScope.hotels" result-type="dataModel" />
    </on-render>
    <transition on="next">
        <evaluate expression="searchCriteria.nextPage()" />
    </transition>
</view-state>
            
¿©±â¼­ searchCriteria ÀνºÅϽº¿¡¼­ page Ä«¿îÆ®¸¦ Áõ°¡ÇÏ¿© "next" À̺¥Æ®¸¦ ó¸®ÇÑ´Ù. ±×·³ ´ÙÀ½ on-render ¾×¼ÇÀ» º¯°æµÈ criteria·Î È£ÃâÇÑ´Ù. ±×·¯¸é ´ÙÀ½ ÆäÀÌÁö °á°ú¸¦ DataModel·Î ·ÎµùÇØÁØ´Ù. transition  ¿¤¸®¸ÕÆ®¿¡ to ¼Ó¼ºÀÌ ¾ø±â ¶§¹®¿¡ µ¿ÀÏÇÑ ºä¸¦ ´Ù½Ã º¸¿©ÁØ´Ù. ±×¸®°í ¸ðµ¨¿¡ º¯°æµÈ »çÇ×À» ºä¿¡ ¹Ý¿µÇØÁØ´Ù.

12.7.2. JSF ¾×¼Ç À̺¥Æ® ó¸®Çϱâ

in-page À̺¥Æ® ´ÙÀ½ ´Ü°è´Â Á¶ÀÛÇÑ ¸ðµ¨À» °¡Áö°í ´Ù¸¥ ºä·Î À̵¿ÇÏ´Â À̺¥Æ®´Ù. ¼ø¼ö JSF·Î ÀÌ°ÍÀ» ÇÏ·Á¸é faces-config.xml¿¡ ³×ºñ°ÔÀÌ¼Ç ·ÎÁ÷À» Ãß°¡ÇÏ°í ÀÚ¹Ù Äڵ带 JSF°¡ °ü¸®ÇÏ´Â ºó¿¡ Ãß°¡ÇØ¾ß ÇÑ´Ù.(µÎ ÀÛ¾÷ ¸ðµÎ ´Ù½Ã ¹èÆ÷ÇØ¾ß ÇÑ´Ù.) Ç÷οì Á¤ÀÇ ¾ð¾î¸¦ »ç¿ëÇϸé, in-page À̺¥Æ®¸¦ ´Ù·ç´ø ¹æ½Ä°ú ¸Å¿ì ºñ½ÁÇÏ°Ô ÇÑ °÷¿¡¼­ ±×·± °ÍÀ» ´Ù·ê ¼ö ÀÖ´Ù.

°è¼ÓÇؼ­ ÆäÀÌ¡ ó¸®ÇÏ´Â ¸ñ·ÏÀ» »ìÆ캸ÀÚ. º¸¿©Áö´Â DataTableÀÇ °¢°¢ÀÇ row¿¡ row ÀνºÅϽº¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ë ÆäÀÌÁö ¸µÅ©¸¦ °¡Áö°í ÀÖµµ·Ï ÇÏ°íÀÚ ÇÑ´Ù. ¿©·¯ºÐÀº Å×ÀÌºí¿¡ ´ÙÀ½ÀÇ commandLink ÄÄÆ÷³ÍÆ®¸¦ °¡Áö°í ÀÖ´Â Ä÷³À» Ãß°¡ÇÒ ¼ö ÀÖ´Ù.

<h:commandLink id="viewHotelLink" value="View Hotel" action="select"/>
            
ÀÌ°ÍÀº "select" À̺¥Æ®¸¦ ¹ß»ý½ÃŲ´Ù. ±×´ÙÀ½ ±âÁ¸ÀÇ view-state¿¡ ¶Ç ´Ù¸¥ transition ¿¤¸®¸ÕÆ®¸¦ Ãß°¡ÇÏ¿© ÀÌ°ÍÀ» ó¸®ÇÒ ¼ö ÀÖ´Ù.
 
<view-state id="reviewHotels">
    <on-render>
        <evaluate expression="bookingService.findHotels(searchCriteria)" 
            result="viewScope.hotels" result-type="dataModel" />
    </on-render>
    <transition on="next">
        <evaluate expression="searchCriteria.nextPage()" />
    </transition>
    <transition on="select" to="reviewHotel">
            <set name="flowScope.hotel" value="hotels.selectedRow" />
    </transition>
</view-state>
            
¿©±â¼­ "select" À̺¥Æ®´Â DataTable¿¡¼­ ÇöÀç ¼±ÅÃÇÑ hotel ÀνºÅϽº¸¦ ÇÃ·Î¿ì ½ºÄÚÇÁ¿¡ ³Ö¾î¼­ ó¸®ÇÏ°í ÀÖ´Ù. ±×·¸°Ô Çϸé "reviewHotel" view-state¿¡¼­ ÂüÁ¶ÇÒ °ÍÀÌ´Ù.

12.7.3. ¸ðµ¨ °ËÁõ ¼öÇàÇϱâ

JSF´Â º¯°æ »çÇ×À» ¸ðµ¨¿¡ ¹Ý¿µÇϱâ Àü¿¡ Çʵå-¼öÁØ ÀÔ·Â °ËÁõ °ü·Ã À¯¿ëÇÑ ±â´ÉÀ» Á¦°øÇÑ´Ù. ÇÏÁö¸¸ º¯°æ »çÇ×À» Àû¿ëÇÑ µÚ¿¡ ¸ðµ¨-¼öÁØÀÇ Á» ´õ º¹ÀâÇÑ °ËÁõÀ» ¼öÇàÇÒ ÇÊ¿ä°¡ ÀÖ´Ù¸é ¿©·¯ºÐÀº °ü¸®ÇÏ´Â ºóÀÇ JSF ¾×¼Ç ¸Å¼­µå¿¡ Ä¿½ºÅÒ Äڵ带 Ãß°¡ÇØ¾ß ÇÑ´Ù. ÀÌ·± Á¾·ùÀÇ °ËÁõÀº ¸ð¸ÞÀÎ ¸ðµ¨ ÀÚü Ã¥ÀÓÀÌÁö¸¸ µµ¸ÞÀÎ ¸ðµ¨ °èÃþ¿¡ ¿øÇÏÁö ¾Ê´ø JSF API ÀÇÁ¸¼ºÀ» Ãß»çÇÏÁö ¾Ê°í¼­´Â ¿¡·¯ ¸Þ½ÃÁö¸¦ ºä¿¡ Àü´ÞÇϱⰡ ¾î·Æ´Ù.

½ºÇÁ¸µ Faces¸¦ »ç¿ëÇϸé ÀϹÝÀûÀÌ°í ³·Àº-¼öÁØÀÇ MessageContext¸¦ ¿©·¯ºÐÀÇ ºñÁî´Ï½º Äڵ忡¼­ À¯¿ëÇÏ°Ô »ç¿ëÇÒ ¼ö ÀÖ°í ±×°÷¿¡ Ãß°¡ÇÑ ¸ðµç ¸Þ½ÃÁö´Â ·£´õ¸µ ½Ã¿¡ FacesContext¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

¿¹¸¦ µé¾î, »ç¿ëÀÚ°¡ È£ÅÚ ¿¹¾àÀ» ¿Ï·áÇϱâ À§ÇØ ÇÊ¿äÇÑ »ó¼¼ Á¤º¸¸¦ ÀÔ·ÂÇÏ´Â ºä°¡ ÀÖ´Ù°í °¡Á¤ÇÏÀÚ. ¿©·¯ºÐÀº °Å±â¼­ ÀԷ¹ÞÀº üũÀΠüũ¾Æ¿ô ³¯Â¥°¡ ºñÁî´Ï½º ±ÔÄ¢¿¡ ¸Â´ÂÁö È®ÀÎÇØ¾ß ÇÑ´Ù. transition ¿¤¸®¸ÕÆ®¿¡¼­ ±×·¯ÇÑ ¸ðµ¨-¼öÁØ °ËÁõÀ» È£ÃâÇÒ ¼ö ÀÖ´Ù.
 
<view-state id="enterBookingDetails">
    <transition on="proceed" to="reviewBooking">
        <evaluate expression="booking.validateEnterBookingDetails(messageContext)" />
    </transition>
</view-state>
           
¿©±â¼­ "proceed" À̺¥Æ®´Â booking ÀνºÅϽºÀÇ ¸ðµ¨-¼öÁØ °ËÁõ ¸Å¼­µå¸¦ È£ÃâÇÏ¿© ó¸®ÇÑ´Ù. ¸Å¼­µå¸¦ È£ÃâÇÒ ¶§ MessageContext ÀνºÅϽº¸¦ ³Ñ°ÜÁ༭ ¸Þ½ÃÁö¸¦ ±â·ÏÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù. ±×·±´ÙÀ½ h:messages ÄÄÆ÷³ÍÆ®¸¦ »ç¿ëÇÏ¿© JSF ¸Þ½ÃÁö¸¦ º¸¿©ÁÙ ¼ö ÀÖ´Ù.

12.7.4. Ajax À̺¥Æ® ó¸®Çϱâ

½ºÇÁ¸µ Faces´Â Ç¥ÁØ JSF ÄÄÆ÷³ÍÆ®¿¡ Ajax-±â¹Ý ÀϺΠºä ¼öÁ¤ ±â´ÉÀ» Ãß°¡ÇÑ ¸î¸î Ưº°ÇÑ UICommand ÄÄÆ÷³ÍÆ®¸¦ Á¦°øÇÑ´Ù. À̵é ÄÄÆ÷³ÍÆ®´Â »ç¿ëÀÚ°¡ »ç¿ëÇÏ´Â ºê¶ó¿ìÁ®ÀÇ ±â´ÉÀÌ ¶³¾îÁø´Ù¸é Àüü ÆäÀÌÁö¸¦ ¸®ÇÁ·¡½Ã ÇÏ¿© ¸ðµÎ Àß µ¿ÀÛÇÒ °ÍÀÌ´Ù.

[³ëÆ®] ³ëµå
½ºÇÁ¸µ FacesÀÇ ÄÚ¾î JSF Áö¿øÀÌ JSF 1.1 ȣȯ°¡´É ÇÏÁö¸¸, ½ºÇÁ¸µ Faces Ajax ÄÄÆ÷³ÍÆ®´Â JSF 1.2¸¦ ÇÊ¿ä·Î ÇÑ´Ù.

Revisiting the earlier example with the paged table, you can change the "More Results" link to use an Ajax request by replacing the standard commandButton with the Spring Faces version (note that the Spring Faces command components use Ajax by default, but they can alternately be forced to use a normal form submit by setting ajaxEnabled="false" on the component):

            
<sf:commandLink id="nextPageLink" value="More Results" action="next" />
            

This event is handled just as in the non-Ajax case with the transition element, but now you will add a special render action that specifies which portions of the component tree need to be re-rendered:

<view-state id="reviewHotels">
    <on-render>
        <evaluate expression="bookingService.findHotels(searchCriteria)" 
                  result="viewScope.hotels" result-type="dataModel" />
    </on-render>
    <transition on="next">
        <evaluate expression="searchCriteria.nextPage()" />
        <render fragments="hotels:searchResultsFragment" />
    </transition>
</view-state>
            

The fragments="hotels:searchResultsFragment" is an instruction that will be interpreted at render time, such that only the component with the JSF clientId "hotels:searchResultsFragment" will be rendered and returned to the client. This fragment will then be automatically replaced in the page. The fragments attribute can be a comma-delimited list of ids, with each id representing the root node of a subtree (meaning the root node and all of its children) to be rendered. If the "next" event is fired in a non-Ajax request (i.e., if JavaScript is disabled on the client), the render action will be ignored and the full page will be rendered as normal.

In addition to the Spring Faces commandLink component, there is a corresponding commandButton component with the same functionality. There is also a special ajaxEvent component that will raise a JSF action even in response to any client-side DOM event. See the Spring Faces tag library docs for full details.

An additional built-in feature when using the Spring Faces Ajax components is the ability to have the response rendered inside a rich modal popup widget by setting popup="true" on a view-state .

<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
    <on-entry>
        <render fragments="hotelSearchFragment" />
    </on-entry>
    <transition on="search" to="reviewHotels">
        <evaluate expression="searchCriteria.resetPage()"/>
    </transition>
</view-state>
            

If the "changeSearchCriteria" view-state is reached as the result of an Ajax-request, the result will be rendered into a rich popup. If JavaScript is unavailable, the request will be processed with a full browser refresh, and the "changeSearchCriteria" view will be rendered as normal. 

½Å°í

'Spring Web Flow > Chapter 12' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 12Àå JSF ÅëÇÕ  (0)2009.03.10
top

SWF 11Àå ½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ® Äü ·¹ÆÛ·±½º



11.1 µµÀÔ

½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®(spring-js)´Â Dojo °°ÀÌ ÀÚÁÖ »ç¿ëÇÏ´Â ÀÚ¹Ù½ºÅ©¸³Æ® ÅøŶ¿¡ ´ëÇÑ °æ·® Ãß»óÈ­´Ù. ¸ñÇ¥´Â °øÅëÀÇ Å¬¶óÀÎÆ®-ÂÊ ÇÁ·Î±×·¡¹Ö ¸ðµ¨À» Á¦°øÇÏ¿© À¥ ÆäÀÌÁö¸¦ ¸®Ä¡ À§Á¬°ú ¾ÖÀÌÀÛ½º ¸®¸ðÆÃÀ¸·Î ±Þ°ÝÈ÷ °³¼±ÇÏ´Â °ÍÀÌ´Ù.

11.2. ÀÚ¹Ù½ºÅ©¸³Æ® ¸®¼Ò½º Á¦°øÇϱâ

½ºÇÁ¸µ JS´Â À¥ ¾ÖÇø®ÄÉÀÌ¼Ç ·çÆ® µð·ºÅ丮¿Í jar ÆÄÀÏ¿¡¼­ ÀÚ¹Ù½ºÅ©¸³Æ®¿Í CSS ÆÄÀÏ °°Àº À¥ ¸®¼Ò½º¸¦ ¼­ºùÇÏ´Â ResourceServlet¸¦ Á¦°øÇÑ´Ù. ÀÌ ¼­ºí¸´Àº Spring.js ÆÄÀÏÀ» ¿©·¯ºÐ ÆäÀÌÁö¿¡ °ø±ÞÇÏ´Â Æí¸®ÇÑ ¹æ¹ýÀ» Á¦°øÇÑ´Ù. ÀÌ ¼­ºí¸´À» ¹èÆ÷ÇÏ·Á¸é web.xml¿¡ ´ÙÀ½°ú °°ÀÌ ¼³Á¤Ç϶ó.

<!-- Serves static resource content from .jar files such as spring-js.jar -->
<servlet>
    <servlet-name>Resource Servlet</servlet-name>
    <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
</servlet>
        
<!-- Map all /resources requests to the Resource Servlet for handling -->
<servlet-mapping>
    <servlet-name>Resource Servlet</servlet-name>
    <url-pattern>/resources/*</url-pattern>
</servlet-mapping>
        
11.3. ½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®¸¦ ÆäÀÌÁö¿¡ Æ÷ÇÔ½ÃÅ°±â

½ºÇÁ¸µ JS´Â ÀÚ½ÅÀÇ API ±¸Çöü¸¦ À¯¸íÇÑ ÀÚ¹Ù½ºÅ©¸³Æ® ÅøŶÀ¸·Î ºôµå ÇÒ ¼ö ÀÖ°Ô ¼³°èµÆ´Ù. Spring.js ±âº» ±¸Çöü´Â Dojo ÅøŶÀ» ±â¹ÝÀ¸·Î ÇÑ´Ù.

½º ÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®¸¦ ÆäÀÌÁö¿¡¼­ »ç¿ëÇÏ·Á¸é º¸Åë ±â¹ÝÀ¸·Î ÇÏ´Â ÅøŶ, Spring.js ±â¹Ý ÀÎÅÍÆäÀ̽º ÆÄÀÏ, ½ºÇÁ¸µ-(¶óÀ̺귯¸® ±¸Çöü).js ÆÄÀÏÀ» Æ÷ÇÔ½Ãų ÇÊ¿ä°¡ ÀÖ´Ù. ¿¹¸¦ µé¾î ´ÙÀ½Àº ResourceServlet¸¦ »ç¿ëÇÏ¿© Dojo ±¸Çöü¸¦ °¡Á®¿Â´Ù.

<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>
        
±â ¹Ý ¶óÀ̺귯¸®ÀÇ À§Á¬ ½Ã½ºÅÛÀ» »ç¿ëÇÏ¸é º¸Åë ¿©·¯ºÐÀº ¹Ýµå½Ã ¿øÇÏ´Â ·è¾ØÇÊ(look and feel)À» ¾ò±â À§ÇØ CSS ¸®¼Ò½º¸¦ Æ÷ÇÔ½Ãų°ÍÀÌ´Ù. booking-mvc ·¹ÆÛ·±½º ¾ÖÇø®ÄÉÀ̼ÇÀº DojoÀÇ tundra.css¸¦ Æ÷ÇÔ½ÃŲ´Ù.

<link type="text/css" rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css" />" />
        
11.4. ½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ® µ¥ÄÚ·¹À̼Ç

½º ÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®ÀÇ ÁÖ¿ä °³³äÀº ±âÁ¸ DOM ³ëµå¿¡ µ¥ÄÚ·¹À̼ÇÀ» Àû¿ëÇÏ´Â °³³äÀÌ´Ù. ÀÌ ±â¼úÀº ±â´ÉÀÌ ÁÁÄ¡ ¾ÊÀº ºê¶ó¿ìÀú¿¡¼­µµ ¿©ÀüÈ÷ µ¿ÀÛÇÒ ÆäÀÌÁö °°Àº À¥ ÆäÀÌÁö¸¦ Çõ½ÅÀûÀ¸·Î °³¼±ÇÒ ¶§ »ç¿ëÇÑ´Ù. addDecoration ¸Å¼­µå´Â µ¥ÄÚ·¹À̼ÇÀ» Àû¿ëÇÒ ¶§ »ç¿ëÇÑ´Ù.

´ÙÀ½ ¿¹Á¦´Â ½ºÇÁ¸µ MVCÀÇ <form:input> ű׿¡ dzºÎÇÑ Á¦¾È ±â´ÉÀ» °¡´ÉÇÏ°Ô ÇÏ´Â °ÍÀ» º¸¿©ÁØ´Ù.

<form:input id="searchString" path="searchString"/>
<script type="text/javascript">
    Spring.addDecoration(new Spring.ElementDecoration({
        elementId: "searchString",
        widgetType: "dijit.form.ValidationTextBox",
        widgetAttrs: { promptMessage : "Search hotels by name, address, city, or zip." }}));
</script>
        
ElementDecoration ´Â ¸®Ä¡ À§Á¬ ±â´ÉÀ» ±âÁ¸ÀÇ DOM ³ëµå¿¡ Ãß°¡ÇÒ ¶§ »ç¿ëÇÑ´Ù. ÀÌ µ¥ÄÚ·¹ÀÌ¼Ç Å¸ÀÔÀº ±â¹ÝÀ¸·Î ÇÏ´Â ÅøŶÀ» ¿ÏÀüÈ÷ °¨Ãß´Â °ÍÀ» ¸ñÇ¥·Î ÇÏÁö ¾Ê´Â´Ù. µû¶ó¼­ ÅøŶÀÇ ³×ÀÌƼºê À§Á¬ ŸÀÔ°ú ¼Ó¼ºÀ» Á÷Á¢ »ç¿ëÇÑ´Ù. ÀÌ ¹æ¹ýÀº °øÅëÀÇ µ¥ÄÚ·¹ÀÌ¼Ç ¸ðµ¨À» »ç¿ëÇÏ¿© ±â¹ÝÇÏ´Â ÅøŶÀÇ ¸ðµç À§Á¬À» ÀÏ°üÀûÀÎ ¹æ¹ýÀ¸·Î ÅëÇÕÇϱâ À§ÇÑ °ÍÀÌ´Ù. booking-mvc ·¹ÆÛ·±½º ¾ÖÇø®ÄÉÀ̼ǿ¡¼­ Á¦¾È¿¡¼­ ºÎÅÍ Å¬¶óÀ̾ðÆ®ÂÊ °ËÁõ±îÁö µ¥ÄÚ·¹À̼ÇÀ» Àû¿ëÇÏ´Â ¸¹Àº ¿¹Á¦¸¦ ÂüÁ¶Ç϶ó.

ElementDecoration¸¦ »ç¿ëÇÏ¿© ¸®Ä¡ °ËÁõ ±â´ÉÀ» °®Ãá À§Á¬À» Àû¿ëÇÒ ¶§ ÀϹÝÀûÀÎ ¿ä±¸ »çÇ×Àº ÆûÀÌ °ËÁõÀ» Åë°úÇϱâ Àü±îÁö´Â ¼­ºê¹ÔÇÏÁö ¾Ê´Â °ÍÀÌ´Ù. ValidateAllDecorationÀ¸·Î ±×°ÍÀ» ÇÒ ¼ö ÀÖ´Ù.

<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed" />
<script type="text/javascript">
    Spring.addDecoration(new Spring.ValidateAllDecoration({ elementId:'proceed', event:'onclick' }));
</script>
        

ÀÌ°ÍÀº "Proceed" ¹öÆ°À» Ŭ¶óÀ̾ðÆ® ÂÊ °ËÁõÀ» ÇÏ°í ¼º°øÀûÀ¸·Î Æнº ÇÒ ¶§ ±îÁö Æû ¼­ºê¹ÔÀ» Çã¿ëÇÏÁö ¾Ê´Â Ưº°ÇÑ onclick À̺¥Æ® Çڵ鷯·Î µ¥ÄÚ·¹ÀÌÆ®ÇÑ´Ù.

AjaxEventDecoration´Â ¿ø°Ý ¾ÖÀÌÀÛ½º ¿äûÀ» ¼­¹ö·Î º¸³»´Â Ŭ¶óÀ̾ðÆ®ÂÊ À̺¥Æ® ¸®½º³Ê¸¦ Àû¿ëÇÑ´Ù. ¶ÇÇÑ ÀÀ´äÇÒ ¶§ ÀÚµ¿À¸·Î Äݹé ÇÔ¼ö¸¦ ¸µÅ©¿¡ µî·ÏÇÑ´Ù.

<a id="prevLink" href="search?searchString=${criteria.searchString}&page=${criteria.page - 1}">Previous</a>
<script type="text/javascript">
    Spring.addDecoration(new Spring.AjaxEventDecoration({
        elementId: "prevLink",
        event: "onclick",
        params: { fragments: "body" }
    }));
</script>
        
ÀÌ °ÍÀº "Previous Results" ¸µÅ©ÀÇ onclick À̺¥Æ®¸¦ ÀÀ´ä½Ã¿¡ ƯÁ¤ Á¶°¢À» ´Ù½Ã ·£´õ¸µÇϵµ·Ï Ưº°ÇÑ ¸Å°³º¯¼ö¿Í ÇÔ²² ¾ÖÀÌÀÛ½º È£Ãâ·Î ²Ù¸çÁØ´Ù. ÀÌ ¸µÅ©´Â Ŭ¶óÀ̾ðÆ®¿¡¼­ ÀÚ¹Ù½ºÅ©¸³Æ®¸¦ »ç¿ëÇÒ ¼ö ¾ø´Â °æ¿ì¿¡µµ ¿©ÀüÈ÷ µ¿ÀÛÇÑ´Ù´Â °Í¿¡ ÁÖ¸ñÇ϶ó. (¾ÖÀÌÀÛ½º ¿äû ´Ù·ç±â¿¡¼­ ¼­¹ö¿¡ ¿äûÀ» ¾î¶»°Ô ´Ù·ç´ÂÁö ÀÚ¼¼È÷ »ìÆ캸¶ó.)

¶ÇÇÑ ÇϳªÀÇ ¿¤¸®¸ÕÆ®¿¡ ¿©·¯ °³ÀÇ µ¥ÄÚ·¹À̼ÇÀ» Àû¿ëÇÏ´Â °Íµµ °¡´ÉÇÏ´Ù. ´ÙÀ½ ¿¹Á¦´Â ¾ÖÀÌÀÛ½º¿Í validate-all ¼­ºê¹Ô ±ÝÁö¸¦ °°ÀÌ Àû¿ëÇÑ ¹öÆ°¿¡ ´ëÇÑ ¿¹Á¦´Ù.

<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed" />  
<script type="text/javascript">
    Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
    Spring.addDecoration(new Spring.AjaxEventDecoration({elementId:'proceed', event:'onclick',formId:'booking', params:{fragments:'messages'}}));
</script>
        
DojoÀÇ Äõ¸® API¸¦ »ç¿ëÇÏ¿© ÇÑ ÁÙ·Î ¿©·¯ ¿¤¸®¸ÕÆ®¿¡ ÇϳªÀÇ µ¥ÄÚ·¹À̼ÇÀ» Àû¿ëÇÏ´Â °Íµµ °¡´ÉÇÏ´Ù. ´ÙÀ½ ¿¹Á¦´Â üũ¹Ú½º ÁýÇÕÀ» Dojo Checkbox À§Á¬À¸·Î ²Ù¹Î´Ù.

<div id="amenities">
<form:checkbox path="amenities" value="OCEAN_VIEW" label="Ocean View" /></li>
<form:checkbox path="amenities" value="LATE_CHECKOUT" label="Late Checkout" /></li>
<form:checkbox path="amenities" value="MINIBAR" label="Minibar" /></li>
<script type="text/javascript">
    dojo.query("#amenities input[type='checkbox']").forEach(function(element) {
        Spring.addDecoration(new Spring.ElementDecoration({
            elementId: element.id,
            widgetType : "dijit.form.CheckBox",
            widgetAttrs : { checked : element.checked }
        }));
    });
</script>
</div>

11.5. ¾ÖÀÌÀÛ½º ¿äû ´Ù·ç±â

½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®ÀÇ Å¬¶óÀ̾ðÆ® ÂÊ ¾ÖÀÌÀÛ½º ÀÀ´ä ´Ù·ç±â´Â ¼­¹ö¿¡¼­ "Á¶°¢" ¹Þ±â °³³äÀ» ±â¹ÝÀ¸·Î Çß´Ù. À̵é Á¶°¢Àº ´Ü¼øÇÑ Ç¥ÁØ HTML·Î ±âÁ¸ ÆäÀÌÁöÀÇ ÀϺθ¦ ±³Ã¼ÇÒ Àǵµ¸¦ °¡Áö°í ÀÖ´Ù. ¼­¹ö¿¡¼­ ÇÊ¿äÇÑ ÇÙ½É Á¶°¢Àº Àüü ÀÀ´ä Áß¿¡¼­ ¾î¶² Á¶°¢À» ÀϺθ¸ ·£´õ¸µ ÇØ¾ß ÇÏ´ÂÁö ÆÇ´ÜÇÒ ¶§ »ç¿ëÇÑ´Ù.

Àüü ÀÀ´ä Áß¿¡ ÀϺΠÁ¶°¢¸¸ ·£´õ¸µ ÇÏ·Á¸é Àüü ÀÀ´äÀº ¹Ýµå½Ã ÀÀ´ä ±¸¼ºÇÒ ¶§ ÄÄÆ÷Áö¼ÇÀ» »ç¿ëÇÒ ¼ö ÀÖ°í ±× ÄÄÆ÷Áö¼ÇÀÇ ±¸¼º ¿ä¼ÒµéÀº °³º°ÀûÀ¸·Î ÂüÁ¶Çϰųª ·£´õ¸µ ÇÒ ¼ö ÀÖ´Â ÅÛÇø´ ±â¼úÀ» »ç¿ëÇؼ­ ¸¸µé¾î¾ß ÇÑ´Ù. ½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®´Â ŸÀÏÁî(Tiles)¸¦ »ç¿ëÇÏ´Â °£´ÜÇÑ ½ºÇÁ¸µ MVC È®ÀåÀ» ÅëÇØ ÀÌ°ÍÀ» ´Þ¼ºÇÑ´Ù. ÄÄÆ÷Áö¼ÇÀ» Áö¿øÇÏ´Â ¾î¶² ÅÛÇø´ ½Ã½ºÅÛÀ̵çÁö ÀÌ·ÐÀûÀ¸·Î´Â °°Àº ±â¼ú·Î »ç¿ëÇÒ ¼ö ÀÖ´Ù.

½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®ÀÇ ¾ÖÀÌÀÛ½º ¸®¸ðÆà ±â´ÉÀº ¾ÖÀÌÀÛ½º ¿äûÀ» ´Ù·ç´Â Äڵ尡 ÀÏ¹Ý ºê¶ó¿ìÀú ¿äû°ú ´Ù¸£Áö ¾Ê¾Æ¾ß ÇÑ´Ù´Â °³³äÀ» ±â¹ÝÀ¸·Î ÇÑ´Ù. µû¶ó¼­ ¾ÖÀÌÀÛ½º ¿äû¿¡ ´ëÇÑ º°µµÀÇ Áö½ÄÀº Äڵ忡¼­ Á÷Á¢ÀûÀ¸·Î ÇÊ¿äÇÏÁö ¾Ê°í µ¿ÀÏÇÑ Çڵ鷯¸¦ µÎ °¡Áö ½ºÅ¸ÀÏÀÇ ¿äû¿¡ ¸ðµÎ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

11.5.1. ½ºÇÁ¸µ MVC ÄÁÆ®·Ñ·¯·Î ¾ÖÀÌÀÛ½º ¿äû ´Ù·ç±â

¾ÖÀÌÀÛ½º ¿äûÀ» ½ºÇÁ¸µ MVC ÄÁÆ®·Ñ·¯·Î ´Ù·ç·Á¸é ½ºÇÁ¸µ MVC È®ÀåÀÌ Á¦°øÇÏ´Â ¼³Á¤À» ¿©·¯ºÐÀÇ ½ºÇÁ¸µ ¾ÖÇø®ÄÉÀÌ¼Ç ÄÁÅؽºÆ®¿¡ ÀϺΠÀÀ´äÀ» ·£´õ¸µ Çϵµ·Ï Ãß°¡ÇÏ¸é µÈ´Ù.

<bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTilesView"/>
</bean>
            
ÀÌ°ÍÀº AjaxUrlBasedViewResolver¸¦ ¼³Á¤ÇÏ¿© ¾ÖÀÌÀÛ½º ¿äûÀ» ºÐ¼®ÇÏ°í FlowAjaxTilesView °´Ã¼¸¦ ¸¸µé¾î¼­ ÀûÀýÇÑ ºÎºÐÀ» ·£´õ¸µÇÏ´Â °ÍÀ» ó¸®ÇÏ°Ô ÇÑ´Ù. FlowAjaxTilesView´Â À¥ Ç÷οì¿Í ¼ø¼ö ½ºÇÁ¸µ MVC ¿äûÀ» ¸ðµÎ ·£´õ¸µÇÏ´Â ÀÛ¾÷À» ÇÒ ¼ö ÀÖ´Ù. Á¶°¢Àº ŸÀÏÁî ºä Á¤ÀÇÀÇ °³º° ¼Ó¼º¿¡ ´ëÀÀÇÑ´Ù. ¿¹¸¦ µé¾î, ´ÙÀ½ÀÇ Å¸ÀÏÁî ºä Á¤ÀǸ¦ º¸ÀÚ.

<definition name="hotels/index" extends="standardLayout">
    <put-attribute name="body" value="index.body" />
</definition>

<definition name="index.body" template="/WEB-INF/hotels/index.jsp">
    <put-attribute name="hotelSearchForm" value="/WEB-INF/hotels/hotelSearchForm.jsp" />
    <put-attribute name="bookingsTable" value="/WEB-INF/hotels/bookingsTable.jsp" />
</definition>
            
¾ÖÀÌÀÛ½º ¿äûÀº "body", "hotelSearchForm", "bookingsTable"¸¦ ±â¼úÇÏ¿© ¿äû¿¡¼­ ÀϺθ¦ ·£´õ¸µÇÒ ¼ö ÀÖ´Ù.

11.5.2. ½ºÇÁ¸µ MVC + ½ºÇÁ¸µ À¥ Ç÷ο쿡¼­ ¾ÖÀÌÀÛ½º ¿äû ´Ù·ç±â

½ºÇÁ¸µ À¥ Ç÷οì´Â Á¶°¢ÀÇ ºÎ°¡ÀûÀÎ ·£´õ¸®À» Ç÷οì Á¤ÀÇ ¾ð¾î¿¡¼­ render ¿¤¸®¸ÕÆ®·Î Á÷Á¢ ´Ù·é´Ù. ÀÌ ¹æ¹ýÀÇ ÀåÁ¡Àº Á¶°¢ÀÇ ¼±ÅÃÀÌ Å¬¸®À̾ðÆ® ÂÊ ÄÚµå¿Í ¿ÏÀüÈ÷ ºÐ¸® µÈ´Ù´Â °ÍÀÌ´Ù. ½ºÇÁ¸µ MVC ÄÁÆ®·Ñ·¯ Á¢±Ù ¹æ¹ý¿¡¼­ »ç¿ëÇϵíÀÌ ¿äû¿¡ ³Ñ°ÜÁÖ´Â º°µµÀÇ ¸Å°³º¯¼ö°¡ ÇÊ¿ä ¾ø´Ù. ¿¹¸¦ µé¾î, ¸¸¾à ¾Õ¼± ¿¹Á¦ ŸÀÏÁî ºä¸¦ ¸®Ä¡ ÀÚ¹Ù½ºÅ©¸³Æ® Æ˾÷À¸·Î "hotelSearchForm" Á¶°¢À» ·£´õ¸µ ÇÏ°í ½Í´Ù¸é ´ÙÀ½°ú °°ÀÌ ÇÒ ¼ö ÀÖ´Ù.

<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
    <on-entry>
        <render fragments="hotelSearchForm" />
    </on-entry>
    <transition on="search" to="reviewHotels">
        <evaluate expression="searchCriteria.resetPage()"/>
    </transition>
</view-state>                
            
        
½Å°í
top

SWF 10Àå ½ºÇÁ¸µ MVC ÅëÇÕ



10.1. µµÀÔ

À̹ø Àå¿¡¼­´Â À¥ Ç÷ո¦ ½ºÇÁ¸µ MVC À¥ ¾ÖÇø®ÄÉÀ̼ÇÀ¸·Î ¾î¶»°Ô ÅëÇÕÇÏ´ÂÁö »ìÆ캸°Ú´Ù. booking-mvc ¿¹Á¦ ¾ÖÇø®ÄÉÀ̼ÇÀº À¥ Ç÷οì¿Í ½ºÇÁ¸µ MVC¿¡ ´ëÇÑ ÁÁÀº Âü°íÀÚ·á´Ù. ÀÌ ¾ÖÇø®ÄÉÀ̼ÇÀº °£´ÜÇÏ°Ô ¸¸µç ¿©Çà »çÀÌÆ®·Î »ç¿ëÀÚ°¡ È£ÅÚ ¹æÀ» °Ë»öÇÏ°í ¿¹¾àÇÒ ¼ö ÀÖ´Ù.

10.2 web.xml ¼³Á¤Çϱâ

½ºÇÁ¸µ MVC¸¦ »ç¿ëÇϴ ù ¹ø? ´Ü°è´Â DispatcherServletÀ» web.xml¿¡ ¼³Á¤ÇÏ´Â °ÍÀÌ´Ù. ¿©·¯ºÐÀº ÀϹÝÀûÀ¸·Î À¥ ¾ÖÇø®ÄÉÀÌ¼Ç ¸¶´Ù ÇÑ ¹ø¾¿ ÀÌ ÀÛ¾÷À» ÇÒ °ÍÀÌ´Ù.

¾Æ ·¡ ¿¹Á¦´Â /spring/ À¸·Î ½ÃÀÛÇÏ´Â ¸ðµç ¿äûÀ» DispatcherServletÀ¸·Î ¸ÊÇÎÇÑ´Ù. init-paramÀ» »ç¿ëÇÏ¿© contextConfigurationLocationÀ» Á¦°øÇÑ´Ù. ÀÌ ¼³Á¤ ÆÄÀÏÀº À¥ ¾ÖÇø®ÄÉÀ̼ǿ¡ °üÇÑ °ÍÀÌ´Ù.

<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>/WEB-INF/web-application-config.xml</param-value>
    </init-param>
</servlet>
    
<servlet-mapping>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <url-pattern>/spring/*</url-pattern>
</servlet-mapping>

10.3. Ç÷οì·Î µð½ºÆÐĪÇϱâ

DispatcherServletÀº ¾ÖÇø®ÄÉÀÌ¼Ç ¸®¼Ò½º¿¡ ´ëÇÑ ¿äûÀ» Çڵ鷯¿¡°Ô Àü´ÞÇÑ´Ù. Ç÷οì´Â Çڵ鷯 ÇϳªÀÇ Çڵ鷯 ŸÀÔ´Ï´Ù.

10.3.1. FlowHandlerAdapter µî·ÏÇϱâ

¿äûÀ» Ç÷οì·Î µð½ºÆÐĪÇϴ ù ¹ø° ´Ü°è´Â ½ºÇÁ¸µ MVC¿¡¼­ Ç÷οì 󸮰¡ °¡´ÉÇÏ°Ô ÇÏ´Â °ÍÀÌ´Ù. ±×·¸°Ô ÇÏ·Á¸é FlowHandlerAdapter¸¦ ¼³Ä¡Ç϶ó.

<!-- Enables FlowHandler URL mapping -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
    <property name="flowExecutor" ref="flowExecutor" />
</bean>
            

10.3.2. ÇÃ·Î¿ì ¸ÊÇÎ Á¤ÀÇÇϱâ

Ç÷οì 󸮸¦ °¡´ÉÇÏ°Ô Çß´Ù¸é, ´ÙÀ½ ´Ü°è´Â ƯÁ¤ ¾ÖÇø®ÄÉÀÌ¼Ç ¸®¼Ò½º¸¦ ¿©·¯ºÐ Ç÷οì·Î ¸ÊÇÎÇÏ´Â °ÍÀÌ´Ù. ±×·¸°Ô ÇÏ´Â °¡Àå °£´ÜÇÑ ¹æ¹ýÀº FlowHandlerMapping¸¦ Á¤ÀÇÇÏ´Â °ÍÀÌ´Ù.

<!-- Maps request paths to flows in the flowRegistry;
     e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->        
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
    <property name="flowRegistry" ref="flowRegistry"/>
    <property name="order" value="0"/>
</bean>
            
ÀÌ ¸ÊÇÎÀ» ¼³Á¤ÇÔÀ¸·Î½á Dispatcher´Â ¾ÖÇø®ÄÉÀÌ¼Ç ¸®¼Ò½º °æ·Î¸¦ ÇÃ·Î¿ì ·¹Áö½ºÆ®¸®¿¡ ÀÖ´Â Ç÷οì·Î ¸ÊÇÎÇÑ´Ù. ¿¹¸¦ µé¾î, /hotels/booking °æ·ÎÀÇ ¸®¼Ò½º¿¡ Á¢±ÙÇÑ´Ù¸é ·¹Áö½ºÆ®¸®´Â hotels/booking id¸¦ °¡Áö°í ÀÖ´Â Ç÷ο츦 ã´Â´Ù. ¸¸¾à ÇØ´ç id¸¦ °¡Áø Ç÷ο츦 ¹ß°æÇÏ¸é ±× Ç÷ο찡 ¿äûÀ» ó¸®ÇÑ´Ù. ¸¸¾à Ç÷ο츦 ãÁö ¸øÇÏ¸é ´ÙÀ½ Dispatcher¿¡ ÀÖ´Â (ordered chain)¼ø¼­¿¡ µû¶ó ´ÙÀ½ Çڵ鷯 ¸ÊÇÎÀÌ Ã£¾Æº¸°Å³ª "noHandlerFound" ÀÀ´äÀ» ¹ÝȯÇÑ´Ù.

10.3.3. Ç÷οì ó¸® ¿öÅ©Ç÷οì

À¯È¿ÇÑ ÇÃ·Î¿ì ¸ÊÇÎÀ» ¹ß°ßÇϸé, FlowHandlerAdapter´Â Ç÷οìÀÇ »õ·Î¿î ½ÇÇà ½ÃÀÛ ÁöÁ¡ÀÌ ¾îµòÁö ¾Ë¾Æ³»°Å³ª ÇöÀç HTTP ¿äû Á¤º¸¸¦ ±â¹ÝÀ¸·Î ±âÁ¸ÀÇ ½ÇÇàÀ» ´Ù½Ã ½ÃÀÛÇÑ´Ù. ¾îÅÇÅÍ°¡ Àû¿ëÇÒ ÇÃ·Î¿ì ½ÇÇàÀ» »õ·Î ½ÃÀÛÇϰųª ´Ù½Ã ½ÃÀÛÇϴµ¥ °ü·ÃµÈ ¿©·¯ ±âº» ÇàÀ§°¡ Á¸ÀçÇÑ´Ù.

  • HTTP ¿äû ¸Å°³º¯¼öµéÀº ¸ðµç ½ÃÀÛ ÇÃ·Î¿ì ½ÇÇà¿¡¼­ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù.
  • ÇÃ·Î¿ì ½ÇÇàÀÌ ÃÖÁ¾ ÀÀ´ä ¾øÀÌ Á¾·áµÇ¸é ±âº» Çڵ鷯°¡ µ¿ÀÏÇÑ ¿äûÀ» »õ·Î¿î ½ÇÇà ½ÃÀÛÀ» ½ÃµµÇÑ´Ù.
  • ¿¹ ¿Ü°¡ NoSuchFlowExecutionExceptionÀÌ ¾Æ´Ï¶ó¸é ó¸®ÇÏÁö ¾Ê´Â ¿¹¿Ü¸¦ DispatcherSerlvet¿¡ À§ÀÓÇÑ´Ù. ±âº» Çڵ鷯´Â NoSuchFlowExecutionException¸¦ ¸¸³ª¸é »õ·Î¿î ½ÇÇàÀ» ½ÃÀÛÇÏ¿© ¿¹¿Ü¸¦ ±Øº¹ÇÏ·Á°í ÇÑ´Ù.
º¸´Ù ÀÚ¼¼ÇÑ ³»¿ëÀº FlowHandlerAdapter API ¹®¼­¸¦ ÂüÁ¶Ç϶ó. ¿©·¯ºÐÀº ÀÌ·± ±âº» ÇàÀ§¸¦ »ó¼Ó ¶Ç´Â ¿©·¯ºÐ ¸¸ÀÇ FlowHandler¸¦ ±¸ÇöÇÏ¿© ÀçÁ¤ÀÇ ÇÒ ¼ö ÀÖ´Ù. ´ÙÀ½ Àý¿¡¼­ ÀÚ¼¼È÷ ´Ù·ç°Ú´Ù.

10.4. Ä¿½ºÅÒ FlowHandler ±¸ÇöÇϱâ

FlowHandler´Â HTTP ¼­ºí¸´ ȯ°æ¿¡¼­ Ç÷ο츦 ¾î¶»°Ô ½ÇÇàÇÒÁö Ä¿½ºÅ͸¶ÀÌ¡ ÇÒ ¶§ »ç¿ëÇÒ ¼ö ÀÖ´Â È®Àå ÁöÁ¡ÀÌ´Ù. FlowHandler´Â FlowHandlerAdapter°¡ »ç¿ëÇÏ¸ç ´ÙÀ½À» Ã¥ÀÓÁø´Ù.
  • ½ÇÇàÇÒ Ç÷οì Á¤ÀÇÀÇ id¸¦ ¹ÝȯÇÑ´Ù.
  • ½ÃÀÛÇÒ ¶§ Ç÷οìÀÇ »õ·Î¿î ½ÇÇà¿¡ ³Ñ°ÜÁÙ ÀԷ°ªÀ» ¸¸µç´Ù.
  • Á¾·áÇÒ ¶§ Ç÷οìÀÇ ½ÇÇà¿¡¼­ ¹ÝȯÇÏ´Â °á°ú¸¦ ó¸®ÇÑ´Ù.
  • ÇÃ·Î¿ì ½ÇÇà Áß¿¡ ¹ß»ýÇÏ´Â ¿¹¿Ü¸¦ ó¸®ÇÑ´Ù.
ÀÌ·± Ã¥ÀÓµéÀº org.springframework.mvc.servlet.FlowHandler ÀÎÅÍÆäÀ̽º¿¡ Á¤ÀÇ¿¡ ³ªÅ¸³ªÀÖ´Ù.

public interface FlowHandler {

    public String getFlowId();

    public MutableAttributeMap createExecutionInputMap(HttpServletRequest request);

    public String handleExecutionOutcome(FlowExecutionOutcome outcome,
        HttpServletRequest request, HttpServletResponse response);

    public String handleException(FlowException e,
        HttpServletRequest request, HttpServletResponse response);
}                
        
To implement a FlowHandler, subclass AbstractFlowHandler. All these operations are optional, and if not implemented the defaults will apply. You only need to override the methods that you need. Specifically:

FlowHandler¸¦ ±¸ÇöÇÏ·Á¸é AbstractFlowHandler¸¦ »ó¼ÓÇ϶ó. ¸ðµç ±â´ÉÀº ºÎ°¡ÀûÀÎ °ÍÀ̱â ??¹®¿¡ ±¸ÇöÇÏÁö ¾ÊÀ¸¸é ±âº» ¼³Á¤ÀÌ Àû¿ëµÈ´Ù. ¿©·¯ºÐÀº ÇÊ¿äÇÑ ¸Å¼­µå¸¸ ÀçÁ¤ÀÇÇÏ¸é µÈ´Ù. ƯÈ÷...
  • ¿©·¯ºÐ Ç÷οìÀÇ id¸¦ Http ¿äû¿¡¼­ Á÷Á¢ °¡Á®¿Ã ¼ö ¾øÀ» ¶§ getFlowId(HttpServletRequest)¸¦ ÀçÁ¤ÀÇÇ϶ó. ±âº»À¸·Î ½ÇÇàÇÒ Ç÷οìÀÇ id´Â ¿äû URIÀÇ pathinfo ºÎºÐ¿¡¼­ °¡Á®¿Â´Ù. ¿¹¸¦ µé¾î http://localhost/app/hotels/booking?hotelId=1´Â ±âº»À¸·Î Ç÷οì id·Î hotels/booking¸¦ °¡Á®¿Â´Ù.
  • HttpServletRequest¿¡¼­ Ç÷οì ÀÔ·Â ¸Å°³º¯¼ö ÃßÃâÀ» »ó¼¼ÇÏ°Ô Á¦¾îÇÏ°í ½Í´Ù¸é createExecutionInputMap(HttpServletRequest)¸¦ ÀçÁ¤ÀÇÇ϶ó. ±âº»À¸·Î ¸ðµç ¿äû ¸Å°³º¯¼ö¸¦ Ç÷οì ÀÔ·Â ¸Å°³º¯¼ö·Î »ç¿ëÇÑ´Ù.
  • ƯÁ¤ ÇÃ·Î¿ì ½ÇÇà °á°ú¸¦ º°µµ ¹æ½ÄÀ¸·Î ó¸®ÇÏ°í ½Í´Ù¸é handleExecutionOutcomeÀ» ÀçÁ¤ÀÇÇ϶ó ±âº» ÇàÀ§´Â Á¾·áÇÑ Ç÷οìÀÇ URL·Î ¸®´ÙÀÌ·ºÆ®ÇÏ¿© Ç÷οìÀÇ »õ·Î¿î ½ÇÇàÀ» ½ÃÀÛÇÑ´Ù.
  • unhandled ÇÃ·Î¿ì ¿¹¿Ü¸¦ »ó¼¼ÇÏ°Ô Á¦¾îÇÏ°í ½Í´Ù¸é handleExceptionÀ» ÀçÁ¤ÀÇÇ϶ó. ±âº» ÇൿÀº Ŭ¶óÀ̾ðÆ®°¡ Á¾·áµÆ°Å³ª ¸¸·áµÈ ÇÃ·Î¿ì ½ÇÇà¿¡ Á¢±ÙÇϸé Ç÷οì Àç½ÃÀÛÀ» ½ÃµµÇÑ´Ù. ±×¹ÛÀÇ ¿¹¿Ü´Â ½ºÇÁ¸µ MVC ExceptionResolver ±â¹Ý ½Ã¼³¿¡ ´øÁ®ÁØ´Ù.
10.4.1. FlowHandler ¿¹Á¦

½ºÇÁ¸µ MVC¿Í À¥ ÇÃ·Î¿ì »çÀÌ¿¡ ÈçÇÑ Çù·ÂÀº Á¾·áÇßÀ» ¶§ @Controller·Î ¸®´ÙÀÌ·ºÆ® ÇÏ´Â °ÍÀÌ´Ù. FlowHandler´Â ƯÁ¤ ÄÁÆ®·Ñ·¯ URL·Î Ç÷οì Á¤ÀÇ¿¡ °áÇÕÇÏÁö ¾Ê°íµµ ÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ½ºÇÁ¸µ MVC·Î ¸®´ÙÀÌ·ºÆ®ÇÏ´Â FlowHandler ¿¹Á¦´Â ¾Æ·¡¿Í °°´Ù.

public class BookingFlowHandler extends AbstractFlowHandler {
    public String handleExecutionOutcome(FlowExecutionOutcome outcome,
                                         HttpServletRequest request, HttpServletResponse response) {
        if (outcome.getId().equals("bookingConfirmed")) {
            return "/booking/show?bookingId=" + outcome.getOutput().get("bookingId");
        } else {
            return "/hotels/index";
        }
    }
}
            
ÀÌ Çڵ鷯´Â ¿ÀÁ÷ ÇÃ·Î¿ì ½ÇÇà °á°ú¸¦ ƯÁ¤ ¹æ¹ýÀ¸·Î ´Ù·ï¾ß Çϱ⠶§¹®¿¡ ´Ù¸¥ °ÍÀº ÀçÁ¤ÀÇÇÒ ÇÊ¿ä°¡ ¾ø´Ù. bookingConfirmed °á°ú¸¸ »õ·Î¿î ¿¹¾àÀ» º¸¿©ÁÖµµ·Ï ¸®´ÙÀÌ·ºÆ®ÇÒ °ÍÀÌ´Ù. ±×¹Û¿¡ ´Ù¸¥ °á°ú´Â È£ÅÚ À妽º ÆäÀÌÁö·Î ´Ù½Ã ¸®´ÙÀÌ·ºÆ® ÇÑ´Ù.

10.4.2. Ä¿½ºÅÒ FlowHandler ¹èÆ÷Çϱâ

To install a custom FlowHandler, simply deploy it as a bean. The bean name must match the id of the flow the handler should apply to.

Ä¿½ºÅÒ FlowHandler¸¦ ¼³Ä¡ÇÏ·Á¸é °£´ÜÇÏ°Ô ºóÀ¸·Î ¹èÆ÷ÇÏ¸é µÈ´Ù. ºó À̸§Àº ¹Ýµå½Ã Çڵ鷯¸¦ Àû¿ëÇÒ Ç÷οìÀÇ id¿Í ÀÏÄ¡ÇØ¾ß ÇÑ´Ù.

<bean name="hotels/booking" class="org.springframework.webflow.samples.booking.BookingFlowHandler" />
            
ÀÌ ¼³Á¤¿¡¼­ /hotels/booking¿¡ Á¢±ÙÇÏ´Â °ÍÀº Ä¿½ºÅÒ BookingFlowHandler¸¦ »ç¿ëÇÏ´Â /hotels/booking Ç÷ο츦 ½ÇÇàÇÏ´Â °ÍÀÌ´Ù. ¿¹¾à Ç÷ο찡 Á¾·áµÇ¸é FlowHandler´Â ÇÃ·Î¿ì ½ÇÇà °á°ú¸¦ ó¸®ÇÏ°í ÀûÀýÇÑ ÄÁÆ®·Ñ·¯·Î ¸®´ÙÀÌ·ºÆ® ÇÑ´Ù.

10.4.3. FlowHandler ¸®´ÙÀÌ·ºÆ®

FlowExecutionOutcome ¶Ç´Â FlowException¸¦ ó¸®ÇÏ´Â FlowHandler´Â ó¸® ÇÑ ´ÙÀ½ ¸®´ÙÀÌ·ºÆ® ÇÒ ¸®¼Ò½º¸¦ °¡¸®Å°´Â ¹®ÀÚ¿­À» ¹ÝȯÇÑ´Ù. ¾Õ¼± ¿¹Á¦¿¡¼­ BookingFlowHandler´Â bookingConfirmed °á°ú´Â booking/show ¸®¼Ò½º URI·Î ¸®´ÙÀÌ·ºÆ® ÇÏ°í ±×¹Û¿¡ ¸ðµç °á°ú´Â hotels/index ¸®¼Ò½º·Î ¸®´ÙÀÌ·ºÆ® Çß´Ù.

±âº»À¸·Î, ¹ÝȯµÈ ¸®¼Ò½º À§Ä¡´Â ÇöÀç ¼­ºí¸´ ¸ÊÇÎÀ» ±âÁØÀ¸·Î »ó´ëÀûÀÌ´Ù. ÀÌ·ÎÀÎÇØ Ç÷οì Çڵ鷯°¡ »ó´ë °æ·Î¸¦ »ç¿ëÇÏ¿© ¾ÖÇø®ÄÉÀ̼ÇÀÇ ´Ù¸¥ ÄÁÆ®·Ñ·¯·Î ¸®´ÙÀÌ·ºÆ® ÇÒ ¼ö ÀÖ´Ù. ¶ÇÇÑ ¸í½ÃÀûÀÎ ¸®´ÙÀÌ·ºÆ® Á¢µÎ¾î´Â Á» ´õ Á¦¾î°¡ ÇÊ¿äÇÑ °æ¿ì¿¡ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

Áö¿øÇÏ´Â ¸í½ÃÀûÀÎ ¸®´ÙÀÌ·ºÆ® Á¢µÎ¾î´Â ´ÙÀ½°ú °°´Ù.
  • servletRelative: - ÇöÀç ¼­ºí¸´¿¡¼­ »ó´ëÀûÀÎ À§Ä¡ÀÇ ¸®¼Ò½º·Î ¸®´ÙÀÌ·ºÆ® Ç϶ó.
  • contextRelative: - ÇöÀç À¥ ¾ÖÇø®ÄÉÀÌ¼Ç ÄÁÅؽºÆ® °æ·Î¿¡ »ó´ëÀûÀÎ À§Ä¡ÀÇ ¸®¼Ò½º·Î ¸®´ÙÀÌ·ºÆ® Ç϶ó.
  • servetRelative: - ¼­¹ö ·çÆ®¿¡ »ó´ëÀûÀÎ À§Ä¡ÀÇ ¸®¼Ò½º·Î ¸®´ÙÀÌ·ºÆ® Ç϶ó.
  • http:// ¶Ç´Â https://: - Àüü¸¦ ¸í½ÃÇÑ ¸®¼Ò½º URI·Î ¸®´ÙÀÌ·ºÆ® Ç϶ó.
ÀÌ°Í°ú µ¿ÀÏÇÑ Á¢¹Ì¾î¸¦ exteralRedirect¸¦ »ç¿ëÇÏ¿© Ç÷οì Á¤ÀÇ¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù. view-state ¶Ç´Â end-state¿¡¼­ Áö½ÃÀÚ·Î ¾µ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î view="externalRedirect:http://springframework.org" ÀÌ·¸°Ô ¾µ ¼ö ÀÖ´Ù.

10.5. View Resolution

À¥ Ç÷οì 2´Â ´Ù¸¥ °ÍÀ» ±â¼úÇÏÁö ¾ÊÀ¸¸é ¼±ÅÃÇÑ ºä ½Äº°ÀÚ¸¦ Ç÷οì ÀÛ¾÷ µð·ºÅ丮¿¡ À§Ä¡ÇÑ ÆÄÀÏ·Î ¸ÊÇÎÇÑ´Ù. ±âÁ¸ÀÇ ½ºÇÁ¸µ MVC + À¥ ÇÃ·Î¿ì ¾ÖÇø®ÄÉÀ̼ǿ¡¼­´Â ¿ÜºÎ viewResolver°¡ ÀÌ¹Ì ÀÌ·± ¸ÊÇÎÀ» ´Ù·ç°í ÀÖÀ» °ÍÀÌ´Ù. µû¶ó¼­ ±× ¸®Á¹¹ö¸¦ °è¼Ó ÇÏ¿ëÇÏ°í ÇÃ·Î¿ì ºä¸¦ ÆÐŰ¡ ÇÏ´Â ¹æ¹ýÀ» ¹Ù²Ù°í ½ÍÁö ¾Ê´Ù¸é À¥ Ç÷ο츦 ´ÙÀ½°ú °°ÀÌ ¼³Á¤Ç϶ó.

<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
   <webflow:location path="/WEB-INF/hotels/booking/booking.xml" />
</webflow:flow-registry>

<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"/>

<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
   <property name="viewResolvers" ref="myExistingViewResolverToUseForFlows"/>
</bean>
       
10.6. ºä¿¡¼­ ¹ß»ýÇÑ À̺¥Æ® ½ÅÈ£º¸³»±â

When a flow enters a view-state it pauses, redirects the user to its execution URL, and waits for a user event to resume. Events are generally signaled by activating buttons, links, or other user interface commands. How events are decoded server-side is specific to the view technology in use. This section shows how to trigger events from HTML-based views generated by templating engines such as JSP, Velocity, or Freemarker.

Ç÷ο찡 ¸ØÃá view-state·Î µé¾î°¡¸é, »ç¿ëÀÚ¸¦ ½ÇÇà URL·Î ¸®´ÙÀÌ·ºÆ® ÇÏ°í »ç¿ëÀÚ°¡ ´Ù½Ã ½ÃÀÛ À̺¥Æ®¸¦ ¹ß»ýÇÒ ¶§±îÁö ±â´Ù¸°´Ù. À̺¥Æ®´Â º¸Åë È°¼ºÈ­ ¹öÆ°, ¸µÅ© ¶Ç´Â ´Ù¸¥ »ç¿ëÀÚ ÀÎÅÍÆäÀ̽º Ä¿¸Çµå¿¡ ÀÇÇØ ½ÅÈ£°¡ º¸³»Áø´Ù. À̺¥Æ®°¡ ¼­¹öÂÊ¿¡ ¾î¶»°Ô µðÄÚµå µÇ´À³Ä´Â »ç¿ëÇÏ´Â ºä ±â¼ú¿¡ µû¶ó ´Ù¸£´Ù. À̹ø Àý¿¡¼­ (JSP, Velocity, ¶Ç´Â Freemarker °°Àº ÅÛÇø´ ¿£Áø¿¡ ÀÇÇØ ¸¸µé¾îÁø ºä¸¦ ±â¹ÝÀ¸·Î) HTML¿¡¼­ À̺¥Æ®¸¦ ¾î¶»°Ô ¹ß»ý½ÃÅ°´ÂÁö »ìÆ캸°Ú´Ù.

10.6.1. À̸§ÀÌ ÀÖ´Â HTML ¹öÆ° »ç¿ëÇÏ¿© À̺¥Æ® ½ÅÈ£ º¸³»±â

¾Æ·¡ ¿¹Á¦´Â Ŭ¸¯ÇßÀ» ¶§ °¢°¢ proceed¿Í cancel À̺¥Æ® ½ÅÈ£¸¦ º¸³»´Â µÎ °³ÀÇ ¹öÆ°À» º¸¿©ÁØ´Ù.

<input type="submit" name="_eventId_proceed" value="Proceed" />
<input type="submit" name="_eventId_cancel" value="Cancel" />

¹öÆ°ÀÌ ´­¸®¸é À¥ Ç÷οì´Â  _eventId_ ·Î ½ÃÀÛÇÏ´Â ¿äû ¸Å°³ º¯¼ö ã°í ³ª¸ÓÁö ¹®ÀÚ¿­À» À̺¥Æ® id·Î °£ÁÖÇÑ´Ù. ÀÌ ¿¹Á¦¿¡¼­ _eventId_proceed¸¦ º¸³»¸é proceed°¡ id°¡ µÈ´Ù. °°Àº Æû¿¡¼­ ¹ß»ýÇÒ ¼ö ÀÖ´Â ¿©·¯ À̺¥Æ®°¡ ÀÖÀ» ¶§ ÀÌ·± ½ºÅ¸ÀÏÀ» »ç¿ëÇÒ ¼ö ÀÖ°Ú´Ù.

10.6.2. °¨ÃçÁø HTML Æû ¸Å°³º¯¼ö¸¦ »ç¿ëÇÏ¿© À̺¥Æ® ½ÅÈ£ º¸³»±â

¾Æ·¡ ¿¹Á¦´Â ¼­ºê¹Ô ÇÒ ¶§ proceed À̺¥Æ®¸¦ º¸³»´Â ÆûÀÌ´Ù.

<input type="submit" value="Proceed" />
<input type="hidden" name="_eventId" value="proceed" />    
           
¿©±â¼­ À¥ Ç÷οì´Â °£´ÜÇÏ°Ô Æ¯¼öÇÑ _eventId ¸Å°³º¯¼ö¸¦ ã°í ±× °ªÀ» À̺¥Æ® id·Î »ç¿ëÇÑ´Ù. ÀÌ·± ½ºÅ¸ÀÏÀº ¿ÀÁ÷ Æû¿¡¼­ ¹ß»ýÇÏ´Â À̺¥Æ®°¡ ÇÑ °³ ÀÏ ¶§¿¡¸¸ »ç¿ëÇ϶ó.

10.6.3. HTML ¸µÅ©¸¦ »ç¿ëÇÏ¿© À̺¥Æ® ½ÅÈ£ º¸³»±â

¾Æ·¡ ¿¹Á¦´Â È°¼ºÈ­ ÇßÀ» ¶§ cancle À̺¥Æ®¸¦ º¸³»´Â ¸µÅ©´Ù.

<a href="${flowExecutionUrl}&_eventId=cancel">Cancel</a>        
           
À̺¥Æ®¸¦ ¹ß»ý½ÃÅ°¸é HTTP ¿äûÀÌ ¼­¹ö·Î º¸³»Áø´Ù. ¼­¹ö ÂÊ¿¡¼­´Â Ç÷ο찡 ÇöÀç view-state¿¡¼­ À̺¥Æ®¸¦ µðÄÚµùÇÑ´Ù. ¾î¶»°Ô ÀÌ µðÄÚµù ÇÁ·Î¼¼½º°¡ µ¿ÀÛÇÏ´ÂÁö´Â ºä ±¸Çöü¿¡ µû¶ó ´Ù¸£´Ù. ½ºÇÁ¸µ MVC ºä ±¸Çöü°¡ °£´ÜÇÏ°Ô _eventId À̸§À» °¡Áö°í ÀÖ´Â ¿äû ¸Å°³º¯¼ö¸¦ ã´Â °ÍÀ» ±â¾ïÇ϶ó. ¸¸¾à _eventId ¸Å°³º¯¼ö°¡ ¾ø´Ù¸é ºä´Â _eventId_·Î ½ÃÀÛÇÏ´Â ¸Å°³º¯¼ö¸¦ ã°í ÇØ´ç ¹®ÀÚ¿­ÀÇ ³²Àº ºÎºÐÀ» À̺¥Æ® id·Î »ç¿ëÇÑ´Ù. ¸¸¾à µÑ ´Ù ¾ø´Â °æ¿ì¿¡´Â ¾î¶² Ç÷ο쵵 ½ÇÇàÇÏÁö ¾Ê´Â´Ù.
½Å°í

'Spring Web Flow > Chapter 10' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 10Àå ½ºÇÁ¸µ MVC ÅëÇÕ  (0)2009.03.04
top

SWF 9Àå ½Ã½ºÅÛ ¼³Á¤



9.1. µµÀÔ

À̹ø Àå¿¡¼­´Â À¥ ÇÃ·Î¿ì ½Ã½ºÅÛÀ» À¥ ȯ°æ¿¡¼­ »ç¿ëÇϱâ Àû´çÇϵµ·Ï ¼³Á¤ÇÏ´Â ¹æ¹ýÀ» »ìÆ캻´Ù.

9.2. webflow-config.xsd

À¥ Ç÷οì´Â ½ºÇÁ¸µ ½ºÅ°¸¶¸¦ Á¦°øÇÏ¿© ¿©·¯ºÐÀÌ ½Ã½ºÅÛÀ» ¼³Á¤ÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù. ÀÌ ½ºÅ°¸¶¸¦ »ç¿ëÇÏ·Á¸é ±×°ÍÀ» ±â¹Ý½Ã¼³ °èÃþÀÇ ºó ÆÄÀÏ Áß Çϳª¿¡ Ãß°¡Ç϶ó.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:webflow="http://www.springframework.org/schema/webflow-config"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/webflow-config
           http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">        

    <!-- Setup Web Flow here -->
    
</beans>

9.3. ±âº» ½Ã½ºÅÛ ¼³Á¤

´ÙÀ½ Àý¿¡¼­ À¥ ÇÃ·Î¿ì ½Ã½ºÅÛÀ» ¿©·¯ºÐ ¾ÖÇø®ÄÉÀ̼ǿ¡ ¼³Á¤ÇÒ ¶§ ÇÊ¿äÇÑ ÃÖ¼ÒÇÑÀÇ ¼³Á¤À» »ìÆ캸°Ú´Ù

9.3.1. FlowRegistry

Ç÷ο츦 FlowRegistry¿¡ µî·ÏÇ϶ó.

<webflow:flow-registry id="flowRegistry">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

9.3.2. FlowExecutor

Ç÷ο츦 ½ÇÇàÇÏ´Â ÇÙ½É ¼­ºñ½º FlowExecutor¸¦ ¹èÆ÷Ç϶ó.

<webflow:flow-executor id="flowExecutor" />

½ºÇÁ¸µ MVC¿Í ½ºÇÁ¸µ Faces ºÎºÐ¿¡¼­ À¥ ÇÃ·Î¿ì ½Ã½ºÅÛÀ» ¾î¶»°Ô MVC¿Í JSF¿¡ ÅëÇÕÇÏ´ÂÁö »ìÆ캸¶ó.

9.4. flow-registry ¿É¼Ç

À̹ø ÀýÀº flow-registry ¼³Á¤ ¿É¼ÇÀ» »ìÆ캻´Ù

9.4.1. Ç÷οì À§Ä¡ ¸í½ÃÇϱâ

location ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© µî·ÏÇÒ Ç÷οì Á¤ÀÇ °æ·Î¸¦ ¸í½ÃÇÑ´Ù. ±âº»À¸·Î base-path°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê´Ù¸é Ç÷οì´Â ÀÚ½ÅÀÇ ÆÄÀÏ À̸§¿¡¼­ È®ÀåÀÚ¸¦ »« ½Äº°ÀÚ¸¦ ºÎ¿©¹Þ´Â´Ù.

<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
         
9.4.2. Ä¿½ºÅÒ ÇÃ·Î¿ì ½Äº°ÀÚ ºÎ¿©Çϱâ

id¸¦ ¸í½ÃÇÏ¿© Ä¿½ºÅÒ µî·Ï ½Äº°ÀÚ¸¦ Ç÷ο쿡 ºÎ¿©ÇÑ´Ù.

<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" id="bookHotel" />
            
9.4.3. Ç÷οì meta-attributes ºÎ¿©Çϱâ

flow-definition-attributes ¿¤¸®¸ÕƲ¸£ »ç¿ëÇÏ¿© µî·ÏÇÑ Ç÷ο쿡 Ä¿½ºÅÒ meta-attributes¸¦ ºÎ¿©ÇÑ´Ù.

<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml">
    <flow-definition-attributes>
        <attribute name="caption" value="Books a hotel" />
    </flow-definition-attributes>
</webflow:flow-location>
            

9.4.4. À§Ä¡ ÆÐÅÏÀ¸·Î ÇÃ·Î¿ì µî·ÏÇϱâ

flow-location-pattern ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ¸í½ÃÇÑ ¸®¼Ò½º À§Ä¡ ÆÐÅÏ¿¡ ´ëÀÀÇÏ´Â Ç÷ο츦 µî·ÏÇÑ´Ù.

<webflow:flow-location-pattern value="/WEB-INF/flows/**/*-flow.xml" />
            
9.4.5. Ç÷οì À§Ä¡ ±â¹Ý °æ·Î

base-path ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ¾ÖÇø®ÄÉÀ̼ÇÀÇ ¸ðµç Ç÷ο쿡 ´ëÇÑ ±âº» À§Ä¡¸¦ Á¤ÀÇÇÑ´Ù. ¸ðµç Ç÷οì À§Ä¡´Â ±âº» °æ·Î¸¦ ±âÁØÀ¸·Î »ó´ë °æ·Î°¡ µÈ´Ù. ±âº» °æ·Î´Â '/WEB-INF'°°Àº ¸®¼Ò½º °æ·Î ¶Ç´Â 'classpath:org/springframework/webflow/samples' °°Àº Ŭ·¡½ºÆнº À§Ä¡°¡ µÉ ¼ö ÀÖ´Ù.

<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location path="/hotels/booking/booking.xml" />
</webflow:flow-registry>
            
With a base path defined, the algorithm that assigns flow identifiers changes slightly. Flows will now be assigned registry identifiers equal to the the path segment between their base path and file name. For example, if a flow definition is located at '/WEB-INF/hotels/booking/booking-flow.xml' and the base path is '/WEB-INF' the remaining path to this flow is 'hotels/booking' which becomes the flow id.

±âº» °æ·Î¸¦ Á¤ÀÇÇÔÀ¸·Î¼­ ÇÃ·Î¿ì ½Äº°ÀÚ¸¦ ºÎ¿©ÇÏ´Â ¾Ë°í¸®ÁòÀÌ ¾à°£ ¹Ù²ï´Ù. Ç÷οì´Â ÀÌÁ¦ ±âº» °æ·Î¿Í ÆÄÀÏÀ̸§ »ç¾ÆÀÇ °ªÀ» µî·Ï ½Äº°ÀÚ·Î ºÎ¿©¹Þ´Â´Ù. ¿¹¸¦ µé¾î, Ç÷ο찡 Á¤ÀǵǾî ÀÖ´Â À§Ä¡°¡ '/WEB-INF/hotels/booking/booking-flow.xml' ÀÌ·¸°í ±âº» °æ·Î°¡ '/WEB-INF' ¶ó¸é ³²´Â ºÎºÐÀΠ 'hotels/booking'°¡ Ç÷οìÀÇ id°¡ µÈ´Ù.

[ÆÁ]    µð·ºÅ丮 ´ç Ç÷οì Á¤ÀÇ
°¢°¢ÀÇ Ç÷οì Á¤ÀǸ¦ º°µµÀÇ µð·ºÅ丮·Î ¹­´Â °ÍÀÌ ÁÁÀº ½À°üÀ̶ó´Â °ÍÀ» ±â¾ïÇصÎÀÚ. ÀÌ·¸°Ô ÇÏ¸é ¸ðµâÈ­¸¦ ÁõÁø½ÃÅ°°í µ¶¸³ÀûÀÎ ¸®¼Ò½º¸¦ ÇÁ·Î¿ì Á¤ÀÇ¿Í ÇÔ²² ¹­À» ¼ö ÀÖ´Ù. ¶ÇÇÑ ±Ô¾àÀ» ÀÌ¿ëÇÒ ¶§ µÎ °³ÀÇ Ç÷ο찡 °°Àº ½Äº°ÀÚ¸¦ °®´Â °ÍÀ» ¹æÁöÇÒ ¼ö ÀÖ´Ù.

¸¸¾à ±âº» °æ·Î°¡ ¸í½ÃµÇ¾î ÀÖÁö ¾Ê°Å³ª Ç÷οì Á¤ÀÇ°¡ ±âº» °æ·Î¿¡ ÀÖ´Ù¸é ÆÄÀÏÀ̸§(¿¡¼­ È®ÀåÀÚ¸¦ ?A)°ÍÀ» »ç¿ëÇÏ¿© id¸¦ ´ëÀÔÇÑ´Ù. ¿¹¸¦ µé¾î, ¸¸¾à Ç÷οì Á¤ÀÇ ÆÄÀÏÀÌ 'booking.xml'¶ó¸é ÇÃ·Î¿ì ½Äº°ÀÚ´Â °£´ÜÇÏ°Ô 'booking'ÀÌ µÈ´Ù.

À§Ä¡ ÆÐÅÏÀº µî·Ï ±âº» °æ·Î¿Í ÇÔ²² »ç¿ëÇÏ¸é ¸Å¿ì ¸·°­ÇÏ´Ù. ÇÃ·Î¿ì ½Äº°ÀÚ°¡ '*-flow'°¡ µÇÁö ¾Ê°í µð·ºÅ丮 °æ·Î ±â¹ÝÀÌ µÈ´Ù. ¿¹¸¦ µé¾î..

<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
            
À§ ¿¹Á¦¿¡¼­ WEB-INF ¹Ø¿¡ /user/login, /user/registration, /hotels/booking, /flights/booking¿¡ À§Ä¡ÇÑ Ç÷οìµéÀÌ ÀÖ´Ù°í ÇßÀ» ¶§ Ç÷οì id´Â °¢°¢ user/login, user/registration, hotels/booking,  flights/booking°¡ µÈ´Ù.

9.4.6. FlowRegistry °èÃþ±¸Á¶ ¼³Á¤Çϱâ

Use the parent attribute to link two flow registries together in a hierarchy. When the child registry is queried, if it cannot find the requested flow it will delegate to its parent.

parent ¼Ó¼ºÀ» »ç¿ëÇÏ¿© µÎ ÇÃ·Î¿ì µî·ÏÀ» ÇϳªÀÇ °èÃþ±¸Á¶·Î ¹­À» ¼ö ÀÖ´Ù. ¿äû¹ÞÀº Ç÷ο츦 ÇÏÀ§ ·¹Áö½ºÆ®¸®¿¡¼­ ãÁö ¸øÇϸé parent·Î À§ÀÓÇÑ´Ù.

<!-- my-system-config.xml -->
<webflow:flow-registry id="flowRegistry" parent="sharedFlowRegistry">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

<!-- shared-config.xml -->
<webflow:flow-registry id="sharedFlowRegistry">
    <!-- Global flows shared by several applications -->
</webflow:flow-registry>
            
9.4.7. Ä¿½ºÅÒ FlowBuilder ¼­ºñ½º ¼³Á¤Çϱâ

flow-builder-services ¼Ó¼ºÀ» »ç¿ëÇÏ¿© flow-registry¿¡¼­ Ç÷ο츦 ¸¸µé ¶§ »ç¿ëÇÒ ¼­ºñ½º¿Í ¼³Á¤À» Ä¿½ºÅ͸¶ÀÌ¡ÇÒ ¼ö ÀÖ´Ù. ¸¸¾à flow-builder-services űװ¡ ¸í½ÃµÇ¾î ÀÖÁö ¾Ê´Ù¸é ±âº» ¼­ºñ½º ±¸Çöü¸¦ »ç¿ëÇÑ´Ù. űװ¡ Á¤ÀǵǾî ÀÖ´Ù¸é Ä¿½ºÅ͸¶ÀÌ¡ ÇÏ°í ½ÍÀº ¼­ºñ½º¸¦ ÂüÁ¶ÇÏ¸é µÈ´Ù.

<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

<webflow:flow-builder-services id="flowBuilderServices" />
            

¼³Á¤ °¡´ÉÇÑ ¼­ºñ½º´Â conversion-service, expression-parser, view-factory-creator´Ù. ÀÌ ¼­ºñ½ºµéÀº ¿©·¯ºÐÀÌ Á¤ÀÇÇÑ Ä¿½ºÅÒ ºóÀ» ÷Á¶Çϵµ·Ï ¼³Á¤µÇ¾ú´Ù. ¿¹¸¦ µé¾î..

<webflow:flow-builder-services id="flowBuilderServices"
    conversion-service="conversionService"
    expression-parser="expressionParser"
    view-factory-creator="viewFactoryCreator" />

<bean id="conversionService" class="..." />
<bean id="expressionParser" class="..." />
<bean id="viewFactoryCreator" class="..." />
            

9.4.7.1. conversion-service

conversion-service ¼Ó¼ºÀ» »ç¿ëÇÏ¿© À¥ ÇÃ·Î¿ì ½Ã½ºÅÛÀÌ »ç¿ëÇÒ ConversionService¸¦ Ä¿½ºÅ͸¶ÀÌ¡ÇÒ ¼ö ÀÖ´Ù. Converter´Â ÇÃ·Î¿ì ½ÇÇ൵Áß ¾î¶² ŸÀÔÀ» ´Ù¸¥ ŸÀÔÀ¸·Î º¯°æÇÒ ÇÊ¿ä°¡ ÀÖÀ» ¶§ »ç¿ëÇÑ´Ù. ±âº» ConversionService´Â ¼ýÀÚ, Ŭ·¡½º, Enum°°Àº ±âº» °´Ã¼ ŸÀÔ¿¡ ´ëÇÑ ÄÁ¹öÅ͸¦ µî·ÏÇÑ´Ù.

9.4.7.2. expression-parser

expression-parser ¼Ó¼ºÀ» »ç¿ëÇÏ¿© À¥ ÇÃ·Î¿ì ½Ã½ºÅÛÀÌ »ç¿ëÇÒ ExpressionParser¸¦ Ä¿½ºÅ͸¶ÀÌ¡ÇÒ ¼ö ÀÖ´Ù. ±âº» ExpressionParser´Â Ŭ·¡½ºÆнº¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Ù¸é Unified ELÀ» »ç¿ëÇÏ°í ±×·¸Áö ¾Ê´Ù¸é OGNLÀ» »ç¿ëÇÑ´Ù.

9.4.7.3. view-factory-creator

view-factory-creator ¼Ó¼ºÀ» »ç¿ëÇÏ¿© À¥ ÇÃ·Î¿ì ½Ã½ºÅÛÀÌ »ç¿ëÇÒ ViewFactoryCreator¸¦ Ä¿½ºÅ͹ÌÀÌ¡ ÇÒ ¼ö ÀÖ´Ù. ±âº» ViewFactoryCreator´Â JSP, Velocity, Freemarker¸¦ ·£´õ¸µ ÇÒ ¼ö ÀÖ´Â ½ºÇÁ¸µ MVC ViewFactory¸¦ »ý¼ºÇÑ´Ù.

¼³Á¤ °¡´ÉÇÑ ¼³Á¤Àº development´Ù. ÀÌ ¼³Á¤Àº ÇÃ·Î¿ì »ý¼º °úÁ¤ Áß¿¡ Àû¿ëÇÒ Àü¿ª ¼³Á¤ ¼Ó¼ºÀÌ´Ù.

9.4.7.4. development

Ç÷ο츦 °³¹ß ¸ðµå·Î º¯°æÇÏ·Á¸é ÀÌ°ÍÀ» true·Î ¼³Á¤Ç϶ó. °³¹ß ¸ðµå´Â ¸Þ½ÃÁö ¹øµé °°Àº µ¶¸³ÀûÀÎ ÇÃ·Î¿ì ¸®¼Ò½º º¯°æÀ» Æ÷ÇÔÇÏ¿© Ç÷οì Á¤ÀÇ º¯°æ ÇÖ-¸±·ÎµùÀ» º¯°æÇÑ´Ù. 

9.5. flow-executor ¿É¼Ç

À̹ø Àå¿¡¼­´Â flow-executor ¼³Á¤ ¿É¼ÇÀ» »ìÆ캻´Ù.

9.5.1. ÇÃ·Î¿ì ½ÇÇà ¸®½º³Ê ºÎÂøÇϱâ

flow-execution-listeners ¿¤¸®¸ÕƲ¸£ »ç¿ëÇÏ¿© ÇÃ·Î¿ì ½ÇÇà »ý¸íÁֱ⠸®½º³Ê¸¦ µî·ÏÇÑ´Ù.

<flow-execution-listeners>
    <listener ref="securityListener"/>
    <listener ref="persistenceListener"/>
</flow-execution-listeners>
            
ƯÁ¤ Ç÷ο츸 °üÂûÇÒ ¸®½º³Ê¸¦ ¼³Á¤ÇÒ ¼öµµ ÀÖ´Ù.

<listener ref="securityListener" criteria="securedFlow1,securedFlow2"/>
            

9.5.2. FlowExecution ¿µ¼Ó¼º Æ©´×Çϱâ

flow-execution-repository ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ÇÃ·Î¿ì ½ÇÇà ¿µ¼Ó¼º ¼³Á¤À» Æ©´×ÇÑ´Ù.

<flow-execution-repository max-executions="5" max-execution-snapshots="30" />
            
9.5.2.1. max-executions

max-executions ¼Ó¼ºÀ» ¼³Á¤ÇÏ¿© »ç¿ëÀÚ ¼¼¼Ç´ç »ý¼ºÇÒ ¼ö ÀÖ´Â ÇÃ·Î¿ì ½ÇÇà ¼ö »óÇѼ±À» ¼³Á¤ÇÑ´Ù.

9.5.2.2. max-execution-snapshots

max-execution-snapshots ¼Ó¼ºÀ» ¼³Á¤ÇÏ¿© ÇÃ·Î¿ì ½ÇÇà´ç °¡Áú ¼ö ÀÖ´Â È÷½ºÅ丮 ½º³À¼¦ ¼ö »óÇѼ±À» Á¤ÇÒ ¼ö ÀÖ´Ù. ½º³À¼¦À» ¸øÂï°Ô ÇÏ·Á¸é ÀÌ °ªÀ» 0À¸·Î ¼³Á¤Ç϶ó. ¹«ÇÑ´ë·Î ½º³À¼¦À» ÂïÀ¸·Á¸é ÀÌ °ªÀ» -1·Î ¼³Á¤Ç϶ó.
½Å°í

'Spring Web Flow > Chapter 9' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 9Àå ½Ã½ºÅÛ ¼³Á¤  (0)2009.02.18
top

SWF 8Àå ÇÃ·Î¿ì »ó¼Ó



8.1. °³¿ä

ÇÃ·Î¿ì »ó¼ÓÀº ÇÑ Ç÷ο찡 ´Ù¸¥ ÇÃ·Î¿ì ¼³Á¤À» »ó¼ÓÇÒ ¼ö ÀÖ°ÔÇÑ´Ù. »ó¼ÓÀº Ç÷οì¿Í ½ºÅ×ÀÌÆ® ¼öÁØ¿¡¼­ ¸ðµÎ ¹ß»ýÇÒ ¼ö ÀÖ´Ù. °¡Àå ÈçÇÑ À¯ÁîÄÉÀ̽º´Â »óÀ§ Ç÷οì·Î Àü¿ªÀûÀÎ Æ®·£Áö¼Ç°ú ¿¹¿Ü Çڵ鷯¸¦ Á¤ÀÇÇÏ°í ÇÏÀ§ Ç÷οì·Î ±× ¼³Á¤À» »ó¼Ó¹Þ´Â °ÍÀÌ´Ù.

»óÀ§ Ç÷ο츦 ãÀ¸·Á¸é ´Ù¸¥ Ç÷οìµéó·³ flow-registry¿¡ Ãß°¡ÇØ¾ß µÈ´Ù.

8.2. ÇÃ·Î¿ì »ó¼ÓÀº ÀÚ¹Ù »ó¼Ó°ú ºñ½ÁÇÑ°¡?

»óÀ§¿¡ Á¤ÀÇÇÑ ¿ä¼Ò¸¦ ÇÏÀ§¿¡¼­ Á¢±ÙÇÒ ¼ö ÀÖ´Ù´Â Ãø¸é¿¡¼­´Â ÀÚ¹Ù »ó¼Ó°ú ÇÃ·Î¿ì »ó¼ÓÀÌ ºñ½ÁÇÏ´Ù. ÇÏÁö¸¸ ÁÖ¿ä Â÷ÀÌÁ¡ÀÌ ÀÖ´Ù.

ÇÏÀ§ Ç÷οì´Â »óÀ§ Ç÷οìÀÇ ¿ä¼Ò¸¦ ÀçÁ¤ÀÇ ÇÒ ¼ö ¾ø´Ù. »óÀ§¿Í ÇÏÀ§ Ç÷ο쿡 ÀÖ´Â °°Àº ¿ä¼Ò´Â º´ÇÕ(merge)µÈ´Ù. »óÀ§ Ç÷ο쿡¸¸ ÀÖ´Â ¿ä¼Ò´Â ÇÏÀ§ Ç÷ο쿡 Ãß°¡µÈ´Ù.

ÇÏÀ§ Ç÷οì´Â ¿©·¯ »óÀ§ Ç÷ο츦 »ó¼Ó¹ÞÀ» ¼ö ÀÖ´Ù. ÀÚ¹Ù »ó¼ÓÀº ´ÜÀÏ Å¬·¡½º·Î Á¦ÇѵȴÙ.

8.3. ÇÃ·Î¿ì »ó¼Ó ŸÀÔ

8.3.1. ÇÃ·Î¿ì ¼öÁØ »ó¼Ó

ÇÃ·Î¿ì ¼öÁØ »ó¼ÓÀº flow ¿¤¸®¸ÕÆ®ÀÇ parent ¼Ó¼ºÀ¸·Î Á¤ÀÇÇÑ´Ù. ÀÌ ¼Ó¼ºÀº ÄÞ¸¶·Î ±¸ºÐÇÑ »ó¼Ó¹ÞÀ» ÇÃ·Î¿ì ½Äº°ÀÚ ¸ñ·ÏÀ» ¸í½ÃÇÑ´Ù. ÇÏÀ§ ÇÁ·Î¿ì´Â ¸ñ·Ï¿¡ ¸í½ÃµÈ ¼ø¼­´ë·Î °¢°¢ÀÇ »óÀ§ Ç÷ο츦 »ó¼Ó ¹Þ´Â´Ù. ù ¹ø° »ó¼ÓÀ¸·Î »óÀ§ Ç÷ο쿡 ÀÖ´Â ¿ä¼Ò¿Í ³»¿ëÀ» Ãß°¡ÇÏ°í ³ª¸é ±×°ÍÀ» ´Ù½Ã ÇÏÀ§ Ç÷οì·Î °£ÁÖÇÏ°í ±× ´ÙÀ½ »óÀ§ ÇÁ·Î¿ì¸¦ »ó¼Ó ¹Þ´Â´Ù. ±×·±½ÄÀ¸·Î °è¼Ó À̾îÁø´Ù.

<flow parent="common-transitions, common-states">

8.3.2. ½ºÅ×ÀÌÆ® ¼öÁØ »ó¼Ó

½ºÅ×ÀÌÆ® ¼öÁØ »ó¼ÓÀº ÇÃ·Î¿ì ¼öÁØ »ó¼Ó°ú ºñ½ÁÇÏ´Ù. À¯ÀÏÇÑ Â÷ÀÌÁ¡Àº Ç÷οì Àüü°¡ ¾Æ´Ï¶ó ¿ÀÁ÷ ÇØ´ç ½ºÅ×ÀÌÆ® Çϳª¸¸ »óÀ§·Î ºÎÅÍ »ó¼Ó ¹Þ´Â´Ù.

ÇÃ·Î¿ì »ó¼Ó°ú ´Þ¸® ¿ÀÁ÷ ÇϳªÀÇ »óÀ§¸¸ Çã¿ëÇÑ´Ù. ¶ÇÇÑ »ó¼Ó¹ÞÀ» ÇÃ·Î¿ì ½ºÅ×ÀÌÆ®ÀÇ ½Äº°ÀÚ°¡ ¹Ýµå½Ã Á¤ÀǵǾî ÀÖ¾î¾ß ÇÑ´Ù. Ç÷οì¿Í ½ºÅ×ÀÌÆ® ½Äº°ÀÚ´Â #·Î ±¸ºÐÇÑ´Ù.

»óÀ§¿Í ÇÏÀ§ ½ºÅ×ÀÌÆ®´Â ¹Ýµå½Ã °°Àº ŸÀÔÀ̾î¾ß ÇÑ´Ù. ¿¹¸¦ µé¾î view-state´Â ent-state¸¦ »ó¼Ó¹ÞÀ» ¼ö ¾ø´Ù. ¿ÀÁ÷ view-state¸¸ »ó¼Ó¹ÞÀ» ¼ö ÀÖ´Ù.

<view-state id="child-state" parent="parent-flow#parent-view-state">
            
8.4. Ãß»ó Ç÷οì

Á¾Á¾ »óÀ§ Ç÷οì´Â Á÷Á¢ È£ÃâÇÏÁö ¾Êµµ·Ï ¼³°èÇÑ´Ù. ±×·± Ç÷ο츦 ½ÇÇàÇÏÁö ¸øÇϵµ·Ï abstract·Î ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. ¸¸¾à Ãß»ó Ç÷ο츦 ½ÇÇàÇÏ·Á°í Çϸé FlowBuilderException°¡ ¹ß»ýÇÑ´Ù.

<flow abstract="true">

8.5. »ó¼Ó ¾Ë°í¸®Áò

ÇÏÀ§ Ç÷ο찡 »óÀ§ Ç÷ο츦 »ó¼ÓÇÒ ¶§ ¹ß»ýÇÏ´Â ±âº»ÀûÀÎ ÀÏÀº »óÀ§¿Í ÇÏÀ§ Ç÷ο츦 º´ÇÕÇÏ¿© »õ·Î¿î Ç÷ο츦 ¸¸µå´Â °ÍÀÌ´Ù. À¥ Ç÷οì Á¤ÀÇ ¾ð¾î¿¡´Â °¢°¢ÀÇ ¿¤¸®¸ÕÆ®¿¡ ´ëÇØ ¾î¶»°Ô º´ÇÕÇÒ °ÍÀΰ¡¿¡ ´ëÇÑ ±ÔÄ¢ÀÌ ÀÖ´Ù.

¿¤¸®¸ÕÆ®¿¡´Â µÎ Á¾·ù°¡ ÀÖ´Ù. º´ÇÕ °¡´ÉÇÑ °Í(mergeable)°ú º´ÇÕÀÌ °¡´ÉÇÏÁö ¾ÊÀº °Í(non-mergeableÀÌ ÀÖ´Ù. º´ÇÕ°¡´ÉÇÑ ¿¤¸®¸ÕÆ®´Â ¸¸¾à ¿¤¸®¸ÕÆ®°¡ °°´Ù¸é º´ÇÕÀ» ½ÃµµÇÑ´Ù. º´ÇÕÀÌ °¡´ÉÇÏÁö ¾ÊÀº ¿¤¸®¸ÕÆ®´Â Ç×»ó ÃÖÁ¾ Ç÷ο쿡 Á÷Á¢ Æ÷ÇԵȴÙ. º´ÇÕ °úÁ¤ Áß¿¡ ¼öÁ¤ÇÏÁö ¾Ê´Â´Ù.

³ëÆ®
»óÀ§ Ç÷ο쿡ÀÖ´Â ¿ÜºÎ ¸®¼Ò½º °æ·Î´Â Àý´ë °æ·Î¿©¾ß ÇÑ´Ù. »ó´ë °æ·Î´Â µÎ Ç÷ο츦 º´ÇÕÇÒ ¶§ »óÀ§ Ç÷οì¿Í ÇÏÀ§ Ç÷ο찡 À§Ä¡ÇÑ µð·ºÅ丮°¡ ´Ù¸£¸é ±úÁú ¼ö ÀÖ´Ù. ÀÏ¹Ý º´ÇÕÇϸé, »óÀ§ Ç÷ο쿡 ÀÖ´ø ¸ðµç »ó´ë °æ·Î´Â ÇÏÀ§ ÇÃ·Î¿ì ±âÁØÀ¸·Î ¹Ù²ï´Ù.

8.5.1. º´ÇÕ °¡´ÉÇÑ ¿¤¸®¸ÕÆ®

¸¸¾à °°Àº ŸÀÔÀÇ ¿¤¸®¸ÕÆ®°í ÀÔ·ÂÇÑ ¼Ó¼ºÀÌ °°´Ù¸é »óÀ§ ¿¤¸®¸ÕÆ®ÀÇ ³»¿ëÀ» ÇÏÀ§ ¿¤¸®¸ÕÆ®·Î º´ÇÕÇÑ´Ù. º´ÇÕ ¾Ë°í¸®ÁòÀº °è¼ÓÇؼ­ º´ÇÕÇÏ´Â »óÀ§¿Í ÇÏÀ§ÀÇ ¼­ºê ¿¤¸®¸ÕÆ®¸¦ °¢°¢ º´ÇÕÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é »óÀ§ Ç÷οìÀÇ ¿¤¸®¸ÕÆ®¸¦ ÇÏÀ§ Ç÷ο쿡 »õ·Î¿î ¿¤¸®¸ÕÆ®·Î Ãß°¡ÇÑ´Ù.

´ëºÎºÐÀÇ °æ¿ì »óÀ§ ÇÁ·Î¿ì?l ¿¤¸®¸ÕÆ®°¡ ÇÏÀ§ ÇÃ·Î¿ì ¿¤¸®¸ÕÆ®¿¡ Ãß°¡µÈ´Ù. ÀÌ ±ÔÄ¢¿¡ ¿¹¿Ü·Î´Â ½ÃÀÛÇÒ ¶§ Ãß°¡ µÉ ¾×¼Ç ¿¤¸®¸ÕÆ®(evaluate, render, set)°¡ ÀÖ´Ù. »óÀ§ ¾×¼ÇÀÇ °á°ú¸¦ ÇÏÀ§ ¾×¼Ç °á°ú·Î »ç¿ëÇÏ°Ô ÇÑ´Ù.

º´ÇÕÀÌ °¡´ÉÇÑ ¿¤¸®¸ÕÆ®´Â ´ÙÀ½°ú °°´Ù.
  • action-state: id
  • attribute: name
  • decision-state: id
  • end-state: id
  • flow: Ç×»ó º´ÇÕ
  • if: test
  • on-end: Ç×»ó º´ÇÕ
  • on-entry: Ç×»ó º´ÇÕ
  • on-exit: Ç×»ó º´ÇÕ
  • on-render: Ç×»ó º´ÇÕ
  • on-start: Ç×»ó º´ÇÕ
  • input: name
  • output: name
  • secured: attributes
  • subflow-state: id
  • transition: on and on-exception
  • view-state: id
8.5.2. º´ÇÕ ÇÒ ¼ö ¾ø´Â ¿¤¸®¸ÕÆ®

º´ÇÕÇÒ ¼ö ¾ø´Â ¿¤¸®¸ÕÆ®´Â ´ÙÀ½°ú °°´Ù
  • bean-import
  • evaluate
  • exception-handler
  • persistence-context
  • render
  • set
  • var

½Å°í

'Spring Web Flow > Chapter 8' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 8Àå ÇÃ·Î¿ì »ó¼Ó  (0)2009.02.16
top

SWF 7Àå ÇÃ·Î¿ì º¸¾ÈÇϱâ



7.1 °³¿ä

º¸¾ÈÀº ¸ðµç ¾ÖÇø®ÄÉÀ̼ǿ¡¼­ Áß¿äÇÑ °³³äÀÌ´Ù. ÃÖÁ¾ »ç¿ëÀÚ´Â URLÀ» ÃßÃøÇÏ¿© »çÀÌÆ®ÀÇ ÀÓÀÇ ¿µ¿ª¿¡ Á¢±ÙÇؼ­´Â ¾È µÈ´Ù. Áß¿äÇÑ ºÎºÐÀº ¹Ýµå½Ã ±ÇÇÑÀ» °¡Áö°í ÀÖ´Â ¿äû¸¸ Á¢±ÙÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. ½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼´Â °ËÁõµÈ º¸¾È Ç÷§ÆûÀ¸·Î ¾ÖÇø®ÄÉÀ̼ǿ¡ ¿©·¯ ¼öÁØÀ¸·Î ÅëÇÕÇÒ ¼ö ÀÖ´Ù. À̹ø Àå¿¡¼­´Â ÇÃ·Î¿ì ½ÇÇà º¸¾ÈÀ» ÁýÁßÀûÀ¸·Î »ìÆ캻´Ù.

7.2. Ç÷ο츦 ¾î¶»°Ô º¸¾ÈÇÒ±î?

ÇÃ·Î¿ì ½ÇÇà º¸¾ÈÀº ¼¼ ´Ü°è·Î ÇÑ´Ù.
  • ½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼¸¦ ÀÎÁõ ±ÇÇÑ ±ÔÄ¢À¸·Î ¼³Á¤ÇÑ´Ù.
  • Ç÷οì Á¤ÀÇ¿¡ º¸¾È ±ÔÄ¢À» Á¤ÀÇÇÏ´Â secured ¿¤¸®¸ÕÆ®¸¦ Ãß°¡ÇÑ´Ù.
  • SecurityFlowExecutionListener¸¦ Ãß°¡ÇÏ¿© º¸¾È ±ÔÄ¢À» ó¸®ÇÑ´Ù.
ÀÌ ¸ðµç ´Ü°è¸¦ ¿Ï·áÇØ¾ß ÇÏ¸ç ±×·¸Áö ¾ÊÀ¸¸é º¸¾È ±ÔÄ¢Àº Àû¿ëµÇÁö ¾Ê´Â´Ù.

7.3. secured ¿¤¸®¸ÕÆ®

secured ¿¤¸®¸ÕÆ®´Â ¿ÏÀüÈ÷ µé¾î¿À±â Àü¿¡ ±ÇÇÑ È®ÀÎÀ» Çϵµ·Ï °í¾ÈµÇ¾ú´Ù. º¸¾ÈÇÏ°í ÀÖ´Â ÇÃ·Î¿ì ½ÇÇà ½ºÅ×ÀÌÁö ¸¶´Ù µÎ ¹ø ÀÌ»ó ¹ß»ýÇÏ¸é ¾È µÈ´Ù.

ÇÃ·Î¿ì ½ÇÇà¿¡¼­ ¼¼ ´Ü°è¸¦ º¸¾ÈÇÒ ¼ö ÀÖ´Ù. flow, state, transitionÀÌ´Ù. °¢°¢¿¡¼­ secured ¿¤¸®¸ÕÆ®ÀÇ Àǹ̴ ¸ðµÎ µ¿ÀÏÇÏ´Ù. secured ¿¤¸®¸ÕÆ®´Â ÀÚ½ÅÀÌ º¸¾ÈÇÏ´Â ¿¤¸®¸ÕÆ® ¾È¿¡ À§Ä¡ÇÑ´Ù. ¿¹¸¦ µé¾î state¸¦ º¸¾ÈÇÏ·Á¸é ÇØ´ç state ³»ºÎ¿¡ secured ¿¤¸®¸ÕÆ®¸¦ Ãß°¡ÇÏ¸é µÈ´Ù.

<view-state id="secured-view">
    <secured attributes="ROLE_USER" />
    ...
</view-state>
        
7.3.1. º¸¾È ¼Ó¼º

attributes ¼Ó¼ºÀº ÄÞ¹Ù·Î ±¸ºÐÇÑ ½ºÇÁ¸µ ½ÃÅ¥¸®ºñ ±ÇÇÑ ¼Ó¼º ¸ñ·ÏÀÌ´Ù. º¸Åë ƯÁ¤ º¸¾È ·Ñ(role)À» ¸í½ÃÇÑ´Ù. ½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼ Á¢±Ù °áÁ¤ ¸Å´ÏÀú(access decision manager)¿¡ ÀÇÇØ ÀÌ ¼Ó¼º¿¡ ÀÔ·ÂÇÑ °ª°ú »ç¿ëÀÚ°¡ °¡Áö°í ÀÖ´Â °ªÀ» ºñ±³ÇÑ´Ù.

<secured attributes="ROLE_USER" />
            
±âº»ÀûÀ¸·Î, ·Ñ ±â¹Ý Á¢±Ù °áÁ¤ °ü¸®ÀÚ¸¦ »ç¿ëÇÏ¿© »ç¿ëÀÚ°¡ Á¢±ÙÇÒ ¼ö ÀÖ´ÂÁö È®ÀÎÇÑ´Ù. ¸¸¾à ¾ÖÇø®ÄÉÀ̼ÇÀÌ ±ÇÇÑ ·êÀ» »ç¿ëÇÏÁö ¾Ê´Â´Ù¸é ÀÌ ºÎºÐÀ» ¿À¹ö¶óÀ̵ùÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.

7.3.2. ¸ÅĪ ŸÀÔ

°¡¿ëÇÑ ¸ÅĪ ŸÀÔ¿¡´Â µÎ °¡Áö°¡ ÀÖ´Ù. any¿Í allÀÌ ÀÖ´Ù. Any´Â ÇÊ¿äÇÑ º¸¾È ¼Ó¼º Áß¿¡ »ç¿ëÀÚ°¡ Çϳª¶óµµ °¡Áö°í ÀÖ´Ù¸é Á¢±ÙÀ» Çã¿ëÇÑ´Ù. AllÀº »ç¿ëÀÚ°¡ ¸í½ÃµÇ¾î ÀÖ´Â º¸¾È ¼Ó¼ºÀ» ¸ðµÎ °¡Áö°í ÀÖ´Â °æ¿ì¿¡ Á¢±ÙÀ» Çã¿ëÇÑ´Ù.

<secured attributes="ROLE_USER, ROLE_ANONYMOUS" match="any" />
    
ÀÌ ¼Ó¼ºÀº Çʼö°¡ ¾Æ´Ï´Ù. Á¤ÀÇÇÏÁö ¾ÊÀ¸¸é ±âº» °ªÀº any´Ù.

The match attribute will only be respected if the default access decision manager is used. 

7.4. SecurityFlowExecutionListener

º¸¾È ±ÔÄ¢À» Æú·Î¿ì ³»ºÎ¿¡ Á¤ÀÇÇÏ´Â °Í ¸¸À¸·Î´Â ÇÃ·Î¿ì ½ÇÇàÀ» º¸È£ÇÏÁö ¸øÇÑ´Ù. SecurityFlowExecutionListener°¡ À¥ ÇÃ·Î¿ì ¼³Á¤¿¡ Á¤ÀǵǾî ÀÖ¾î¾ß ÇÃ·Î¿ì ½ÇÇà±â(executor)¿¡ Àû¿ëµÈ´Ù.

<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
    <webflow:flow-execution-listeners>
        <webflow:listener ref="securityFlowExecutionListener" />
    </webflow:flow-execution-listeners>
</webflow:flow-executor>

<bean id="securityFlowExecutionListener" 
      class="org.springframework.webflow.security.SecurityFlowExecutionListener" />

¾ÖÇø®ÄÉÀ̼ÇÀÇ Æ¯Á¤ ºÎºÐ¿¡¼­ ¸¸¾à Á¢±ÙÀÌ °ÅºÎµÇ¸é AccessDeniedException¸¦ ´øÁø´Ù. ÀÌ ¿¹¿Ü´Â ³ªÁß¿¡ ½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼°¡ ó¸®ÇÏ°í »ç¿ëÀÚ¿¡°Ô ±ÇÇÑÀ» ¿äûÇϴµ¥ »ç¿ëµÈ´Ù. ÀÌ ¿¹¿Ü´Â ¿¹¿Ü ½ºÅÃÀ» ¹«Á¦ÇÑÀ¸·Î ¿Ã¶ó°¥ ¼ö ÀÖ´Ù´Â °ÍÀÌ Áß¿äÇѵ¥ ÀÌ·¸°Ô ÇÏÁö ¾ÊÀ¸¸é ÃÖÁ¾ »ç¿ëÀÚ´Â ±ÇÇÑÀ» ¿äûÇÒ ¼ö ¾ø´Ù.

7.4.1. Ä¿½ºÅÒ Á¢±Ù °áÁ¤ °ü¸®ÀÚ

¸¸¾à ¾ÖÇø®ÄÉÀ̼ÇÀÌ ·Ñ ±â¹ÝÀÌ ¾Æ´Ñ ±ÇÇÑÀ» »ç¿ëÁßÀ̶ó¸é Ä¿½ºÅÒ AccessDecisionManager¸¦ ¼³Á¤ÇÒ ÇÊ¿ä°¡ ÀÖ´Ù. ±âº» °áÁ¤ °ü¸®ÀÚ¸¦ ¿À¹ö¶óÀ̵å ÇÏ°í ½ÃÅ¥¸®Æ¼ ¸®½º³ÊÀÇ accessDecisionManager ¼Ó¼º¿¡ ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. ½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼ ·¹ÆÛ·±½º ¹®¼­¸¦ ÂüÁ¶ÇÏ¿© °áÁ¤ °ü¸®ÀÚ¿¡ ´ëÇØ ÀÚ¼¼È÷ »ìÆ캸±â ¹Ù¶õ´Ù.

<bean id="securityFlowExecutionListener"
      class="org.springframework.webflow.security.SecurityFlowExecutionListener">
    <property name="accessDecisionManager" ref="myCustomAccessDecisionManager" />
</bean>

7.5. ½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼ ¼³Á¤Çϱâ

½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼´Â ÀÏ°üµÈ ¼³Á¤ ¿É¼ÇÀ» Á¦°øÇÑ´Ù. ¸ðµç ¾ÖÇø®ÄÉÀ̼ǰú ȯ°æÀÌ ÀڽŸ¸ÀÇ º¸¾È ¿ä±¸»çÇ×À» °¡Áö°í ÀÖ±â ??¹®¿¡ ½ºÇÁ¸µ ½ÃÅ¥¸®Æ¼ ·¹ÆÛ·±½º ¹®¼­¿¡¼­ °¡¿ëÇÑ ¿É¼ÇÀ» ÀÍÈ÷´Â°ÍÀÌ ÁÁ´Ù.

 7.5.1. ½ºÇÁ¸µ ¼³Á¤

½ºÇÁ¸µ ¼³Á¤Àº (º¸È£ÇÏ´Â URL°ú ·Î±×ÀÎ/·Î±×¾Æ¿ô ¹æ¹ý °°Àº) http °ü·Ã ¼³Á¤°ú authentication-provider¸¦ ¼³Á¤ÇÑ´Ù. ¿¹Á¦ ¾ÖÇø®ÄÉÀ̼ǿ¡ ·ÎÄà ÀÎÁõ °ø±ÞÀÚ¸¦ ¼³Á¤Çß´Ù.

<security:http auto-config="true">
    <security:form-login login-page="/spring/login" 
                         login-processing-url="/spring/loginProcess"
                         default-target-url="/spring/main" 
                         authentication-failure-url="/spring/login?login_error=1" />  
    <security:logout logout-url="/spring/logout" logout-success-url="/spring/logout-success" />
</security:http>

<security:authentication-provider>
    <security:password-encoder hash="md5" />
    <security:user-service>
        <security:user name="keith" password="417c7382b16c395bc25b5da1398cf076" 
                       authorities="ROLE_USER,ROLE_SUPERVISOR" />
        <security:user name="erwin" password="12430911a8af075c6f41c6976af22b09" 
                       authorities="ROLE_USER,ROLE_SUPERVISOR" />
        <security:user name="jeremy" password="57c6cbff0d421449be820763f03139eb" 
                       authorities="ROLE_USER" />
        <security:user name="scott" password="942f2339bf50796de535a384f0d1af3e" 
                       authorities="ROLE_USER" />
    </security:user-service>
</security:authentication-provider>
            
7.5.2. web.xml ¼³Á¤

web.xml ÆÄÀÏ¿¡¼­ filter´Â ¸ðµç ¿äûÀ» °¡·Îäµµ·Ï Á¤ÀÇÇß´Ù. ÀÌ ÇÊÅÍ´Â ·Î±×ÀÎ/·Î±×¾Æ¿ô ¿äûÀ» ´Ù·ç°í ÀûÀýÇÏ°Ô Ã³¸®ÇÒ °ÍÀÌ´Ù. ¶ÇÇÑ AccesDeniedExceptions ¿¹¿Ü¸¦ Àâ¾Æ¼­ »ç¿ëÀÚ¸¦ ·Î±×ÀÎ ÆäÀÌÁö·Î ¸®´ÙÀÌ·ºÆ® ½ÃŲ´Ù.



 
½Å°í

'Spring Web Flow > Chapter 7' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 7Àå ÇÃ·Î¿ì º¸¾ÈÇϱ⠠(0)2009.02.12
top

SWF 6Àå Ç÷ο찡 °ü¸®ÇÏ´Â ¿µ¼Ó¼º



6.1. °³¿ä

´ëºÎºÐÀÇ ¾ÖÇø®ÄÉÀ̼ÇÀº ¿©·¯ ¹æ¹ýÀ¸·Î µ¥ÀÌÅÍ¿¡ Á¢±ÙÇÑ´Ù. ¿©·¯ »ç¿ëÀÚ°¡ °øÀ¯ÇÏ´Â µ¥ÀÌÅ͸¦ ¿©·µÀÌ ¼öÁ¤ÇÑ´Ù. µû¶ó¼­ Æ®·£Àè¼Ç µ¥ÀÌÅÍ Á¢±Ù ¼Ó¼ºÀÌ ÇÊ¿äÇÏ´Ù. °ü°èÇü µ¥ÀÌÅÍ ÁýÇÕÀ» µµ¸ÞÀÎ °´Ã¼·Î º¯ÇüÇÏ¿© ¾ÖÇø®ÄÉÀÌ¼Ç Ã³¸®¸¦ µµ¿ÍÁØ´Ù. À¥ Ç÷οì´Â "Ç÷ο찡 °ü¸®ÇÏ´Â ¿µ¼Ó¼º"(flow managed persistence)À» Á¦°øÇÏ¿© Ç÷ο찡 °´Ã¼ ¿µ¼Ó¼º ¹®¸ÆÀ» ¸¸µé°í, Ä¿¹ÔÇÏ°í, ´ÝÀ» ¼ö ÀÖµµ·Ï ÇÑ´Ù. À¥ Ç÷οì´Â ÇÏÀ̹ö³×ÀÌÆ®¿Í JPA °´Ã¼ ¿µ¼ÓÈ­ ±â¼ú°ú ¿¬µ¿ÇÑ´Ù.

Ç÷οì-°ü¸® ¿µ¼Ó¼º°ú º°µµ·Î PesistenceContext °ü¸®¸¦ ¾ÖÇø®ÄÉÀ̼ÇÀÇ ¼­ºñ½º °èÃþ¿¡¼­ ¿ÏÀüÈ÷ ĸ½¶È­ÇÏ´Â ÆÐÅÏÀÌ ÀÖ´Ù. ÀÌ·± °æ¿ì À¥ °èÃþÀº ¿µ¼ÓÈ­¿¡ °ü¿©ÇÏÁö ¾Ê´Â´Ù. ±× ´ë½Å ¼­ºñ½º °èÃþÀ¸·Î ³äÁְܰųª ¹Ýȯ¹ÞÀº detached object¸¦ °¡Áö°í µ¿ÀÛÇÑ´Ù. À̹ø ÀåÀº Ç÷οì-°ü¸® ¿µ¼Ó¼º¿¡ ÃÊÁ¡À» ¸ÂÃß°í ÀÌ ±â´ÉÀ» ¾ðÁ¦ ¾î¶»°Ô »ç¿ëÇÏ´ÂÁö »ìÆ캸°Ú´Ù.

6.2. FlowScoped PersistenceContext

ÀÌ ÆÐÅÏÀº Ç÷ο찡 ½ÃÀÛÇÒ ¶§ flowScope ¾È¿¡ PersistenceContext¸¦ »ý¼ºÇÑ´ÙÀÌ ÄÁÅؽºÆ®¸¦ »ç¿ëÇÏ¿© ÇÃ·Î¿ì ½ÇÇà Äڵ忡¼­ µ¥ÀÌÅÍ Á¢±ÙÀ» ÇÏ°í ¸¶Áö¸·¿¡ ¿µ¼ÓÈ­ ¿ä¼Ò¿¡ ´ëÇÑ º¯°æÀ» Ä¿¹ÔÇÑ´ÙÀÌ ÆÐÅÏÀº º¯°æ»çÇ× Ä¿¹ÔÀ» ¿ÀÁ÷ ÇÃ·Î¿ì ½ÇÇà ¸¶Áö¸·¿¡¸¸ Çϱ⠶§¹®¿¡ Áß°£ ´Ü°è ÆíÁý µ¶¸³¼ºÀ» Á¦°øÇÑ´ÙÀÌ ÆÐÅÏÀº º¸Åë ³«ÃµÀûÀÎ ?ôÅ·À¸·? ¿©·¯ »ç¿ëÀÚÀÇ µ¿½Ã ¼öÁ¤ ¹«°á¼ºÀ» º¸ÀåÇÑ´ÙÇÃ·Î¿ì °úÁ¤À» ÀÏÁ¤ ½Ã°£À» ³Ñ¾î¼­±îÁö ÀúÀåÇϰųª Àç½ÃÀÛ ÇÏ·Á¸é ÇÃ·Î¿ì »óÅ¿¡ ´ëÇÑ ¿µ¼Ó¼º ÀúÀå¼Ò¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù¸¸¾à ÀúÀå°ú Àç½ÃÀÛ ±â´ÉÀÌ ÇÊ¿ä ¾ø´Ù¸é ÇÃ·Î¿ì »óŸ¦ Ç¥ÁØ HTTP ¼¼¼Ç-±â¹ÝÀ¸·Î ÀúÀåÇصµ ÃæºÐÇÏ´Ù±×·± °æ¿ì Ä¿¹Ô ÀÌÀü¿¡ ¼¼¼Ç ¸¸·á³ª Á¾°¡ ¹ß»ýÇÏ¸é º¯°æ »çÇ×µéÀ» ÀÒ¾î¹ö¸®°Ô µÈ´Ù.

 

FlowScoped PersistenceContext ÆÐÅÏÀ» »ç¿ëÇÏ·Á¸é ÇØ´ç Ç÷ο츦 persistence-context·Î ¼³Á¤Ç϶ó.

 

<?xml version="1.0" encoding="UTF-8"?>

<flow xmlns="http://www.springframework.org/schema/webflow"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://www.springframework.org/schema/webflow

                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

 

    <persistence-context />

 

</flow>

 

±×·± ´ÙÀ½ Àû´çÇÑ FlowExecutionListener¸¦ ¼³Á¤ÇÏ¿© ÀÌ ÆÐÅÏÀ» Ç÷ο쿡 Àû¿ëÇ϶󸸾à ÇÏÀ̹ö³×ÀÌÆ®¸¦ »ç¿ëÇÏ°í ÀÖ´Ù¸é HibernateFlowExecutionListener¸¦ µî·ÏÇÏ°í, JPA¸¦ »ç¿ëÇÏ°í ÀÖ´Ù¸é JpaFlowExecutionListener¸¦ µî·ÏÇ϶ó.

 

<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">

    <webflow:flow-execution-listeners>

        <webflow:listener ref="jpaFlowExecutionListener" />

    </webflow:flow-execution-listeners>

</webflow:flow-executor>

 

<bean id="jpaFlowExecutionListener"

      class="org.springframework.webflow.persistence.JpaFlowExecutionListener">

    <constructor-arg ref="entityManagerFactory" />

    <constructor-arg ref="transactionManager" />

</bean>

 

Á¾·á ÁöÁ¡¿¡¼­ Ä¿¹Ô ÇÏ·Á¸é end-state¿¡ commit ¼Ó¼º¿¡ ¸í½ÃÇ϶ó.

 

<end-state id="bookingConfirmed" commit="true" />

 

ÀÌ·¸°ÔÇ÷ο츦 ½ÃÀÛÇÏ¸é ¸®½º³Ê´Â »õ·Î¿î EntiryManager¸¦ flowScope¿¡ ÇÒ´çÇÑ´ÙÀÌ EntityManager´Â persistenceContext º¯¼ö¸¦ »ç¿ëÇÏ¿© ¿©·¯ºÐ ÇÃ·Î¿ì ³»¿¡¼­ ¾îµð¼­µç ÂüÁ¶ÇÒ ¼ö ÀÖ´Ù°Ô´Ù°¡ ½ºÇÁ¸µÀ» »ç¿ëÇÏ´Â ¸ðµç µ¥ÀÌÅÍ Á¢±ÙÀº ÀÚµ¿À¸·Î ÀÌ EntityManager¸¦ »ç¿ëÇÏ°Ô µÉ °ÍÀÌ´Ù±×·± µ¥ÀÌÅÍ Á¢±Ù ÀÛ¾÷Àº Áß°£ ´Ü°è ÆíÁýÀ» µ¶¸³ÀûÀ¸·Î °ü¸®Çϱâ À§ÇØ Ç×»ó Æ®·£Àè¼ÇÀÌ ¾ø°Å³ª  Àбâ-Àü¿ë Æ®·£Àè¼ÇÀ¸·Î ¼öÇàÇÑ´Ù

½Å°í

'Spring Web Flow > Chapter 6' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 6Àå Ç÷ο찡 °ü¸®ÇÏ´Â ¿µ¼Ó¼º  (0)2009.02.11
top

SWF 5Àå ¾×¼Ç ½ÇÇàÇϱâ



5.1. ¼Ò°³

À̹ø Àå¿¡¼­´Â action-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ÇÃ·Î¿ì ³»¿¡¼­ ƯÁ¤ ½ÃÀú¿¡ ¾×¼Ç ½ÇÇàÀ» Á¦¾îÇÏ´Â ¹æ¹ýÀ» »ìÆ캻´Ù. ¶ÇÇÑ decision-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ÇÃ·Î¿ì ¹æÇâÀ» °áÁ¤ÇÏ´Â ¹æ¹ýµµ »ìÆ캻´Ù. ¸¶Áö¸·À¸·Î ÇÃ·Î¿ì ³»¿¡¼­ °¡´ÉÇÑ ´Ù¾çÇÑ ÁöÁ¡¿¡¼­ ¾×¼ÇÀ» È£ÃâÇÏ´Â ¿¹Á¦¸¦ ´Ù·ê °ÍÀÌ´Ù.

5.2. ¾×¼Ç ½ºÅ×ÀÌÆ® Á¤ÀÇÇϱâ

¾×¼ÇÀ» È£ÃâÇÏ°í ½ÍÀ» ¶§ action-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¸é ¾×¼ÇÀÇ °á°ú¿¡ ±â¹ÝÇÏ¿© ´Ù¸¥ »óÅ·ΠÀüÀÌÇÑ´Ù.

<action-state id="moreAnswersNeeded">
    <evaluate expression="interview.moreAnswersNeeded()" />
    <transition on="yes" to="answerQuestions" />
    <transition on="no" to="finish" />
</action-state>

À§ÀÇ action-state¸¦ »ç¿ëÇÏ¿© ÀÎÅͺ並 ¿Ï¼ºÇϴµ¥ ´õ ¸¹Àº Áú¹®ÀÌ ÇÊ¿äÇÑÁö È®ÀÎÇÏ´Â ÀÎÅͺä Ç÷οì´Â ´ÙÀ½°ú °°´Ù.

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <on-start>
        <evaluate expression="interviewFactory.createInterview()" result="flowScope.interview" />
    </on-start>

    <view-state id="answerQuestions" model="questionSet">
        <on-entry>
            <evaluate expression="interview.getNextQuestionSet()" result="viewScope.questionSet" />
        </on-entry>
        <transition on="submitAnswers" to="moreAnswersNeeded">
            <evaluate expression="interview.recordAnswers(questionSet)" />
        </transition>
    </view-state>
    
    <action-state id="moreAnswersNeeded">
        <evaluate expression="interview.moreAnswersNeeded()" />
        <transition on="yes" to="answerQuestions" />
        <transition on="no" to="finish" />
    </action-state>

    <end-state id="finish" />
    
</flow>

5.3. ÀÇ»ç°áÁ¤ »óÅ Á¤ÀÇÇϱâ

decision-state ¿¤¸®¸ÕÆ®¸¦ action-state ´ë½Å »ç¿ëÇÏ¿© Æí¸®ÇÑ if/else ¹®¹ýÀ» »ç¿ëÇÏ¿© °æ·Î °áÁ¤À» ÇÒ ¼ö ÀÖ´Ù. ¾Æ·¡ ¿¹Á¦´Â À§¿¡¼­ ºÃ´ø moreAnswersNeeded »óŸ¦ action-state ´ë½Å ÀÇ»ç°áÁ¤ »óÅ·Π±¸ÇöÇÑ °ÍÀÌ´Ù.

<decision-state id="moreAnswersNeeded">
    <if test="interview.moreAnswersNeeded()" then="answerQuestions" else="finish" />
</decision-state>
            
5.4. ¾×¼Ç °á°ú À̺¥Æ® ¸ÊÇÎ

¾×¼ÇÀº º¸Åë ÀÏ¹Ý ÀÚ¹Ù °´Ã¼ÀÇ ¸Å¼­µå¸¦ È£ÃâÇÑ´Ù. action-state¿Í decision-state¿¡¼­ È£ÃâÇÑ ¸Å¼­µå´Â ºä »óŸ¦ ÀüÀÌÇÒ ¶§ »ç¿ëÇÒ °ªÀ» ¹ÝȯÇÑ´Ù. ÀüÀÌ´Â À̺¥Æ®¿¡ ÀÇÇØ ¹ß»ýÇϱ⠶§¹®¿¡ ¸Å¼­µåÀÇ ¹Ýȯ°ªÀº ¹Ýµå½Ã ¸ÕÀú Event °´Ã¼·Î ¸ÊÇεǾî¾ß ÇÑ´Ù. ´ÙÀ½ Ç¥´Â ÈçÇÑ ¹Ýȯ°ªÀ» ¾î¶»°Ô Event °´Ã¼·Î ¸ÊÇÎÇÏ´ÂÁö º¸¿©ÁØ´Ù.

Ç¥ 5.1. ¾×¼Ç ¸Å¼­µå ¹Ýȯ °ªÀ» À̺¥Æ® id·Î ¸ÊÇÎÇϱâ

|| ¸Å¼­µå ¹Ýȯ °ª || ¸ÊÇÎÇÑ À̺¥Æ® ½Äº°ÀÚ Ç¥Çö½Ä ||
| java.lang.String | ¹®ÀÚ¿­ °ª |
| java.lang.Boolean | (true ¸é) yes, (false ¸é) no |
| java.lang.Enum | Enum À̸§ |
| ±×¹Û¿¡ ´Ù¸¥ ŸÀÔ | success |

¾Æ·¡ ¿¹Á¦ÀÇ ¾×¼Ç ½ºÅ×ÀÌÆ®¿¡¼­ ¸Å¼­µå°¡ boolean °ªÀ» ¹ÝȯÇÑ´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù.

<action-state id="moreAnswersNeeded">
    <evaluate expression="interview.moreAnswersNeeded()" />
    <transition on="yes" to="answerQuestions" />
    <transition on="no" to="finish" />
</action-state>
        
5.5. ¾×¼Ç ±¸Çö

¾×¼Ç Äڵ带 POJO ·ÎÁ÷À¸·Î ÀÛ¼ºÇÏ´Â °ÍÀÌ °¡Àå ÀϹÝÀûÀÌÁö¸¸, ´Ù¸¥ ¾×¼Ç ±¸Çö ¹æ¹ýµµ ÀÖ´Ù. °¡²ûÀº ¾×¼Ç Äڵ忡¼­ Ç÷οì ÄÁÅؽºÆ®¿¡ Á¢¼ÓÇÒ ÇÊ¿ä°¡ ÀÖÀ» °ÍÀÌ´Ù. ÀÌ ¶§ POJO¸¦ È£ÃâÇÏ°í °Å±â¿¡ flowRequestContext¸¦ EL º¯¼ö·Î ³Ñ°ÜÁÙ ¼ö ÀÖ´Ù. ¶Ç´Â, Action ÀÎÅÍÆäÀ̽º¸¦ ±¸ÇöÇϰųª MultiAction ±âº» Ŭ·¡½º¸¦ »ó¼Ó¹ÞÀ» ¼öµµ ÀÖ´Ù. ÀÌ·¯ÇÑ ´ë¾ÈµéÀÌ º¸´Ù °­ÇÑ Å¸ÀÔ ¾ÈÀü¼ºÀ» Á¦°øÇÏ¿© ¿©·¯ºÐÀÇ ¾×¼Ç ÄÚµå¿Í ½ºÇÁ¸µ À¥ Ç÷οì API »çÀ̸¦ ÀÚ¿¬½º·´°Ô ¿¬°áÇØÁØ´Ù. ¾Æ·¡¿¡¼­ ÀÌµé °¢°¢¿¡ ´ëÇÑ ¿¹Á¦¸¦ »ìÆ캸ÀÚ.

5.5.1. POJO ¾×¼Ç È£ÃâÇϱâ

<evaluate expression="pojoAction.method(flowRequestContext)" />    
            

public class PojoAction {
    public String method(RequestContext context) {
        ... 
    }
}
            
5.5.2. Ä¿½ºÅÒ Action ±¸Çöü È£ÃâÇϱâ

<evaluate expression="customAction" />    
            

public class CustomAction implements Action {
    public Event execute(RequestContext context) {
        ... 
    }
}
            
5.5.3. MultiAction ±¸Çöü È£ÃâÇϱâ

<evaluate expression="multiAction.actionMethod1" />
    
            

public class CustomMultiAction extends MultiAction {
    public Event actionMethod1(RequestContext context) {
        ... 
    }

    public Event actionMethod2(RequestContext context) {
        ... 
    }

    ...
}
            
5.6. ¾×¼Ç ¿¹¿Ü

¾×¼ÇÀº º¸Åë º¹ÀâÇÑ ºñÁî´Ï½º ·ÎÁ÷À» ĸ½¶È­ÇÑ ¼­ºñ½º¸¦ È£ÃâÇÑ´Ù. ÀÌ·¯ÇÑ ¼­ºñ½º´Â ¾×¼Ç Äڵ尡 ó¸®ÇØ¾ß ÇÒ ºñÁî´Ï½º ¿¡¿Ü¸¦ ´øÁú ¼öµµ ÀÖ´Ù.

5.6.1. ºñÁî´Ï½º ¿¹¿Ü¸¦ POJO ¾×¼Ç¿¡¼­ ó¸®Çϱâ

´Ù¸§ ¿¹Á¦´Â ºñÁî´Ï½º ¿¹¿Ü¸¦ Àâ´Â ¾×¼ÇÀ» È£ÃâÇÏ°í, ¿¡·¯ ¸Þ½ÃÁö¸¦ ÄÁÅؽºÆ®¿¡ Ãß°¡ÇÏ°í, °á°ú À̺¥Æ® ½Äº°ÀÚ¸¦ ¹ÝȯÇÑ´Ù. °á°ú´Â È£ÃâÇÑ Ç÷ο찡 ¹ÝÀÀÇÒ ¼ö ÀÖ´Â Ç÷οì À̺¥Æ®·Î °£ÁÖÇÑ´Ù.

<evaluate expression="bookingAction.makeBooking(booking, flowRequestContext)" />    
            

public class BookingAction {
   public String makeBooking(Booking booking, RequestContext context) {
       try {
           BookingConfirmation confirmation = bookingService.make(booking);
           context.getFlowScope().put("confirmation", confirmation);
           return "success";
       } catch (RoomNotAvailableException e) {
           context.addMessage(new MessageBuilder().error().
               .defaultText("No room is available at this hotel").build());
           return "error";
       }
   }
}
            
5.6.2. ºñÁî´Ï½º ¿¹¿Ü¸¦ MultiActionÀ¸·Î ó¸®Çϱâ

´ÙÀ½ ¿¹Á¦´Â ±â´ÉÀûÀ¸·Î À§¿¡ °Í°ú °°Áö¸¸ POJO ¾×¼ÇÀÌ ¾Æ´Ï¶ó MultiActionÀ¸·Î ±¸ÇöÇß´Ù. MultiActionÀº ${methodName}(RequestContext) ÇüÅÂÀÇ ¾×¼Ç ¸Å¼­µå¸¦ ÇÊ¿ä·Î ÇÏ¸ç °­ÇÑ Å¸ÀÔ ¾ÈÀü¼ºÀ» Á¦°øÇÑ´Ù. ¹Ý¸é POJO ¾×¼¢Àº ´õ ¸¹Àº ÀÚÀ¯¸¦ Á¦°øÇÑ´Ù.

<evaluate expression="bookingAction.makeBooking" />    
            

public class BookingAction extends MultiAction {
   public Event makeBooking(RequestContext context) {
       try {
           Booking booking = (Booking) context.getFlowScope().get("booking");
           BookingConfirmation confirmation = bookingService.make(booking);
           context.getFlowScope().put("confirmation", confirmation);
           return success();
       } catch (RoomNotAvailableException e) {
           context.getMessageContext().addMessage(new MessageBuilder().error().
               .defaultText("No room is available at this hotel").build());
           return error();
       }
   }
}
            
5.7. ±âŸ ¾×¼Ç È£Ãâ ¿¹Á¦

5.7.1. on-start

´ÙÀ½ ¿¹Á¦´Â ¼­ºñ½ºÀÇ ¸Å¼­µå¸¦ È£ÃâÇÏ¿© »õ·Î¿î Booking °´Ã¼¸¦ ¸¸µå´Â ¾×¼ÇÀ» º¸¿©ÁØ´Ù.

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <input name="hotelId" />

    <on-start>
        <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" 
                  result="flowScope.booking" />
    </on-start>

</flow>
    

5.7.2. on-entry

´ÙÀ½ ¿¹Á¦´Â »óÅ ÁøÀÔ ¾×¼ÇÀ¸·Î Ưº°ÇÑ fragments º¯¼ö¸¦ Á¤ÀÇÇÏ¿© view-state°¡ ºäÀÇ ÀϺθ¸ ·£´õ¸µ Çϵµ·Ï ÇÏ°í ÀÖ´Ù.

<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
    <on-entry>
        <render fragments="hotelSearchForm" />
    </on-entry>
</view-state>
            

5.7.3. on-exit

´ÙÀ½ ¿¹Á¦´Â »óÅ Á¾·á(exit) ¾×¼ÇÀ¸·Î ÆíÁýÁßÀÌ´ø ·¹Äڵ忡 ´ëÇÑ ?ôÀ? ÇØÁ¦ÇÏ°í ÀÖ´Ù.

<view-state id="editOrder">
    <on-entry>
        <evaluate expression="orderService.selectForUpdate(orderId, currentUser)"
                  result="viewScope.order" />
    </on-entry>
    <transition on="save" to="finish">
        <evaluate expression="orderService.update(order, currentUser)" />
    </transition>
    <on-exit>
        <evaluate expression="orderService.releaseLock(order, currentUser)" />
    </on-exit>
</view-state>

5.7.4. on-end

´ÙÀ½ ¿¹Á¦´Â À§¿Í °°Àº °´Ã¼ ?ôÅ·À? ÇÃ·Î¿ì ½ÃÀÛ°ú Á¾·á(end) ¾×¼ÇÀ¸·Î ÇÏ´Â °ÍÀ» º¸¿©ÁØ´Ù.

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <input name="orderId" />

    <on-start>
        <evaluate expression="orderService.selectForUpdate(orderId, currentUser)"
                  result="flowScope.order" />
    </on-start>

    <view-state id="editOrder">
        <transition on="save" to="finish">
            <evaluate expression="orderService.update(order, currentUser)" />
        </transition>
    </view-state>

    <on-end>
        <evaluate expression="orderService.releaseLock(order, currentUser)" />
    </on-end>
    
</flow>

5.7.5. on-render

´ÙÀ½ ¿¹Á¦´Â ·£´õ ¾×¼ÇÀ¸·Î ºä¸¦ ·£´õ¸µ Çϱâ Àü¿¡ º¸¿©Á٠ȣÅÚ ¸ñ·ÏÀ» ·ÎµùÇÑ´Ù.

<view-state id="reviewHotels">
    <on-render>
        <evaluate expression="bookingService.findHotels(searchCriteria)"
                  result="viewScope.hotels" result-type="dataModel" />
    </on-render>
    <transition on="select" to="reviewHotel">
        <set name="flowScope.hotel" value="hotels.selectedRow" />
    </transition>
</view-state>
            
5.7.6. on-transition

´ÙÀ½ ¿¹Á¦´Â ÇÏÀ§ÇÃ·Î¿ì °á°ú À̺¥Æ® ¼Ó¼ºÀ» Ä÷º¼Ç¿¡ Ãß°¡ÇÏ´Â Æ®·£Áö¼Ç ¾×¼ÇÀ» º¸¿©ÁØ´Ù.

<subflow-state id="addGuest" subflow="createGuest">
    <transition on="guestCreated" to="reviewBooking">
        <evaluate expression="booking.guestList.add(currentEvent.attributes.newGuest)" />  
    </transition>
</subfow-state>
            
5.7.7. Names actions

´ÙÀ½ ¿¹Á¦´Â ÇϳªÀÇ action-state ³»¿¡¼­ ¾×¼Ç üÀÎÀ» È£ÃâÇÏ´Â ¹æ¹ýÀ» º¸¿©ÁØ´Ù. °¢°¢ÀÇ ¾×¼Ç À̸§Àº ¾×¼Ç °á°ú À̺¥Æ®¿¡ ´ëÇÑ ½Äº°ÀÚ°¡ µÈ´Ù.

<action-state id="doTwoThings">
    <evaluate expression="service.thingOne()">
        <attribute name="name" value="thingOne" />
    </evaluate>
    <evaluate expression="service.thingTwo()">
        <attribute name="name" value="thingTwo" />
    </evaluate>
    <transition on="thingTwo.success" to="showResults" />
</action-state>
        
ÀÌ ¿¹Á¦¿¡¼­, Ç÷οì´Â thingTwo°¡ ¹«»çÈ÷ ¿Ï·áµÇ¸é showResults·Î ÀüÀÌÇÒ °ÍÀÌ´Ù.

½Å°í

'Spring Web Flow > Chapter 5' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 5Àå ¾×¼Ç ½ÇÇàÇϱ⠠(0)2009.01.30
top

SWF 4Àå ºä ·£´õ¸µ



4. ºä ·£´õ¸µ

4.1. ¼Ò°³

À̹ø Àå¿¡¼­´Â view-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© Ç÷ο쿡¼­ ºä¸¦ ·£´õ¸µÇÏ´Â ¹æ¹ýÀ» »ìÆ캻´Ù.

4.2. ºä »óÅ Á¤ÀÇÇϱâ

view-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ºä¸¦ ·£´õ¸µÇÏ°í »ç¿ëÀÚ À̺¥Æ®¸¦ ´ë±âÇÏ´Â ÇÃ·Î¿ì ½ºÅÇÀ» Á¤ÀÇÇÑ´Ù. 

<view-state id="enterBookingDetails">
    <transition on="submit" to="reviewBooking" />
</view-state>
        
±Ô¾à¿¡ µû¶ó, view-state´Â ÀÚ½ÅÀÇ id¸¦ flow°¡ À§Ä¡ÇÑ µð·ºÅ͸®¿¡¼­ ºä ÅÛÇø´À¸·Î ¸ÊÇÎÇÑ´Ù. ¿¹¸¦ µé¾î, ¸¸¾à¿¡ flow ÀÚü°¡ /WEB-INF/hotels/booking¿¡ ÀÖ´Ù¸é À§ÀÇ state´Â /WEB-INF/hotels/booking/enterBookingDetails.xhtmlÀ» ·£´õ¸µÇÒ °ÍÀÌ´Ù.

¾Æ·¡´Â ¿¹Á¦ µð·ºÅ͸® ±¸Á¶·Î ºä¿Í ¸Þ½ÃÁö ¹øµé °°Àº ±âŸ ¸®¼Ò½º°¡ ±×µéÀÇ Ç÷οì Á¤ÀÇ¿Í °°ÀÌ ÀÖ´Â °ÍÀ» º¸¿©ÁØ´Ù.

»ç¿ëÀÚ »ðÀÔ À̹ÌÁö

4.3. ºä ½Äº°ÀÚ ÀÛ¼ºÇϱâ

view ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ·£´õ¸µ ÇÒ ºä¸¦ ¸í½ÃÀûÀ¸·Î ±âÀÔÇÑ´Ù.

4.3.1. ÇÃ·Î¿ì »ó´ë ºä id

ºä id´Â Ç÷ο찡 ÀÖ´Â ÀÛ¾÷ µð·ºÅ͸®¿¡ À§Ä¡ÇÑ ºä ¸®¼Ò½º¿¡ ´ëÇÑ »ó´ë °æ·Î°¡ µÉ ¼ö ÀÖ´Ù.

<view-state id="enterBookingDetails" view="bookingDetails.xhtml">
            
4.3.2. Àý´ë ºä id

ºä id´Â À¥ ¾ÖÇø®ÄÉÀÌ¼Ç ·çÆ® µð·ºÅ͸®¿¡ ÀÖ´Â ºäÀÇ Àý´ë °æ·Î°¡ µÉ ¼öµµ ÀÖ´Ù.

<view-state id="enterBookingDetails" view="/WEB-INF/hotels/booking/bookingDetails.xhtml">
            
4.3.3. ³í¸® ºä id

½ºÇÁ¸µ MVCÀÇ ºä ÇÁ·¹ÀÓ¿öÅ© °°Àº ¸î¸î ºä ÇÁ·¹ÀÓ¿öÅ©¿¡¼­ ºä id´Â ÇÁ·¹ÀÓ¿öÅ©°¡ ÆÇ´ÜÇÒ ?? »ç¿ëÇÒ ³í¸®ÀûÀÎ ½Äº°ÀÚ°¡ µÉ ¼öµµ ÀÖ´Ù.

<view-state id="enterBookingDetails" view="bookingDetails">
            
½ºÇÁ¸µ MVC ¿¬µ¿ »Ó¿¡¼­ ¾î¶»°Ô MVC ViewResolver ±â¹Ý ½Ã¼³°ú ¿¬µ¿ÇÏ´ÂÁö ´õ ¸¹Àº Á¤º¸¸¦ »ìÆ캸µµ·Ï ÇÏÀÚ.

4.4. ºä ½ºÄÚÇÁ

view-state´Â µé¾î¿Ã ¶§¸¶´Ù »õ·Î¿î viewScopeÀ» ÇÒ´çÇÑ´Ù. ÀÌ ½ºÄÚÇÁ´Â Ajax ¿äûó·³ °°Àº ºä¿¡¼­ ¿©·¯ ¿äû¿¡ °ÉÃÄ °´Ã¼¸¦ Á¶ÀÛÇÒ ¶§ À¯¿ëÇÏ´Ù. view-state´Â ÇØ´ç state¸¦ ³ª°¥ ¶§ viewScopeÀ» ¼Ò¸êÇÑ´Ù.

4.4.1. ºä º¯¼ö ÇÒ´çÇϱâ

var ű׸¦ »ç¿ëÇÏ¿© ºä º¯¼ö¸¦ ¼±¾ðÇÑ´Ù. ÇÃ·Î¿ì º¯¼öó·³, ºä »óÅ°¡ ´Ù½Ã ½ÃÀÛÇÏ¸é  ¸ðµç @Autowired ·¹ÆÛ·±½º¸¦ ÀÚµ¿À¸·Î º¹¿øÇÑ´Ù.

<var name="searchCriteria" class="com.mycompany.myapp.hotels.SearchCriteria" />
            
4.4.2. viewScope º¯¼ö ÇÒ´çÇϱâ

on-render ű׸¦ »ç¿ëÇÏ¿© ºä ·£´õ¸µÇϱâ Àü¿¡ ¾×¼Ç °á°ú¿¡ º¯¼ö¸¦ ÇÒ´çÇÑ´Ù.

<on-render>
    <evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
</on-render>
            

4.4.3. ºä ½ºÄÚÇÁ¿¡ ÀÖ´Â °´Ã¼ Á¶ÀÛÇϱâ

ºä ½ºÄÚÇÁ¿¡ ÀÖ´Â °´Ã¼´Â º¸Åë µ¿ÀÏÇÑ ºä¿¡¼­ ¿©·¯ ¿äû¿¡ ÀÇÇØ Á¶À۵ȴÙ. ´ÙÀ½ ¿¹Á¦ ÆäÀÌÁö´Â °Ë»ö °á°ú ¸ñ·ÏÀ» º¸¿©ÁØ´Ù. ¸ñ·ÏÀº ¸Å¹ø ·£´õ¸µ Çϱâ Àü¿¡ ºä ½ºÄÚÇÁ¿¡¼­ ¼öÁ¤µÈ´Ù. ºñµ¿±â À̺¥Æ® Çڵ鷯°¡ ÇöÀç µ¥ÀÌÅÍ ÆäÀÌÁö¸¦ ¼öÁ¤ÇÏ°í °Ë»ö °á°ú ºÎºÐ¿¡ ´ëÇÑ ¿äûÀ» ´Ù½Ã ·£´õ¸µ ÇÑ´Ù.

<view-state id="searchResults">
    <on-render>
        <evaluate expression="bookingService.findHotels(searchCriteria)"
                  result="viewScope.hotels" />
    </on-render>
    <transition on="next">
        <evaluate expression="searchCriteria.nextPage()" />
        <render fragments="searchResultsFragment" />            
    </transition>
    <transition on="previous">
        <evaluate expression="searchCriteria.previousPage()" />
        <render fragments="searchResultsFragment" />          
    </transition>
</view-state>
            
4.5. render ¾×¼Ç ½ÇÇàÇϱâ

on-render ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ºä ·£´õ¸µÀ» ÇϱâÀü¿¡ ÇÑ °³ ÀÌ»óÀÇ ¾×¼ÇÀ» ½ÇÇàÇÑ´Ù. ºäÀÇ ÀϺθ¸ ´Ù½Ã ·£´õ¸µÇÏ´Â °ÍÀ» Æ÷ÇÔÇÏ¿© ·£´õ ¾×¼ÇÀº ÀÌÈÄÀÇ ¸®ÇÁ·¡½Ã¿Í ¸¶Âù°¡Áö·Î Ãʱ⠷£´õ¸µ ´Ü°è¿¡ ½ÇÇàµÈ´Ù.

<on-render>
    <evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
</on-render>
        
4.6. ¸ðµ¨·Î ¹ÙÀεùÇϱâ

model ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ºä¸¦ ¹ÙÀεùÇÒ ¸ðµ¨ °´Ã¼¸¦ ¼±¾ðÇÑ´Ù. ÀÌ ¼Ó¼ºÀº º¸Åë Æû °°Àº µ¥ÀÌÅÍ ÄÁÆ®·ÑÀ» ·£´õ¸µÇÏ´Â ºä¶û °°ÀÌ »ç¿ëÇÑ´Ù. Æû µ¥ÀÌÅÍ ¹ÙÀεù°ú °ËÁõ ÀÛ¾÷À» ¸ðµ¨ °´Ã¼¿¡ ´ëÇÑ ¸ÞŸµ¥ÀÌÅÍ·Î ÁÖµµÇÒ ¼ö ÀÖ´Ù.

´ÙÀ½ ¿¹´Â booking ¸ðµ¨À» ´Ù·ç´Â enterBookingDetails State´Ù.

<view-state id="enterBookingDetails" model="booking">

¸ðµ¨Àº flowScope ¶Ç´Â viewScope °°ÀÌ Á¢±Ù °¡´ÉÇÑ ¸ðµç ½ºÄÚÇÁ¿¡ ÀÖ´Â °´Ã¼´Ù. modelÀ» Á¤ÀÇÇÏ¸é ºä À̺¥Æ®°¡ ¹ß»ýÇÒ ¶§ ´ÙÀ½ ÀÛ¾÷ÀÌ ÀÌ·ïÁø´Ù.
  1. ºä¿¡¼­ ¸ðµ¨·Î ¹ÙÀεù. ºä Æ÷½ºÆ®¹é(postback)À» ÇÒ ¶§ »ç¿ëÀÚ ÀÔ·Â °ªÀ» ¸ðµ¨ °´Ã¼ ¼Ó¼ºÀ¸·Î ¹ÙÀεùÇÑ´Ù.
  2. ¸ðµ¨ °ËÁõ. ¹ÙÀεùÀ» ÇÑ ´ÙÀ½, ¸¸¾à ¸ðµ¨ °´Ã¼°¡ °ËÁõÀ» ÇÊ¿ä·Î Çϸé, °ËÁõ ·ÎÁ÷À» È£ÃâÇÑ´Ù.
ºä »óÅ ÀüÀ̸¦ ÇÒ ¼ö ÀÖ´Â Ç÷οì À̺¥Æ®°¡ ¹ß»ýÇÒ ¶§, ¸ðµ¨ ¹ÙÀεùÀº ¹Ýµå½Ã ¼º°øÀûÀ¸·Î ¿Ï·áµÇ¾î¾ß ÇÑ´Ù. ¸¸¾à ¹ÙÀεùÀÌ ½ÇÆÐÇϸé, ºä´Â ´Ù½Ã ·£´õ¸µÇÏ¿© »ç¿ëÀÚ°¡ ´Ù½Ã ÆíÁýÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù.

4.7. ŸÀÔ º¯È¯ ¼öÇàÇϱâ

ºä Æ÷½ºÆ®¹éÀ» ÇÒ ¶§ ¸ðµ¨ ¹ÙÀεùÀÌ ¹ß»ýÇϸé, ¹ÙÀεù ½Ã½ºÅÛÀº ÇÊ¿äÇÏ´Ù¸é ÀÔ·Â °ªÀ» Ÿ°Ù ¸ðµ¨ ¼Ó¼º ŸÀÔÀ¸·Î º¯È¯À» ½ÃµµÇÒ °ÍÀÌ´Ù. ¼ýÀÚµé°ú ±âº»Å¸ÀÔ, À̳Ñ, ±×¸®°í Date¿¡ ´ëÇÑ ±âº» ÄÁ¹öÅÍ(Converter)´Â ÀÚµ¿À¸·Î Àû¿ëµÈ´Ù. »ç¿ëÀÚ´Â ¶ÇÇÑ ÀڽŵéÀÌ Á÷Á¢ Á¤ÀÇÇÑ Å¸ÀÔ¿¡ ´ëÇÑ ÄÁ¹öÅ͸¦ µî·ÏÇÒ ¼ö ÀÖ°í ±âº» ÄÁ¹öÅ͸¦ ÀçÁ¤ÀÇ ÇÒ ¼öµµ ÀÖ´Ù.

4.7.1. ÄÁ¹öÅÍ ±¸ÇöÇϱâ

ÄÁ¹öÅ͸¦ ±¸ÇöÇÏ·Á¸é, org.springframework.binding.convert.converters.TwoWayConverter ÀÎÅÍÆäÀ̽º¸¦ ±¸ÇöÇ϶ó. ÀԷ°ªÀ¸·Î ¹®ÀÚ¿­À» ¹Þ¾Æ¼­ »ç¿ëÀÚ°¡ Á¤ÀÇÇÑ °´Ã¼·Î º¯°æÇÏ´Â ÄÁ¹öÅ͸¦ ¸¸µé ¶§ ÀÌ ÀÎÅÍÆäÀ̽º ±¸ÇöÀ» Æí¸®ÇÏ°Ô ÇØÁÖ´Â ±âº» Ŭ·¡½º StringToObject¸¦ Á¦°øÇÑ´Ù. °£´ÜÇÏ°Ô ÀÌ Å¬·¡½½¸£ »ó¼ÓÇÏ°í µÎ °³ÀÇ ¸Å¼­µå¸¦ ÀçÁ¤ÀÇÇÏ¸é µÈ´Ù.

protected abstract Object toObject(String string, Class targetClass) throws Exception;

protected abstract String toString(Object object) throws Exception;            
           
toObject(String, Class)´Â ÀÔ·Â ¹®ÀÚ¿­À» °´Ã¼ ŸÀÔÀ¸·Î ¹Ù²ã¾ß ÇÏ°í toString(Object)´Â ±× ¹Ý´ë ÀÏÀ» ÇØ¾ß ÇÑ´Ù.

´ÙÀ½ ¿¹Á¦´Â ¹®ÀÚ¿­À» MonetaryAmount·Î º¯È¯ÇÏ´Â ÄÁ¹öÅÍ´Ù.

public class StringToMonetaryAmount extends StringToObject {

  public StringToMonetaryAmount() {
      super(MonetaryAmount.class);
  }

  @Override
  protected Object toObject(String string, Class targetClass) {
      return MonetaryAmount.valueOf(string);
  }

  @Override
  protected String toString(Object object) {
      MonetaryAmount amount = (MonetaryAmount) object;
      return amount.toString();
  }
}            
   
´õ ¸¹Àº ÄÁ¹öÅÍ ±¸Çö ¿¹Á¦¸¦ º¸°í ½Í´Ù¸é org.springframework.binding.convert.converters ÆÐÅ°Áö¿¡ ¹Ì¸® ¸¸µé¾îµÐ ÄÁ¹öÅ͵éÀ» Âü°íÇ϶ó.

4.7.2. ÄÁ¹öÅÍ µî·ÏÇϱâ

¿©·¯ºÐÀÌ ÀÛ¼ºÇÑ ÄÁ¹öÅ͸¦ µî·ÏÇϰųª ±âº» ÄÁ¹öÅ͸¦ º¯°æÇÏ°í ½Í´Ù¸é, org.springframework.binding.convert.service.DefaultConversionService¸¦ »ó¼ÓÇÏ°í addDefaultConverters() ¸Å¼­µå¸¦ ÀçÁ¤ÀÇ Ç϶ó. addConverter(Converter) ¸Å¼­µå¸¦ »ç¿ëÇÏ¿© String°ú MonetaryAmount °°Àº µÎ ŸÀÔÀ» º¯È¯ÇÒ ¶§ »ç¿ëÇÒ ÁÖ¿ä ÄÁ¹öÅÍ(Primary Converter)¸¦ µî·ÏÇ϶ó. ºÎ°¡ÀûÀ¸·Î addConverter(String, Converter)¸¦ »ç¿ëÇÏ¿© °°Àº ŸÀÔ¿¡ ´ëÇÑ ¿©·¯ ´ëü ÄÁ¹öÅÍ(Alternate Converter)¸¦ µî·ÏÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î, java.util.Date¸¦ ¿©·¯ ÇüÅÂÀÇ ¹®ÀÚ¿­·Î º¯È¯ÇÒ ¼ö ÀÖ°Ú´Ù.

´ëü ÄÁ¹öÅÍ´Â À¯ÀÏÇÑ converterId·Î À妽ÌÀ» Çϴµ¥ ¸ðµ¨ ¹ÙÀεùÀ» ¼³Á¤ÇÒ ¶§ ÂüÁ¶ÇÒ ¼ö ÀÖ´Ù. converterId¸¦ ÁöÁ¤ÇÏÁö ¾ÊÀ¸¸é ÁÖ¿ä ÄÁ¹öÅ͸¦ »ç¿ëÇÑ´Ù.

ConversionService´Â À¥ Ç÷ο찡 ·±Å¸ÀÓ¿¡ ¾î¶² ŸÀÔÀ» ´Ù¸¥ ŸÀÔÀ¸·Î º¯È¯ ÇØÁÖ´Â º¯È¯ ½ÇÇà±â¸¦ ·è¾÷ÇÒ ¶§ »ç¿ëÇÏ´Â °´Ã¼´Ù. ¾ÖÇø®ÄÉÀÌ¼Ç ´ç ÇϳªÀÇ ConversionService°¡ ÀÖ´Ù. System Setup  ÀýÀ» ÂüÁ¶ÇÏ¿© ¾ÖÇø®ÄÉÀÌ¼Ç Àü¹Ý¿¡ °ÉÃÄ Ä¿½ºÅÒ ÄÁ¹öÅ͸¦ µî·ÏÇÏ´Â ConversionService ±¸Çöü¸¦ ¼³Á¤ÇÏ´Â ¹æ¹ýÀ» »ìÆ캸¶ó. ¶ÇÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº Convert API¸¦ Âü°íÇ϶ó.

4.8. ¹ÙÀεù ¹æÁöÇϱâ

bind ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ƯÁ¤ ºä À̺¥Æ®¿¡ ´ëÇÑ °ËÁõ°ú ¸ðµ¨ ¹ÙÀεùÀ» ¹æÁöÇÒ ¼ö ÀÖ´Ù. ´ÙÀ½ ¿¹´Â cancel À̺¥Æ®°¡ ¹ß»ýÇßÀ» ¶§ ¹ÙÀεùÀ» ¹æÁöÇÑ´Ù.

<view-state id="enterBookingDetails" model="booking">
    <transition on="proceed" to="reviewBooking">
    <transition on="cancel" to="bookingCancelled" bind="false" />
</view-state>

4.9. ¸í½ÃÀûÀ¸·Î ¹ÙÀεù ¼³Á¤Çϱâ

binder ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ºä¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Â ¸ðµ¨ ¹ÙÀεù ÁýÇÕÀ» ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº ƯÈ÷ ½ºÇÁ¸µ MVC ȯ°æ¿¡¼­ ºä ¸¶´Ù "Çã¿ëÇÏ´Â ÀԷ°ª" ÁýÇÕÀ» Á¦ÇÑÇÒ ¶§ À¯¿ëÇÏ´Ù.

<view-state id="enterBookingDetails" model="booking">
    <binder>
        <binding property="creditCard" />
        <binding property="creditCardName" />
        <binding property="creditCardExpiryMonth" />
        <binding property="creditCardExpiryYear" />
    </binder>
    <transition on="proceed" to="reviewBooking" />
    <transition on="cancel" to="cancel" bind="false" />
</view-state>

 ¸¸¾à¿¡ binder ¿¤¸®¸ÕÆ®¸¦ ¼³Á¤ÇÏÁö ¾ÊÀ¸¸é ¸ðµ¨ÀÇ ¸ðµç public ¼Ó¼ºÀÌ ºä¿¡¼­ ¹ÙÀεùÇÏ´Â ´ë»óÀÌ µÈ´Ù. binder ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ¿ÀÁ÷ ¸í½ÃÀûÀ¸·Î Ç¥ÇöÇÑ ¼Ó¼º¸¸ ¹ÙÀεù ÇÑ´Ù.

°¢°¢ÀÇ ¹ÙÀεùÀº ÄÁ¹öÅ͸¦ Àû¿ëÇÏ¿© ¸ðµ¨ ¼Ó¼º °ªÀ» »ç¿ëÀÚ¿¡°Ô Àͼ÷ÇÑ ÇüÅ·Πº¯°æÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¸¸¾à ÄÁ¹öÅ͸¦ ¸í½ÃÇÏÁö ¾ÊÀ¸¸é ¸ðµ¨ ¼Ó¼º ŸÀÔ¿¡ µû¶ó ±âº» ÄÁ¹öÅ͸¦ »ç¿ëÇÏ°Ô µÈ´Ù.

<view-state id="enterBookingDetails" model="booking">
    <binder>
        <binding property="checkinDate" converter="shortDate" />
        <binding property="checkoutDate" converter="shortDate" />    
        <binding property="creditCard" />
        <binding property="creditCardName" />
        <binding property="creditCardExpiryMonth" />
        <binding property="creditCardExpiryYear" />
    </binder>
    <transition on="proceed" to="reviewBooking" />
    <transition on="cancel" to="cancel" bind="false" />
</view-state>

À§ÀÇ ¿¹Á¦¿¡¼­ shortDate ÄÁ¹öÅ͸¦ chekingDate¿Í checkoutDate ¼Ó¼º¿¡ Àû¿ëÇÏ°í ÀÖ´Ù. Ä¿½ºÅÒ ÄÁ¹öÅ͸¦ ¾ÖÇø®ÄÉÀ̼ÇÀÇ ConventionService·Î µî·ÏÇÒ ¼öµµ ÀÖ´Ù.

°¢°¢ÀÇ ¹ÙÀεùÀº ¶ÇÇÑ Çʼö ¿©ºÎ¸¦ È®ÀÎÇÏ¿© »ç¿ëÀÚ°¡ ÀÔ·ÂÇÑ °ªÀÌ ºñ¾îÀÖ´Ù¸é °ËÁõ ¿¡·¯¸¦ ¹ß»ý½ÃÅ°µµ·Ï ÇÒ ¼ö ÀÖ´Ù.

<view-state id="enterBookingDetails" model="booking">
    <binder>
        <binding property="checkinDate" converter="shortDate" required="true" />
        <binding property="checkoutDate" converter="shortDate" required="true" />
        <binding property="creditCard" required="true" />
        <binding property="creditCardName" required="true" />
        <binding property="creditCardExpiryMonth" required="true" />
        <binding property="creditCardExpiryYear" required="true" />
    </binder>
    <transition on="proceed" to="reviewBooking">
    <transition on="cancel" to="bookingCancelled" bind="false" />
</view-state>

À§ÀÇ ¿¹Á¦¿¡¼­ ¸ðµç ¹ÙÀεùÀ» Çʼö·Î ¼³Á¤Çß´Ù. ¸¸¾à ¹ÙÀεù ÇÒ ÀԷ°ªÀÌ Çϳª¶óµµ ºñ¾ú´Ù¸é ¿¡·¯¸¦ ¸¸µé°í ºä¸¦ ¿¡·¯¿Í ÇÔ²² ´Ù½Ã º¸¿©ÁÙ °ÍÀÌ´Ù.

4.10. ¸ðµ¨ °ËÁõÇϱâ

¸ðµ¨ °ËÁõÀº µµµ¨ °´Ã¼¿¡ ±â¹ÝÇÏ¿© ¼³Á¤ÇÑ Á¦¾à»çÇ×À¸·Î ÁÖµµÇÑ´Ù. À¥ Ç÷οì´Â ±×·¯ÇÑ Á¦¾à »çÇ×À» ÇÁ·Î±×·¡¹ÖÀ¸·Î Á¦°øÇÑ´Ù.

4.10.1. ÇÁ·Î±×·¡¹ÖÀûÀÎ °ËÁõ

¸ðµ¨ °ËÁõÀ» ÇÁ·Î±×·¡¹ÖÀûÀ¸·Î ¼öÇàÇÏ´Â µÎ °¡Áö ¹æ¹ýÀÌ ÀÖ´Ù. Çϳª´Â °ËÁõ ·ÎÁ÷À» ¸ðµ¨ °´Ã¼ ³»ºÎ¿¡ ±¸ÇöÇÏ´Â °ÍÀÌ´Ù. µÎ ¹ø°´Â º°µµÀÇ Validator¸¦ ±¸ÇöÇÏ´Â °ÍÀÌ´Ù. µÎ °¡Áö ¹æ¹ý ¸ðµÎ ValidationContext¸¦ »ç¿ëÇÏ¿© ¿¡·¯ ¸Þ½ÃÁö¸¦ ±â·ÏÇÏ°í ÇöÀç »ç¿ëÀÚ Á¤º¸¿¡ Á¢±ÙÇÒ ¼ö ÀÖ´Ù.

4.10.1.1. ¸ðµ¨ °ËÁõ ¸Å¼­µå ±¸ÇöÇϱâ

¸ðµ¨ °´Ã¼ ³»ºÎ¿¡ °ËÁõ ·ÎÁ÷À» Á¤ÀÇÇÏ´Â °ÍÀº ±× »óŸ¦ °ËÁõÇÏ´Â °¡Àå °£´ÜÇÑ ¹æ¹ýÀÌ´Ù. ÇÑ ¹ø ÀÌ·± ·ÎÁ÷À» À¥ ÇÃ·Î¿ì ±Ô¾à¿¡ ¸Â°Ô ¸¸µé¾î µÎ¸é À¥ Ç÷ο찡 ÀÚµ¿À¸·Î ±× ·ÎÁ÷À» view-state Æ÷½ºÆ®¹é ¶óÀÌÇÁ»çÀÌŬ µ¿¾È¿¡ È£ÃâÇÒ °ÍÀÌ´Ù. À¥ Ç÷α¸ ±Ô¾àÀº ºä¿¡¼­ ¼öÁ¤ÇÏ´Â ¸ðµ¨ ¼Ó¼º ¼­ºê¼ÂÀ» ½±°Ô °ËÁõÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÀÌ·¸°Ô ÇÏ·Á¸é °£´ÜÇÏ°Ô validate${state} ÇüÅÂÀÇ À̸§À» °¡Áø public ¸Å¼­µå¸¦ ¸¸µé¸é µÈ´Ù. ${state}´Â °ËÁõÀ» ¼öÇàÇÒ view-stateÀÇ id´Ù. ¿¹¸¦ º¸ÀÚ.

public class Booking {
    private Date checkinDate;
    private Date checkoutDate;
    ...
        
    public void validateEnterBookingDetails(ValidationContext context) {
        MessageContext messages = context.getMessages();
        if (checkinDate.before(today())) {
            messages.addMessage(new MessageBuilder().error().source("checkinDate").
                defaultText("Check in date must be a future date").build());
        } else if (!checkinDate.before(checkoutDate)) {
            messages.addMessage(new MessageBuilder().error().source("checkoutDate").
                defaultText("Check out date must be later than check in date").build());
        }
    }
}

À§ ¿¹Á¦¿¡¼­, Booking ¸ðµ¨À» ÆíÁýÇÏ´Â enterBookingDetails view-state·Î ÀüÀÌ°¡ ¹ß»ýÇϸé À¥ Ç÷οì´Â ÇØ´ç ÀüÀÌ¿¡ °ËÁõÀ» ¹æÁöÇÏÁö ¾Ê¾Ò´Ù¸é validateEnterBookingDetails(ValidationContext) ¸Å¼­µå¸¦ ÀÚµ¿À¸·Î È£ÃâÇÑ´Ù. ±×·± view-state ¿¹Á¦´Â ¾Æ·¡¿Í °°´Ù.

<view-state id="enterBookingDetails" model="booking">
    <transition on="proceed" to="reviewBooking">
</view-state>
        
¸ðµç °ËÁõ ¸Þ¼Òµå¸¦ Á¤ÀÇÇß´Ù. ÀϹÝÀûÀ¸·Î Ç÷οì´Â ¸ðµ¨À» ¿©·¯ ºä¿¡¼­ ÆíÁýÇÑ´Ù. ÀÌ °æ¿ì¿¡ °ËÁõÀ» ¼öÇàÇÒ ÇÊ¿ä°¡ ÀÖ´Â °¢°¢ÀÇ view-state¿¡ ´ëÇÑ °ËÁõ ¸Å¼­µå¸¦ Á¤ÀÇÇßÀ» °ÍÀÌ´Ù.

4.10.1.2. Validator ±¸ÇöÇϱâ

µÎ ¹ø° ¹æ¹ýÀº ¸ðµ¨ °´Ã¼¸¦ °ËÁõÇÒ Validator¶ó°í ÇÏ´Â º°µµÀÇ °´Ã¼¸¦ Á¤ÀÇÇÏ´Â °ÍÀÌ´Ù. ±×·¸°Ô ÇÏ·Á¸é ¿ì¼± ${model}Validator ÆÐÅÏÀÇ À̸§À» °¡Áø Ŭ·¡½º¸¦ ¸¸µç´Ù. ${model}Àº booking °°Àº ¸ðµ¨ Ç¥Çö½Ä ÇüŸ¦ ¶è´Ù. ±×·± ´ÙÀ½ validate${state} ÇüÅÂÀÇ À̸§À» °¡Áø ¸Å¼­µå¸¦ Á¤ÀÇÇÑ´Ù. ${state}´Â enteringBookingDetails°°Àº view-state id¿¡ ÇØ´çÇÑ´Ù. Ŭ·¡½º´Â ½ºÇÁ¸µ ºóÀ¸·Î ¹èÆ÷µÉ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. ¿©·¯ °ËÁõ ¸Å¼­µå¸¦ Á¤ÀÇÇÒ ¼ö ÀÖ´Ù, ¿¹Á¦¸¦ º¸ÀÚ.

@Component
public class BookingValidator {
    public void validateEnterBookingDetails(Booking booking, ValidationContext context) {
        MessageContext messages = context.getMessages();
        if (booking.getCheckinDate().before(today())) {
            messages.addMessage(new MessageBuilder().error().source("checkinDate").
                defaultText("Check in date must be a future date").build());
        } else if (!booking.getCheckinDate().before(booking.getCheckoutDate())) {
            messages.addMessage(new MessageBuilder().error().source("checkoutDate").
                defaultText("Check out date must be later than check in date").build());
        }
    }
}
                
À§ ¿¹Á¦¿¡¼­ Booking ¸ðµ¨À» ÆíÁýÇÏ´Â enterBookingDetilas view-state·Î ÀüÀÌ°¡ ¹ß»ýÇϸé À¥ Ç÷οì´Â validateEnterBookingDetails(Booking, ValidationContext) ¸Å¼­µå¸¦ ÀÚµ¿À¸·Î È£ÃâÇÒ °ÍÀÌ´Ù. ´Ü À̶§ ÇØ´ç ÀüÀÌ¿¡ ´ëÇÑ °ËÁõÀ» ¹æÁöÇÑ »óÅ°¡ ¾Æ´Ï¾î¾ß ÇÑ´Ù.

¶ÇÇÑ Validator´Â ½ºÇÁ¸µ MVCÀÇ Errors °´Ã¼·Î ¹ÞÀ» ¼ö ÀÖ´Ù. ÀÌ °´Ã¼´Â ±âÁ¸ÀÇ ½ºÇÁ¸µ °ËÁõ±â¸¦ È£ÃâÇÒ ¶§ Çʼö´Ù.

°ËÁõ±â´Â ½ºÇÁ¸µ ºóÀ¸·Î µî·ÏµÇ¾î¾ß ÇÏ°í ${model}Validator ¶ó´Â À̸§ ±Ô¾àÀ» ÁöÄÑ¾ß ÇÑ´Ù ±×·³ ÀÚµ¿À¸·Î °¨ÁöµÇ°í È£ÃâµÈ´Ù. À§ ¿¹Á¦¿¡¼­ ½ºÇÁ¸µ 2.5 Ŭ·¡½ºÆнº-½ºÄµÀ» ÇÏ°Ô µÇ¸é @Component¸¦ °¨ÁöÇÏ°í ÀÚµ¿À¸·Î bookingValidator¶ó´Â À̸§ÀÇ ºóÀ¸·Î µî·ÏÀÌ µÈ´Ù. ±×·¯¸é bokking ¸ðµ¨ °ËÁõÀÌ ÇÊ¿äÇÒ ¶§ ÀÌ bookingValidator ÀνºÅϽº°¡ È£ÃâµÉ °ÍÀÌ´Ù.

4.10.2. ValidationContext

ValidationContext´Â MessageContext¸¦ °¡Á®¿Í¼­ °ËÁõÀ» ÇÏ´Â µ¿¾È ¸Þ½ÃÁö¸¦ ±â·ÏÇÑ´Ù. ¶ÇÇÑ userEvent¿Í ÇöÀç »ç¿ëÀÚÀÇ Principal °°ÀÌ ÇöÀç »ç¿ëÀÚ¿¡ ´ëÇÑ Á¤º¸¸¦ °ø°³ÇÑ´Ù. ÀÌ·¯ÇÑ Á¤º¸´Â °ËÁõ ·ÎÁ÷À» Á¢¼ÓÇÑ »ç¿ëÀÚ ¶Ç´Â UIÀÇ ¾î¶² ¹öÆ° ¶Ç´Â ¸µÅ©¿¡ ±â¹ÝÇÏ¿© Ä¿½ºÅ͸¶ÀÌ¡ ÇÒ ¼ö ÀÖµµ·Ï ÇØÁØ´Ù. ÀÚ¼¼ÇÑ Á¤º¸´Â ValidationContext API¸¦ Âü°íÇ϶ó.

4.11. °ËÁõ ¹æÁöÇϱâ

validate ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ƯÁ¤ ºä À̺¥Æ®¿¡ ´ëÇÑ ¸ðµ¨ °ËÁõÀ» ¹æÁöÇÒ ¼ö ÀÖ´Ù.

<view-state id="chooseAmenities" model="booking">
    <transition on="proceed" to="reviewBooking">
    <transition on="back" to="enterBookingDetails" validate="false" />
</view-state>
        
À§ ¿¹Á¦´Â back À̺¥Æ®°¡ ¹ß»ýÇÒ °æ¿ì ¹ÙÀεùÀº ÇÏÁö¸¸ °ËÁõÀº ÇÏÁö ¾Ê´Â´Ù.

4.12. ºä ÀüÀÌ ½ÇÇàÇϱâ

Çϳª ¶Ç´Â ±× ÀÌ»óÀÇ transition ¿¤¸®¸ÕÆ®¸¦ Á¤ÀÇÇÏ¿© ºä¿¡¼­ ¹ß»ýÇÏ´Â »ç¿ëÀÚ À̺¥Æ®¸¦ ´Ù·ê ¼ö ÀÖ´Ù. Æ®·£Áö¼ÇÀº »ç¿ëÀÚÇÑÅ× ´Ù¸¥ ºä¸¦ º¸¿©Áְųª ´Ü¼øÇÏ°Ô ¾×¼ÇÀ» ½ÇÇàÇϰųª ÇöÀç ºä¸¦ ´Ù½Ã º¸¿©ÁÖ´Â ÀÏÀ» ÇÑ´Ù. ¶ÇÇÑ Æ®·£Áö¼ÇÀº ¾ÖÀÌÀÛ½º(Ajax)¸¦ ´Ù·ê ¶§ ÇÁ·¹±×¸ÕÃ÷("fragments")¶ó°í ÇÏ´Â ºäÀÇ ÀϺθ¦ ´Ù½Ã º¸¿©ÁÖ±æ ¿äûÇÒ ¼öµµ ÀÖ´Ù. ¸¶Áö¸·À¸·Î ±Û·Î¹ú("global") Æ®·£Áö¼ÇÀ̶ó°í ÇÏ´Â ¿©·¯ ºä¿¡ °ÉÃļ­ °øÀ¯ÇÏ´Â °ÍÀ» Á¤ÀÇÇÒ ¼öµµ ÀÖ´Ù.

ºä Æ®·£Áö¼ÇÀ» Á¤ÀÇÇÏ´Â ¹æ¹ýÀ» ´ÙÀ½ Àý¿¡¼­ »ìÆ캸µµ·Ï ÇÏÀÚ.

4.12.1. Æ®·£Áö¼Ç ¾×¼Ç

view-state Æ®·£Áö¼ÇÀ» ¼öÇàÇϱâ Àü¿¡ Çϳª ¶Ç´Â ±× ÀÌ»óÀÇ ¾×¼ÇÀ» ½ÇÇàÇÒ ¼ö ÀÖ´Ù. ÀÌ·¯ÇÑ ¾×¼ÇÀº ¾Æ¸¶ ÇöÀç view-state¸¦ Á¾·áÇÏÁö ¸øÇÏ°Ô ¿¡·¯ °á°ú¸¦ ¹ÝȯÇÒ ¼öµµ ÀÖ´Ù. ¸¸¾à ¿¡·¯ °á°ú°¡ ÀÖ´Ù¸é, ºä´Â ´Ù½Ã º¸¿©Áú °ÍÀÌ¸ç »ç¿ëÀÚ¿¡°Ô ÀûÀýÇÑ ¸Þ½ÃÁö¸¦ º¸¿©ÁÙ °ÍÀÌ´Ù.

¸¸¾à Æ®·£Áö¼Ç ¾×¼ÇÀÌ ÀÏ¹Ý ÀÚ¹Ù ¸Å¼­µå¸¦ È£ÃâÇϸé, È£ÃâµÈ ¸Å¼­µå´Â false¸¦ ¹ÝȯÇÏ¿© Æ®·£Áö¼Ç ½ÇÇàÀ» ¹æÁöÇÒ ¼ö ÀÖ´Ù. ÀÌ·± ±â¼úÀº ¼­ºñ½º-°èÃþ ¸Å¼­µå¿¡¼­ ¹ß»ýÇÑ ¿¹¿Ü¸¦ ´Ù·ê ¶§ »ç¿ëÇÒ ¼ö ÀÖ°Ú´Ù. ¾Æ·¡ ¿¹Á¦´Â ¼­ºñ½º¸¦ È£ÃâÇÏ´Â ¾×¼ÇÀ» È£ÃâÇÏ°í ¿¹¿Ü »óȲÀ» ´Ù·é´Ù.

<transition on="submit" to="bookingConfirmed">
    <evaluate expression="bookingAction.makeBooking(booking, messageContext)" />
</transition>
            

public class BookingAction {
   public boolean makeBooking(Booking booking, MessageContext context) {
       try {
           bookingService.make(booking);
           return true;
       } catch (RoomNotAvailableException e) {
           context.addMessage(builder.error().
               .defaultText("No room is available at this hotel").build());
           return false;
       }
   }
}
            
4.12.2. Global Æ®·£Áö¼Ç

Ç÷οìÀÇ global-transitions ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ¿©·¯ ºä¿¡ °ÉÃÄ Àû¿ëÇÒ Æ®·£Áö¼ÇÀ» »ý¼ºÇÑ´Ù, Global-transitionÀº Á¾Á¾ ·¹À̾ƿôÀ» ±¸¼ºÇÏ´Â ¸Þ´º ¸µÅ© °°Àº °ÍÀ» ´Ù·ê ¶§ »ç¿ëÇÑ´Ù.

<global-transitions>
    <transition on="login" to="login">
    <transition on="logout" to="logout">
</global-transitions>
            
4.12.3. À̺¥Æ® Çڵ鷯

view-state¿¡¼­ Ÿ°ÙÀÌ ¾ø´Â Æ®·£Áö¼ÇÀ» Á¤ÀÇÇÒ ¼öµµ ÀÖ´Ù. ÀÌ·¯ÇÑ Æ®·£Áö¼ÇÀ» "À̺¥Æ® Çڵ鷯"¶ó°í ÇÑ´Ù.

<transition on="event">
    <!-- Handle event -->
</transition>
        
ÀÌ·± À̺¥Æ® Çڵ鷯´Â Ç÷οìÀÇ »óŸ¦ º¯°æÇÏÁö ¾Ê´Â´Ù. ´ÜÁö ±×µéÀÇ ¾×¼ÇÀ» ½ÇÇàÇÏ°í ÇöÀç ºä ¶Ç´Â Çϳª ÀÌ»óÀÇ ÇÁ·¹±×¸ÕÆ®¸¦ ´Ù½Ã º¸¿©ÁØ´Ù.

4.12.4. ÇÁ·¹±×¸ÕÆ® ´Ù½Ã º¸¿©ÁÖ±â

Æ®·£Áö¼Ç¿¡¼­ render ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© À̺¥Æ®¸¦ ó¸®ÇÑ ´ÙÀ½ ÇöÀç ºä¿¡¼­ ÀϺκи¸ ´Ù½Ã º¸¿©ÁÖµµ·Ï ¿äûÇÒ ¼ö ÀÖ´Ù.

<transition on="next">
    <evaluate expression="searchCriteria.nextPage()" />
    <render fragments="searchResultsFragment" />            
</transition>
            
fragments ¼Ó¼ºÀº ´Ù½Ã º¸¿©ÁÖ±æ ¿øÇÏ´Â ºä ¿¤¸®¸ÕÆ®(µé)ÀÇ id(¿©·¯°³)°¡ µÉ °ÍÀÌ´Ù. ¿©·¯ ¿¤¸®¸ÕÆ®¸¦ ´Ù½Ã º¸¿©ÁÖµµ·Ï ¼³Á¤ÇÏ·Á¸é ÄÞ¸¶·Î ±¸ºÐÇÏ¿© ÀûÀ¸¸é µÈ´Ù.

ÀÌ·¸°Ô ÀϺθ¦ ´Ù½Ã º¸¿©ÁÖ´Â ±â¹ýÀºÈ­¸éÀÇ Æ¯Á¤ ºÎÀ§¸¦ ¾÷µ¥ÀÌÆ®ÇÏ´Â Ajax¿¡ ÀÇÇÑ À̺¥·Î »ç¿ëµÈ´Ù.

4.13. ¸Þ½ÃÁö ´Ù·ç±â

½ºÇÁ¸µ À¥ Ç÷οìÀÇ MessageContext´Â ÇÃ·Î¿ì ½ÇÇà µµÁß¿¡ ¸Þ½ÃÁö¸¦ ±â·ÏÇϱâ À§ÇÑ API´Ù. ÀÏ¹Ý ÅؽºÆ® ¸Þ½ÃÁö´Â ¹°·ÐÀÌ°í ½ºÇÁ¸µ MessageSource¸¦ »ç¿ëÇÏ´Â ±¹Á¦È­ ¸Þ½ÃÁöµµ Ãß°¡ÇÒ ¼ö ÀÖ´Ù. ¸Þ½ÃÁö´Â ºä¿¡¼­ º¸¿©Áö¸ç ÀÚµ¿À¸·Î ÇÃ·Î¿ì ½ÇÇà ¸®´ÙÀÌ·ºÆ®¿¡µµ »ì¾Æ³²À» °ÍÀÌ´Ù. ¼¼ Á¾·ùÀÇ ¸Þ½ÃÁö¸¦ Á¦°øÇÑ´Ù. info, warning, error´Ù. ¶ÇÇÑ, Æí¸®ÇÑ MessageBuilder¸¦ Á¦°øÇÏ¿© ¸Þ½ÃÁö ÀÛ¼ºÀ» µ½°í ÀÖ´Ù.

4.13.1. ÀÏ¹Ý ÅؽºÆ® ¸Þ½ÃÁö Ãß°¡Çϱâ

MessageContext context = ...
MessageBuilder builder = new MessageBuilder();
context.addMessage(builder.error().source("checkinDate")
    .defaultText("Check in date must be a future date").build());
context.addMessage(builder.warn().source("smoking")
    .defaultText("Smoking is bad for your health").build());
context.addMessage(builder.info()
    .defaultText("We have processed your reservation - thank you and enjoy your stay").build());

4.13.2. ±¹Ã¼È­ ¸Þ½ÃÁö Ãß°¡Çϱâ

MessageContext context = ...
MessageBuilder builder = new MessageBuilder();
context.addMessage(builder.error().source("checkinDate").code("checkinDate.notFuture").build());
context.addMessage(builder.warn().source("smoking").code("notHealthy")
    .resolvableArg("smoking").build());            
context.addMessage(builder.info().code("reservationConfirmation").build());
            
4.13.3. ¸Þ½ÃÁö ¹øµé »ç¿ëÇϱâ

±¹Á¦È­ ¸Þ½ÃÁö´Â ½ºÇÁ¸µ MessageSource·Î Á¢±ÙÇÏ´Â ¸Þ½ÃÁö ¹øµé¿¡ Á¤ÀÇÇÑ´Ù. Ç÷οì-°ü·Ã ¸Þ½ÃÁö ¹øµéÀ» ¸¸µé·Á¸é, °£´ÜÇÏ°Ô message.properties ÆÄÀÏÀ» ÇÃ·Î¿ì µð·ºÅ͸®¿¡ ¸¸µç´Ù. messages.properties ÆÄÀÏÀ» ¸¸µé°í Áö¿øÇÏ°íÀÚ ÇÏÇÏ´Â Áö¿ª Locale¿¡ ÇØ´çÇÏ´Â .properties ÆÄÀÏÀ» °¢°¢ Ãß°¡ÇÑ´Ù.

#messages.properties
checkinDate=Check in date must be a future date
notHealthy={0} is bad for your health
reservationConfirmation=We have processed your reservation - thank you and enjoy your stay
            
ºä ¶Ç´Â Ç÷ο쿡¼­ ¿©·¯ºÐÀº resourceBundle EL º¯¼ö¸¦ »ç¿ëÇÏ¿© ¸Þ½ÃÁö ¹øµé¿¡ Á¢±ÙÇÒ ¼öµµ ÀÖ´Ù.

<h:outputText value="#{resourceBundle.reservationConfirmation}" />
            
4.13.4. ½Ã½ºÅÛÀÌ »ý¼ºÇÑ ¸Þ½ÃÁö ÀÌÇØÇϱâ

À¥ Ç÷οì ÀÚü°¡ »ç¿ëÀÚ¿¡°Ô º¸¿©ÁÙ ¸Þ½ÃÁö¸¦ »ý¼ºÇÏ´Â ¸î¸î ºÎºÐÀÌ ÀÖ´Ù. ÀÌ·± ÀÏÀÌ ¹ß»ýÇÏ´Â Áß¿äÇÑ ÁöÁ¡ Áß Çϳª´Â ºä¿¡¼­ ¸ðµ¨·Î µ¥ÀÌÅÍ ¹ÙÀεùÀ» ÇÒ ¶§´Ù. º¯È¯ ¿¡·¯ °°Àº ¹ÙÀεù ¿¡·¯°¡ ¹ß»ýÇϸé À¥ Ç÷οì´Â ÀÚµ¿À¸·Î ¿¡·¯¸¦ ¿©·¯ºÐ ¸®¼Ò½º¹øµé¿¡¼­ °¡Á®¿Â ¸Þ½ÃÁö·Î ¸ÊÇÎÇÑ´Ù. º¸¿©ÁÙ ¸Þ½ÃÁö¸¦ °¡Á®¿À·Á°í À¥ Ç÷οì´Â ¹ÙÀεù ¿¡·¯ ÄÚµå¿Í Ÿ°Ù ¼Ó¼º À̸§À» ´ã°í ÀÖ´Â ¸®¼Ò½º Å°¸¦ ½ÃµµÇÑ´Ù.

¾Æ·¡ ¿¹Á¦´Â Booking °´Ã¼ÀÇ checkinDate ¼Ó¼º¿¡ ¹ÙÀεùÀ» »ý°¢Çغ¸°í ÀÖ´Ù. »ç¿ëÀÚ°¡ ¾ËÆĺª ¹®ÀÚ¿­À» ÀÔ·ÂÇß´Ù°í ÇÏÀÚ. ÀÌ·± °æ¿ì ŸÀÔ º¯È¯ ¿¡·¯°¡ ¹ß»ýÇÒ °ÍÀÌ´Ù. À¥ Ç÷οì´Â "typeMismatch' ¿¡·¯ Äڵ带 ¿©·¯ºÐ ¸®¼Ò½º ¹øµé Áß¿¡ ÀÖ´Â ¸Þ½ÃÁö¸¦ ãÀ» ¶§ ´ÙÀ½ Å°¸¦ »ç¿ëÇÒ °ÍÀÌ´Ù.

booking.checkinDate.typeMismatch

Å°ÀÇ ¾Õ ºÎºÐÀº ¸ðµ¨ Ŭ·¡½ºÀÇ ÂªÀº À̸§ÀÌ´Ù. µÎ ¹ø° ºÎºÐÀº ¼Ó¼ºÀÇ À̸§ÀÌ´Ù, ¼¼ ¹ø° ºÎºÐÀº ¿¡·¯ ÄÚµå´Ù. ¸ðµ¨ ¼Ó¼º¿¡ ¹ÙÀεùÀÌ ½ÇÆÐÇÏ¸é »ç¿ëÀÚ¿¡°Ô º¸¿©ÁÙ À¯ÀÏÇÑ ¸Þ½ÃÁö¸¦ ÀÌ·±½ÄÀ¸·Î ã´Â´Ù. ¾Æ¸¶ ´ÙÀ½°ú °°Àº ¸Þ½ÃÁöÀÏ ¼ö ÀÖ´Ù.

booking.checkinDate.typeMismatch=The check in date must be in the format yyyy-mm-dd.

¸¸¾à Àú Çü½Ä¿¡ ÇØ´çÇÏ´Â Å°¸¦ ãÁö ¸øÇϸé, º¸´Ù ÀϹÝÀûÀÎ Å°·Î ½ÃµµÇغ»´Ù. ÀÌ Å°´Â °£´ÜÇÑ ¿¡·¯ ÄÚµå ÇüÅ´Ù. ¼Ó¼ºÀÇ Çõå À̸§Àº ¸Þ½ÃÁö ÀÎÀÚ·Î Á¦°øµÈ´Ù.

typeMismatch=The {0} field is of the wrong type.
            
4.14. Æ˾÷ º¸¿©ÁÖ±â

popup ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ¸ðµ¨ Æ˾÷ â¿¡¼­ ºä¸¦ ·£´õ¸µ ÇÑ´Ù.

<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
        
½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®¶û °°ÀÌ À¥ Ç÷ο츦 »ç¿ëÇϸé, Æ˾÷À» º¸¿©ÁÙ ¶§ Ŭ¶óÀ̾ðÆ® ÂÊ Äڵ带 »ç¿ëÇÒ ÇÊ¿ä°¡ ¾ø´Ù. À¥ Ç÷οì´Â Æ˾÷¿¡¼­ ºä·Î ¸®´ÙÀÌ·ºÆ®¸¦ ¿äûÇÏ´Â »ç¿ëÀÚ¿¡°Ô ÀÀ´äÀ» º¸³¾ °ÍÀÌ°í ±× °á°ú Ŭ¶óÀ̾ðÆ®´Â ¿äûÀº Àß Ã³¸®µÉ °ÍÀÌ´Ù.

4.15. ºä ¹éÆ®·¢Å·(backtracking)

±âº»ÀûÀ¸·Î, ºä ½ºÅ×ÀÌÆ®¸¦ Á¾·áÇÏ°í »õ·Î¿î ºä ½ºÅ×ÀÌÆ®·Î ÀüÀÌÇϸé, ¿©·¯ºÐÀº ºê¶ó¿ìÀúÀÇ µÚ·Î °¡±â ¹öÆ°À» »ç¿ëÇÏ¿© ÀÌÀü »óÅ·ΠÀ̵¿ÇÒ ¼ö ÀÖ´Ù. ÀÌ·¯ÇÑ ºä ½ºÅ×ÀÌÆ® È÷½ºÅ丮 Á¤Ã¥Àº history ¼Ó¼ºÀ» »ç¿ëÇÏ¿© Æ®·£Áö¼Ç ´ç ¼³Á¤ÇÒ ¼ö ÀÖ´Ù.

4.15.1. È÷½ºÅ丮 ¹æÁöÇϱâ

history ¼Ó¼ºÀ» discard·Î ¼³Á¤ÇÏ¿© ºä ¹éÆ®·¢Å·À» ¹æÁöÇÒ ¼ö ÀÖ´Ù.

<transition on="cancel" to="bookingCancelled" history="discard">

4.15.2. È÷½ºÅ丮 ±ÝÁöÇϱâ

history ¼Ó¼ºÀ» invalidate·Î ¼³Á¤ÇÏ¿© ºä ¹éÆ®·¢Å·À» ¹æÁöÇÏ°í ÀÌÀüÀÇ ºä·Î ÀüÀÌÇÏ´Â °Íµµ ¹æÁöÇÑ´Ù.

<transition on="confirm" to="bookingConfirmed" history="invalidate">
            
½Å°í

'Spring Web Flow > Chapter 4' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 4Àå ºä ·£´õ¸µ  (0)2009.01.30
top

SWF 3Àå EL(Expression Language)



ÂüÁ¶ ¹× ¹ø¿ª: http://static.springframework.org/spring-webflow/docs/2.0.x/reference/html/index.html

3.1. ¼Ò°³

À¥ Ç÷οì´Â ELÀ» »ç¿ëÇÏ¿© µ¥ÀÌÅÍ ¸ðµ¨¿¡ Á¢±ÙÇÏ¸ç ¾×¼ÇÀ» È£ÃâÇÑ´Ù. À̹ø Àå¿¡¼­ ¿©·¯ºÐÀº EL ¹®¹ý°ú Ç÷οì Á¤ÀÇ¿¡¼­ ÂüÁ¶ÇÒ ¼ö Àִ Ưº°ÇÑ EL º¯¼öµé¿¡ Àͼ÷ÇØÁú °ÍÀÌ´Ù.

3.2. Áö¿øÇÏ´Â EL ±¸Çöü

3.2.1. Unified EL

À¥ Ç÷οì´Â ±âº»À¸·Î Unified EL »ç¿ëÀ» ½ÃµµÇÑ´Ù. jboss-elÀÌ ÇöÀç ±âº» EL ±¸ÇöüÀÌ´Ù. ¿©·¯ºÐÀÇ Å¬·¡½ºÆнº¿¡¼­ el-apiÀ» ¹ß°ßÇϸé ÀÚµ¿ÀûÀ¸·Î ±×°ÍÀ» »ç¿ëÇÑ´Ù. JBoss EL jar ÆÄÀÏÀº ½ºÇÁ¸µ¼Ò½º ¹øµé ÀúÀå¼Ò¿¡¼­ ãÀ» ¼ö ÀÖ´Ù. 

³ëÆ®

el-api ÀÇÁ¸¼ºÀº º¸Åë À¥ ÄÁÅ×À̳ʿ¡¼­ Á¦°øÇÏ´Â provided´Ù. ¿¹¸¦ µé¾î ÅèĹ 6´Â ±×°ÍÀ» °¡Áö°í ÀÖ´Ù.

3.2.2. OGNL

OGNLÀº À¥ Ç÷οì 2°¡ Áö¿øÇÏ´Â ¶Ç´Ù¸¥ ELÀÌ´Ù. OGNLÀº À¥ ÇÃ·Î¿ì ¹öÀü 1.0 »ç¿ëÀÚ¿¡°Ô °¡Àå Àͼ÷ÇÑ ELÀÌ´Ù. ognlÀ» »ç¿ëÇÏ·Á¸é, jboss-el ´ë½Å¿¡ ognlÀ» Ŭ·¡½ºÆнº¿¡ Ãß°¡ÇÏ¸é µÈ´Ù. ¹®¹ýÀ» ÀÍÈ÷·Á¸é OGNL ·¹ÆÛ·±½º °¡À̵带 ÂüÁ¶Ç϶ó.

3.3. EL À̽ļº

º¸Åë, UEL(Unified EL)°ú OGNLÀº ¹®¹ýÀÌ ºñ½ÁÇÏ´Ù. ±âº» º¯¼ö ÀνÄ, ÇÁ·ÎÆÛƼ Á¢±Ù, ±×¸®°í ¸Þ¼Òµå È£Ãâ ¹®¹ýÀÌ µ¿ÀÏÇÏ´Ù. ¿ì¸®´Â °¡´ÉÇϸé UELÀ» »ç¿ëÇÒ °ÍÀ» ±ÇÀåÇϸç ÇÊ¿äÇÑ °æ¿ì¿¡¸¸ º°µµÀÇ EL ±â´ÉÀ» »ç¿ëÇ϶ó.

3.4. EL »ç¿ë¹ý

ELÀº Ç÷ο쿡¼­ ¿©·¯ °æ¿ì¿¡ »ç¿ëÇÒ ¼ö ÀÖ´Ù.
  1. Ç÷οì input ¼Ó¼ºÀ̳ª request ¸Å°³º¯¼ö °°Àº Ŭ¶óÀ̾ðÆ®°¡ Á¦°øÇÏ´Â µ¥ÀÌÅÍ¿¡ Á¢±ÙÇϱâ.
  2. flowScope °°Àº ³»ºÎ µ¥ÀÌÅÍ ±¸Á¶¿¡ Á¢±ÙÇϱâ
  3. ½ºÇÁ¸µ ºóÀÇ ¸Þ¼Òµå È£ÃâÇϱâ
  4. »óÅ ÀüÀÌ criteria, ÇÏÀ§ Ç÷οì id ±×¸®°í ºä À̸§ °°Àº ±¸Á¶ ÀνÄÇϱâ
Ç÷ο쿡 ÀÇÇØ º¸¿©Áö´Â ºä´Â ÀϹÝÀûÀ¸·Î ELÀ» »ç¿ëÇÏ¿© ÇÃ·Î¿ì µ¥ÀÌÅÍ ±¸Á¶¿¡ Á¢±ÙÇÑ´Ù.

3.4.1. Ç¥Çö½Ä ŸÀÔ

À¥ Ç÷ο쿡´Â ±âº»ÀûÀ¸·Î µÎ Á¾·ùÀÇ Ç¥Çö½ÄÀÌ ÀÖ´Ù.

3.4.1.1. Ç¥ÁØ Æò°¡ Ç¥Çö½Ä(standard eval expressions)

óÀ½À¸·Î »ìÆ캼 °ÍÀº °¡Àå ÈçÈ÷ »ç¿ëÇϴ ǥÇö½Ä ŸÀÔÀ¸·Î eval Ç¥Çö½ÄÀÌ´Ù. ÀÌ Ç¥Çö½ÄÀº EL¿¡ ÀÇÇØ µ¿ÀûÀ¸·Î Æò°¡µÇ°í ${} ³ª #{} °°Àº ±¸ºÐÀÚ·Î °¨½ÎÁö ¾Ê´Â´Ù. ¿¹Á¦¸¦ º¸ÀÚ.

<evaluate expression="searchCriteria.nextPage()" />
        
À§ÀÇ Ç¥Çö½ÄÀº °ªÀ» ±¸ÇØ¿Ã ¶§ searchCriteria º¯¼öÀÇ nextPage¶ó´Â ¸Þ¼Òµå¸¦ È£ÃâÇϴ ǥÁØ Ç¥Çö½ÄÀÌ´Ù. ÀÌ Ç¥Çö½ÄÀ» ${} ³ª #{} °°Àº ±¸ºÐÀÚ·Î °¨½Î¸é IllegalArgumentException ¿¹¿Ü°¡ ¹ß»ýÇÑ´Ù.

³ëÆ®

ÀÌ »óȲ¿¡¼­ º°µµÀÇ Æò°¡ ±¸ºÐÀÚ¸¦ »ç¿ëÇÏ´Â °ÍÀº ÇÊ¿ä¾ø´Ù°í º»´Ù. µû¶ó¼­ ¿ÀÁ÷ expression ¼Ó¼º¿¡ »ç¿ëÇÒ ¼ö ÀÖ´Â °ªÀº Æò°¡ Ç¥Çö½Ä ¹®ÀÚ¿­ÀÌ´Ù.

3.4.1.2. ÅÛÇø´ Ç¥Çö½Ä

µÎ ¹ø° Ç¥Çö½Ä ŸÀÔÀº "ÅÛÇø´" Ç¥Çö½ÄÀÌ´Ù. ÀÌ·± Ç¥Çö½ÄÀº ¹®ÀÚ¿­À» ÇÑ °³ ¶Ç´Â ¿©·¯ Æò°¡ ºí·°À¸·Î È¥ÇÕÇÏ´Â °ÍÀ» Çã¿ëÇÑ´Ù. °¢°¢ÀÇ Æò°¡ ºí·°Àº ${} ±¸ºÐÀÚ¸¦ »ç¿ëÇÏ¿© ¸í½ÃÀûÀ¸·Î ±¸ºÐÇÑ´Ù. ¿¹Á¦¸¦ º¸ÀÚ.

<view-state id="error" view="error-${externalContext.locale}.xhtml" />
                
À§ÀÇ Ç¥Çö½ÄÀº ÅÛÇø´ Ç¥Çö½ÄÀÌ´Ù. view ¼Ó¼º °ªÀÇ °á°ú´Â error- µÚ¿¡ externalContext.locale °ªÀ» ÇÕÄ£ ¹®ÀÚ¿­ÀÌ µÉ °ÍÀÌ´Ù. º¸½Ã´Ù½ÃÇÇ ¿©±â¼­´Â ÅÛÇø´ ³»¿¡ Æò°¡ ºí·°À» ±¸ºÐÇϱâ À§ÇØ ¸í½ÃÀûÀÎ ±¸ºÐÀÚ°¡ ÇÊ¿äÇÏ´Ù.

À¥ Ç÷οì XML ½ºÅ°¸¶¸¦ ÂüÁ¶ÇÏ¿© Ç¥ÁØ Ç¥Çö½Ä°ú ÅÛÇø´ Ç¥Çö½Ä¿¡¼­ »ç¿ëÇÒ ¼ö ÀÖ´Â XML ¼Ó¼ºµéÀ» ÀüºÎ È®ÀÎÇÒ ¼ö ÀÖ´Ù.

3.5. Ưº°ÇÑ EL º¯¼ö

ÇÃ·Î¿ì ¾È¿¡¼­ ÂüÁ¶ÇÒ ¼ö ÀÖ´Â ¾Ï¹¬ÀûÀÎ º¯¼öµé ¸î °³°¡ ÀÖ´Ù. À̹ø Àý¿¡¼­ ÀÌ·± º¯¼öµéÀ» ³íÀÇÇÒ °ÍÀÌ´Ù.

3.5.1. flowScope

flowScope¸¦ »ç¿ëÇÏ¿© ÇÃ·Î¿ì º¯¼ö¸¦ ÇÒ´çÇÑ´Ù. ÇÃ·Î¿ì ½ºÄÚÇÁ´Â Ç÷ο찡 ½ÃÀÛÇÒ ¶§ ÇÒ´çµÇ°í Ç÷ο찡 ³¡³¯ ¶§ ¼Ò¸êµÈ´Ù. ±âº» ±¸Çö¿¡ µû¶ó, ÇÃ·Î¿ì ½ºÄÚÇÁ¿¡ ÀúÀåµÈ ¸ðµç °´Ã¼´Â Á÷·ÄÈ­ ÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù.

<evaluate expression="searchService.findHotel(hotelId)" result="flowScope.hotel" />

3.5.2. viewScope

viewScope¸¦ »ç¿ëÇÏ¿© ºä º¯¼ö¸¦ ÇÒ´çÇÑ´Ù. ºä ½ºÄÚÇÁ´Â view-state¿¡ µé¾î°¥ ¶§ ÇÒ´çµÇ°í »óÅ°¡ Á¾·áµÇ¸é ¼Ò¸êµÈ´Ù. ºä ½ºÄÚÇÁ´Â ¿ÀÁ÷ view-state¿¡¼­¸¸ ÂüÁ¶ÇÒ ¼ö ÀÖ´Ù. ±âº» ±¸Çöü µû¶ó, ºä ½ºÄÚÇÁ¿¡ ÀúÀåµÈ ¸ðµç °´Ã¼´Â Áú·ÄÈ­ ÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù.

<on-render>
    <evaluate expression="searchService.findHotels(searchCriteria)" result="viewScope.hotels"
              result-type="dataModel" />
</on-render>

3.5.3. requestScope

requestScope¸¦ »ç¿ëÇÏ¿© ¿äû º¯¼ö¸¦ ÇÒ´çÇÑ´Ù. ¿äû ½ºÄÚÇÁ´Â Ç÷ο츦 È£ÃâÇÑ ¼ø°£¿¡ ÇÒ´çµÇ°í Ç÷ο찡 ¹ÝȯÀ» ÇÏ¸é ¼Ò¸êµÈ´Ù.

<set name="requestScope.hotelId" value="requestParameters.id" type="long" />

3.5.4. flashScope

flashScope¸¦ »ç¿ëÇÏ¿© Ç÷¡½Ã º¯¼ö¸¦ ÇÒ´çÇÑ´Ù. Ç÷¡½Ã ½ºÄÚÇÁ´Â Ç÷ο찡 ½ÃÀÛµÉ ¶§ ÇÒ´çµÇ°í, ¸ðµç ºä ·£´õ¸µÀ» ¸¶Ä£µÚ¿¡ Ŭ¸®¾îÇÏ°í Ç÷ο찡 ³¡³¯ ¶§ ¼Ò¸êÇÑ´Ù. ±âº» ±¸Çö¿¡ µû¶ó, Ç÷¡½Ã ½ºÄÚÇÁ¿¡ ÀúÀåµÈ ¸ðµç °´Ã¼´Â Á÷·ÄÈ­ ÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù.

<set name="flashScope.statusMessage" value="'Booking confirmed'" />    

3.5.5. conversationScope

conversationScope¸¦ »ç¿ëÇÏ¿© ÄÁ¹ö¼¼ÀÌ¼Ç º¯¼ö¸¦ ÇÒ´çÇÑ´Ù. ÄÁ¹ö¼¼ÀÌ¼Ç ½ºÄÚÇÁ´Â ÃÖ»óÀ§ Ç÷ο찡 ½ÃÀÛÇÒ ¶§ ÇÒ´çµÇ°í ÃÖ»óÀ§ Ç÷ο찡 Á¾·áµÇ¸é ¼Ò¸êÇÑ´Ù. ÄÁ¹ö¼¼ÀÌ¼Ç ½ºÄÚÇÁ´Â ÃÖ»óÀ§ Ç÷οì¿Í ¸ðµç ÇÏÀ§Ç÷ο쿡¼­ °øÀ¯ÇÑ´Ù. ±âº» ±¸Çö¿¡ µû¶ó, ÄÁ¹ö¼¼ÀÌ¼Ç ½ºÄÚÇÁ¿¡ ÀúÀåÇÏ´Â °´Ã¼´Â HTTP session¿¡ ÀúÀåÇÏ°í ÀÏ¹Ý ¼¼¼Ç º¹»ç¸¦ Çϱâ À§ÇØ º¸Åë Á÷·ÄÈ­ ÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù.

<evaluate expression="searchService.findHotel(hotelId)" result="conversationScope.hotel" />
            
3.5.6. requestParameters

requestParameters¸¦ »ç¿ëÇÏ¿© Ŭ¶óÀ̾ðÆ® ¿äû ¸Å°³º¯¼ö¿¡ Á¢±ÙÇÑ´Ù.

<set name="requestScope.hotelId" value="requestParameters.id" type="long" />
            
3.5.7. currentEvent

currentEvent¸¦ »ç¿ëÇÏ¿© ÇöÀç À̺¥Æ® ¼Ó¼º¿¡ Á¢±ÙÇÑ´Ù.

<evaluate expression="booking.guests.add(currentEvent.guest)" />
            
3.5.8. currentUser

currentUser¸¦ »ç¿ëÇÏ¿© ·Î±×ÀÎÇÑ »ç¿ëÀÚ Á¤º¸(authenticated Principal)¿¡ Á¢±ÙÇÑ´Ù.

<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" 
          result="flowScope.booking" />
            
3.5.9. messageContext

messageContext¸¦ »ç¿ëÇÏ¿© ÇÃ·Î¿ì ¿¡·¯³ª ¼º°ø ¸Þ½ÃÁö¸¦ Æ÷ÇÔÇÑ ÇÃ·Î¿ì ½ÇÇà ¸Þ½ÃÁö¸¦ »ý¼ºÇÏ°í °¡Á®¿À´Âµ¥ »ç¿ëÇÒ ÄÁÅؽºÆ®¿¡ Á¢±ÙÇÑ´Ù.MessageContext Javadoc¿¡¼­ ÀÚ¼¼ÇÑ ³»¿ëÀ» ÂüÁ¶Ç϶ó.

<evaluate expression="bookingValidator.validate(booking, messageContext)" />
            
3.5.10. resourceBundle

resourceBundleÀ» »ç¿ëÇÏ¿© ¸Þ½ÃÁö ¸®¼Ò½º¿¡ Á¢±ÙÇ϶ó.

<set name="flashScope.successMessage" value="resourceBundle.successMessage" />
            

3.5.11. flowRequestContext

flowRequestContext¸¦ »ç¿ëÇÏ¿© RequestContext API¿¡ Á¢±ÙÇ϶ó. ÀÌ°ÍÀº ÇöÀç ÇÃ·Î¿ì ¿äûÀ» ³ªÅ¸³½´Ù.ÀÚ¼¼ÇÑ ³»¿ëÀº API JavadocÀ» ÂüÁ¶Ç϶ó.

3.5.12. flowExecutionContext

flowExecutionContext¸¦ »ç¿ëÇÏ¿© FlowExecutionContext API¿¡ Á¢±ÙÇ϶ó. ÀÌ°ÍÀº ÇöÀç ÇÁ·Î¿ì »óŸ¦ ³ªÅ¸³½´Ù. ÀÚ¼¼ÇÑ ³»¿ëÀº API JavadocÀ» ÂüÁ¶Ç϶ó.

3.5.13. flowExecutionUrl

flowExecutionUrlÀ» »ç¿ëÇÏ¿© ÇöÀç ÇÃ·Î¿ì ½ÇÇà view-state¿¡ ´ëÇÑ ÄÁÅؽºÆ® °ü·Ã URI¿¡ Á¢±ÙÇ϶ó.

3.5.14. externalContext

externalContext¸¦ »ç¿ëÇÏ¿© »ç¿ëÀÚ ¼¼¼Ç ¼Ó¼º°°Àº Ŭ¶óÀ̾ðÆ® ȯ°æ¿¡ Á¢±ÙÇ϶ó. ÀÚ¼¼ÇÑ ³»¿ëÀº ExternalContext API JavaDocÀ» ÂüÁ¶Ç϶ó.

<evaluate expression="searchService.suggestHotels(externalContext.sessionMap.userProfile)" 
          result="viewScope.hotels" />
            
3.6. Scope °Ë»ö ¾Ë°í¸®Áò

º¯¼ö¸¦ ¾î¶² ÇÃ·Î¿ì ½ºÄÚÇÁ¿¡ ÇÒ´çÇÒ ¶§, ÇØ´ç ½ºÄÚÇÁ¸¦ ÂüÁ¶ÇÏ´Â °ÍÀÌ ÇÊ¿äÇÏ´Ù. ¿¹Á¦¸¦ º¸ÀÚ.

<set name="requestScope.hotelId" value="requestParameters.id" type="long" />
        
¾î¶² ½ºÄÚÇÁ¿¡ µé¾îÀÖ´Â º¯¼ö¿¡ ´Ü¼øÇÏ°Ô Á¢±ÙÇÒ ¶§´Â, ½ºÄÚÇÁ¸¦ ¹Ýµå½Ã ÂüÁ¶ÇÏÁö ¾Ê¾Æµµ µÈ´Ù. ¿¹Á¦¸¦ º¸ÀÚ.

<evaluate expression="entityManager.persist(booking)" />
        
À§¿¡¼­ bookingÀ» »ç¿ëÇÑ°Íó·³ ¸¸¾à ½ºÄÚÇÁ¸¦ ÀûÁö ¾ÊÀ¸¸é ½ºÄÚÇÁ °Ë»ö ¾Ë°í¸®ÁòÀÌ Àû¿ëµÈ´Ù. ¾Ë°í¸®ÁòÀº request, flash, view, flow, conversation ½ºÄÚÇÁ¿¡¼­ º¯¼ö¸¦ ã¾Æº»´Ù. ¸¸¾à ÇØ´ç º¯¼ö¸¦ ãÁö ¸øÇϸé EvaluationException ¿¹¿Ü¸¦ ´øÁø´Ù.


½Å°í

'Spring Web Flow > Chapter 3' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 3Àå EL(Expression Language)  (0)2009.01.08
top

SWF 2Àå Ç÷οì Á¤ÀÇÇϱâ



ÂüÁ¶: http://static.springframework.org/spring-webflow/docs/2.0.x/reference/html/index.html

2.1. °³¿ä

À̹ø ÀåÀº User SectionÀ¸·Î ½ÃÀÛÇÑ´Ù. Ç÷οì Á¤ÀÇ ¾ð¾î(flow definition language)¸¦ »ç¿ëÇÏ¿© Ç÷ο츦 ±¸ÇöÇÏ´Â ¹æ¹ýÀ» »ìÆ캼 °ÍÀÌ´Ù. À̹ø ÀåÀÌ ³¡³¯ ¶§ ¿©·¯ºÐÀº ¾ð¾î ±¸Á¶¸¦ ÀÌÇØÇÏ°í Ç÷ο츦 Á¤ÀÇÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.

2.2 Ç÷οì¶õ ¹«¾ùÀΰ¡?

Ç÷οì´Â ¿©·¯ ¹®¸Æ¿¡¼­ ½ÇÇàµÉ ¼ö ÀÖ´Â Àç»ç¿ë °¡´ÉÇÑ ½ºÅÇÀÇ ¿¬¼Óü¸¦ ĸ½¶È­ ÇÑ °ÍÀÌ´Ù. ¾Æ·¡ ±×¸²Àº Garrett Inforamtion Architecture ´ÙÀ̾î±×·¥À¸·Î È£ÅÚ ¿¹¾à ÇÁ·Î¼¼½ºÀÇ ´Ü°è¸¦ ĸ½¶È­ÇÑ Ç÷ο츦 º¸¿©ÁÖ°í ÀÖ´Ù.

»ç¿ëÀÚ »ðÀÔ À̹ÌÁö

Ç÷ο츦 ³ªÅ¸³»´Â »çÀÌÆ® ¸Ê

2.3. ÀϹÝÀûÀÎ Ç÷οìÀÇ ±¸¼º¿ä¼Ò´Â ¹«¾ùÀΰ¡?

½ºÇÁ¸µ À¥ Ç÷ο쿡¼­, Ç÷οì´Â ½ºÅ×ÀÌÆ®("states")¶ó°í ºÎ¸£´Â ½ºÅÇÀÇ ÀÏ·ÃÀ¸·Î ±¸¼ºÇÑ´Ù. ÇϳªÀÇ ½ºÅ×ÀÌÆ®·Î µé¾î°¡¸é º¸Åë »ç¿ëÀÚ¿¡°Ô ¾î¶² ºä Çϳª¸¦ º¸¿©ÁÖ°Ô µÈ´Ù. ÇØ´ç ºä¿¡¼­, ½ºÅ×ÀÌÆ®°¡ ó¸®ÇÒ »ç¿ëÀÚ À̺¥Æ®°¡ ¹ß»ýÇÑ´Ù. ÀÌ·± À̺¥Æ®´Â ´Ù¸¥ ½ºÅ×ÀÌÆ®·Î À̵¿(transition)À» ½ÃÄѼ­ ºä ³×ÀÌ°ÔÀ̼ÇÀ» ÇÏ°Ô ÇÑ´Ù.

¾Æ·¡ ¿¹Á¦´Â ¾Õ¼± ´ÙÀ̾î±×·¥¿¡¼­ »ìÆ캻 È£ÅÚ ¿¹¾à ÇÃ·Î¿ì ±¸Á¶¸¦ º¸¿©ÁÖ°í ÀÖ´Ù.

»ç¿ëÀÚ »ðÀÔ À̹ÌÁö
ÇÃ·Î¿ì ´ÙÀ̾î±×·¥

2.4. ¾î¶»°Ô Ç÷ο츦 ÀÛ¼ºÇϴ°¡?

Ç÷οì´Â À¥ ¾ÖÇø®ÄÉÀÌ¼Ç °³¹ßÀÚµéÀÌ °£´ÜÇÑ XML ±â¹Ý Ç÷οì Á¤ÀÇ ¾ð¾î¸¦ »ç¿ëÇÏ¿© ÀÛ¼ºÇÑ´Ù. À̹ø °¡À̵åÀÇ ´ÙÀ½ ´Ü°è¿¡¼­ ÀÌ ¾ð¾îÀÇ ±¸¼º ¿ä¼Ò¸¦ »ìÆ캸°Ú´Ù.

2.5. ±âº»ÀûÀÎ ¾ð¾î ±¸¼º ¿ä¼Ò

2.5.1 Ç÷οì(flow)

¸ðµç Ç÷οì´Â ´ÙÀ½ÀÇ ·çÆ® ¿¤¸®¸ÕÆ®·Î ½ÃÀÛÇÑ´Ù.

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

</flow>

Ç÷οìÀÇ ¸ðµç ½ºÅ×ÀÌÆ®(state)¸¦ ÀÌ ¿¤¸®¸ÕÆ® ¾È¿¡ Á¤ÀÇÇÑ´Ù. óÀ½¿¡ Á¤ÀÇÇÑ ½ºÅ×ÀÌÆ®°¡ Ç÷οìÀÇ ½ÃÀÛÁ¡ÀÌ µÈ´Ù.

2.5.2. ºä-½ºÅ×ÀÌÆ®(view-state)

view-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© Ç÷ο쿡¼­ ºä¸¦ º¸¿©ÁÖ´Â ´Ü°è¸¦ Á¤ÀÇÇÑ´Ù.

<view-state id="enterBookingDetails" />

±âº»ÀûÀ¸·Î(by convention), ºä-½ºÅ×ÀÌÆ®´Â ÀÚ½ÅÀÇ id¸¦ Ç÷ο찡 À§Ä¡ÇÑ µð·ºÅ͸®ÀÇ ºä ÅÛÇø´À¸·Î ¸ÊÇÎÇÑ´Ù. ¿¹¸¦ µé¾î, À§ÀÇ ½ºÅ×ÀÌÆ®´Â ¸¸¾à Ç÷ο찡 /WEB-INF/hotels/booking µð·ºÅ͸®¿¡ ÀÖ¾ú´Ù¸é, /WEB-INF/hotels/booking/enterBookingDetails.xhtmlÀ» »ç¿ëÀÚ¿¡°Ô º¸¿©ÁÙ °ÍÀÌ´Ù.(rendering)

2.5.3. Æ®·£Áö¼Ç(transition)

transition ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ½ºÅ×ÀÌÆ®¿¡¼­ ¹ß»ýÇÑ À̺¥Æ®¸¦ ó¸®ÇÑ´Ù.

<view-state id="enterBookingDetails">
    <transition on="submit" to="reviewBooking" />
</view-state>
        
ÀÌ·± Æ®·£Áö¼ÇÀÌ ºä ³×ÀÌ°ÔÀ̼ÇÀ» ²ø¾î³½´Ù.

2.5.4. end-state

end-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© Ç÷οì Á¾·á¸¦ Á¤ÀÇÇÑ´Ù.

<end-state id="bookingCancelled" />

Ç÷οì Æ®·£Áö¼ÇÀÌ Á¾·á-»óÅ¿¡ ´Ù´Ù¸£¸é Ç÷ο츦 ³¡³»°í °á°ú¸¦ ¹ÝȯÇÑ´Ù.

2.5.5. üũÆ÷ÀÎÆ®: ±âº» ¾ð¾î ±¸¼º ¿ä¼Ò

¼¼ °³ÀÇ ±¸¼º ¿ä¼Ò view-state, transition, end-state¸¦ °¡Áö°í ¿©·¯ºÐÀº ºü¸£°Ô ¿©·¯ºÐÀÇ ºä ³×ºñ°ÔÀÌ¼Ç ·ÎÁ÷À» Ç¥ÇöÇÒ ¼ö ÀÖ´Ù. ÆÀ¿¡¼­ Ç÷οì ÇൿÀ» Ãß°¡Çϱâ Àü¿¡ ÀÌ ÀÛ¾÷À» Çغ½À¸·Î½á ¸ÕÀú »ç¿ëÀÚ¿Í ÇÔ²² ¾ÖÇø®ÄÉÀÌ¼Ç UI¸¦ °³¹ß¿¡ ÁýÁßÇÒ ¼ö ÀÖ´Ù. ¾Æ·¡ ¿¹Á¦´Â ÀÌµé ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ºä ³×ºñ°ÔÀÌ¼Ç ·ÎÁ÷À» ±¸ÇöÇÑ °ÍÀÌ´Ù.

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <view-state id="enterBookingDetails">
        <transition on="submit" to="reviewBooking" />
    </view-state>
    
    <view-state id="reviewBooking">
        <transition on="confirm" to="bookingConfirmed" />
        <transition on="revise" to="enterBookingDetails" />
        <transition on="cancel" to="bookingCancelled" />
    </view-state>
    
    <end-state id="bookingConfirmed" />

    <end-state id="bookingCancelled" />
        
</flow>    

2.6. ¾×¼Ç(Actions)

´ëºÎºÐÀÇ Ç÷οì´Â ´Ü¼øÈ÷ ºä ³×ºñ°ÔÀÌ¼Ç ·ÎÁ÷ º¸´Ù ´õ ¸¹Àº °ÍÀ» Ç¥ÇöÇÒ ÇÊ¿ä°¡ ÀÖ´Ù. ÀϹÝÀûÀ¸·Î ¾ÖÇø®ÄÉÀ̼ÇÀÇ ºñÁî´Ï½º ¼­ºñ½º ¶Ç´Â ´Ù¸¥ ¾×¼ÇÀ» È£ÃâÇÒ ÇÊ¿ä°¡ ÀÖ´Ù.

Ç÷ο쿡¼­ ¿©·¯ºÐÀÌ ¾×¼ÇÀ» ½ÇÇàÇÒ ¼ö ÀÖ´Â ¸î¸î Æ÷ÀÎÆ®(point)°¡ ÀÖ´Ù. 
  • On flow start
  • On state entry
  • On view render
  • On transition execution
  • On state exit
  • On flow end
¾×¼ÇÀº °£°áÇÑ EL(expression language)·Î Á¤ÀÇÇÑ´Ù. ½ºÇÁ¸µ À¥ Ç÷οì´Â ±âº»ÀûÀ¸·Î UEL(Unified EL)À» »ç¿ëÇÑ´Ù. ´ÙÀ½ÀÇ ¸î¸î Àý¿¡¼­ ¾×¼ÇÀ» Á¤ÀÇÇÒ ¶§ »ç¿ëÇÏ´Â ±âº» ¾ð¾î ±¸¼º ¿ä¼Ò¸¦ »ìÆ캸°Ú´Ù.

2.6.1. evaluate

¿©·¯ºÐÀÌ »ç¿ëÇÒ ´ëºÎºÐÀÇ ¾×¼Ç ¿¤¸®¸ÕÆ®´Â evaluate ¿¤¸®¸ÕÆ®ÀÏ °ÍÀÌ´Ù. evaluate ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© Ç÷οìÀÇ ¾î¶² ¼ø°£(point)¿¡ Ç¥Çö½ÄÀÇ °ªÀ» ±¸ÇÒ ¼ö ÀÖ´Ù. ÀÌ ÅÂ±× Çϳª·Î ½ºÇÁ¸µ ºó ¶Ç´Â ´Ù¸¥ ÇÃ·Î¿ì º¯¼öÀÇ ¸Þ¼Òµå¸¦ È£ÃâÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î ´ÙÀ½°ú °°ÀÌ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

<evaluate expression="entityManager.persist(booking)" />

2.6.1.1. evaluate °á°ú°ª ´ëÀÔÇϱâ

¸¸¾à Ç¥Çö½ÄÀÌ °ªÀ» ¹ÝȯÇÑ´Ù¸é, ±× °ªÀ» Ç÷οìÀÇ µ¥ÀÌÅÍ ¸ðµ¨ flowScope¿¡ ÀúÀåÇÒ ¼ö ÀÖ´Ù.

<evaluate expression="bookingService.findHotels(searchCriteria)" result="flowScope.hotels" />

2.6.1.2. evaluate °á°ú°ª º¯°æÇϱâ

¸¸¾à Ç¥Çö½ÄÀÌ ¹ÝȯÇÏ´Â °ªÀÌ ÄÁ¹öÆÃÀÌ ÇÊ¿äÇÏ´Ù¸é, ¿øÇϴ ŸÀÔÀ» result-type ¼Ó¼º¿¡ ¸í½ÃÇÒ ¼ö ÀÖ´Ù.

<evaluate expression="bookingService.findHotels(searchCriteria)" result="flowScope.hotels"
          result-type="dataModel"/>
                
2.6.2. üũÆ÷ÀÎÆ®: ÇÃ·Î¿ì ¾×¼Ç

ÀÌÁ¦ ¿¹Á¦ ¿¹¾à Ç÷ο쿡 ¾×¼ÇÀ» Ãß°¡Çغ¸ÀÚ.

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <input name="hotelId" />

    <on-start>
        <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" 
                  result="flowScope.booking" />
    </on-start>

    <view-state id="enterBookingDetails">
        <transition on="submit" to="reviewBooking" />
    </view-state>
    
    <view-state id="reviewBooking">
        <transition on="confirm" to="bookingConfirmed" />
        <transition on="revise" to="enterBookingDetails" />
        <transition on="cancel" to="bookingCancelled" />
    </view-state>
    
    <end-state id="bookingConfirmed" />

    <end-state id="bookingCancelled" />
        
</flow>    

ÀÌ Ç÷οì´Â ÀÌÁ¦ Ç÷ο찡 ½ÃÀ۵Ǹé Booking °´Ã¼¸¦ Ç÷ο쿡 »ý¼ºÇÑ´Ù. ¿¹¾àÇÏ·Á´Â È£ÅÚÀÇ id´Â Ç÷οì input ¼Ó¼º¿¡¼­ ¾ò¾î¿Â´Ù.

2.7. Input/Output ¸ÊÇÎ

°¢°¢ÀÇ Ç÷οì´Â Àß Á¤ÀǵǾî ÀÖ´Â input/output Á¦¾àÀ» °¡Áö°í ÀÖ´Ù. Ç÷ο츦 ½ÃÀÛÇÒ ¶§ input ¼Ó¼º¿¡ flow¸¦ ³Ñ°ÜÁÙ ¼ö ÀÖ°í, Ç÷ο찡 ³¡³¯ ¶§ flow¸¦ output ¼Ó¼º¿¡ ³Ñ°ÜÁÙ ¼ö ÀÖ´Ù. Ç÷ο츦 È£ÃâÇÏ´Â °ÍÀº ´ÙÀ½ ½Ã±×³Êó¸¦ °¡Áø ¸Þ¼Òµå¸¦ È£ÃâÇÏ´Â °Í°ú ºñ½ÁÇÏ´Ù.

FlowOutcome flowId(Map<String, Object> inputAttributes);

FlowOutcomeÀº ´ÙÀ½°ú °°ÀÌ »ý°å´Ù.

public interface FlowOutcome {
   public String getName();                
   public Map<String, Object> getOutputAttributes();
}

2.7.1. input

input ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© Ç÷οìÀÇ input ¼Ó¼ºÀ» ¼±¾ðÇÑ´Ù.

<input name="hotelId" />

ÀÔ·ÂÇÑ °ªÀº ¼Ó¼ºÀÇ nameÀ¸·Î flow ½ºÄÚÇÁ¿¡ ÀúÀåµÈ´Ù. ¿¹¸¦ µé¾î, À§ÀÇ inputÀº hotelId¶ó´Â À̸§À¸·Î ÀúÀåµÉ °ÍÀÌ´Ù.

2.7.1.1. input ŸÀÔ ¼±¾ðÇϱâ

type ¼Ó¼ºÀ» »ç¿ëÇÏ¿© input ¼Ó¼ºÀÇ Å¸ÀÔÀ» ¼±¾ðÇÒ ¼ö ÀÖ´Ù.

<input name="hotelId" type="long" />

¸¸¾à input °ªÀÌ ¼±¾ðÇÑ Å¸ÀÔ°ú ÀÏÄ¡ÇÏÁö ¾ÊÀ¸¸é, ŸÀÔ ÀüȯÀ» ½ÃµµÇÑ´Ù.

2.7.1.2. input °ª ´ëÀÔÇϱâ

value ¼Ó¼ºÀ» »ç¿ëÇÏ¿© input °ª¿¡ ´ëÀÔÇÒ Ç¥Çö½ÄÀ» ±â¼úÇÒ ¼ö ÀÖ´Ù.

<input name="hotelId" value="flowScope.myParameterObject.hotelId" />

type ¼Ó¼ºÀ» ±â¼úÇÏÁö ¾Ê¾ÆÀ» ¶§, Ç¥Çö½Ä °ªÀÇ Å¸ÀÔÀ» ÆǺ°ÇÒ ¼ö ÀÖ´Ù¸é ÇØ´ç ¸ÞŸµ¥ÀÌÅ͸¦ ŸÀÔ Á¦¾àÀ¸·Î »ç¿ëÇÒ °ÍÀÌ´Ù.

2.7.1.3. inputÀ» Çʼö·Î ¸¸µé±â

required ¼Ó¼ºÀ» »ç¿ëÇÏ¿© inputÀÌ nullÀ̰ųª ºó°ªÀÌ ¾Æ´Ïµµ·Ï °­Á¦ÇÒ ¼ö ÀÖ´Ù.

<input name="hotelId" type="long" value="flowScope.hotelId" required="true" />

2.7.2. output

output ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© Ç÷οì output ¼Ó¼ºÀ» ¼±¾ðÇÒ ¼ö ÀÖ´Ù. output ¼Ó¼ºÀº ƯÁ¤ Ç÷οì Á¾·á¸¦ ³ªÅ¸³»´Â end-states ³»ºÎ¿¡ ¼±¾ðÇÑ´Ù.

<end-state id="bookingConfirmed">
    <output name="bookingId" />  
</end-state>
        
output °ªÀº name ¼Ó¼º °ª°ú ÀÏÄ¡ÇÏ´Â °ÍÀ» flow ½ºÄÚÇÁ¿¡¼­ °¡Á®¿Â´Ù. ¿¹¸¦ µé¾î, À§ÀÇ outputÀº bookingId º¯¼öÀÇ °ªÀ» ´ëÀÔÇÒ °ÍÀÌ´Ù.

2.7.2.1. output °ª ±â¼úÇϱâ

value ¼Ó¼ºÀ» »ç¿ëÇÏ¿© output °ª Ç¥Çö½ÄÀ» ±â¼úÇÒ ¼ö ÀÖ´Ù.

<output name="confirmationNumber" value="booking.confirmationNumber" />  

2.7.3. üũÆ÷ÀÎÆ®: input/output ¸ÊÇÎ

ÀÌÁ¦ ¿¹Á¦ ¿¹¾à Ç÷ο쿡¼­ input/output ¸ÊÇÎÀ» ´Ù½Ã »ìÆ캸ÀÚ.

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <input name="hotelId" />

    <on-start>
        <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" 
                  result="flowScope.booking" />
    </on-start>

    <view-state id="enterBookingDetails">
        <transition on="submit" to="reviewBooking" />
    </view-state>
    
    <view-state id="reviewBooking">
        <transition on="confirm" to="bookingConfirmed" />
        <transition on="revise" to="enterBookingDetails" />
        <transition on="cancel" to="bookingCancelled" />
    </view-state>
    
    <end-state id="bookingConfirmed" >
        <output name="bookingId" value="booking.id"/>
    </end-state>

    <end-state id="bookingCancelled" />
        
</flow>    

Ç÷οì´Â hotelId¶ó´Â input ¼Ó¼ºÀ» ¹Þ°í »õ·Î¿î ¿¹¾àÀÌ È®Á¤µÇ¸é bookingId¶ó´Â output ¼Ó¼ºÀ» ¹ÝȯÇÑ´Ù.

2.8. º¯¼ö(Variables)

Ç÷οì´Â ÇÑ °³ ÀÌ»óÀÇ º¯¼ö¸¦ ¼±¾ðÇÒ ¼ö ÀÖ´Ù. ÀÌµé º¯¼ö´Â Ç÷ο찡 ½ÃÀÛÇÒ ¶§ ÀÚ¸®¸¦ Àâ´Â´Ù. º¯¼öµéÀÌ °¡Áö°í ÀÖ´Â ¸ðµç @Autowired Àӽà ·¹ÆÛ·±½ºµé ¶ÇÇÑ Ç÷ο찡 Àç½ÃÀÛ ÇÒ ¶§ ´Ù½Ã ¿ÍÀ̾ÇÑ´Ù.

2.8.1. var

var ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ÇÃ·Î¿ì º¯¼ö¸¦ ¼±¾ðÇÑ´Ù.

<var name="searchCriteria" class="com.mycompany.myapp.hotels.search.SearchCriteria"/>

¿©·¯ ÇÃ·Î¿ì ¿äû(request)¿¡ °ÉÃÄ ÀνºÅϽº »óŸ¦ ÀúÀåÇÒ ¶§ ÇØ´ç Ŭ·¡½º°¡ java.io.SerializableÀ» ±¸ÇöÇß´ÂÁö È®ÀÎÇ϶ó.

2.9. subflow È£ÃâÇϱâ

Ç÷ο쿡¼­ ´Ù¸¥ Ç÷ο츦 ÇÏÀ§ Ç÷οì(subflow)·Î È£ÃâÇÒ ¼ö ÀÖ´Ù. Ç÷οì´Â ¼­ºêÇ÷ο찡 ³¡³¯ ¶§±îÁö ±â´Ù·È´Ù°¡ ¹Ýȯ°ªÀÌ ¿À¸é ±×¶§ ¼­ºê ÇÃ·Î¿ì °á°ú¿¡ ÀÀ´ä(response)À» ÇÑ´Ù.

2.9.1. subflow-state

subflow-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ´Ù¸¥ Ç÷ο츦 ¼­ºêÇ÷οì·Î È£ÃâÇϱâ

<subflow-state id="addGuest" subflow="createGuest">
    <transition on="guestCreated" to="reviewBooking">
        <evaluate expression="booking.guests.add(currentEvent.attributes.guest)" />  
    </transition>
    <transition on="creationCancelled" to="reviewBooking" />
</subfow-state>

À§ÀÇ ¿¹Á¦´Â createGuest¸¦ È£ÃâÇÏ°í ÀÖ´Ù. ±×·± ´ÙÀ½ ¹ÝȯµÇ±â¸¦ ±â´Ù¸°´Ù. Ç÷ο찡 guestCreated¶ó´Â °á°ú¸¦ ¹ÞÀ¸¸é, »õ·Î¿î guest¸¦ booking guest ¸®½ºÆ®¿¡ Ãß°¡ÇÑ´Ù.

2.9.1.1. subflow input Àü´ÞÇϱâ

input ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© inputÀ» ¼­ºêÇ÷ο쿡 Àü´ÞÇÑ´Ù.

<subflow-state id="addGuest" subflow="createGuest">
    <input name="booking" />
    <transition to="reviewBooking" />
</subfow-state>

2.9.1.2. ¼­ºêÇ÷οì output ¸ÊÇÎÇϱâ

°£´ÜÇÏ°Ô ¼­ºêÇ÷οì output ¼Ó¼ºÀ» °á°ú Æ®·£Áö¼Ç¿¡¼­ ±× À̸§À¸·Î ÂüÁ¶ÇÒ ¼ö ÀÖ´Ù.

<transition on="guestCreated" to="reviewBooking">
    <evaluate expression="booking.guests.add(currentEvent.attributes.guest)" />  
</transition>
        
À§¿¡¼­ guest´Â guestCreated °á°ú¿¡ ÀÇÇØ ¹ÝȯµÇ´Â output ¼Ó¼º À̸§ÀÌ´Ù.

2.9.2. üũÆ÷ÀÎÆ®: ¼­ºêÇ÷οì È£ÃâÇϱâ

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <input name="hotelId" />

    <on-start>
        <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" 
                  result="flowScope.booking" />
    </on-start>

    <view-state id="enterBookingDetails">
        <transition on="submit" to="reviewBooking" />
    </view-state>

    <view-state id="reviewBooking">
        <transition on="addGuest" to="addGuest" />
        <transition on="confirm" to="bookingConfirmed" />
        <transition on="revise" to="enterBookingDetails" />
        <transition on="cancel" to="bookingCancelled" />
    </view-state>

    <subflow-state id="addGuest" subflow="createGuest">
        <transition on="guestCreated" to="reviewBooking">
            <evaluate expression="booking.guests.add(currentEvent.attributes.guest)" />  
        </transition>
        <transition on="creationCancelled" to="reviewBooking" />
    </subfow-state>
        
    <end-state id="bookingConfirmed" >
        <output name="bookingId" value="booking.id" />
    </end-state>

    <end-state id="bookingCancelled" />
        
</flow>        

Ç÷οì´Â ÀÌÁ¦ createGuest ¼­ºêÇ÷ο츦 È£ÃâÇÏ¿© »õ·Î¿î °Ô½ºÆ®¸¦ °Ô½ºÆ® ¸ñ·Ï¿¡ Ãß°¡ÇÑ´Ù.
½Å°í

'Spring Web Flow > Chapter 2' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF 2Àå Ç÷οì Á¤ÀÇÇϱ⠠(0)2009.01.02
top

SWF Chapter 1



ÂüÁ¶: ½ºÇÁ¸µ À¥ ÇÃ·Î¿ì ·¹ÆÛ·±½º 1 Àå

1. ¼Ò°³

1.1 ÀÌ °¡À̵尡 ´Ù·ç°í ÀÖ´Â °Í

ÀÌ °¡À̵å´Â ½ºÇÁ¸µ À¥ Ç÷οì¿Í °ü·ÃµÈ ¸ðµç °ÍÀ» ´Ù·é´Ù. ÃÖÁ¾-»ç¿ëÀÚ ¾ÖÇø®ÄÉÀ̼ÇÀÇ Ç÷ο츦 ±¸ÇöÇÏ´Â ¹æ¹ý°ú ±â´É µéÀ» »ç¿ëÇÏ´Â ¹æ¹ýÀ» ´Ù·é´Ù. ¶ÇÇÑ ÇÁ·¹ÀÓ¿öÅ©¸¦ È®ÀåÇÏ´Â ¹æ¹ý°ú ÀüüÀûÀÎ ¾ÆÅ°ÅØó ¸ðµ¨µµ ´Ù·é´Ù.

1.2. À¥ Ç÷ο츦 ½ÇÇàÇÒ ¶§ ÇÊ¿ä·Î ÇÏ´Â °Í

ÀÚ¹Ù 1.4 ÀÌ»ó

½ºÇÁ¸µ 2.5.4 ÀÌ»ó

1.3 Áö¿øÀ» ¹ÞÀ» ¼ö ÀÖ´Â °÷

»ý·«

1.4. °³¹ßÀ» ÁÖµµ ÇÒ ¼ö ÀÖ´Â °÷

»ý·«

1.5. À¥ ÇÃ·Î¿ì ±¸¼º ¿ä¼Ò¸¦ ½ºÇÁ¸µ¼Ò½º ¹øµé ÀúÀå¼Ò¿¡¼­ ¾ò´Â ¹æ¹ý

°¢°¢ÀÇ À¥ ÇÃ·Î¿ì ¹èÆ÷ÆÇÀÇ jar ÆÄÀϵéÀº ½ºÇÁ¸µ¼Ò½º ¿£ÅÍÇÁ¶óÀÌÁî ¹øµé ÀúÀå¼Ò¿¡¼­ ¾òÀ» ¼ö ÀÖ´Ù. ÀÌ jar ÆÄÀϵ鿡 ¸ÞÀ̺ìÀ̳ª Ivy ÀÇÁ¸¼º °ü¸®ÀÚ¸¦ »ç¿ëÇÏ¿© Á¢±ÙÇÒ ¼ö ÀÖ´Ù.

1.5.1. ¸ÞÀ̺ìÀ¸·Î À¥ Ç÷ο쿡 Á¢±ÙÇϱâ

¸ÞÀ̺ìÀ» »ç¿ëÇÏ¿© jar¿¡ Á¢±Ù ÇÏ·Á¸é ´ÙÀ½ ÀúÀå¼Ò¸¦ ¸ÞÀ̺ì pom¿¡ Ãß°¡Ç϶ó.

<repository>
    <id>com.springsource.repository.bundles.release</id>
    <name>SpringSource Enterprise Bundle Repository - SpringSource 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 Releases</name>
    <url>http://repository.springsource.com/maven/bundles/external</url>
</repository>
            

±×·± ´ÙÀ½ ´ÙÀ½ÀÇ ÀÇÁ¸¼ºÀ» Ãß°¡Ç϶ó.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.binding</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency> 

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.js</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency> 

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.webflow</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency> 

        
±×¸®°í ¸¸¾à JSF(JavaServerFaces)¸¦ »ç¿ëÇÏ°í ÀÖ´Ù¸é ´ÙÀ½À» Ãß°¡Ç϶ó.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.faces</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency> 

           
1.5.2. Ivy·Î À¥ Ç÷ο쿡 Á¢±ÙÇϱâ

Ivy¸¦ »ç¿ëÇÏ¿© jar ÆÄÀÏ¿¡ Á¢±ÙÇÏ·Á¸é, ´ÙÀ½ ÀúÀå¼Ò¸¦ Ivy ¼³Á¤¿¡ Ãß°¡Ç϶ó.

<url name="com.springsource.repository.bundles.release">
    <ivy pattern="http://repository.springsource.com/ivy/bundles/release/
                  [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
    <artifact pattern="http://repository.springsource.com/ivy/bundles/release/
                       [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>

<url name="com.springsource.repository.bundles.external">
    <ivy pattern="http://repository.springsource.com/ivy/bundles/external/
                  [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
    <artifact pattern="http://repository.springsource.com/ivy/bundles/external/
                       [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" />
</url>
            

±×·± ´ÙÀ½ ´ÙÀ½ ÀÇÁ¸¼ºÀ» ¼±¾ðÇ϶ó.

<dependency org="org.springframework.webflow" name="org.springframework.binding"
            rev="2.0.5.RELEASE" conf="compile->runtime" />
<dependency org="org.springframework.webflow" name="org.springframework.js"
            rev="2.0.5.RELEASE" conf="compile->runtime" />
<dependency org="org.springframework.webflow" name="org.springframework.webflow"
            rev="2.0.5.RELEASE" conf="compile->runtime" />

            

±×¸®°í ¸¸¾à JSF¸¦ »ç¿ëÇÑ´Ù¸é ´ÙÀ½À» Ãß°¡Ç϶ó.

<dependency org="org.springframework.webflow" name="org.springframework.faces"
            rev="2.0.5.RELEASE" conf="compile->runtime" />

            
1.6. ¸ÞÀ̺ì Áß¾Ó ÀúÀå¼Ò¿¡¼­ À¥ ÇÃ·Î¿ì ±¸¼º ¿ä¼Ò ¾ò´Â ¹æ¹ý

À¥ ÇÃ·Î¿ì ¹èÆ÷ÆÇÀÇ ¸ðµç jar ÆÄÀÏÀº ¸ÞÀ̺ì Áß¾Ó ÀúÀå¼Ò¿¡¼­µµ Á¢±ÙÇÒ ¼ö ÀÖ´Ù.

¸ÞÀ̺ì Áß¾Ó ÀúÀå¼Ò¿¡ ÀÖ´Â À¥ Ç÷οì jar¿¡ Á¢±ÙÇÏ·Á¸é ´ÙÀ½ ÀÇÁ¸¼ºÀ» pom¿¡ Ãß°¡Ç϶ó.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.binding</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency> 

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.js</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency> 

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.webflow</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

        
¸¸¾à JSF¸¦ »ç¿ëÇÑ´Ù¸é ´ÙÀ½À» Ãß°¡Ç϶ó.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.faces</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency> 

        
1.7. ³ªÀÌƲ¸® ºôµå ¾ò´Â ¹æ¹ý

³ªÀÌƲ¸® ½º³À¼¦ ¹öÀüÀÇ À¥ Ç÷οì Æ®··Å©´Â ½ºÇÁ¸µ ¼Ò½º ¹øµé ÀúÀå¼Ò¿¡¼­ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù. ½º³À¼¦¿¡ Á¢±ÙÇÏ·Á¸é ´ÙÀ½ ÀúÀå¼Ò¸¦ pom¿¡ Ãß°¡Ç϶ó.

<repository>
    <id>com.springsource.repository.bundles.snapshot</id>
    <name>SpringSource Enterprise Bundle Repository - Nightly Snapshots</name>
    <url>http://repository.springsource.com/maven/bundles/snapshot</url>
</repository>
        
±×¸®°í ´ÙÀ½ ÀÇÁ¸¼ºÀ» ¼±¾ðÇ϶ó.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.binding</artifactId>
    <version>3.0.0.CI-###</version>
</dependency> 

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.js</artifactId>
    <version>3.0.0.CI-###</version>
</dependency> 

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.webflow</artifactId>
    <version>3.0.0.CI-###</version>
</dependency> 

            
±×¸®°í ¸¸¾à JSF¸¦ »ç¿ëÇÑ´Ù¸é ´ÙÀ½À» Ãß°¡Ç϶ó.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.faces</artifactId>
    <version>3.0.0.CI-###</version>
</dependency> 

        
À§¿¡¼­ '# # #'Àº 3.0.0.CI-500 °°Àº ºôµå ³Ñ¹ö¸¦ ³ªÅ¸³½ °ÍÀÌ´Ù. ÃÖ±Ù ºôµå ³Ñ¹ö¸¦ ¾Ë°í ½Í´Ù¸é ³ªÀÌƲ¸® ºôµå ¿µ¿ªÀ» ÂüÁ¶Ç϶ó.
½Å°í

'Spring Web Flow > Chapter 1' Ä«Å×°í¸®ÀÇ ´Ù¸¥ ±Û

SWF Chapter 1  (0)2008.12.27
top

Spring Web Flow 2.0 Ư¡

Spring Web Flow/etc : 2008.04.26 11:11


ÂüÁ¶ : http://www.infoq.com/news/2008/04/spring-webflow-2rc
¿¹Á¦ : http://richweb.springframework.org/swf-booking-faces/spring/intro

Web Flow 2.0ÀÇ »õ·Î¿î ±â´ÉÀº?

- Progressive Ajax:  Ajax À̺¥Æ® Çڵ鸵 ±â´ÉÀ» Ãß°¡Çß´Ù. ´Ù¸¥ À¥ Ç÷οì À̺¥Æ®Ã³·³ Ajax À̺¥Æ®¸¦ ó¸®ÇÒ ¼ö ÀÖ´Ù. ÀÚ¹Ù½ºÅ©¸³Æ®¸¦ Ŭ¶óÀ̾ðÆ® ÂÊ¿¡¼­ »ç¿ëÇÏÁö ¾Ê¾Æµµ Á¦´ë·Î µ¿ÀÛÇϵµ·ÏÇسù´Ù. Ajax Áö¿ø ±â´ÉÀº ¼­¹öÂÊ ±â´É°ú Ŭ¶óÀ̾ðÆ®ÂÊ ±â´É µÑ·Î ³ª´²Á®ÀÖ´Ù.

- Spring MVC¿Í ´õ ±ä¹ÐÇÑ ÅëÇÕ: Spring MVC¿Í »óÈ£ º¸¿Ï °ü°èÀÌ´Ù. StatelessÇÑ Spring MVC @Controller°¡ Folw¸¦ È£ÃâÇÒ ¼ö ÀÖ°í FlowÀÇ °á°ú°¡ ÄÁÆ®·Î·¯¿¡ ¸ÊÇ뵃 ¼ö ÀÖ´Ù. 

- À籸¼ºÇÏ°í È®ÀåµÈ JSF¿ÍÀÇ ÅëÇÕ: JSF ³»¿ëÀº Æнº Àúµµ Àß ¸ð¸£±â ¶«½Ã..

- Spring Security¾ÆÀÇ ÅëÇÕ: Ç÷ο쿡 º¸¾È ±â´ÉÀ» Ãß°¡ÇÒ ¼ö ÀÖ´Ù. Ç÷οì, ½ºÅ×ÀÌÆ®, Æ®·£Áö¼Ç¿¡ @Secured¸¦ ¾Ö³ëÅ×À̼ÇÀ» ºÙÀ̸é SecurityFlowExecutionListener°¡ »ç¿ëÀÚÀÇ ÀÎÁõÀ» ¿ä±¸ÇÑ µÚ¿¡ Ç÷ο츦 ½ÃÀÛÇÏ°í, ½ºÅÜÀ» ÁøÇàÇÏ°í À̺¥Æ®¸¦ ½ÃÀÛÇÒ °ÍÀÌ´Ù.

- º¸´Ù °£´ÜÇÑ Spring Folw Definition Language: 200ÁÙ °¡·®ÀÇ ÄÚµå¿Í 6°³ÀÇ ÆÄÀÏÀÌ ÇÊ¿äÇÑ ¾ÖÇø®ÄÉÀ̼ÇÀÌ µ¿ÀÏÇÑ ±â´ÉÀ» ÀÌÁ¦´Â 93¶óÀÎÀÇ ÄÚµå¿Í 2°³ÀÇ ÆÄÀÏ·Î ÇÒ ¼ö ÀÖ´Ù.

- »õ·Î¿î ¸ðµâÈ­ ±â´É: Ç÷οìÀÇ °³³äÀ» "Àç»ç¿ë °¡´ÉÇϸç, µ¶¸³ÀûÀÎ ¾ÖÇø®ÄÉÀÌ¼Ç ÄÁÆ®·Ñ ¸ðµâ"·Î È®ÀåÇß´Ù. µû¶ó¼­ ±âº»ÀûÀ¸·Î Ç÷οì¿Í ±×°ÍÀÌ »ç¿ëÇÏ´Â ¸®¼Ò½ºÀÎ ºä, ¸Þ½ÃÁö, ÇïÆÛµîÀ» Çϳª·Î ÆÐŰ¡µÈ´Ù. 

À̹ø ¹èÆ÷ÀÇ ¹è°æÀÌ µÇ´Â öÇÐÀº ¹«¾ùÀΰ¡?

- »ç¿ë¼º ÆíÀÇ´Ù.

1.0¿¡¼­ 2.0À¸·Î ÀÌÀüÇϴµ¥ ÇÊ¿äÇÑ Áß´ë º¯È­´Â?

- Web Flow Definition Language´Ù. ±×·¡¼­ 1.0 Á¤ÀǸ¦ 2.0À¸·Î ¹Ù²ãÁÖ´Â ±â´ÉÀ» Á¦°øÇÑ´Ù. Àϸí WebFlowUpgrader xnf.

½ºÇÁ¸µ À¥ Ç÷ο츦 Áö¿øÇÏ´Â µµ±¸´Â?

- ½ºÇÁ¸µ IDE

¾ÕÀ¸·Î À¥ Ç÷οìÀÇ °³¹ß ¹æÇâ°ú, 2.1 ¹èÆ÷ÀÇ ÃÊÁ¡Àº?

- ¼±¾ðÀûÀÎ ¸ðµ¨ °ËÁõ. ¾Ö³ëÅ×À̼ÇÀ¸·Î ValidationÀ» ÇÒ ¼ö ÀÖµµ·Ï.. ¼±¾ðÀûÀ¸·Î ¸ðµ¨¿¡ º§¸®µ¥ÀÌ¼Ç ±ÔÄ¢À» ºÙ¿©µÎ¸é, ±×°ÍÀ» ¼­¹ö »çÀ̵å¿Í Ŭ¶óÀ̾ðÆ® »çÀ̵忡 ¹Ý¿µÇØÁÖ´Â.. 
- Grooby·Î Flow Definition ÀÛ¼ºÇÏ´Â ±â´É.