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

More than 3 years have passed since last update.

ほぼ自分用メモです。

ハンズオンの話です。

今回は期待外のことは起こらなかったので、ほぼそのままです。

やったことと感想を中心に書きます。


ここまでの話はこちら

初心者だけど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

できた!

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