컨트롤러는 일반적인 POJO로 작성되며 특별한 인터페이스를 구현함으로써 J2EE에 종속적인 인스턴스들이 주입될 수 있다. 이번에는 간단한 로그인 액션을 통해서 컨트롤러가 세션을 처리하는 방식을 보인다.
다음과 같이 Form의 제출을 위한 간단한 JSP를 작성한다.
/WebRoot/loginForm.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login Form</title>
</head>
<body>
<h2>Please Log in</h2>
<form name="loginForm" action="login.action" method="post">
ID : <input type="text" name="id" size="12"> <br />
PW : <input type="password" name="password" size="12"> <br />
This is my Hello JSP page. ${message}<br> ${param}
</body>
</html>
다음은 web.controller에 Form의 제출을 처리하는 LoginAction을 작성한다.
/src/web/controller/LoginAction.java
package web.controller;
import net.kldp.beat.annotation.Result;
import net.kldp.beat.annotation.Results;
import net.kldp.beat.web.aware.SessionMapAware;
import java.util.Map;
import java.util.HashMap;
@Results({
@Result(name = "success", value="/success.jsp"),
@Result(name = "failure", value="/failure.jsp", type="redirect")
})
public class LoginAction implements SessionMapAware {
private String id;
private String password;
private Map<String, Object> session;
public void setSession(Map<String, Object> session) {
this.session = session;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public String execute() {
if("myid".equals(id) && "mypassword".equals(password) {
session.put("user", this);
return "success";
} else {
return "failure";
}
}
}
다음으로는 success와 failure에 대응할 뷰 페이지를 작성한다.
/WebRoot/success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login Success!</title>
</head>
<body>
<h2>Login is Success!</h2>
Your is is ${sessionScope.user.id}
</body>
</html>
/WebRoot/failure.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login Failure!</title>
</head>
<body>
<h2>Login is Failure!</h2>
Retry : <a href="loginForm.action">Login</a>
</body>
</html>
위 코드를 테스트 해 보자. http://localhost:8080/myapp/loginForm.action 에 접속하여 폼을 채우고 Submit해보자. 폼에 입력한 결과에 따라 success.jsp와 failure.jsp가 나타나는것을 알 수 있을것이다.
컨트롤러가 net.kldp.beat.web.aware의 인터페이스를 구현하면 setter를 통해 서블릿에 종속적인 객체에 접근할 수 있다. Beat는 이들 몇몇 프로퍼티를 맵으로 제공하는데, 이로써 서블릿에 종속되지 않으면서도 일반적인 Map 접근을 통해 세션 및 request 속성에 접근할 수 있다. aware 패키지의 특별한 인터페이스의 목록은 다음과 같다.
RequestMapAware - Request 맵에 접근할 수 있다.
SessionMapAware - Session 맵에 접근할 수 있다.
ServletContextAware - ServletContext객체에 접근할 수 있다.
ServletDispatcherAware - ServletDispatcher를 포함한 몇가지 Request객체와 Response객체에 접근할수 있는 메서드를 제공한다.
ServletRequestAware - 서블릿 Request객체에 접근할 수 있다.
ServletResponseAware - 서블릿 Reponse객체에 접근할 수 있다.
Action의 Result가 2개 이상일 경우, Results 어노테이션을 통해 이들을 묶어야 한다. 또한 위 예제 Action의 failure 를 정의하는 Result 어노테이션은 type이라는 속성을 가지고 있는데, 이것은 "forward", "redirect", "stream"중의 하나로 "redirect"로 정의되었을 경우에는 브라우저를 통해 URL을 리다이렉트하게 된다. 또한 type 속성을 정의하지 않으면 기본적으로 "forward"이다.
net.kldp.beat.web.aware 패키지의 인터페이스를 구현하면 서블릿 종속적인 객체를 주입받을 수 있다고 하였는데, 이들 중 ValidationAware는 특별히 폼값 검증을 위한 인터페이스이다. 이번에는 위의 로그인 액션 예제중에 몇가지를 추가하여 폼 입력값 검증을 만들어보자.
위의 소스중 loginForm.jsp와 LoginAction.java 파일을 다음과 같이 수정한다.
/WebRoot/loginForm.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login Form</title>
</head>
<body>
<h2>Please Log in</h2>
<h2>${errorsMap}</h2>
<form name="loginForm" action="login.action" method="post">
ID : <input type="text" name="id" size="12" value="${id}"> <br />
PW : <input type="password" name="password" size="12"> <br />
This is my Hello JSP page. ${message}<br> ${param}
</body>
</html>
/src/web/controller/LoginAction.java
package web.controller;
import net.kldp.beat.annotation.Result;
import net.kldp.beat.annotation.Results;
import net.kldp.beat.aware.SessionMapAware;
import net.kldp.beat.aware.ValidationAware;
import java.util.Map;
import java.util.HashMap;
@Results({
@Result(name = "input", value="/loginForm.action"),
@Result(name = "success", value="/success.jsp"),
@Result(name = "failure", value="/failure.jsp", type="redirect")
})
public class LoginAction implements SessionMapAware, ValidationAware {
private String id;
private String password;
private Map<String, Object> session;
private Map<String, String> errors = new HashMap<String, String>();
public void setSession(Map<String, Object> session) {
this.session = session;
}
public Map<String,String> getErrorsMap() {
return errors;
}
public void validate() {
if(id == null || id.equals(""))
errors.put("id", "ID is Blank");
if(password == null || password.equals(""))
errors.put("password", "Password is Blank");
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public String execute() {
if("myid".equals(id) && "mypassword".equals(password) {
session.put("user", this);
return "success";
} else {
return "failure";
}
}
위의 LoginAction이 ValidationAware를 구현하면서 추가적으로 해야할 일은 두가지 이다. 하나는 validate메서드를 구현해야 하고, 하나는 에러 메세지를 담을 맵을 제공해야 한다. 만약 리턴하는 맵의 크기가 0이상이라면 Result어노테이션에 선언된 input 메시지를 정의한 URL로 디스패치될 것이다.
그리고 LoginForm에서는 에러 메세지에 대한 접근을 일반적인 맵처럼 할 수 있게 됨으로써 에러를 표시할 수 있다.