Struts2で表形式の出力をする方法
Struts2で表形式の出力をする一番単純な方法は java.util.List 実装クラス(ArrayList)に格納して、アクセサ(getメソッド)を用意します。
List<SampleDTO> results;
public List<SampleDTO> getResults {
return results;
}
こうすると、View側も繰り返し処理用のタグで results の名前で扱えます。
今回はView側のテンプレートに、Struts2標準のJSPではなく、Thymeleaf3を選びました。
Struts2-Thymeleaf3プラグインの入手と設定
Qiita:Struts2.5でThymeleaf3を使う で公開しております。
mavenリポジトリにも公開してますので、例えばEclipseのmavenプラグインを使って、アーティファクト名(jar)を、
struts2-thymeleaf3-plugin
と入れるとサジェストしてくれるでしょう。
Actionクラス
Struts2-Conventionプラグインを使ったActionクラスにしております。アノテーションベースなのでActionクラス用に設定ファイルを作りません。
package serendip.sturts.thymeleaf.struts2_thymeleaf_sampleapp.actions;
import java.util.List;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.ActionSupport;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import serendip.sturts.thymeleaf.struts2_thymeleaf_sampleapp.model.ProductService;
import serendip.sturts.thymeleaf.struts2_thymeleaf_sampleapp.model.SampleProduct;
/**
* <code>Set welcome message.</code>
*/
@Namespace("/")
@ParentPackage("struts-thymeleaf")
@Results({@Result(name=ActionSupport.SUCCESS,type="thymeleaf",location="list")})
@Log4j2
public class DisplayListAction extends ActionSupport {
@Action("list")
public String execute() throws Exception {
ProductService service = new ProductService();
products = service.search();
log.info("- search:{}" , products);
return SUCCESS;
}
@Getter @Setter
List<SampleProduct> products;
}
このActionクラスでは、検索処理を模したProductServiceから、検索結果として SampleProduct インスタンスを複数取得したListに格納します。
Actionクラスから呼び出す ProductService
本来ならデータベースなど外部ストレージから検索結果を取得したものを返すクラスですが、今回は定型的なものを返す、モッククラスを作成しました。
package serendip.sturts.thymeleaf.struts2_thymeleaf_sampleapp.model;
import java.util.Arrays;
import java.util.List;
/**
* @author A-pZ
*
*/
public class ProductService {
public List<SampleProduct> search() {
List<SampleProduct> resultList =
Arrays.asList(
new SampleProduct("A-1", "試作品X-290PA1", 10, true, true),
new SampleProduct("A-2", "試作品X-290PA2", 20, true, true),
new SampleProduct("B-3", "試作品X-B3", 10, true, true),
new SampleProduct("B-4", "試作品X-B4", 30, true, true),
new SampleProduct("C-5", "試作品X-C5", 10, true, false),
new SampleProduct("C-6", "試作品X-C6", 40, true, false),
new SampleProduct("D-7", "試作品X-D7", 10, false, true),
new SampleProduct("D-8", "試作品X-D8", 50, false, true),
new SampleProduct("E-9", "試作品X-E9", 10, true, true),
new SampleProduct("Z-1000", "試作品Z-1000", 0, false, false)
);
return resultList;
}
}
検索結果に使われるSampleProductクラスは以下のとおりです。
package serendip.sturts.thymeleaf.struts2_thymeleaf_sampleapp.model;
import java.io.Serializable;
import lombok.Data;
/**
* @author A-pZ
*
*/
@Data
public class SampleProduct implements Serializable {
public SampleProduct(String id, String name, long stock, boolean secret, boolean editable) {
super();
this.id = id;
this.name = name;
this.stock = stock;
this.secret = secret;
this.editable = editable;
}
private String id;
private String name;
private long stock;
private boolean secret;
private boolean editable;
}
Thymeleaf3のテンプレートHTML
Actionクラスから、検索結果は products の名前で扱っていますので、テンプレートでも products で参照します。
Struts2-Thymeleaf3-pluginで扱うThymeleafテンプレートは、Thymeleaf3テンプレートそのままで、特に変わったことはしていません。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sth="http://serendip.thymeleaf">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
</head>
<body>
<div class="container">
<table class="table table-bordered">
<thead>
<th>id</th>
<th>製品名</th>
<th>在庫数</th>
<th>公開可?</th>
<th>編集可?</th>
</thead>
<tbody>
<tr th:each="product : ${products}">
<td th:text="${product.getId()}"></td>
<td th:text="${product.getName()}"></td>
<td th:text="${product.getStock()}"></td>
<td th:text="${product.isSecret()?'👍':''}"></td>
<td th:text="${product.isEditable()?'👍':''}"></td>
</tr>
</tbody>
</table>
</div>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
</body>
</html>
secretとisEditableについてはbooleanなので、trueなら👍の絵文字を出すようにしています。
繰り返し表示もとても簡単ですね!
出力結果
今回の例では bootstrap 4.0.0-alpha6 で出しました。
他にもナビゲーションバーやデフォルトのスタイルを当てると、次のような画面になるでしょう。