Controller
컨트롤러는 MVC중 C(Controller)에 해당하며 사용자의 입력을 받은 뒤 적절한 뷰를 찾아 뷰에 필요한 모델 객체를 넘겨 준다.
Spring MVC에서는 다양한 Controller Interface의 구현체를 제공한다.
구현체의 대표적인 몇 가지를 살펴보도록 한다.
AbstractController
다양한 컨트롤러들의 가장 기반이 되는 구현체인 AbstractController이다.
AbstractController를 사용하기 위해서는
handleRequestInternal 메소드를 구현해줘야 하며 구현 예는 다음과 같다.
public class AbstractUserController extends AbstractController {
private static Log log = LogFactory.getLog(AbstractController.class);
UserService userService = null;
//setter injection of userSerivce
public void setUserService(UserService userService){
this.userService = userService;
}
//override handleRequestInternal() method.
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
log.debug("handleRequestInternal() method of AbstractController called");
//userId setting from request
String userId = request.getParameter("userId");
UserVO userVO = new UserVO();
//call business service
userVO = userService.getUser(userId);
//return a ModelAndView object. argument is view name.
return new ModelAndView("/jsp/user/userInformResult.jsp", "users", userVO);
}
}
위와 같이 작성할 경우 해당 컨트롤러는 요청 처리 후 ModelAndView를 FrontController인 DispatcherServlet으로 리턴하고 view 이름은 /jsp/user/userInformResult.jsp이다 view에서는 users라는 이름으로 UserVO객체를 사용할 수 있다.
MultiActionController
웹 애플리케이션을 개발하면서 하나의 페이지가 추가될 때마다 새로운 컨트롤러를 추가해야하는 번거로움을 없애기 위해
MultiActionController를 사용할 수 있다. 이 컨트롤러는 하나의 컨트롤러에 여러개의 request handling 메소드를 정의 할 수 있다.
이러한 메소드별 request handling을 하기 위해서는 다음과 같은 methodNameResolver를 추가해 줘야 한다.
<bean name="/getUser.do"
class="anyframe.sample.springmvc.web.controller.basic.MultiUserController">
<property name="userService" ref="userService" />
<property name="methodNameResolver">
<ref local="paramResolver" />
</property>
</bean>
<bean id="paramResolver"
class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName"><value>method</value></property>
</bean>>
위에서 참조하는 MultiUserController 클래스는 다음과 같다.
위 설정파일에 통하면 /getUser.do?method=getUser 요청은 아래의 MultiUserController getUser 메소드를 /getUser.do?method=getMessage 요청은 getMessage
메소드를 호출하게 된다.
public class MultiUserController extends MultiActionController {
UserService userService = null;
// setter injection of userSerivce
public void setUserService(UserService userService) {
this.userService = userService;
}
public ModelAndView getUser(HttpServletRequest request,
HttpServletResponse response) throws Exception {
UserVO userVO = new UserVO();
// data binding
bind(request, userVO);
// call business service
userVO = userService.getUser(userVO);
// return a ModelAndView object. argument is view name.
return new ModelAndView("/jsp/user/userInformResult.jsp", "users",
userVO);
}
public ModelAndView getMessage(HttpServletRequest request,
HttpServletResponse response) throws Exception {
UserVO userVO = new UserVO();
// data binding
bind(request, userVO);
// call business service
String message = userService.getUserMessage(userVO.getUserId());
// return a ModelAndView object.
return new ModelAndView("/jsp/user/userInformResult.jsp", "message",
message);
}
}
MultiActionController에서 제공하는 bind 메소드는 입력 폼의 데이터를 request로 받아 도메인 모델로 바인드 시켜 준다.
또한 클라이언트가 입력한 데이터를 도메인 모델과 데이터 바인딩하기 위해서는 입력 화면에서 사용한 attrubute name과 도메인 모델의 attrubute name이 같아야 한다.
method의 return type은 ModelAndView, Map, String, void가 될 수 있다.
AbstractCommandController
Spring MVC의 Command컨트롤러는 HttpServletRequest로 받아온 파라미터를 동적으로 특정한 데이터 객체로 바인드 할 수 있다.
Spring에서는 데이터 객체가 Struts의 ActionForm과 같이 framework-specific 인터페이스를 implement하지 않아도 된다.
그 중 대표적인 command 컨트롤러에는 AbstractCommandController가 있다.
AbstractCommandController는 특정 객체로 request의 파라미터를 바인딩 할 수 있다.
폼 기능은 제공하지 않지만 validation을 할 수 있으며 바인딩 객체를 사용하여 원하는 일을 할 수 있다.
이러한 AbstractCommandController를 사용한 클래스의 예는 다음과 같다.
public class CommandUserController extends AbstractCommandController{
UserService userService = null;
//setter injection of userSerivce
public void setUserService(UserService userService){
this.userService = userService;
}
//setting command class for data binding
public CommandUserController() {
setCommandClass(UserVO.class);
}
//override handle() method.
protected ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object command, BindException exception)
throws Exception {
//data binding using command object
UserVO userVO = (UserVO)command;
//call business service
userVO = userService.getUser(userVO);
//setting view name
ModelAndView mav = new ModelAndView("/jsp/user/userInformResult.jsp");
mav.addObject(userVO);
//return a ModelAndView object.
return mav;
}
}
입력 파라미터로 들어온 Object를 트랜스퍼 오브젝트에 바인딩 시킬 때 생성자에서 정의해준 Command Class와 같은 타입에 객체로 바인딩 시켜줘야 한다.
SimpleFormController
Spring MVC는 입력폼을 구현하기 위해 SimpleFormController를 지원한다.
이 컨트롤러는 입력화면에 대한 정보와 작업이 성공적으로 완료했을 때 이동하게될 URL정보를 설정할 수 있으며 입력 폼 화면에 필요한 데이터들을 전달하기 위해
formBackingObject() 메소드를 지원한다. 또한 SimpleFormController는 데이터 유효성을 체크하는중에 에러가 발생할 경우 입력 폼 화면으로 이동하며 에러메시지를 출력해준다.
validator관련 사항은 본 매뉴얼 SpringMVC >> basic >>
validator
을 참고한다.
SimpleFormController를 작성하는 방법은 다음과 같다.
public class SimpleFormUserController extends SimpleFormController {
UserService userService = null;
// setter injection of userSerivce
public void setUserService(UserService userService) {
this.userService = userService;
}
// setting command class for data binding
public SimpleFormUserController() {
setCommandClass(UserVO.class);
setCommandName("users");
setValidator(new UserValidator());
setFormView("/jsp/user/userForm.jsp");
setSuccessView("/jsp/user/userInform.jsp");
}
// override onSubmit() method.
protected ModelAndView onSubmit(Object command) throws Exception {
// data binding using command object
UserVO userVO = (UserVO) command;
// call business service
userVO = userService.getUser(userVO);
// setting view name
ModelAndView mav = new ModelAndView(getSuccessView());
mav.addObject(userVO);
// return a ModelAndView object.
return mav;
}
protected Map formBackingObject(HttpServletRequest request)
throws Exception {
Map address = new HashMap();
address.put("seoul", "서울");
address.put("daegu", "대구");
address.put("busan", "부산");
Map hobby = new HashMap();
hobby.put("reading", "독서");
hobby.put("listeningMusic", "음악감상");
hobby.put("study", "공부");
map.addAttribute("hobby", hobby);
map.addAttribute("address", address);
return new UserVO();
}
}
위 코드에서 볼수 있듯이 폼입력 화면 설정인 setFormView, 입력 화면에 대한 작업이 완료되었을 때 보여줄 setSuccessView,
폼 입력 값을 받아온 command 객체를 바인딩할 클래스를 지정해주는 setCommandClass, validation 체크를 위한 validator를 지정해주는 setValidator의 설정을 할 수 있다. 생성자에서 셋팅해주는 이러한 설정들은
모두 Controller 빈의 Property로 정의할 수 있다.
또한 onSubmit메소드를 구현하여 요청에 대한 작업을 수행한다.
여기서 commandName으로 지정된 "users"는 JSP의 spring form 태그의 commandName과 같아야 하며 그 값은 위의 formBckingObject에서 return된 객체의 값이 자동으로 셋팅된다.
다음은 JSP페이지 spring form 태그의 commandName지정 모습이다. form 태그의 자세한 사항은 본 매뉴얼 >> Spring MVC >> Basic >> View >>
Tag Library
부분을 참조한다.
<form:form commandName="users">
또한 onSubmit메소드를 구현하여 요청된 액션에 대한 작업을 수행한다.
이러한 SimpleFormController는 다양한 폼 기능 뿐만 아니라 중복 폼 서브밋 방지기능을 제공한다. 하지만 SimpleFormControllef를 사용하여 중복 폼 서브밋 방지 기능을 구현하기에는 설정과 방법이 복잡하기 때문에 Anyframe Web에서는 SimpleFormController와 MultiActionController를 확장한
AnyframeFormController
를 사용하는 것을 가이드 한다.
UrlFilenameViewController
단지 HTML이나 JSP화면을 출력해주는 정적인 페이지로의 포워딩을 해주기 위해 별도의 컨트롤러 작성 없이
Spring MVC에서 제공하는 UrlFilenameViewController를 사용한다.
이러한 정적인 페이지로의 이동은 다음과 같이 간단하게 정의할 수 있다.
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/index.do=jspViewController
</value>
</property>
</bean>
<bean id="jspViewController"
class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
UrlFilnameViewController를 사용하게 되면 요청된 url에서 확장자를 뺀 부분을 view이름으로 가지고 viewResolver에 따른 view 결정을 한다. 그러므로 중복된 view 이름이 없도록 주의해야한다.
위같이 정의할 경우에는 index를 view 이름으로 하여 viewResolver에 의해 결정된 view를 출력해 주게 되는 것이다.
ParameterizableViewController
정적인 페이지로의 포워딩을 해주기 위해 위에서 설명한 UrlFilenameViewController를 이용할 수 있지만 url을 가지고 view 이름을 결정하므로 url과 view 이름이 같아야 한다.
이렇게 url로 view 이름을 정하지 않고 사용자가 정한 view 이름으로 포워딩 해줄 때 ParameterizableViewController를 사용한다.
org.springframework.web.servlet.mvc.ParameterizableViewController를 Controller Class로 정의한 다음 "viewName"이라는 property에 출력해줄 view 이름을 정의한다.
<bean name="/addUserView.do"
class="org.springframework.web.servlet.mvc.ParameterizableViewController">
<property name="viewName" value="/sample/user/addUser.jsp" />
</bean>
Resources
다운로드
이클립스 프로젝트 형태의 샘플 웹 어플리케이션을 포함하고 있는 anyframe-springmvc-sample-basic.zip 파일을 다운받은 후, 테스트 환경 설정
을 참조하여
위에서 제시한 예제 코드를 실행해 볼 수 있다.
| Name
|
Download
|
| anyframe-springmvc-sample-basic.zip |
Download
|
참고자료