Controller
컨트롤러는 MVC중 C에 해당하며 사용자의 입력을 받은 뒤 뷰에 보여주기 적당한 모델로 바꿔준다.
Spring MVC에서는 다양한 컨트롤러 인터페이스를 제공한다.
이러한 컨트롤러 인터페이스의 대표적인 몇가지를 살펴보도록 한다.
AbstractController
다양한 컨트롤러들의 가장 기반이 되는 구현체인 AbstractController이다.
AbstractController를 사용하기 위해서는 handleRequestInternal 메소드를 구현해줘야 하며 구현 예는 다음과 같다.
public class HelloworldAbstractController extends AbstractController {
private static Log log = LogFactory
.getLog(HelloworldAbstractController.class);
private HelloworldService helloworldService = null;
//setter injection을 통해 HelloworldService 객체 생성
public void setHelloworldService(HelloworldService helloworldService) {
this.helloworldService = helloworldService;
}
// ModelAndView 객체인 handleRequestInternal 메소드 구현
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
log.debug("Returning hello view");
HelloVO helloVO= new HelloVO();
helloVO.setUserName(request.getParameter("userName"));
helloworldService.getMessage(helloVO);
//helloVO 객체를 "message"라는 이름의 객체로 넘기고 view 네임으로는 "hello"를 넘김
return new ModelAndView("hello","message",helloVO);
}
}
또한 ModelAndView 클래스에 view 네임을 넘길때 "redirect:" prefix를 사용하여 정적인 페이지 뿐만아니라 사용자가 원하는 url로 포워딩 해줄 수 있다.
return new ModelAndView("redirect:/getUserList.do");
MultiActionController
웹 애플리케이션을 개발하면서 하나의 페이지가 추가될 때마다 새로운 Controller를 추가해야하는 번거로움을 없애기 위해
MultiActionController를 사용할 수 있다.이 컨트롤러는 하나의 컨트롤러에 여러개의 request handling 메소드를 정의 할 수 있다.
이러한 메소드별 request handling을 하기 위해서는 다음과 같은 methodNameResolver를 추가해 줘야 한다.
<bean name="/getUser.do"
class="sample.web.controller.HelloworldMultiActionController">
<property name="helloworldService" ref="helloworldService" />
<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>>
위에서 참조하는 HelloworldMultiActionController 클래스는 다음과 같다.
위 설정파일에 통하면 /getUser.do?method=view 요청은 아래의 HelloworldMultiActionController의 view메소드를 /getUser.do?method=command 요청은 command
메소드를 호출하게 된다.
/**
* MultiActionController
* 유효성 체크 기능을 사용하지 않고 데이터 바인딩 기능만을 이용하고자 할 때 사용
* 하나의 Controller를 구현함으로써 다수의 요청을 처리하는 것이 가능하도록 지원한다.
* @author Rainbow
*
*/
public class HelloworldMultiActionController extends MultiActionController{
private static Log log = LogFactory.getLog(HelloworldMultiActionController.class);
private HelloworldService helloworldService = null;
public void setHelloworldService(HelloworldService helloworldService) {
this.helloworldService = helloworldService;
}
public ModelAndView view(HttpServletRequest request,
HttpServletResponse response) throws Exception {
log.debug("Returning hello view");
HelloVO command = new HelloVO();
/**
*MultiActionController 클래스의 bind()메소드를 이용하여
*HttpServletRequest에 전달된 인자를 HelloVO 도메인 모델에 전달한다.
*
*클라이언트가 입력한 데이터를 도메인 모델과 데이터 바인딩하기 위해서는
*입력 화면에서 사용한 속성 이름과 도메인 모델의 속성 이름이 같아야 한다.
*/
bind(request, command);
helloworldService.getMessage1(command);
return new ModelAndView("hello","message",command);
}
public ModelAndView command(HttpServletRequest request,
HttpServletResponse response) throws Exception( {
log.debug("Returning hello view");
String command="";
command=helloworldService.getMessage2();
return new ModelAndView("multiAction","message", command);
}
}
MultiActionController에서 제공하는 bind메소드는입력폼의 데이터를 request로 받아 도메인 모델로 바인드 시켜 준다.
또한 클라이언트가 입력한 데이터를 도메인 모델과 데이터 바인딩하기 위해서는 입력 화면에서 사용한 속성 이름과 도메인 모델의 속성 이름이 같아야 한다.
AbstractCommandController
Spring의 Command 컨트롤러는 HttpServletRequest로 받아온 파라미터를 동적으로 특정한 데이터 객체로 바인드 할 수 있다.
이것의 역할을 Struts의 ActionForm의 기능과 유사하다.
그러나 Spring에서는 데이터 객체가 framework-specific 인터페이스를 implement하지 않아도 된다.
그 중 대표적인 command 컨트롤러에는 AbstractCommandController가 있다.
AbstractCommandController는 특정 객체로 request의 파라미터를 바인딩 할 수 있다.
폼 기능은 제공하지 않지만 validation을 할 수 있으며 바인딩 객체를 사용하여 원하는 일을 할 수 있다.
이러한 AbstractCommandController를 사용한 클래스의 예는 다음과 같다.
/**
* AbstractCommandController
*/
public class HelloworldCommandController extends AbstractCommandController {
private static Log log = LogFactory
.getLog(HelloworldCommandController.class);
private HelloworldService helloworldService = null;
public void setHelloworldService(HelloworldService helloworldService) {
this.helloworldService = helloworldService;
}
/**
* 데이터 객체를 바인딩할 commandClass지정
*
*/
public HelloworldCommandController() {
setCommandClass(HelloVO.class);
}
public ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object command, BindException ex)
throws Exception {
log.debug("Returning hello view");
HelloVO helloVO = (HelloVO) command;
helloworldService.getMessage1(helloVO);
System.out.println("here is Command Controller");
return new ModelAndView("result", "message", helloVO);
}
}
AbstractCommandController에서 command객체를 사용하기 위해서는 setter injection이 필요하다.
SimpleFormController
Spring MVC는 입력폼을 구현하기 위해 SimpleFormController를 지원한다.
이 컨트롤러는 입력화면에 대한 정보와 작업이 성공적으로 완료했을 때 이동하게될 URL정보를 설정할 수 있으며 입력 폼 화면에 필요한 데이터들을 전달하기 위해
formBackingObject() 메소드를 지원하다. 또한 SimpleFormController는 데이터 유효성을 체크하는중에 에러가 발생할 경우 입력 폼 화면으로 이동하며 에러메시지를 출력해준다.
validator관련 사항은 본 매뉴얼
SpringMVC validator을 참고한다.
SimpleFormController를 작성하는 방법은 다음과 같다.
public class HelloworldTestController extends SimpleFormController {
...중략...
public HelloworldTestController() {
setCommandName("user");
setCommandClass(HelloVO.class);
setFormView("test");
setSuccessView("success");
setValidator(new UserValidator());
}
protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command,
BindException exception) throws Exception {
...중략...
HelloVO vo = (HelloVO) command;
helloworldService.getMessage1(vo);
return new ModelAndView(getSuccessView(),"vo", vo);
}
protected Object formBackingObject(HttpServletRequest request)
throws Exception {
request.setAttribute("user",new sample.services.HelloVO());
return new HelloVO();
}
}
위 코드에서 볼수 있듯이 폼입력 화면 설정인 setFormView, 입력 화면에 대한 작업이 완료되었을 때 보여줄 setSuccessView, JSP페이지에서 받아온 commandName의 SetterInjection,
폼 입력 값을 받아온 command 객체를 바인딩할 클래스를 지정해주는 setCommandClass, validation 체크를 위한 validator를 지정해주는 setValidator의 설정을 할 수 있다. 또한
onSubmit메소드를 구현하여 요청된 액션에 대한 작업을 수행한다.
여기서 commandName으로 지정된 "user"는 JSP의 spring form태그의 commandName과 같아야 하며 그 값은 위의 formBckingObject에서 request로 설정해 줄 수 있다.
다음은 JSP페이지 spring form 태그의 commandName지정 모습이다. form 태그의 자세한 사항은 본 매뉴얼
Spring's form tag 부분을 참조한다.
<form:form commandName="user">
또한 onSubmit메소드를 구현하여 요청된 액션에 대한 작업을 수행한다.
이러한 SimpleFormController는 다양한 폼 기능 뿐만 아니라 중복 폼 서브밋 방지기능을 제공한다. 하지만 SimpleFormControllef를 사용하여 중복 폼 서브밋 방지 기능을 구현하기에는 설정과 방법이 복잡하여 이때 우리는 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를 출력해 주게 되는 것이다.
Resources
다운로드
Spring MVC Sample Application을 포함하고 있는
anyframe-sample-springmvc.zip 파일을 Spring MVC - Sample 다운로드 페이지에서 다운받은 후
위 코드를 확인해 볼 수 있으며 위 내용이 포함된 Spring MVC Sample Application을 실행시킬 수 있다.
참고자료