SimpleFormController는 앞서 살펴본 AbstractCommandController를 상속해서 구현된 Controller로서...

GET 방식으로 요청이 들어올 경우 formView 프로퍼티에 지정된 뷰를 보여주고..

POST 방식으로 요청이 들어오게 되면 폼으로 넘어온 데이터를 처리한 후 successView 프로퍼티에 지정된 뷰를 보여준다...

물론 폼으로 넘어온 데이터는 commandClass 프로퍼티에 설정된 커맨드 객체에 저장된다..

보통 로그인 페이지를 작성한다고 하면 입력 화면을 처리하는 컨트롤러와 로그인을 처리하는 컨트롤러가 필요하지만..

Spring에서는 이거 하나만 가지고도 2가지 역할을 모두 할 수 있다...

SimpleFormController의 처리 흐름은 다음과 같다...

 

GET 방식인 경우

1. formBackingObject() 메소드 호출

2. showForm() 메소드 호출

 

POST 방식인 경우

1. formBackingObject() 메소드 호출

2. 입력된 폼 검증

    3-1. 검증이 실패할 경우 showForm() 메소드 호출

    3-2. 검증이 성공할 경우 onSubmit() 메소드 호출

 

그렇다면 직접 SimpleFormController를 구현해보도록 하자..

 

public class LoginController extends SimpleFormController
{
    @Override
    protected ModelAndView onSubmit(HttpServletRequest req, HttpServletResponse res,

                                                       Object command, BindException errors) throws Exception
    {
        LoginCommand login = (LoginCommand)command;
  
        if(login.getId().equals("id") && login.getPswd().equals("pswd"))
        {
            ModelAndView mav = new ModelAndView();
            mav.setViewName(getSuccessView());
            mav.addAllObjects(errors.getModel());
   
            return mav;
        }
        else
            return showForm(req, res, errors);
        }

}

 

위와 같이 onSubmit() 메소드를 재정의해주면 된다...

SimpleFormController가 AbstractCommandController를 상속받기 때문에 command를 매개변수로 갖는 것을 볼 수 있다...

아무튼 입력된 폼을 검증하는 코드를 수행한 후에는...

getSuccessView()를 호출하면 successView 프로퍼티에 지정된 뷰를 가져오게 된다...

만약 검증에 실패해서 showForm() 메소드를 실행해주면 formView 프로퍼티에 지정된 뷰를 보여주게 된다...

원한다면 검증 오류 페이지로 ModelAndView를 만들어도 될 것이다..

BindException 객체는 커맨드 객체 정보 및 요청 파라미터 값 검증 결과를 담고 있는데...

getModel() 메소드를 호출하면...

commandName 프로퍼티에 설정된 이름과 commandClass 프로퍼티에 설정된 커맨드 객체 쌍으로 된 Map 객체를 리턴한다...

따라서 View에서는 commandName에 지정된 이름을 통해 커맨드 객체에 접근할 수 있게 된다...

좀 더 자세한 내용은 다음에 알아보도록 하고...

커맨드 클래스는 아래와 같이 간단히 id와 패스워드를 갖도록 만들어 주면 된다...

 

public class LoginCommand
{
    private String id;
    private String pswd;
 
    public String getId()
    {
        return id;
    }
    public void setId(String id)
    {
        this.id = id;
    }
    public String getPswd()
    {
        return pswd;
    }
    public void setPswd(String pswd)
    {
        this.pswd = pswd;
    }
}

 

그 후 XML 다음과 같이 XML 설정을 해주면 된다...

 

<bean name="loginController" class="org.cuvic.web.LoginController">
     <property name="commandClass" value="org.cuvic.web.command.LoginCommand"/>
     <property name="commandName" value="login"/>
     <property name="formView" value="login"/>
     <property name="successView" value="result"/>
</bean>

 

commandClass와 commandName은 AbstractCommandController와 동일한 역할을 하고..

위에서 알아보았듯이 formView는 GET 방식일 때 보여줄 View이고..

successView는 POST 방식으로 넘어온 후 결과를 보여줄 View를 설정해주면 된다...

 

실제 로그인하는 페이지인 login.jsp를 간단하게 만들어 보자...

 

<html>
    <head>
        <title>로그인 테스트</title>
    </head>
    <body>
        <form method="post">
            <input type="text" name="id">
            <input type="password" name="pswd">
            <input type="submit">
        </form>
    </body>
