Actionメソッドの処理
では、画面遷移に従って、それぞれのActionメソッドを見ていきましょう。まずは、ログイン処理のActionです。
未ログイン時には、addActionErrorで何らかのメッセージが登録されていますので、Actionメソッドの処理はスキップされ、login.jspにて、ユーザーIDとパスワードを入力するフォームが表示されます。
<s:actionerror /> <s:form action="login" > <s:textfield label="ユーザーID" name="userid" /> <s:password label="パスワード" name="password" /> <s:submit value="ログイン" /> </s:form>
ログインボタンにて、loginアクションがsubmitされます。
ログイン処理
ToDoLoginActionクラスで、loginアクションを定義しています。
@Action("/login")
public String excute() throws Exception {
LoginDao login = new LoginDao();
// DBへ問い合わせ
if (login.confirm(this.user.getUserid(), this.user.getPassword())) {
this.user.setUsername(login.getUsername());
this.user.setState(1); // ログイン状態に更新
}
else {
addActionError("ユーザーIDの登録がないか、パスワードが異なっています。");
this.user.setPassword("");
return "input";
}
return "todo";
}
フィールドのuserが、Modelオブジェクトで、フォームから入力された値がセットされています。
LoginDaoクラスが実際のログイン処理を行うクラスです。confirmメソッドにユーザーIDとパスワードを渡して、データベースに登録されているかどうかを問い合わせます。
LoginDaoクラスのconfirmメソッドは、次のようなコードになっています。
public boolean confirm(String userid, String password){
try {
User[] user = BaseDao.getInstance().getEntityManager().find(User.class,
"userid=? and password=?",userid,password );
if ( user.length>0 ){
this.username = user[0].getUsername();
return true;
}
}
catch (SQLException e) {
System.out.println(e.getMessage());
}
return false;
}
ActiveObjectsのfindメソッドを用いて、データベースに問い合わせ、ユーザーIDとパスワードが登録されていれば、そのユーザーのユーザー名を取得しています。
ユーザーテーブル
ここで、今回のアプリケーションのデータベースについて説明しておきましょう。データベースのEntityとしては、ユーザー情報と、ToDO情報の2つになります。それぞれを定義したインターフェイスは、次のようになります。
public interface User extends Entity {
@Unique
@Default("")
public String getUserid();
public void setUserid(String userid);
@Default("")
public String getPassword();
public void setPassword(String password);
@Default("")
public String getUsername();
public void setUsername(String username);
}
ユーザーEntityの要素としては、ユーザーID、パスワード、ユーザー名となります。
ToDoを格納するEntityは、次のTodoListです。要素は、ユーザーID、完了すべき日時、ToDO内容、有効無効フラグとなります。
public interface TodoList extends Entity {
@Default("")
public String getUserid();
public void setUserid(String userid);
@Default("CURRENT_TIMESTAMP")
public Date getDeadline();
public void setDeadline(Date deadline);
@Default("")
public String getTodo();
public void setTodo(String todo);
@Default("1")
public int getValid();
public void setValid(int valid);
}
これら2つのインターフェイスの実装は、フレームワークのActiveObjectsが自動生成します。また、テーブルの作成も、この定義を用いて行うことができます。例えば、次のようなコードを実行すると、データベース上にテーブルが作成されます(あらかじめデータベースの作成は必要です)。
EntityManager manager =
new EntityManager("jdbc:mysql://localhost/todo", "root", "wings");
// テーブル作成
manager.migrate(TodoList.class, User.class);
ローカルホストのtodoデータベースに、root/wingsにて接続し、migrateメソッドにて、インターフェイス定義にしたがったテーブルを作成します。
Actionのchain
ログイン処理の説明に戻りましょう。データベースにユーザーの登録があることが確認できれば、状態をログイン済みに更新し、Result値の"todo"を返します。"todo"の遷移先は、Resultアノテーションのlocation属性でtodoアクションを指定しています。
@Result(name = "todo", location = "todo", type = "chain")
"chain"は、アクションからアクションに遷移する場合に使用します。
なお、Conventionプラグインのマニュアルには、同じパッケージ内であれば、Result値の指定のみで、chain遷移できると書いてあります。ところが指定どおりに記述しても、うまく動作しませんでした(同じActionクラス内のメソッドには遷移できます)。そのため、ここではResultアノテーションで指定しています。
todoアクション
ログインから遷移したtodoアクション(ToDoActionクラスで定義)の目的は、メイン画面の表示です。Actionメソッドのコードは、単にResult値の"success"を返すだけで、直ちに、次のlist.jspのビュー表示となります。このように書くと、todoアクションに遷移しなくても、ログインのResultで、list.jspを指定すればいいように思えます。しかし、それではうまくいかない箇所がlist.jspにはあるのです。
list.jspでは、2つのフォームを定義しています。まず最初は、ToDoメッセージの追加用です。
<s:form action="entryexec" > <s:textfield name="todoStr" label="ToDo" size="50"/> <s:submit value="Add TODO"/> </s:form> <s:actionmessage />
Todoメッセージの追加処理は、特に問題ないでしょう。submitにて、entryexecアクションを呼び出しています。entryexecアクションのコードは、次のようになります。
private String todoStr; // ToDo追加データ用
// ToDo追加
@Action("/entryexec")
public String entryexec() throws Exception {
// 入力なしの場合は、何もしない
if ( this.getTodoStr()==null || this.getTodoStr().length()==0 )
return "success";
// バリデーション
if (this.getTodoStr().length()>80) {
addActionMessage("文字数オーバーです");
return "success";
}
// 日本語文字変換(Struts2の暫定バグ対応)
this.setTodoStr( FixString.encoding(this.getTodoStr()));
// DB登録
TodoDao todo = new TodoDao();
todo.entry( this.user.getUserid(), this.getTodoStr() );
this.setTodoStr("");
return "success";
}
データベースへの登録は、次のTodoDaoクラスのentryメソッドで行います。
public boolean entry(String userid, String str){
try {
TodoList todo = BaseDao.getInstance().getEntityManager().create(TodoList.class);
todo.setTodo(str); // ユーザーIDのセット
todo.setUserid(userid); // メッセージのセット
todo.save();
return true;
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return false;
}
