【入門編】Slim3で始める!GAE/JでWebアプリケーション開発 (第3回)
残機能の開発
<記事詳細>ページのControllerとJSPの実装(続き)
- 必要な処理の実装ReadController を以下のように修正しました。
read.jsp
package simplebbs.controller.bbs; import org.slim3.controller.Controller; import org.slim3.controller.Navigation; import org.slim3.util.ApplicationMessage; import simplebbs.model.bbs.Head; import simplebbs.service.bbs.BbsService; public class ReadController extends Controller { @Override public Navigation run() throws Exception { BbsService service = new BbsService(); Head head = null; try { // 指定されたkeyから記事を取得 Key key = asKey("key"); head = service.get(key); } catch (Exception e) { // keyが不正な場合 } // 記事が取得できなかった場合 if (head == null) { // エラーメッセージをセットしてトップページへフォワード errors.put("message", ApplicationMessage.get("error.entry.notfound")); return forward(basePath); } // 記事が存在する場合はリクエストスコープへセット requestScope("head", head); // 記事ヘッダ requestScope("body", head.getBodyRef().getModel()); // 記事本文 requestScope("commentList", head.getCommentRef().getModelList()); // コメント一覧 return forward("read.jsp"); } }
ReadController では指定されたkeyから記事を取得してリクエストパラメータにセットします。記事が取得できない場合は前の画面(トップページ)に戻し、エラーメッセージを表示するようにします。
- 記事の取得
BbsService service = new BbsService(); Head head = null; try { // 指定されたkeyから記事を取得 Key key = asKey("key"); head = service.get(key); } catch (Exception e) { // keyが不正な場合 }
指定された key はキー文字列のため Controller#asKey() を使ってKeyオブジェクトに変換して取得することができます。ただし、前述したようにGETパラメータはブラウザのURL欄から容易に改ざん可能なため try ~ catch文で括っています。不正な値が指定されてきた場合は asKey() で IllegalArgumentException がスローされますが、catch文節で捉えた後、 head が取得できなかった(=null)として以降の処理に続きます。
- 記事が取得できなかった場合
// 記事が取得できなかった場合 if (head == null) { // エラーメッセージをセットしてトップページへフォワード errors.put("message", ApplicationMessage.get("error.entry.notfound")); return forward(basePath); }
記事が取得できなかった場合、エラーメッセージを準備してトップページへフォワードします。
エラーメッセージは ApplicationMessage.get() を使ってメッセージリソースから取得することができます。メッセージリソースとは前回のバリデーションの項でも説明した application_xx.properties のことです。以下のようにメッセージを定義しておくことで取得できるようになります。
application_ja.properties
validator.required={0}は必須です。 … (省略) … error.entry.notfound=該当の記事が見つかりません。
application_en.properties(英語用)にも同じキーで英文メッセージを追加しておきましょう。ちなみにメッセージリソースファイルもHOT reloadingの対象なので定義を追加しても開発サーバの再起動は不要です。
そして取得したエラーメッセージをJSPで表示するため “message” というキーでerrorsオブジェクトにputします。
// エラーメッセージをセットしてトップページへフォワード errors.put("message", ApplicationMessage.get("error.entry.notfound")); return forward(basePath);
errorsオブジェクトも前回のバリデーションの項で出てきたErrorsオブジェクトのことです。
- 記事が取得できた場合
// 記事が存在する場合はリクエストスコープへセット requestScope("head", head); // 記事ヘッダ requestScope("body", head.getBodyRef().getModel()); // 記事本文 requestScope("commentList", head.getCommentRef().getModelList()); // コメント一覧 return forward("read.jsp");
記事が取得できた場合は記事情報をリクエストスコープにセットして記事詳細画面を表示します。
また、記事本文の body とコメント一覧の commentList は、Headからのリレーションシップで取得することができるので、上記のように記述することができます。
- 記事の取得
- テストケースの実行ReadController の実装が終わったら保存してテストを実行してみましょう。
結果がグリーンになれば ReadController は完成です。画面からも挙動を確認してみましょう。先にブラウザで開いていた記事詳細画面をリロードしてみて下さい。
記事のタイトル、投稿者名、本文が表示されるようになりました。コメントはまだ一件も投稿されていないので表示されていません。試しにこのままブラウザのURL上の /bbs/read?key=…に続くパラメータを改ざんしてみましょう。
上記は key=hogehogehoge と不正な値に変更してアクセスしてみたところです。想定どおり<トップ>ページに戻されました。しかし、エラーメッセージがどこにも表示されていません。/bbs/index.jsp を確認してみましょう。index.jsp
<%@page pageEncoding="UTF-8" isELIgnored="false" session="false"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <%@taglib prefix="f" uri="http://www.slim3.org/functions"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>SimpleBBS</title> <link href="/css/bbs.css" rel="stylesheet" type="text/css" /> </head> <body> <div id="page"> <h1>SimpleBBS</h1> <table> <thead> <tr> <td class="subject">タイトル</td> <td class="username">投稿者</td> <td class="post_date">投稿日時</td> <td class="last_comment_id">コメント数</td> <td class="last_comment_date">最終コメント日時</td> </tr> </thead> <tbody> <c:forEach var="head" items="${headList}" varStatus="hs" > <tr> <td><a href="read?key=${f:h(head.key)}">${f:h(head.subject)}</a></td> <td>${f:h(head.username)}</td> <td><fmt:formatDate value="${head.postDate}" pattern="yyyy/MM/dd HH:mm:ss" /></td> <td>${head.lastCommentId}</td> <td><fmt:formatDate value="${head.lastCommentDate}" pattern="yyyy/MM/dd HH:mm:ss" /></td> </tr> </c:forEach> </tbody> </table> <p><a href="create">新しい記事を投稿する</a></p> </div> </body> </html>
ReadController でセットしているエラーメッセージを表示する記述がどこにもないため表示できていませんでした。以下の一文を index.jsp に追加します。
… <body> <div id="page"> <h1>SimpleBBS</h1> <div class="err">${errors.message}</div> <table> <thead> …
これで errorsオブジェクトに message というキーで登録されたメッセージを表示できるようになります。再度、ブラウザをリロードしてみて下さい。
エラーメッセージの表示も確認できました。以上で記事詳細の実装は完了です。ここまでで作成したソースは以下になります。
- slimplebbs.controller.bbs.ReadController.java
- slimplebbs.controller.bbs.ReadControllerTest.java
- war/bbs/read.jsp
- war/bbs/index.jsp (修正版)
次は<記事編集>ページを実装していきます。