LoginSignup
1
2

More than 5 years have passed since last update.

初心者だけどlastafluteを使ってみたい!〜”ハンズオン”まで〜

Posted at

ほぼ自分用メモです。
ハンズオンの話です。
今回は期待外のことは起こらなかったので、ほぼそのままです。
やったことと感想を中心に書きます。

ここまでの話はこちら

初心者だけどlastafluteを使ってみたい!〜”ちょっと前提”まで〜

手順1 URLを決める

今回は例示通り
/sea/land/[商品ID]?pay=[支払方法]
(例:/sea/land/3?pay=HAN)
というGETリクエストの対応する Action を作ることにします

手順2 Actionクラスを作る

手順2.1 Action名を決める

規約により

  1. SeaAction#land()
  2. SeaLandAction#index()

のどちらかです。
例えばSeaAction#land()SeaAction クラスの land()メソッドのことです。
今回は例示通りSeaLandAction#index()にします

手順2.2 Actionのパッケージ(配置場所)を決める

規約により

  1. app.web.SeaLandAction
  2. app.web.sea.SeaLandAction
  3. app.web.sea.land.SeaLandAction

のどれかです。
今回は2番目のapp.web.sea.SeaLandActionにします

手順2.3 実際に作る

src/main/java/org/docksidestage/app/web/sea/

SeaLandAction クラスを作成しました。
この3つならパッケージはどこでも変わらないそうです。

(ちなみにこのパッケージだけ.gitignoreでgit管理されないみたいです)

手順3 Executeメソッドを準備

クラスは、[アプリ名]BaseActionクラスを継承します。
今回はHarborBaseActionクラスを継承します。

メソッドは

  • Executeアノテーションを付ける
  • 戻り値は HtmlResponse
  • URLパラメーター /3 を受け取る引数を最初に定義
  • GETパラメーターを受け取る Form を最後の引数に定義

ここまでで出来たのがこちら

SeaLandAction.java
public class SeaLandAction extends HarborBaseAction {

    @Execute
    public HtmlResponse index(int productId, SeaLandForm form) {
        return null; //コンパイルエラーが嫌なので付けました
    }
}

手順4 Formを作る

Formクラスを定義

クラス名は [名前]Form です(規約)。
[名前]は任意ですが、Actionとイメージの近い名前がオススメだそうなので、
例示通り、SeaLandForm を作ります。
Actionの隣に置いたので、
src/main/java/org/docksidestage/app/web/sea/SeaLandForm
を作りました。

Formの実装

受け取る値をpublicフィールドに置きます。
型は自動で変換してくれます。

SeaLandForm.java
public class SeaLandForm {
    public CDef.PaymentMethod pay;
}

バリデーションはアノテーションで行ないます。

SeaLandForm.java
public class SeaLandForm {

    @Required
    public CDef.PaymentMethod pay;
}

手順5 HTMLテンプレートを作る

HTMLテンプレートファイルを作って、自動生成をします。

HTMLテンプレートのファイル名

規約により、
関連するActionクラスを識別できる名前にします。
今回はsea_land.jspです。

HTMLテンプレートのディレクトリ

規約により
src/main/webapp/WEB-INF/view/の下に作り、
その中で、今回の場合

  • sea/ <-今回はこっちにします
  • sea/land/

のどちらかの下に置くと決まっています。

FreeGenを叩いてパス自動生成

コンソールでDBFluteクライアントに移動します。
bash
$ cd lastaflute-example-harbor/dbflute_maihamadb
$ sh manage.sh

ここでメニューが表示されるので12 (freegen) を入力して[Enter]
ここでは HarborHtmlPath に path_Sea_SeaLandJsp というパス定義が追加される

JavaでWeb開発したことがなかったので
正直何を言っているのかよくわかっていませんが、
git でdiffをとると

