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; }