</html>

 

그 후 결과를 보여줄 result.jsp 파일도 간단하게 만든다...

 

<html>
    <head>
        <title>로그인 성공</title>
    </head>
    <body>

        로그인 성공!!

    </body>
</html>

 

그냥 GET 방식으로 접속하면 login.jsp로 접속이 되고...

POST로 전송을 하면 문제가 없다면 result.jsp가 보이고 뭔가 문제가 있으면 바로 login.jsp 페이지가 보여진다...

 

로그인 페이지를 예로 했기 때문에 간단했지만..

회원 가입 폼이나 기타 다른 폼에서는 기본적으로 무언가 정해진 값을 선택해야 하는 경우가 있다..

예를 들어 직업이라던가 학교같은 것들을 콤보박스로 선택할 수 있게 해 놓은 경우라 할 수 있다..

이런 값들은 대개 DB에서 값을 읽어다가 출력하게 되는데...

이렇게 입력 폼에서 사용할 수 있는 값을 설정할 수 있도록 referenceData() 메소드가 제공된다..

이 메소드에서 입력 폼에서 사용할 값을 설정해서 ModelAndView로 전달할 수 있다...

 

@Override

protected Map referenceData(HttpServletRequest request) throws Exception

{

    List job = new ArrayList();

    job.add("학생");

    job.add("직장인");

    job.add("백수");

 

    Map data = new HashMap();

    data.put("job", job);

   

    return data;

}

 

위와 같이 해주면 job이라는 이름으로 입력 폼에서 값을 사용할 수가 있다...

그리고 회원 정보 수정이나 각종 정보 수정 시에는 수정할 정보가 이미 출력이 되어 있어야 하는데..

이럴 때 formBackingObject() 메소드를 사용한다...

이 메소드는 GET방식이던 POST방식이던 무조건 호출되서 커맨드 객체를 생성한다...

그 후 POST방식이면 요청 파라미터 값을 커맨드 객체에 반영하게 된다...

그러므로 폼에 미리 값을 출력해주려면 이 메소드를 재정의한다..

 

@Override

protected Object formBackingObject(HttpServletRequest request) throws Exception

{

    if(!isFormSubmission(request))

    {

        FooCommand foo = new FooCommand();

        foo = barDAO.getFoo();

 

        return foo;

    }

    else

    {

        return super.formBackingObject(request);

    }

}

 

isFormSubmission() 메소드는 POST 요청인지 판단하는 메소드이다..

! 연산자가 사용되어 POST가 아닌 경우..

즉 GET 요청인 경우 BarDAO에서 FooCommand 값을 가져오고 있는 것을 볼 수 있다..

그 외에 POST 요청인 경우에는 전달된 요청 파라미터를 그대로 처리하기 위해...

부모 클래스의 formBackingObject() 메소드를 호출하는 것을 볼 수 있다...

 

AbstractFormController에는 sessionForm 프로퍼티가 있는데..

기본 값은 false이지만 이 값을 true로 설정할 경우 아래와 같이 처리 과정이 약간 달라진다...

 

GET 방식인 경우

1. formBackingObject() 메소드 호출

2. showForm() 메소드 호출

3. HttpSession에 커맨드 객체 저장

 

POST 방식인 경우

1. HttpSession에 커맨드 객체가 있는지 확인

   2-1. 커맨드 객체가 없는 경우 GET 방식 호출

   2-2  커맨드 객체가 있는 경우 HttpSession에서 커맨드 객체 제거 후 입력 폼 검증

          3-1 검증이 실패할 경우 showForm() 메소드 호출

          3-2 검증이 성공할 경우 onSubmit() 메소드 호출

 

GET 요청이 있는 경우 커맨드 객체를 생성하여 HttpSession에 저장하게 된다..

그 후 POST 요청이 들어오면 HttpSession에서 저장된 커맨드 객체를 가져다 사용하게 된다...

왜 이렇게 사용하는지는 Spring 문서를 살펴보면..

 

Indicates whether the form object should be kept in the session when a user asks for a new form.

This allows you e.g. to retrieve an object from the database, let the user edit it, and then persist it again.

Otherwise, a new command object will be created for each request

(even when showing the form again after validation errors).

이 글은 스프링노트에서 작성되었습니다.

Posted by 이버리
,