--- a/src/main/java/org/docksidestage/mylasta/action/HarborHtmlPath.java
+++ b/src/main/java/org/docksidestage/mylasta/action/HarborHtmlPath.java
@@ -53,6 +53,9 @@ public interface HarborHtmlPath {
     /** The path of the HTML: /purchase/purchase_list.jsp */
     HtmlNext path_Purchase_PurchaseListJsp = new HtmlNext("/purchase/purchase_l
ist.jsp");

+    /** The path of the HTML: /sea/sea_land.jsp */
+    HtmlNext path_Sea_SeaLandJsp = new HtmlNext("/sea/sea_land.jsp");
+
     /** The path of the HTML: /signin/signin.jsp */
     HtmlNext path_Signin_SigninJsp = new HtmlNext("/signin/signin.jsp");

となったので、そういうことみたいです。

JSPの実装(...はさておいて)

ここからほぼコピペです。
ここでもとりあえずコピペしました。

sea_land.jsp
<c:import url="${viewPrefix}/common/default_layout.jsp">
<c:param name="contents">
<!-- <main> start main content -->
<div class="contents">
    <h2 class="pg-content-title"><la:caption key="labels.purchase.list.title"/></h2>
    <section class="purchase-result-box">
        <p>
            Payment Method: ${f:h(pay)} <la:errors property="pay"/>
        </p>
        <h3 class="pg-content-title-second">Search Results</h3>
        <table class="purchase-list-tbl">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Member Name</th>
                    <th>Product Name</th>
                    <th>Product Handle Code</th>
                    <th>Purchase Date</th>
                    <th>Purchase Price</th>
                </tr>
            </thead>
            <tbody>
                <c:forEach var="bean" items="${beans}">
                <tr>
                    <td>${f:h(bean.purchaseId)}</td>
                    <td>${f:h(bean.memberName)}</td>
                    <td>${f:h(bean.productName)}</td>
                    <td>${f:h(bean.productHandleCode)}</td>
                    <td>${f:h(bean.purchaseDate)}</td>
                    <td>${f:h(bean.purchasePrice)}</td>
                </tr>
                </c:forEach>
            </tbody>
        </table>
    </section>
</div>
<!-- </main> end of main content -->
</c:param>
</c:import>

これで何か表示されそうですね

手順6 Executeメソッドを実装

ひとまずreturnを書いておく

SeaLandAction.java
@Execute
public HtmlResponse index(int productId, SeaLandForm form) {
    return asHtml(path_Sea_SeaLandJsp); 
}

validate()を呼ぶ

SeaLandAction.java
@Execute
public HtmlResponse index(int productId, SeaLandForm form) {
    validate(form, messages -> {}, () -> {
        return asHtml(path_Sea_SeaLandJsp);
    });
    return asHtml(path_Sea_SeaLandJsp); 
}

DBFluteを使う

DBFluteを使って検索・更新などを行います
基点テーブルの Behavior を DI します。
ここでは、購入の一覧でしたから、基点テーブルは PURCHASE です。

SeaLandAction.java
@Resource
private PurchaseBhv purchaseBhv;

@Execute
public HtmlResponse index(int productId, SeaLandForm form) {
    ...
}

スイマセン。「DI?便利らしいけどどういうこと?」状態です。

ConditionBeaで検索します

SeaLandAction.java
@Execute
public HtmlResponse index(int productId, SeaLandForm form) {
    validate(form, messages -> {}, () -> {
        return asHtml(path_Sea_SeaLandJsp);
    });
    Integer userId = getUserBean().get().getUserId();
    ListResultBean<Purchase> purchaseList = purchaseBhv.selectList(cb -> {
        cb.setupSelect_Member();
        cb.setupSelect_Product();
        cb.query().setProductId_Equal(productId);
        cb.orScopeQuery(orCB -> {
            orCB.query().setMemberId_Equal(userId);
            orCB.query().queryMember().existsMemberFollowingByYourMemberId(followingCB -> {
                followingCB.query().setMyMemberId_Equal(userId);
            });
        });
        cb.query().existsPurchasePayment(paymentCB -> {
            paymentCB.query().setPaymentMethodCode_Equal_AsPaymentMethod(form.pay);
        });
        cb.query().addOrderBy_PurchaseDatetime_Desc();
    });

正直意味わかってないですが、
検索してるらしいです。

表示データのBeanを作る

SeaLandRowBean というクラスをActionの隣に作ります。
○○Beanを使ってjspに値を渡すみたいです。
Beanって何!?調べてみました↓
http://yyyank.blogspot.jp/2013/07/javabeansbeandtoentityvoformwhat-is.html
http://qiita.com/DQMerA/items/4b97057b8dcb82aa236b
これにはフィールドはprivateって書いてあるけど?
って感想ですが、そのうち分かるでしょう!

SeaLandRowBean.java
public class SeaLandRowBean {

    public Long purchaseId;
    public String memberName;
    public String productName;
    public String productHandleCode;
    public String purchaseDate;
    public Integer purchasePrice;
}

このBeanに値を設定します。

SeaLandAction.java
@Execute
public HtmlResponse index(int productId, SeaLandForm form) {
    validate(form, messages -> {}, () -> {
        return asHtml(path_Sea_SeaLandJsp);
    });
    ListResultBean<Purchase> purchaseList = purchaseBhv.selectList(cb -> {
        ...
    });
    List<SeaLandRowBean> beans = purchaseList.mappingList(purchase -> {
        SeaLandRowBean bean = new SeaLandRowBean();
        bean.purchaseId = purchase.getPurchaseId();
        purchase.getMember().alwaysPresent(member -> {
            bean.memberName = member.getMemberName();
        });
        purchase.getProduct().alwaysPresent(product -> {
            bean.productName = product.getProductName();
            bean.productHandleCode = product.getProductHandleCode();
        });
        bean.purchaseDate = toStringDate(purchase.getPurchaseDatetime()).get();
        bean.purchasePrice = purchase.getPurchasePrice();
        return bean;
    });
    return asHtml(path_Sea_SeaLandJsp); 
}

表示データをResponseに設定

さっきのBeanをviewに渡します

SeaLandAction.java
@Execute
public HtmlResponse index(int productId, SeaLandForm form) {
    validate(form, messages -> {}, () -> {
        return asHtml(path_Sea_SeaLandJsp);
    });
    ListResultBean<Purchase> purchaseList = ...
    List<SeaLandRowBean> beans = ...
    return asHtml(path_Sea_SeaLandJsp).renderWith(data -> {
        data.register("beans", beans);
    });
}

手順7 ラフスケッチできた

今回の完成形です。

SeaLandAction.java
/**
 * @author yourname
 */
public class SeaLandAction extends HarborBaseAction {

    @Execute
    public HtmlResponse index(int productId, SeaLandForm form) {
        validate(form, messages -> {}, () -> {
            return asHtml(path_Sea_SeaLandJsp);
        });
        ListResultBean<Purchase> purchaseList = purchaseBhv.selectList(cb -> {
            cb.setupSelect_Member();
            cb.setupSelect_Product();
            cb.query().setProductId_Equal(productId);
            cb.orScopeQuery(orCB -> {
                orCB.query().setMemberId_Equal(userId);
                orCB.query().queryMember().existsMemberFollowingByYourMemberId(followingCB -> {
                    followingCB.query().setMyMemberId_Equal(userId);
                });
            });
            cb.query().existsPurchasePayment(paymentCB -> {
                paymentCB.query().setPaymentMethodCode_Equal_AsPaymentMethod(form.pay);
            });
            cb.query().addOrderBy_PurchaseDatetime_Desc();
        });
        List<SeaLandRowBean> beans = purchaseList.mappingList(purchase -> {
            SeaLandRowBean bean = new SeaLandRowBean();
            bean.purchaseId = purchase.getPurchaseId();
            purchase.getMember().alwaysPresent(member -> {
                bean.memberName = member.getMemberName();
            });
            purchase.getProduct().alwaysPresent(product -> {
                bean.productName = product.getProductName();
                bean.productHandleCode = product.getProductHandleCode();
            });
            bean.purchaseDate = toStringDate(purchase.getPurchaseDatetime()).get();
            bean.purchasePrice = purchase.getPurchasePrice();
            return bean;
        });
        return asHtml(path_Sea_SeaLandJsp).renderWith(data -> {
            data.register("beans", beans);
        });
    }
}

Bootしてアクセスしてみましょう

HarborBoot クラスの main() を実行してみます
色々ログが出て、、、

(中略)
Boot successful as development: url -> http://localhost:8090/harbor

http://localhost:8090/harbor/sea/land/3?pay=HAN
にアクセスすると・・・

clipular.png

できた!
次は自分の作りたいのを作っていきます!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2