Spring MVC - MultiActionController를 이용하여 다수의 요청 처리하기

2010. 8. 27. 01:06plming/Java - Spring

  비즈니스 계층과의 통신이 없는 정적인 페이지에 접근해야 되는 경우가 종종 발생한다. 정적인 페이지에 직접 접근할 수도 있겠지만 웹 애플리케이션의 모든 URL에 대하여 공통적인 작업을 처리할 필요가 있을 경우에는 정적인 페이지 또한 DispatcherServlet을 통하여 접근하도록 개발할 경우 쉽게 해결할 수 있다.

  모델 2 개발 방식으로 애플리케이션을 개발할 때 항상 논란의 여지가 되는 부분이 정적인 페이지, 입력화면에 직접 접근하는 것을 허용할지에 대한 여부이다.  물론 이 같은 페이지에 DispatcherServlet을 거치지 않고 직접 접근하는 것도 좋은 방법이다.  하지만 이와 같이 개발할 경우 애플리케이션 전체에 걸쳐서 영향을 미치게 될 인증이나 공통적인 기능을 구현할 경우 문제가 발생할 수 있다.  따라서 가능한 페이지에 직접 접근하는 것을 막는 것이 좋은 방법이다.

  개발자 뿐만 아니라 일반 사용자들이 JSP파일에 직접적으로 접근하는 것을 막기 위하여 모든 JSP파일을 WEB-INF 디렉토리내에서 관리하고 있다.  WEB-INF 디렉토리는 일반 사용자들이 직접 접근할 수 없는 디렉토리 이므로 모델 2 개발 방식으로 개발할 때 JSP파일을 관리하기 위하여 좋은 곳이다.



1. MultiActionController를 이용하여 다수의 요청 처리하기
   MultiActionController는 하나의 Controller를 구현함으로서 다수의 요청을 처리하는 것이 가능하도록 지원한다.  클라이언트가 전달하는 입력데이터가 많지 않아 특별한 유효성 체크가 필요하지 않고 비즈니스 계층과의 통신이 필요한 경우에 유용하게 사용될 수 있다.

 public class UserController extends MultiActionController {
     private UserService userService = null;

     public void setUserService(UserService userService) {
         this.userService = userService;
     }

     public ModelAndView view(HttpServletRequest request,
             HttpServletResponse response) throws Exception {
         return new ModelAndView("user/view", "user", userService
                 .findUser(userId)
);
     }

     public ModelAndView list(HttpServletRequest request,
             HttpServletResponse response) throws Exception {
         return new ModelAndView("user/list", "userList", userService
                 .findUserList()
);
     }
 }


 action-servlet-xml : URL과 매핑하는 부분

 <bean name="/user/listUser.do /user/viewUser.do" class="net.javajigi.user.web.UserController">
     <property name="methodNameResolver">
         <ref local="userControllerMethodNameResolver" />
     </property>
     <property name="userService" ref="userService" />
 </bean>

 <bean id="userControllerMethodNameResolver"
 class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
     <property name="mappings">
         <props>
             <prop key="/user/listUser.do">list</prop>
             <prop key="/user/viewUser.do">view</prop>
         </props>
     </property>
 </bean>


위의 예제를 보면, UserController하나에 두개(/user/listUser.do, /user/viewUser.do)의 URL이 매핑된 것을 확인할 수 있다.  이 각각의 URL이 호출될 때 UserController의 메써드에서 어느 메써드가 호출될지에 대한 정보는 "userControllerMethodNameResolver" 빈에서 PropertiesMethodNameResolver 클래스를 이용하여 매핑할 수 있다.  이와 같이 매핑을 연결할 경우 "/user/listUser.do"가 호출될 때 UserController의 list() 메써드가 호출되게 된다.

또한, 비즈니스 계층을 담당하고 있는 UserService 인스턴스가 Spring 프레임워크의 Setter Injection 방식으로 전달되고 있는 것을 확인할 수 있다.  이와 같이 Spring MVC를 이용할 경우 웹 애플리케이션 개발을 위한 모든 결합이 Dependency Injection 방식으로 구현하는 것이 가능해진다.


 action-servlet.xml : URL과 매핑하는 부분

 <bean name="/board/board.do" class="net.javajigi.board.web.BoardController">
     <property name="boardService" ref="boardService" />
     <property name="methodNameResolver" ref="methodNameResolver" />
 </bean>

 <bean id="methodNameResolver"
 class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
     <property name="paramName">
         <value>method</value>
     </property>
     <property name="defaultMethodName">
         <value>list</value>
     </property>
 </bean>


위의 매핑 정보는 "/board/board.do" 하나의 URL에 BoardController를 매핑하고 있다.  BoardController의 메써드를 호출하도록 결정하는 부분은 "methodNameResolver" 빈에서 ParameterMethodNameResolver를 이용하는 부분이다.  URL을 통하여 전달되는 인자 중 "method"라는 이름을 가지는 인자의 값에 해당하는 메써드를 호출한다는 것이다.  만약 "method"라는 인자가 없을 경우에는 list() 메써드를 디폴트로 호출하게 된다.

URL을 "/board/board.do"의 인자에 "method=view"로 호출할 경우(/board/board.do?method=view&...) BoardController의 view() 메써드가 실행된다.


Spring MVC의 ParameterMethodNameResolver을 이용할 경우 MultiActionController에 메써드가 추가되더라도 빈 설정파일에 추가적인 설정이 필요없다.  단지 화면 이동시에 추가된 메써드 이름을 인자로 전달하면 된다.

MultiActionController를 사용할 때 매핑 방식을 어떤 방식으로 사용할지는 개발자들의 취향에 달려있으며 굳이 어느 방법을 사용할지 고정시킬 필요는 없다.


[출처] http://www.javajigi.net/pages/viewpage.action?pageId=28377093
[출처] Spring 프레임워크 워크북